Merge tag 'ovl-fixes-6.6-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/overla...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 5 Oct 2023 17:56:18 +0000 (10:56 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 5 Oct 2023 17:56:18 +0000 (10:56 -0700)
Pull overlayfs fixes from Amir Goldstein:

 - Fix for file reference leak regression

 - Fix for NULL pointer deref regression

 - Fixes for RCU-walk race regressions:

   Two of the fixes were taken from Al's RCU pathwalk race fixes series
   with his consent [1].

   Note that unlike most of Al's series, these two patches are not about
   racing with ->kill_sb() and they are also very recent regressions
   from v6.5, so I think it's worth getting them into v6.5.y.

   There is also a fix for an RCU pathwalk race with ->kill_sb(), which
   may have been solved in vfs generic code as you suggested, but it
   also rids overlayfs from a nasty hack, so I think it's worth anyway.

Link: https://lore.kernel.org/linux-fsdevel/20231003204749.GA800259@ZenIV/
* tag 'ovl-fixes-6.6-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/overlayfs/vfs:
  ovl: fix NULL pointer defer when encoding non-decodable lower fid
  ovl: make use of ->layers safe in rcu pathwalk
  ovl: fetch inode once in ovl_dentry_revalidate_common()
  ovl: move freeing ovl_entry past rcu delay
  ovl: fix file reference leak when submitting aio

29 files changed:
Documentation/devicetree/bindings/iommu/arm,smmu.yaml
Documentation/tools/rtla/rtla-timerlat-hist.rst
drivers/acpi/nfit/core.c
drivers/base/regmap/regcache-rbtree.c
drivers/iommu/apple-dart.c
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
drivers/iommu/intel/iommu.c
drivers/iommu/intel/iommu.h
drivers/iommu/mtk_iommu.c
drivers/mtd/ubi/build.c
drivers/regulator/core.c
drivers/regulator/mt6358-regulator.c
drivers/s390/scsi/zfcp_aux.c
drivers/scsi/fnic/fnic.h
drivers/scsi/fnic/fnic_io.h
drivers/scsi/fnic/fnic_main.c
drivers/scsi/fnic/fnic_scsi.c
drivers/target/target_core_device.c
fs/nfs/nfs4proc.c
fs/nfs/nfs4state.c
fs/nfs/write.c
net/sunrpc/auth.c
net/sunrpc/auth_tls.c
net/sunrpc/clnt.c
net/sunrpc/xprtsock.c
tools/testing/selftests/Makefile
tools/tracing/rtla/src/timerlat_aa.c
tools/tracing/rtla/src/timerlat_u.c

index cf29ab1..b1b2cf8 100644 (file)
@@ -270,6 +270,7 @@ allOf:
           contains:
             enum:
               - qcom,msm8998-smmu-v2
+              - qcom,sdm630-smmu-v2
     then:
       anyOf:
         - properties:
@@ -311,7 +312,6 @@ allOf:
         compatible:
           contains:
             enum:
-              - qcom,sdm630-smmu-v2
               - qcom,sm6375-smmu-v2
     then:
       anyOf:
index 057db78..03b7f3d 100644 (file)
@@ -36,11 +36,11 @@ EXAMPLE
 In the example below, **rtla timerlat hist** is set to run for *10* minutes,
 in the cpus *0-4*, *skipping zero* only lines. Moreover, **rtla timerlat
 hist** will change the priority of the *timerlat* threads to run under
-*SCHED_DEADLINE* priority, with a *10us* runtime every *1ms* period. The
+*SCHED_DEADLINE* priority, with a *100us* runtime every *1ms* period. The
 *1ms* period is also passed to the *timerlat* tracer. Auto-analysis is disabled
 to reduce overhead ::
 
-  [root@alien ~]# timerlat hist -d 10m -c 0-4 -P d:100us:1ms -p 1ms --no-aa
+  [root@alien ~]# timerlat hist -d 10m -c 0-4 -P d:100us:1ms -p 1000 --no-aa
   # RTLA timerlat histogram
   # Time unit is microseconds (us)
   # Duration:   0 00:10:00
index f0e6738..f96bf32 100644 (file)
@@ -855,7 +855,7 @@ static size_t sizeof_idt(struct acpi_nfit_interleave *idt)
 {
        if (idt->header.length < sizeof(*idt))
                return 0;
-       return sizeof(*idt) + sizeof(u32) * (idt->line_count - 1);
+       return sizeof(*idt) + sizeof(u32) * idt->line_count;
 }
 
 static bool add_idt(struct acpi_nfit_desc *acpi_desc,
index db716ff..3db88bb 100644 (file)
@@ -453,7 +453,8 @@ static int regcache_rbtree_write(struct regmap *map, unsigned int reg,
                if (!rbnode)
                        return -ENOMEM;
                regcache_rbtree_set_register(map, rbnode,
-                                            reg - rbnode->base_reg, value);
+                                            (reg - rbnode->base_reg) / map->reg_stride,
+                                            value);
                regcache_rbtree_insert(map, &rbtree_ctx->root, rbnode);
                rbtree_ctx->cached_rbnode = rbnode;
        }
