Merge branch 'for-linus' of git://git.kernel.dk/linux-block
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 20 May 2017 23:12:30 +0000 (16:12 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 20 May 2017 23:12:30 +0000 (16:12 -0700)
Pull block fixes from Jens Axboe:
 "A small collection of fixes that should go into this cycle.

   - a pull request from Christoph for NVMe, which ended up being
     manually applied to avoid pulling in newer bits in master. Mostly
     fibre channel fixes from James, but also a few fixes from Jon and
     Vijay

   - a pull request from Konrad, with just a single fix for xen-blkback
     from Gustavo.

   - a fuseblk bdi fix from Jan, fixing a regression in this series with
     the dynamic backing devices.

   - a blktrace fix from Shaohua, replacing sscanf() with kstrtoull().

   - a request leak fix for drbd from Lars, fixing a regression in the
     last series with the kref changes. This will go to stable as well"

* 'for-linus' of git://git.kernel.dk/linux-block:
  nvmet: release the sq ref on rdma read errors
  nvmet-fc: remove target cpu scheduling flag
  nvme-fc: stop queues on error detection
  nvme-fc: require target or discovery role for fc-nvme targets
  nvme-fc: correct port role bits
  nvme: unmap CMB and remove sysfs file in reset path
  blktrace: fix integer parse
  fuseblk: Fix warning in super_setup_bdi_name()
  block: xen-blkback: add null check to avoid null pointer dereference
  drbd: fix request leak introduced by locking/atomic, kref: Kill kref_sub()

13 files changed:
drivers/block/drbd/drbd_req.c
drivers/block/xen-blkback/xenbus.c
drivers/nvme/host/fc.c
drivers/nvme/host/pci.c
drivers/nvme/target/core.c
drivers/nvme/target/fc.c
drivers/nvme/target/fcloop.c
drivers/nvme/target/nvmet.h
drivers/nvme/target/rdma.c
drivers/scsi/lpfc/lpfc_nvmet.c
fs/fuse/inode.c
include/linux/nvme-fc-driver.h
kernel/trace/blktrace.c

index b5730e17b45584ad4109df8c1c6eac5a35e81a4f..656624314f0d68dc7385b3896d0de9ae1a1cc457 100644 (file)
@@ -315,24 +315,32 @@ void drbd_req_complete(struct drbd_request *req, struct bio_and_error *m)
 }
 
 /* still holds resource->req_lock */
-static int drbd_req_put_completion_ref(struct drbd_request *req, struct bio_and_error *m, int put)
+static void drbd_req_put_completion_ref(struct drbd_request *req, struct bio_and_error *m, int put)
 {
        struct drbd_device *device = req->device;
        D_ASSERT(device, m || (req->rq_state & RQ_POSTPONED));
 
+       if (!put)
+               return;
+
        if (!atomic_sub_and_test(put, &req->completion_ref))
-               return 0;
+               return;
 
        drbd_req_complete(req, m);
 
+       /* local completion may still come in later,
+        * we need to keep the req object around. */
+       if (req->rq_state & RQ_LOCAL_ABORTED)
+               return;
+
        if (req->rq_state & RQ_POSTPONED) {
                /* don't destroy the req object just yet,
                 * but queue it for retry */
                drbd_restart_request(req);
-               return 0;
+               return;
        }
 
-       return 1;
+       kref_put(&req->kref, drbd_req_destroy);
 }
 
 static void set_if_null_req_next(struct drbd_peer_device *peer_device, struct drbd_request *req)
@@ -519,12 +527,8 @@ static void mod_rq_state(struct drbd_request *req, struct bio_and_error *m,
        if (req->i.waiting)
                wake_up(&device->misc_wait);
 
-       if (c_put) {
-               if (drbd_req_put_completion_ref(req, m, c_put))
-                       kref_put(&req->kref, drbd_req_destroy);
-       } else {
-               kref_put(&req->kref, drbd_req_destroy);
-       }
+       drbd_req_put_completion_ref(req, m, c_put);
+       kref_put(&req->kref, drbd_req_destroy);
 }
 
 static void drbd_report_io_error(struct drbd_device *device, struct drbd_request *req)
