diff options
| -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 181ea036482..ab2bd09d54b 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 47d223c2409..34f224b018b 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) |