index 2082081..0b89275 100644 (file)
@@ -671,8 +671,7 @@ static int apple_dart_attach_dev(struct iommu_domain *domain,
                return ret;
 
        switch (domain->type) {
-       case IOMMU_DOMAIN_DMA:
-       case IOMMU_DOMAIN_UNMANAGED:
+       default:
                ret = apple_dart_domain_add_streams(dart_domain, cfg);
                if (ret)
                        return ret;
index 4d83edc..8a16cd3 100644 (file)
@@ -186,6 +186,15 @@ static void arm_smmu_free_shared_cd(struct arm_smmu_ctx_desc *cd)
        }
 }
 
+/*
+ * Cloned from the MAX_TLBI_OPS in arch/arm64/include/asm/tlbflush.h, this
+ * is used as a threshold to replace per-page TLBI commands to issue in the
+ * command queue with an address-space TLBI command, when SMMU w/o a range
+ * invalidation feature handles too many per-page TLBI commands, which will
+ * otherwise result in a soft lockup.
+ */
+#define CMDQ_MAX_TLBI_OPS              (1 << (PAGE_SHIFT - 3))
+
 static void arm_smmu_mm_arch_invalidate_secondary_tlbs(struct mmu_notifier *mn,
                                                struct mm_struct *mm,
                                                unsigned long start,
@@ -201,8 +210,13 @@ static void arm_smmu_mm_arch_invalidate_secondary_tlbs(struct mmu_notifier *mn,
         * range. So do a simple translation here by calculating size correctly.
         */
        size = end - start;
-       if (size == ULONG_MAX)
-               size = 0;
+       if (!(smmu_domain->smmu->features & ARM_SMMU_FEAT_RANGE_INV)) {
+               if (size >= CMDQ_MAX_TLBI_OPS * PAGE_SIZE)
+                       size = 0;
+       } else {
+               if (size == ULONG_MAX)
+                       size = 0;
+       }
 
        if (!(smmu_domain->smmu->features & ARM_SMMU_FEAT_BTM)) {
                if (!size)
index e82bf1c..bd0a596 100644 (file)
@@ -1895,18 +1895,23 @@ static void __arm_smmu_tlb_inv_range(struct arm_smmu_cmdq_ent *cmd,
                /* Get the leaf page size */
                tg = __ffs(smmu_domain->domain.pgsize_bitmap);
 
+               num_pages = size >> tg;
+
                /* Convert page size of 12,14,16 (log2) to 1,2,3 */
                cmd->tlbi.tg = (tg - 10) / 2;
 
                /*
-                * Determine what level the granule is at. For non-leaf, io-pgtable
-                * assumes .tlb_flush_walk can invalidate multiple levels at once,
-                * so ignore the nominal last-level granule and leave TTL=0.
+                * Determine what level the granule is at. For non-leaf, both
+                * io-pgtable and SVA pass a nominal last-level granule because
+                * they don't know what level(s) actually apply, so ignore that
+                * and leave TTL=0. However for various errata reasons we still
+                * want to use a range command, so avoid the SVA corner case
+                * where both scale and num could be 0 as well.
                 */
                if (cmd->tlbi.leaf)
                        cmd->tlbi.ttl = 4 - ((ilog2(granule) - 3) / (tg - 3));
-
-               num_pages = size >> tg;
+               else if ((num_pages & CMDQ_TLBI_RANGE_NUM_MAX) == 1)
+                       num_pages++;
        }
 
        cmds.num = 0;
index 5db283c..3685ba9 100644 (file)
@@ -2998,13 +2998,6 @@ static int iommu_suspend(void)
        struct intel_iommu *iommu = NULL;
        unsigned long flag;
 
-       for_each_active_iommu(iommu, drhd) {
-               iommu->iommu_state = kcalloc(MAX_SR_DMAR_REGS, sizeof(u32),
-                                            GFP_KERNEL);
-               if (!iommu->iommu_state)
-                       goto nomem;
-       }
-
        iommu_flush_all();
 
        for_each_active_iommu(iommu, drhd) {
@@ -3024,12 +3017,6 @@ static int iommu_suspend(void)
                raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
        }
        return 0;
-
-nomem:
-       for_each_active_iommu(iommu, drhd)
-               kfree(iommu->iommu_state);
-
-       return -ENOMEM;
 }
 
 static void iommu_resume(void)
@@ -3061,9 +3048,6 @@ static void iommu_resume(void)
 
                raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
        }
-
-       for_each_active_iommu(iommu, drhd)
-               kfree(iommu->iommu_state);
 }
 
 static struct syscore_ops iommu_syscore_ops = {
index c18fb69..7dac94f 100644 (file)
@@ -681,7 +681,7 @@ struct intel_iommu {
        struct iopf_queue *iopf_queue;
        unsigned char iopfq_name[16];
        struct q_inval  *qi;            /* Queued invalidation info */
-       u32 *iommu_state; /* Store iommu states between suspend and resume.*/
+       u32 iommu_state[MAX_SR_DMAR_REGS]; /* Store iommu states between suspend and resume.*/
 
 #ifdef CONFIG_IRQ_REMAP
        struct ir_table *ir_table;      /* Interrupt remapping info */
index 6402758..fab6c34 100644 (file)
@@ -262,7 +262,7 @@ struct mtk_iommu_data {
        struct device                   *smicomm_dev;
 
        struct mtk_iommu_bank_data      *bank;
-       struct mtk_iommu_domain         *share_dom; /* For 2 HWs share pgtable */
+       struct mtk_iommu_domain         *share_dom;
 
        struct regmap                   *pericfg;
        struct mutex                    mutex; /* Protect m4u_group/m4u_dom above */
@@ -643,8 +643,8 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom,
        struct mtk_iommu_domain *share_dom = data->share_dom;
        const struct mtk_iommu_iova_region *region;
 
-       /* Always use share domain in sharing pgtable case */
-       if (MTK_IOMMU_HAS_FLAG(data->plat_data, SHARE_PGTABLE) && share_dom) {
+       /* Share pgtable when 2 MM IOMMU share the pgtable or one IOMMU use multiple iova ranges */
+       if (share_dom) {
                dom->iop = share_dom->iop;
                dom->cfg = share_dom->cfg;
                dom->domain.pgsize_bitmap = share_dom->cfg.pgsize_bitmap;
@@ -677,8 +677,7 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom,
        /* Update our support page sizes bitmap */
        dom->domain.pgsize_bitmap = dom->cfg.pgsize_bitmap;
 
-       if (MTK_IOMMU_HAS_FLAG(data->plat_data, SHARE_PGTABLE))
-               data->share_dom = dom;
+       data->share_dom = dom;
 
 update_iova_region:
        /* Update the iova region for this domain */
index 8b91a55..8ee51e4 100644 (file)
@@ -894,6 +894,13 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
                return -EINVAL;
        }
 
+       /* UBI cannot work on flashes with zero erasesize. */
+       if (!mtd->erasesize) {
+               pr_err("ubi: refuse attaching mtd%d - zero erasesize flash is not supported\n",
+                       mtd->index);
+               return -EINVAL;
+       }
+
        if (ubi_num == UBI_DEV_NUM_AUTO) {
                /* Search for an empty slot in the @ubi_devices array */
                for (ubi_num = 0; ubi_num < UBI_MAX_DEVICES; ubi_num++)
index d8e1caa..3137e40 100644 (file)
@@ -5542,6 +5542,8 @@ regulator_register(struct device *dev,
                goto rinse;
        }
        device_initialize(&rdev->dev);
+       dev_set_drvdata(&rdev->dev, rdev);
+       rdev->dev.class = &regulator_class;
        spin_lock_init(&rdev->err_lock);
 
        /*
@@ -5603,11 +5605,9 @@ regulator_register(struct device *dev,
                rdev->supply_name = regulator_desc->supply_name;
 
        /* register with sysfs */
-       rdev->dev.class = &regulator_class;
        rdev->dev.parent = config->dev;
        dev_set_name(&rdev->dev, "regulator.%lu",
                    (unsigned long) atomic_inc_return(&regulator_no));
-       dev_set_drvdata(&rdev->dev, rdev);
 
        /* set regulator constraints */
        if (init_data)
@@ -5724,15 +5724,11 @@ wash:
        mutex_lock(&regulator_list_mutex);
        regulator_ena_gpio_free(rdev);
        mutex_unlock(&regulator_list_mutex);
-       put_device(&rdev->dev);
-       rdev = NULL;
 clean:
        if (dangling_of_gpiod)
                gpiod_put(config->ena_gpiod);
-       if (rdev && rdev->dev.of_node)
-               of_node_put(rdev->dev.of_node);
-       kfree(rdev);
        kfree(config);
+       put_device(&rdev->dev);
 rinse:
        if (dangling_cfg_gpiod)
                gpiod_put(cfg->ena_gpiod);
index b9cda22..65fbd95 100644 (file)
@@ -43,7 +43,7 @@ struct mt6358_regulator_info {
        .desc = {       \
                .name = #vreg,  \
                .of_match = of_match_ptr(match),        \
-               .ops = &mt6358_volt_range_ops,  \
+               .ops = &mt6358_buck_ops,        \
                .type = REGULATOR_VOLTAGE,      \
                .id = MT6358_ID_##vreg,         \
                .owner = THIS_MODULE,           \
@@ -139,7 +139,7 @@ struct mt6358_regulator_info {
        .desc = {       \
                .name = #vreg,  \
                .of_match = of_match_ptr(match),        \
-               .ops = &mt6358_volt_range_ops,  \
+               .ops = &mt6358_buck_ops,        \
                .type = REGULATOR_VOLTAGE,      \
                .id = MT6366_ID_##vreg,         \
                .owner = THIS_MODULE,           \
@@ -450,7 +450,7 @@ static unsigned int mt6358_regulator_get_mode(struct regulator_dev *rdev)
        }
 }
 
-static const struct regulator_ops mt6358_volt_range_ops = {
+static const struct regulator_ops mt6358_buck_ops = {
        .list_voltage = regulator_list_voltage_linear,
        .map_voltage = regulator_map_voltage_linear,
        .set_voltage_sel = regulator_set_voltage_sel_regmap,
@@ -464,6 +464,18 @@ static const struct regulator_ops mt6358_volt_range_ops = {
        .get_mode = mt6358_regulator_get_mode,
 };
 
+static const struct regulator_ops mt6358_volt_range_ops = {
+       .list_voltage = regulator_list_voltage_linear,
+       .map_voltage = regulator_map_voltage_linear,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+       .get_voltage_sel = mt6358_get_buck_voltage_sel,
+       .set_voltage_time_sel = regulator_set_voltage_time_sel,
+       .enable = regulator_enable_regmap,
+       .disable = regulator_disable_regmap,
+       .is_enabled = regulator_is_enabled_regmap,
+       .get_status = mt6358_get_status,
+};
+
 static const struct regulator_ops mt6358_volt_table_ops = {
        .list_voltage = regulator_list_voltage_table,
        .map_voltage = regulator_map_voltage_iterate,
index df78264..ab2f35b 100644 (file)
@@ -518,12 +518,12 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn,
        if (port) {
                put_device(&port->dev);
                retval = -EEXIST;
-               goto err_out;
+               goto err_put;
        }
 
        port = kzalloc(sizeof(struct zfcp_port), GFP_KERNEL);
        if (!port)
-               goto err_out;
+               goto err_put;
 
        rwlock_init(&port->unit_list_lock);
        INIT_LIST_HEAD(&port->unit_list);
@@ -546,7 +546,7 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn,
 
        if (dev_set_name(&port->dev, "0x%016llx", (unsigned long long)wwpn)) {
                kfree(port);
-               goto err_out;
+               goto err_put;
        }
        retval = -EINVAL;
 
@@ -563,7 +563,8 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn,
 
        return port;
 
-err_out:
+err_put:
        zfcp_ccw_adapter_put(adapter);
+err_out:
        return ERR_PTR(retval);
 }
index 93c6893..22cef28 100644 (file)
@@ -27,7 +27,7 @@
 
 #define DRV_NAME               "fnic"
 #define DRV_DESCRIPTION                "Cisco FCoE HBA Driver"
-#define DRV_VERSION            "1.6.0.56"
+#define DRV_VERSION            "1.6.0.57"
 #define PFX                    DRV_NAME ": "
 #define DFX                     DRV_NAME "%d: "
 
@@ -237,6 +237,8 @@ struct fnic {
        unsigned int cq_count;
 
        struct mutex sgreset_mutex;
+       spinlock_t sgreset_lock; /* lock for sgreset */
+       struct scsi_cmnd *sgreset_sc;
        struct dentry *fnic_stats_debugfs_host;
        struct dentry *fnic_stats_debugfs_file;
        struct dentry *fnic_reset_debugfs_file;
index f4c8769..5895ead 100644 (file)
@@ -52,6 +52,8 @@ struct fnic_io_req {
        unsigned long start_time; /* in jiffies */
        struct completion *abts_done; /* completion for abts */
        struct completion *dr_done; /* completion for device reset */
+       unsigned int tag;
+       struct scsi_cmnd *sc; /* midlayer's cmd pointer */
 };
 
 enum fnic_port_speeds {
index 984bc5f..f27f931 100644 (file)
@@ -754,6 +754,8 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        for (i = 0; i < FNIC_IO_LOCKS; i++)
                spin_lock_init(&fnic->io_req_lock[i]);
 
+       spin_lock_init(&fnic->sgreset_lock);
+
        err = -ENOMEM;
        fnic->io_req_pool = mempool_create_slab_pool(2, fnic_io_req_cache);
        if (!fnic->io_req_pool)
index 9761b2c..416d819 100644 (file)
@@ -1047,9 +1047,9 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic,
 {
        u8 type;
        u8 hdr_status;
-       struct fcpio_tag tag;
+       struct fcpio_tag ftag;
        u32 id;
-       struct scsi_cmnd *sc;
+       struct scsi_cmnd *sc = NULL;
        struct fnic_io_req *io_req;
        struct fnic_stats *fnic_stats = &fnic->fnic_stats;
        struct abort_stats *abts_stats = &fnic->fnic_stats.abts_stats;
@@ -1058,27 +1058,43 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic,
        unsigned long flags;
        spinlock_t *io_lock;
        unsigned long start_time;
+       unsigned int tag;
 
-       fcpio_header_dec(&desc->hdr, &type, &hdr_status, &tag);
-       fcpio_tag_id_dec(&tag, &id);
+       fcpio_header_dec(&desc->hdr, &type, &hdr_status, &ftag);
+       fcpio_tag_id_dec(&ftag, &id);
 
-       if ((id & FNIC_TAG_MASK) >= fnic->fnic_max_tag_id) {
+       tag = id & FNIC_TAG_MASK;
+       if (tag == fnic->fnic_max_tag_id) {
+               if (!(id & FNIC_TAG_DEV_RST)) {
+                       shost_printk(KERN_ERR, fnic->lport->host,
+                                               "Tag out of range id 0x%x hdr status = %s\n",
+                                               id, fnic_fcpio_status_to_str(hdr_status));
+                       return;
+               }
+       } else if (tag > fnic->fnic_max_tag_id) {
                shost_printk(KERN_ERR, fnic->lport->host,
-               "Tag out of range tag %x hdr status = %s\n",
-               id, fnic_fcpio_status_to_str(hdr_status));
+                                       "Tag out of range tag 0x%x hdr status = %s\n",
+                                       tag, fnic_fcpio_status_to_str(hdr_status));
                return;
        }
 
-       sc = scsi_host_find_tag(fnic->lport->host, id & FNIC_TAG_MASK);
+       if ((tag == fnic->fnic_max_tag_id) && (id & FNIC_TAG_DEV_RST)) {
+               sc = fnic->sgreset_sc;
+               io_lock = &fnic->sgreset_lock;
+       } else {
+               sc = scsi_host_find_tag(fnic->lport->host, id & FNIC_TAG_MASK);
+               io_lock = fnic_io_lock_hash(fnic, sc);
+       }
+
        WARN_ON_ONCE(!sc);
        if (!sc) {
                atomic64_inc(&fnic_stats->io_stats.sc_null);
                shost_printk(KERN_ERR, fnic->lport->host,
                          "itmf_cmpl sc is null - hdr status = %s tag = 0x%x\n",
-                         fnic_fcpio_status_to_str(hdr_status), id);
+                         fnic_fcpio_status_to_str(hdr_status), tag);
                return;
        }
-       io_lock = fnic_io_lock_hash(fnic, sc);
+
        spin_lock_irqsave(io_lock, flags);
        io_req = fnic_priv(sc)->io_req;
        WARN_ON_ONCE(!io_req);
@@ -1089,7 +1105,7 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic,
                shost_printk(KERN_ERR, fnic->lport->host,
                          "itmf_cmpl io_req is null - "
                          "hdr status = %s tag = 0x%x sc 0x%p\n",
-                         fnic_fcpio_status_to_str(hdr_status), id, sc);
+                         fnic_fcpio_status_to_str(hdr_status), tag, sc);
                return;
        }
        start_time = io_req->start_time;
@@ -1938,6 +1954,10 @@ static inline int fnic_queue_dr_io_req(struct fnic *fnic,
        struct scsi_lun fc_lun;
        int ret = 0;
        unsigned long intr_flags;
+       unsigned int tag = scsi_cmd_to_rq(sc)->tag;
+
+       if (tag == SCSI_NO_TAG)
+               tag = io_req->tag;
 
        spin_lock_irqsave(host->host_lock, intr_flags);
        if (unlikely(fnic_chk_state_flags_locked(fnic,
@@ -1964,7 +1984,8 @@ static inline int fnic_queue_dr_io_req(struct fnic *fnic,
        /* fill in the lun info */
        int_to_scsilun(sc->device->lun, &fc_lun);
 
-       fnic_queue_wq_copy_desc_itmf(wq, scsi_cmd_to_rq(sc)->tag | FNIC_TAG_DEV_RST,
+       tag |= FNIC_TAG_DEV_RST;
+       fnic_queue_wq_copy_desc_itmf(wq, tag,
                                     0, FCPIO_ITMF_LUN_RESET, SCSI_NO_TAG,
                                     fc_lun.scsi_lun, io_req->port_id,
                                     fnic->config.ra_tov, fnic->config.ed_tov);
@@ -2146,8 +2167,7 @@ static int fnic_clean_pending_aborts(struct fnic *fnic,
                .ret = SUCCESS,
        };
 
-       if (new_sc)
-               iter_data.lr_sc = lr_sc;
+       iter_data.lr_sc = lr_sc;
 
        scsi_host_busy_iter(fnic->lport->host,
                            fnic_pending_aborts_iter, &iter_data);
@@ -2230,8 +2250,14 @@ int fnic_device_reset(struct scsi_cmnd *sc)
                mutex_lock(&fnic->sgreset_mutex);
                tag = fnic->fnic_max_tag_id;
                new_sc = 1;
-       }
-       io_lock = fnic_io_lock_hash(fnic, sc);
+               fnic->sgreset_sc = sc;
+               io_lock = &fnic->sgreset_lock;
+               FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host,
+                       "fcid: 0x%x lun: 0x%llx flags: 0x%x tag: 0x%x Issuing sgreset\n",
+                       rport->port_id, sc->device->lun, fnic_priv(sc)->flags, tag);
+       } else
+               io_lock = fnic_io_lock_hash(fnic, sc);
+
        spin_lock_irqsave(io_lock, flags);
        io_req = fnic_priv(sc)->io_req;
 
@@ -2247,6 +2273,8 @@ int fnic_device_reset(struct scsi_cmnd *sc)
                }
                memset(io_req, 0, sizeof(*io_req));
                io_req->port_id = rport->port_id;
+               io_req->tag = tag;
+               io_req->sc = sc;
                fnic_priv(sc)->io_req = io_req;
        }
        io_req->dr_done = &tm_done;
@@ -2400,8 +2428,10 @@ fnic_device_reset_end:
                  (u64)sc->cmnd[4] << 8 | sc->cmnd[5]),
                  fnic_flags_and_state(sc));
 
-       if (new_sc)
+       if (new_sc) {
+               fnic->sgreset_sc = NULL;
                mutex_unlock(&fnic->sgreset_mutex);
+       }
 
        FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
                      "Returning from device reset %s\n",
index b7ac60f..b6523d4 100644 (file)
@@ -843,7 +843,6 @@ sector_t target_to_linux_sector(struct se_device *dev, sector_t lb)
 EXPORT_SYMBOL(target_to_linux_sector);
 
 struct devices_idr_iter {
-       struct config_item *prev_item;
        int (*fn)(struct se_device *dev, void *data);
        void *data;
 };
@@ -853,11 +852,9 @@ static int target_devices_idr_iter(int id, void *p, void *data)
 {
        struct devices_idr_iter *iter = data;
        struct se_device *dev = p;
+       struct config_item *item;
        int ret;
 
-       config_item_put(iter->prev_item);
-       iter->prev_item = NULL;
-
        /*
         * We add the device early to the idr, so it can be used
         * by backend modules during configuration. We do not want
@@ -867,12 +864,13 @@ static int target_devices_idr_iter(int id, void *p, void *data)
        if (!target_dev_configured(dev))
                return 0;
 
-       iter->prev_item = config_item_get_unless_zero(&dev->dev_group.cg_item);
-       if (!iter->prev_item)
+       item = config_item_get_unless_zero(&dev->dev_group.cg_item);
+       if (!item)
                return 0;
        mutex_unlock(&device_mutex);
 
        ret = iter->fn(dev, iter->data);
+       config_item_put(item);
 
        mutex_lock(&device_mutex);
        return ret;
@@ -895,7 +893,6 @@ int target_for_each_device(int (*fn)(struct se_device *dev, void *data),
        mutex_lock(&device_mutex);
        ret = idr_for_each(&devices_idr, target_devices_idr_iter, &iter);
        mutex_unlock(&device_mutex);
-       config_item_put(iter.prev_item);
        return ret;
 }
 
index 3508d82..7016eaa 100644 (file)
@@ -10622,7 +10622,9 @@ static void nfs4_disable_swap(struct inode *inode)
         */
        struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
 
-       nfs4_schedule_state_manager(clp);
+       set_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state);
+       clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state);
+       wake_up_var(&clp->cl_state);
 }
 
 static const struct inode_operations nfs4_dir_inode_operations = {
index e079987..9a5d911 100644 (file)
@@ -1209,16 +1209,26 @@ void nfs4_schedule_state_manager(struct nfs_client *clp)
 {
        struct task_struct *task;
        char buf[INET6_ADDRSTRLEN + sizeof("-manager") + 1];
+       struct rpc_clnt *clnt = clp->cl_rpcclient;
+       bool swapon = false;
 
-       if (clp->cl_rpcclient->cl_shutdown)
+       if (clnt->cl_shutdown)
                return;
 
        set_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state);
-       if (test_and_set_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state) != 0) {
-               wake_up_var(&clp->cl_state);
-               return;
+
+       if (atomic_read(&clnt->cl_swapper)) {
+               swapon = !test_and_set_bit(NFS4CLNT_MANAGER_AVAILABLE,
+                                          &clp->cl_state);
+               if (!swapon) {
+                       wake_up_var(&clp->cl_state);
+                       return;
+               }
        }
-       set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state);
+
+       if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0)
+               return;
+
        __module_get(THIS_MODULE);
        refcount_inc(&clp->cl_count);
 
@@ -1235,8 +1245,9 @@ void nfs4_schedule_state_manager(struct nfs_client *clp)
                        __func__, PTR_ERR(task));
                if (!nfs_client_init_is_complete(clp))
                        nfs_mark_client_ready(clp, PTR_ERR(task));
+               if (swapon)
+                       clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state);
                nfs4_clear_state_manager_bit(clp);
-               clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state);
                nfs_put_client(clp);
                module_put(THIS_MODULE);
        }
@@ -2703,6 +2714,13 @@ static void nfs4_state_manager(struct nfs_client *clp)
                nfs4_end_drain_session(clp);
                nfs4_clear_state_manager_bit(clp);
 
+               if (test_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state) &&
+                   !test_and_set_bit(NFS4CLNT_MANAGER_RUNNING,
+                                     &clp->cl_state)) {
+                       memflags = memalloc_nofs_save();
+                       continue;
+               }
+
                if (!test_and_set_bit(NFS4CLNT_RECALL_RUNNING, &clp->cl_state)) {
                        if (test_and_clear_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state)) {
                                nfs_client_return_marked_delegations(clp);
@@ -2741,22 +2759,25 @@ static int nfs4_run_state_manager(void *ptr)
 
        allow_signal(SIGKILL);
 again:
-       set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state);
        nfs4_state_manager(clp);