@@ -1366,8 +1370,7 @@ nodata:
        }
 
 out:
-       if (drbd_req_put_completion_ref(req, &m, 1))
-               kref_put(&req->kref, drbd_req_destroy);
+       drbd_req_put_completion_ref(req, &m, 1);
        spin_unlock_irq(&resource->req_lock);
 
        /* Even though above is a kref_put(), this is safe.
index 8fe61b5dc5a6553d141950506344fe90bbfde2c8..1f3dfaa54d871a36897408898c1e0e9f22100bb1 100644 (file)
@@ -504,11 +504,13 @@ static int xen_blkbk_remove(struct xenbus_device *dev)
 
        dev_set_drvdata(&dev->dev, NULL);
 
-       if (be->blkif)
+       if (be->blkif) {
                xen_blkif_disconnect(be->blkif);
 
-       /* Put the reference we set in xen_blkif_alloc(). */
-       xen_blkif_put(be->blkif);
+               /* Put the reference we set in xen_blkif_alloc(). */
+               xen_blkif_put(be->blkif);
+       }
+
        kfree(be->mode);
        kfree(be);
        return 0;
index 70e689bf1cad286869922764ccd52f1872e92524..dca7165fabcf9ce5df19fee1007e8da8bd794e21 100644 (file)
@@ -1754,6 +1754,10 @@ nvme_fc_error_recovery(struct nvme_fc_ctrl *ctrl, char *errmsg)
        dev_info(ctrl->ctrl.device,
                "NVME-FC{%d}: resetting controller\n", ctrl->cnum);
 
