aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/block/drbd/drbd_req.c20
1 files changed, 14 insertions, 6 deletions
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c
index 09803d0d5207..4c7fee1a5a85 100644
--- a/drivers/block/drbd/drbd_req.c
+++ b/drivers/block/drbd/drbd_req.c
@@ -1086,11 +1086,13 @@ drbd_request_prepare(struct drbd_device *device, struct bio *bio, unsigned long
1086 1086
1087static void drbd_send_and_submit(struct drbd_device *device, struct drbd_request *req) 1087static void drbd_send_and_submit(struct drbd_device *device, struct drbd_request *req)
1088{ 1088{
1089 struct drbd_resource *resource = device->resource;
1089 const int rw = bio_rw(req->master_bio); 1090 const int rw = bio_rw(req->master_bio);
1090 struct bio_and_error m = { NULL, }; 1091 struct bio_and_error m = { NULL, };
1091 bool no_remote = false; 1092 bool no_remote = false;
1093 bool submit_private_bio = false;
1092 1094
1093 spin_lock_irq(&device->resource->req_lock); 1095 spin_lock_irq(&resource->req_lock);
1094 if (rw == WRITE) { 1096 if (rw == WRITE) {
1095 /* This may temporarily give up the req_lock, 1097 /* This may temporarily give up the req_lock,
1096 * but will re-aquire it before it returns here. 1098 * 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
1152 /* needs to be marked within the same spinlock */ 1154 /* needs to be marked within the same spinlock */
1153 _req_mod(req, TO_BE_SUBMITTED); 1155 _req_mod(req, TO_BE_SUBMITTED);
1154 /* but we need to give up the spinlock to submit */ 1156 /* but we need to give up the spinlock to submit */
1155 spin_unlock_irq(&device->resource->req_lock); 1157 submit_private_bio = true;
1156 drbd_submit_req_private_bio(req);
1157 spin_lock_irq(&device->resource->req_lock);
1158 } else if (no_remote) { 1158 } else if (no_remote) {
1159nodata: 1159nodata:
1160 if (__ratelimit(&drbd_ratelimit_state)) 1160 if (__ratelimit(&drbd_ratelimit_state))
@@ -1167,8 +1167,16 @@ nodata:
1167out: 1167out:
1168 if (drbd_req_put_completion_ref(req, &m, 1)) 1168 if (drbd_req_put_completion_ref(req, &m, 1))
1169 kref_put(&req->kref, drbd_req_destroy); 1169 kref_put(&req->kref, drbd_req_destroy);
1170 spin_unlock_irq(&device->resource->req_lock); 1170 spin_unlock_irq(&resource->req_lock);
1171 1171
1172 /* Even though above is a kref_put(), this is safe.
1173 * As long as we still need to submit our private bio,
1174 * we hold a completion ref, and the request cannot disappear.
1175 * If however this request did not even have a private bio to submit
1176 * (e.g. remote read), req may already be invalid now.
1177 * That's why we cannot check on req->private_bio. */
1178 if (submit_private_bio)
1179 drbd_submit_req_private_bio(req);
1172 if (m.bio) 1180 if (m.bio)
1173 complete_master_bio(device, &m); 1181 complete_master_bio(device, &m);
1174} 1182}