diff options
author | Lars Ellenberg <lars.ellenberg@linbit.com> | 2010-11-13 14:42:29 -0500 |
---|---|---|
committer | Jens Axboe <jaxboe@fusionio.com> | 2010-11-27 13:50:43 -0500 |
commit | a115413de13ae6beb0cbfc198afe385a261ab284 (patch) | |
tree | 45afb2173a442b8524cf70fc6b50eee80437c68a /drivers/block | |
parent | c13f7e1a94007c4381814e7daf033e3e8f0663f3 (diff) |
drbd: fix for spin_lock_irqsave in endio callback
In commit 9b7f76dc37919ea36caa9680a3f765e5b19b25fb,
Author: Lars Ellenberg <lars.ellenberg@linbit.com>
Date: Wed Aug 11 23:40:24 2010 +0200
drbd: new configuration parameter c-min-rate
a bad chunk slipped through, which is now reverted as well,
restoring the correct irqsave for the endio callback.
This patch also add comments at both req_mod()
and in the endio callback so it should not happen again.
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/drbd/drbd_req.h | 3 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_worker.c | 10 |
2 files changed, 11 insertions, 2 deletions
diff --git a/drivers/block/drbd/drbd_req.h b/drivers/block/drbd/drbd_req.h index 181ea0364822..ab2bd09d54b4 100644 --- a/drivers/block/drbd/drbd_req.h +++ b/drivers/block/drbd/drbd_req.h | |||
@@ -339,7 +339,8 @@ static inline int _req_mod(struct drbd_request *req, enum drbd_req_event what) | |||
339 | } | 339 | } |
340 | 340 | ||
341 | /* completion of master bio is outside of spinlock. | 341 | /* completion of master bio is outside of spinlock. |
342 | * If you need it irqsave, do it your self! */ | 342 | * If you need it irqsave, do it your self! |
343 | * Which means: don't use from bio endio callback. */ | ||
343 | static inline int req_mod(struct drbd_request *req, | 344 | static inline int req_mod(struct drbd_request *req, |
344 | enum drbd_req_event what) | 345 | enum drbd_req_event what) |
345 | { | 346 | { |
diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index 47d223c2409c..34f224b018b3 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c | |||
@@ -193,8 +193,10 @@ void drbd_endio_sec(struct bio *bio, int error) | |||
193 | */ | 193 | */ |
194 | void drbd_endio_pri(struct bio *bio, int error) | 194 | void drbd_endio_pri(struct bio *bio, int error) |
195 | { | 195 | { |
196 | unsigned long flags; | ||
196 | struct drbd_request *req = bio->bi_private; | 197 | struct drbd_request *req = bio->bi_private; |
197 | struct drbd_conf *mdev = req->mdev; | 198 | struct drbd_conf *mdev = req->mdev; |
199 | struct bio_and_error m; | ||
198 | enum drbd_req_event what; | 200 | enum drbd_req_event what; |
199 | int uptodate = bio_flagged(bio, BIO_UPTODATE); | 201 | int uptodate = bio_flagged(bio, BIO_UPTODATE); |
200 | 202 | ||
@@ -220,7 +222,13 @@ void drbd_endio_pri(struct bio *bio, int error) | |||
220 | bio_put(req->private_bio); | 222 | bio_put(req->private_bio); |
221 | req->private_bio = ERR_PTR(error); | 223 | req->private_bio = ERR_PTR(error); |
222 | 224 | ||
223 | req_mod(req, what); | 225 | /* not req_mod(), we need irqsave here! */ |
226 | spin_lock_irqsave(&mdev->req_lock, flags); | ||
227 | __req_mod(req, what, &m); | ||
228 | spin_unlock_irqrestore(&mdev->req_lock, flags); | ||
229 | |||
230 | if (m.bio) | ||
231 | complete_master_bio(mdev, &m); | ||
224 | } | 232 | } |
225 | 233 | ||
226 | int w_read_retry_remote(struct drbd_conf *mdev, struct drbd_work *w, int cancel) | 234 | int w_read_retry_remote(struct drbd_conf *mdev, struct drbd_work *w, int cancel) |