summaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-05-20 19:12:30 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-05-20 19:12:30 -0400
commit894e21642dde19184f059c485c49abd7ecdd6ec9 (patch)
tree8b0537f773832240f01f123431393c5ba306003f /drivers/block
parentef82f1ad2e3f4509807c83e7eff4ec7c735076e8 (diff)
parent549f01ae7b913355bea76100d3f17694bc9ec769 (diff)
Merge branch 'for-linus' of git://git.kernel.dk/linux-block
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()
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/drbd/drbd_req.c27
-rw-r--r--drivers/block/xen-blkback/xenbus.c8
2 files changed, 20 insertions, 15 deletions
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c
index b5730e17b455..656624314f0d 100644
--- a/drivers/block/drbd/drbd_req.c
+++ b/drivers/block/drbd/drbd_req.c
@@ -315,24 +315,32 @@ void drbd_req_complete(struct drbd_request *req, struct bio_and_error *m)
315} 315}
316 316
317/* still holds resource->req_lock */ 317/* still holds resource->req_lock */
318static int drbd_req_put_completion_ref(struct drbd_request *req, struct bio_and_error *m, int put) 318static void drbd_req_put_completion_ref(struct drbd_request *req, struct bio_and_error *m, int put)
319{ 319{
320 struct drbd_device *device = req->device; 320 struct drbd_device *device = req->device;
321 D_ASSERT(device, m || (req->rq_state & RQ_POSTPONED)); 321 D_ASSERT(device, m || (req->rq_state & RQ_POSTPONED));
322 322
323 if (!put)
324 return;
325
323 if (!atomic_sub_and_test(put, &req->completion_ref)) 326 if (!atomic_sub_and_test(put, &req->completion_ref))
324 return 0; 327 return;
325 328
326 drbd_req_complete(req, m); 329 drbd_req_complete(req, m);
327 330
331 /* local completion may still come in later,
332 * we need to keep the req object around. */
333 if (req->rq_state & RQ_LOCAL_ABORTED)
334 return;
335
328 if (req->rq_state & RQ_POSTPONED) { 336 if (req->rq_state & RQ_POSTPONED) {
329 /* don't destroy the req object just yet, 337 /* don't destroy the req object just yet,
330 * but queue it for retry */ 338 * but queue it for retry */
331 drbd_restart_request(req); 339 drbd_restart_request(req);
332 return 0; 340 return;
333 } 341 }
334 342
335 return 1; 343 kref_put(&req->kref, drbd_req_destroy);
336} 344}
337 345
338static void set_if_null_req_next(struct drbd_peer_device *peer_device, struct drbd_request *req) 346static 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,
519 if (req->i.waiting) 527 if (req->i.waiting)
520 wake_up(&device->misc_wait); 528 wake_up(&device->misc_wait);
521 529
522 if (c_put) { 530 drbd_req_put_completion_ref(req, m, c_put);
523 if (drbd_req_put_completion_ref(req, m, c_put)) 531 kref_put(&req->kref, drbd_req_destroy);
524 kref_put(&req->kref, drbd_req_destroy);
525 } else {
526 kref_put(&req->kref, drbd_req_destroy);
527 }
528} 532}
529 533
530static void drbd_report_io_error(struct drbd_device *device, struct drbd_request *req) 534static void drbd_report_io_error(struct drbd_device *device, struct drbd_request *req)
@@ -1366,8 +1370,7 @@ nodata:
1366 } 1370 }
1367 1371
1368out: 1372out:
1369 if (drbd_req_put_completion_ref(req, &m, 1)) 1373 drbd_req_put_completion_ref(req, &m, 1);
1370 kref_put(&req->kref, drbd_req_destroy);
1371 spin_unlock_irq(&resource->req_lock); 1374 spin_unlock_irq(&resource->req_lock);
1372 1375
1373 /* Even though above is a kref_put(), this is safe. 1376 /* Even though above is a kref_put(), this is safe.
diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c
index 8fe61b5dc5a6..1f3dfaa54d87 100644
--- a/drivers/block/xen-blkback/xenbus.c
+++ b/drivers/block/xen-blkback/xenbus.c
@@ -504,11 +504,13 @@ static int xen_blkbk_remove(struct xenbus_device *dev)
504 504
505 dev_set_drvdata(&dev->dev, NULL); 505 dev_set_drvdata(&dev->dev, NULL);
506 506
507 if (be->blkif) 507 if (be->blkif) {
508 xen_blkif_disconnect(be->blkif); 508 xen_blkif_disconnect(be->blkif);
509 509
510 /* Put the reference we set in xen_blkif_alloc(). */ 510 /* Put the reference we set in xen_blkif_alloc(). */
511 xen_blkif_put(be->blkif); 511 xen_blkif_put(be->blkif);
512 }
513
512 kfree(be->mode); 514 kfree(be->mode);
513 kfree(be); 515 kfree(be);
514 return 0; 516 return 0;