-       if (atomic_read(&cl->cl_swapper)) {
+
+       if (test_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state) &&
+           !test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state)) {
                wait_var_event_interruptible(&clp->cl_state,
                                             test_bit(NFS4CLNT_RUN_MANAGER,
                                                      &clp->cl_state));
-               if (atomic_read(&cl->cl_swapper) &&
-                   test_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state))
+               if (!atomic_read(&cl->cl_swapper))
+                       clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state);
+               if (refcount_read(&clp->cl_count) > 1 && !signalled() &&
+                   !test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state))
                        goto again;
                /* Either no longer a swapper, or were signalled */
+               clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state);
        }
-       clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state);
 
        if (refcount_read(&clp->cl_count) > 1 && !signalled() &&
            test_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state) &&
-           !test_and_set_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state))
+           !test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state))
                goto again;
 
        nfs_put_client(clp);
index 8c1ee1a..7720b5e 100644 (file)
@@ -802,8 +802,8 @@ static void nfs_inode_remove_request(struct nfs_page *req)
        }
 
        if (test_and_clear_bit(PG_INODE_REF, &req->wb_flags)) {
-               nfs_release_request(req);
                atomic_long_dec(&NFS_I(nfs_page_to_inode(req))->nrequests);
+               nfs_release_request(req);
        }
 }
 
