drbd: reduce number of spinlock drop/re-aquire cycles
authorLars Ellenberg <lars.ellenberg@linbit.com>
Wed, 4 Dec 2013 11:07:09 +0000 (12:07 +0100)
committerPhilipp Reisner <philipp.reisner@linbit.com>
Thu, 10 Jul 2014 13:22:21 +0000 (15:22 +0200)
Instead of dropping and re-aquiring the spinlock around the submit,
just remember that we want to submit, and do that only once we have
dropped the spinlock for good.

Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
drivers/block/drbd/drbd_req.c

index 09803d0d5207ce7fccffc5c4a3cb0229071566cd..4c7fee1a5a852dff115a146e12c2830e2c5c25b7 100644 (file)
@@ -1086,11 +1086,13 @@ drbd_request_prepare(struct drbd_device *device, struct bio *bio, unsigned long
 
 static void drbd_send_and_submit(struct drbd_device *device, struct drbd_request *req)
 {
+       struct drbd_resource *resource = device->resource;
        const int rw = bio_rw(req->master_bio);
        struct bio_and_error m = { NULL, };
        bool no_remote = false;
+       bool submit_private_bio = false;
 
-       spin_lock_irq(&device->resource->req_lock);
+       spin_lock_irq(&resource->req_lock);
        if (rw == WRITE) {
                /* This may temporarily give up the req_lock,
                 * but will re-aquire it before it returns here.
@@ -1152,9 +1154,7 @@ static void drbd_send_and_submit(struct drbd_device *device, struct drbd_request
                /* needs to be marked within the same spinlock */
                _req_mod(req, TO_BE_SUBMITTED);
                /* but we need to give up the spinlock to submit */
-               spin_unlock_irq(&device->resource->req_lock);
-               drbd_submit_req_private_bio(req);
-               spin_lock_irq(&device->resource->req_lock);
+               submit_private_bio = true;
        } else if (no_remote) {
 nodata:
                if (__ratelimit(&drbd_ratelimit_state))
@@ -1167,8 +1167,16 @@ nodata:
 out:
        if (drbd_req_put_completion_ref(req, &m, 1))
                kref_put(&req->kref, drbd_req_destroy);
-       spin_unlock_irq(&device->resource->req_lock);
-
+       spin_unlock_irq(&resource->req_lock);
+
+       /* Even though above is a kref_put(), this is safe.
+        * As long as we still need to submit our private bio,
+        * we hold a completion ref, and the request cannot disappear.
+        * If however this request did not even have a private bio to submit
+        * (e.g. remote read), req may already be invalid now.
+        * That's why we cannot check on req->private_bio. */
+       if (submit_private_bio)
+               drbd_submit_req_private_bio(req);
        if (m.bio)
                complete_master_bio(device, &m);
 }