+       /* stop the queues on error, cleanup is in reset thread */
+       if (ctrl->queue_count > 1)
+               nvme_stop_queues(&ctrl->ctrl);
+
        if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_RECONNECTING)) {
                dev_err(ctrl->ctrl.device,
                        "NVME-FC{%d}: error_recovery: Couldn't change state "
@@ -2720,6 +2724,12 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
        unsigned long flags;
        int ret, idx;
 
+       if (!(rport->remoteport.port_role &
+           (FC_PORT_ROLE_NVME_DISCOVERY | FC_PORT_ROLE_NVME_TARGET))) {
+               ret = -EBADR;
+               goto out_fail;
+       }
+
        ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
        if (!ctrl) {
                ret = -ENOMEM;
index fed803232edccbdf63139d89028c694efff52409..4c2ff2bb26bcd7c615e40ae777327a3ba401cf3d 100644 (file)
@@ -1506,6 +1506,11 @@ static inline void nvme_release_cmb(struct nvme_dev *dev)
        if (dev->cmb) {
                iounmap(dev->cmb);
                dev->cmb = NULL;
+               if (dev->cmbsz) {
+                       sysfs_remove_file_from_group(&dev->ctrl.device->kobj,
+                                                    &dev_attr_cmb.attr, NULL);
+                       dev->cmbsz = 0;
+               }
        }
 }
 
@@ -1779,6 +1784,7 @@ static void nvme_pci_disable(struct nvme_dev *dev)
 {
        struct pci_dev *pdev = to_pci_dev(dev->dev);
 
+       nvme_release_cmb(dev);
        pci_free_irq_vectors(pdev);
 
        if (pci_is_enabled(pdev)) {
@@ -2184,7 +2190,6 @@ static void nvme_remove(struct pci_dev *pdev)
        nvme_dev_disable(dev, true);
        nvme_dev_remove_admin(dev);
        nvme_free_queues(dev, 0);
-       nvme_release_cmb(dev);
        nvme_release_prp_pools(dev);
        nvme_dev_unmap(dev);
        nvme_put_ctrl(&dev->ctrl);
index cf90713043da01ea7180d227feb2895da3653f49..eb9399ac97cff2d5bba89457f6a828238854b98a 100644 (file)
@@ -529,6 +529,12 @@ fail:
 }
 EXPORT_SYMBOL_GPL(nvmet_req_init);
 
+void nvmet_req_uninit(struct nvmet_req *req)
+{
+       percpu_ref_put(&req->sq->ref);
+}
+EXPORT_SYMBOL_GPL(nvmet_req_uninit);
+
 static inline bool nvmet_cc_en(u32 cc)
 {
        return cc & 0x1;
index 62eba29c85fb9b5101d4a974a9392dbb2e71c72d..2006fae61980643d2c42f4d34926aaa11f5f05bc 100644 (file)
@@ -517,9 +517,7 @@ nvmet_fc_queue_to_cpu(struct nvmet_fc_tgtport *tgtport, int qid)
 {
        int cpu, idx, cnt;
 
-       if (!(tgtport->ops->target_features &
-                       NVMET_FCTGTFEAT_NEEDS_CMD_CPUSCHED) ||
-           tgtport->ops->max_hw_queues == 1)
+       if (tgtport->ops->max_hw_queues == 1)
                return WORK_CPU_UNBOUND;
 
        /* Simple cpu selection based on qid modulo active cpu count */
index 15551ef79c8c4568a6f611b6e9ba9d736127825b..294a6611fb249164e8d321147823e708cfe8a1d1 100644 (file)
@@ -698,7 +698,6 @@ static struct nvmet_fc_target_template tgttemplate = {
        .dma_boundary           = FCLOOP_DMABOUND_4G,
        /* optional features */
        .target_features        = NVMET_FCTGTFEAT_CMD_IN_ISR |
-                                 NVMET_FCTGTFEAT_NEEDS_CMD_CPUSCHED |
                                  NVMET_FCTGTFEAT_OPDONE_IN_ISR,
        /* sizes of additional private data for data structures */
        .target_priv_sz         = sizeof(struct fcloop_tport),
index 7cb77ba5993b98e0974a66a7712961c434677a7f..cfc5c7fb0ab78411f8d6e96ab7ffaaad241b6244 100644 (file)
@@ -261,6 +261,7 @@ u16 nvmet_parse_fabrics_cmd(struct nvmet_req *req);
 
 bool nvmet_req_init(struct nvmet_req *req, struct nvmet_cq *cq,
                struct nvmet_sq *sq, struct nvmet_fabrics_ops *ops);
+void nvmet_req_uninit(struct nvmet_req *req);
 void nvmet_req_complete(struct nvmet_req *req, u16 status);
 
 void nvmet_cq_setup(struct nvmet_ctrl *ctrl, struct nvmet_cq *cq, u16 qid,
index 99c69018a35f4419b3dc3a14576c373c044e661a..9e45cde633767be2176770c7ebd71a90b3ca3094 100644 (file)
@@ -567,6 +567,7 @@ static void nvmet_rdma_read_data_done(struct ib_cq *cq, struct ib_wc *wc)
        rsp->n_rdma = 0;
 
        if (unlikely(wc->status != IB_WC_SUCCESS)) {
+               nvmet_req_uninit(&rsp->req);
                nvmet_rdma_release_rsp(rsp);
                if (wc->status != IB_WC_WR_FLUSH_ERR) {
                        pr_info("RDMA READ for CQE 0x%p failed with status %s (%d).\n",
index 94434e621c335e678ad2aa1c3301b967cb15a210..0488580eea12eecd0c2767bc6ad5c11a014ac46d 100644 (file)
@@ -764,7 +764,6 @@ lpfc_nvmet_create_targetport(struct lpfc_hba *phba)
        lpfc_tgttemplate.max_sgl_segments = phba->cfg_nvme_seg_cnt + 1;
        lpfc_tgttemplate.max_hw_queues = phba->cfg_nvme_io_channel;
        lpfc_tgttemplate.target_features = NVMET_FCTGTFEAT_READDATA_RSP |
-                                          NVMET_FCTGTFEAT_NEEDS_CMD_CPUSCHED |
                                           NVMET_FCTGTFEAT_CMD_IN_ISR |
                                           NVMET_FCTGTFEAT_OPDONE_IN_ISR;
 
index 5a1b58f8fef4d2437842b73d4c1c12b2e87a32c9..65c88379a3a14311cca68b8750d6bb0b9f107444 100644 (file)
@@ -975,8 +975,15 @@ static int fuse_bdi_init(struct fuse_conn *fc, struct super_block *sb)
        int err;
        char *suffix = "";
 
-       if (sb->s_bdev)
+       if (sb->s_bdev) {
                suffix = "-fuseblk";
+               /*
+                * sb->s_bdi points to blkdev's bdi however we want to redirect
+                * it to our private bdi...
+                */
+               bdi_put(sb->s_bdi);
+               sb->s_bdi = &noop_backing_dev_info;
+       }
        err = super_setup_bdi_name(sb, "%u:%u%s", MAJOR(fc->dev),
                                   MINOR(fc->dev), suffix);
        if (err)
index 0db37158a61d4e4e5af0d16d14c07510ef660330..6c8c5d8041b72ec01097d1c0563b793ea7449f1f 100644 (file)
@@ -27,8 +27,8 @@
 
 /* FC Port role bitmask - can merge with FC Port Roles in fc transport */
 #define FC_PORT_ROLE_NVME_INITIATOR    0x10
-#define FC_PORT_ROLE_NVME_TARGET       0x11
-#define FC_PORT_ROLE_NVME_DISCOVERY    0x12
+#define FC_PORT_ROLE_NVME_TARGET       0x20
+#define FC_PORT_ROLE_NVME_DISCOVERY    0x40
 
 
 /**
@@ -642,15 +642,7 @@ enum {
                 * sequence in one LLDD operation. Errors during Data
                 * sequence transmit must not allow RSP sequence to be sent.
                 */
-       NVMET_FCTGTFEAT_NEEDS_CMD_CPUSCHED = (1 << 1),
-               /* Bit 1: When 0, the LLDD will deliver FCP CMD
-                * on the CPU it should be affinitized to. Thus work will
-                * be scheduled on the cpu received on. When 1, the LLDD
-                * may not deliver the CMD on the CPU it should be worked
-                * on. The transport should pick a cpu to schedule the work
-                * on.
-                */
-       NVMET_FCTGTFEAT_CMD_IN_ISR = (1 << 2),
+       NVMET_FCTGTFEAT_CMD_IN_ISR = (1 << 1),
                /* Bit 2: When 0, the LLDD is calling the cmd rcv handler
                 * in a non-isr context, allowing the transport to finish
                 * op completion in the calling context. When 1, the LLDD
@@ -658,7 +650,7 @@ enum {
                 * requiring the transport to transition to a workqueue
                 * for op completion.
                 */
-       NVMET_FCTGTFEAT_OPDONE_IN_ISR = (1 << 3),
+       NVMET_FCTGTFEAT_OPDONE_IN_ISR = (1 << 2),
                /* Bit 3: When 0, the LLDD is calling the op done handler
                 * in a non-isr context, allowing the transport to finish
                 * op completion in the calling context. When 1, the LLDD
index bd8ae8d5ae9ca865f3738c6b4df579a3a1ca12cc..193c5f5e3f7988e8d27eed5c4292e2345e3c5bf7 100644 (file)
@@ -1662,14 +1662,14 @@ static ssize_t sysfs_blk_trace_attr_store(struct device *dev,
                goto out;
 
        if (attr == &dev_attr_act_mask) {
-               if (sscanf(buf, "%llx", &value) != 1) {
+               if (kstrtoull(buf, 0, &value)) {
                        /* Assume it is a list of trace category names */
                        ret = blk_trace_str2mask(buf);
                        if (ret < 0)
                                goto out;
                        value = ret;
                }
-       } else if (sscanf(buf, "%llu", &value) != 1)
+       } else if (kstrtoull(buf, 0, &value))
                goto out;
 
        ret = -ENXIO;