index 2f16f9d..814b016 100644 (file)
@@ -769,9 +769,14 @@ int rpcauth_wrap_req(struct rpc_task *task, struct xdr_stream *xdr)
  * @task: controlling RPC task
  * @xdr: xdr_stream containing RPC Reply header
  *
- * On success, @xdr is updated to point past the verifier and
- * zero is returned. Otherwise, @xdr is in an undefined state
- * and a negative errno is returned.
+ * Return values:
+ *   %0: Verifier is valid. @xdr now points past the verifier.
+ *   %-EIO: Verifier is corrupted or message ended early.
+ *   %-EACCES: Verifier is intact but not valid.
+ *   %-EPROTONOSUPPORT: Server does not support the requested auth type.
+ *
+ * When a negative errno is returned, @xdr is left in an undefined
+ * state.
  */
 int
 rpcauth_checkverf(struct rpc_task *task, struct xdr_stream *xdr)
index de7678f..87f570f 100644 (file)
@@ -129,9 +129,9 @@ static int tls_validate(struct rpc_task *task, struct xdr_stream *xdr)
        if (*p != rpc_auth_null)
                return -EIO;
        if (xdr_stream_decode_opaque_inline(xdr, &str, starttls_len) != starttls_len)
-               return -EIO;
+               return -EPROTONOSUPPORT;
        if (memcmp(str, starttls_token, starttls_len))
-               return -EIO;
+               return -EPROTONOSUPPORT;
        return 0;
 }
 
index 37b0b21..9c21027 100644 (file)
@@ -2476,8 +2476,7 @@ call_status(struct rpc_task *task)
                goto out_exit;
        }
        task->tk_action = call_encode;
-       if (status != -ECONNRESET && status != -ECONNABORTED)
-               rpc_check_timeout(task);
+       rpc_check_timeout(task);
        return;
 out_exit:
        rpc_call_rpcerror(task, status);
@@ -2725,7 +2724,15 @@ out_unparsable:
 
 out_verifier:
        trace_rpc_bad_verifier(task);
-       goto out_garbage;
+       switch (error) {
+       case -EPROTONOSUPPORT:
+               goto out_err;
+       case -EACCES:
+               /* Re-encode with a fresh cred */
+               fallthrough;
+       default:
+               goto out_garbage;
+       }
 
 out_msg_denied:
        error = -EACCES;
index 71cd916..a15bf2e 100644 (file)
@@ -2672,6 +2672,10 @@ static void xs_tcp_tls_setup_socket(struct work_struct *work)
        rcu_read_lock();
        lower_xprt = rcu_dereference(lower_clnt->cl_xprt);
        rcu_read_unlock();
+
+       if (wait_on_bit_lock(&lower_xprt->state, XPRT_LOCKED, TASK_KILLABLE))
+               goto out_unlock;
+
        status = xs_tls_handshake_sync(lower_xprt, &upper_xprt->xprtsec);
        if (status) {
                trace_rpc_tls_not_started(upper_clnt, upper_xprt);
@@ -2681,6 +2685,7 @@ static void xs_tcp_tls_setup_socket(struct work_struct *work)
        status = xs_tcp_tls_finish_connecting(lower_xprt, upper_transport);
        if (status)
                goto out_close;
+       xprt_release_write(lower_xprt, NULL);
 
        trace_rpc_socket_connect(upper_xprt, upper_transport->sock, 0);
        if (!xprt_test_and_set_connected(upper_xprt)) {
@@ -2702,6 +2707,7 @@ out_unlock:
        return;
 
 out_close:
+       xprt_release_write(lower_xprt, NULL);
        rpc_shutdown_client(lower_clnt);
 
        /* xprt_force_disconnect() wakes tasks with a fixed tk_status code.
index 42806ad..1a21d6b 100644 (file)
@@ -92,7 +92,7 @@ endif
 TARGETS += tmpfs
 TARGETS += tpm2
 TARGETS += tty
-TARGETS += uevents
+TARGETS += uevent
 TARGETS += user
 TARGETS += user_events
 TARGETS += vDSO
index e0ffe69..7093fd5 100644 (file)
@@ -159,6 +159,7 @@ static int timerlat_aa_irq_latency(struct timerlat_aa_data *taa_data,
        taa_data->thread_nmi_sum = 0;
        taa_data->thread_irq_sum = 0;
        taa_data->thread_softirq_sum = 0;
+       taa_data->thread_thread_sum = 0;
        taa_data->thread_blocking_duration = 0;
        taa_data->timer_irq_start_time = 0;
        taa_data->timer_irq_duration = 0;
@@ -337,7 +338,23 @@ static int timerlat_aa_irq_handler(struct trace_seq *s, struct tep_record *recor
                taa_data->timer_irq_start_time = start;
                taa_data->timer_irq_duration = duration;
 
-               taa_data->timer_irq_start_delay = taa_data->timer_irq_start_time - expected_start;
+               /*
+                * We are dealing with two different clock sources: the
+                * external clock source that timerlat uses as a reference
+                * and the clock used by the tracer. There are also two
+                * moments: the time reading the clock and the timer in
+                * which the event is placed in the buffer (the trace
+                * event timestamp). If the processor is slow or there
+                * is some hardware noise, the difference between the
+                * timestamp and the external clock read can be longer
+                * than the IRQ handler delay, resulting in a negative
+                * time. If so, set IRQ start delay as 0. In the end,
+                * it is less relevant than the noise.
+                */
+               if (expected_start < taa_data->timer_irq_start_time)
+                       taa_data->timer_irq_start_delay = taa_data->timer_irq_start_time - expected_start;
+               else
+                       taa_data->timer_irq_start_delay = 0;
 
                /*
                 * not exit from idle.
@@ -528,7 +545,7 @@ static int timerlat_aa_kworker_start_handler(struct trace_seq *s, struct tep_rec
 static void timerlat_thread_analysis(struct timerlat_aa_data *taa_data, int cpu,
                                     int irq_thresh, int thread_thresh)
 {
-       unsigned long long exp_irq_ts;
+       long long exp_irq_ts;
        int total;
        int irq;
 
@@ -545,12 +562,15 @@ static void timerlat_thread_analysis(struct timerlat_aa_data *taa_data, int cpu,
 
        /*
         * Expected IRQ arrival time using the trace clock as the base.
+        *
+        * TODO: Add a list of previous IRQ, and then run the list backwards.
         */
        exp_irq_ts = taa_data->timer_irq_start_time - taa_data->timer_irq_start_delay;
-
-       if (exp_irq_ts < taa_data->prev_irq_timstamp + taa_data->prev_irq_duration)
-               printf("  Previous IRQ interference:    \t\t up to  %9.2f us\n",
-                       ns_to_usf(taa_data->prev_irq_duration));
+       if (exp_irq_ts < taa_data->prev_irq_timstamp + taa_data->prev_irq_duration) {
+               if (taa_data->prev_irq_timstamp < taa_data->timer_irq_start_time)
+                       printf("  Previous IRQ interference:    \t\t up to  %9.2f us\n",
+                               ns_to_usf(taa_data->prev_irq_duration));
+       }
 
        /*
         * The delay that the IRQ suffered before starting.
index 05e3106..01dbf9a 100644 (file)
@@ -45,7 +45,7 @@ static int timerlat_u_main(int cpu, struct timerlat_u_params *params)
 
        retval = sched_setaffinity(gettid(), sizeof(set), &set);
        if (retval == -1) {
-               err_msg("Error setting user thread affinity\n");
+               debug_msg("Error setting user thread affinity %d, is the CPU online?\n", cpu);
                exit(1);
        }
 
@@ -193,7 +193,9 @@ void *timerlat_u_dispatcher(void *data)
                                        procs_count--;
                                }
                        }
-                       break;
+
+                       if (!procs_count)
+                               break;
                }
 
                sleep(1);