summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilipp Reisner <philipp.reisner@linbit.com>2010-11-17 17:24:19 (GMT)
committerPhilipp Reisner <philipp.reisner@linbit.com>2011-03-10 10:35:01 (GMT)
commit8869d683b7491467fd39fcbe79756fce3e6f35e7 (patch)
treeb8634a30967f36ff34f4de8ecf38eb96997f5f28
parent127b317844e7cc0458743b604998bece95eab030 (diff)
downloadlinux-8869d683b7491467fd39fcbe79756fce3e6f35e7.tar.xz
drbd: Fixed inc_ap_bio()
The condition must be checked after perpare_to_wait(). The old implementaion could loose wakeup events. Never observed in real life. Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com> Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
-rw-r--r--drivers/block/drbd/drbd_int.h31
1 files changed, 14 insertions, 17 deletions
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index 77ac676..9a94460 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -2309,15 +2309,21 @@ static inline int __inc_ap_bio_cond(struct drbd_conf *mdev)
return 1;
}
-/* I'd like to use wait_event_lock_irq,
- * but I'm not sure when it got introduced,
- * and not sure when it has 3 or 4 arguments */
-static inline void inc_ap_bio(struct drbd_conf *mdev, int count)
+static inline int _inc_ap_bio_cond(struct drbd_conf *mdev, int count)
{
- /* compare with after_state_ch,
- * os.conn != C_WF_BITMAP_S && ns.conn == C_WF_BITMAP_S */
- DEFINE_WAIT(wait);
+ int rv = 0;
+
+ spin_lock_irq(&mdev->req_lock);
+ rv = __inc_ap_bio_cond(mdev);
+ if (rv)
+ atomic_add(count, &mdev->ap_bio_cnt);
+ spin_unlock_irq(&mdev->req_lock);
+
+ return rv;
+}
+static inline void inc_ap_bio(struct drbd_conf *mdev, int count)
+{
/* we wait here
* as long as the device is suspended
* until the bitmap is no longer on the fly during connection
@@ -2326,16 +2332,7 @@ static inline void inc_ap_bio(struct drbd_conf *mdev, int count)
* to avoid races with the reconnect code,
* we need to atomic_inc within the spinlock. */
- spin_lock_irq(&mdev->req_lock);
- while (!__inc_ap_bio_cond(mdev)) {
- prepare_to_wait(&mdev->misc_wait, &wait, TASK_UNINTERRUPTIBLE);
- spin_unlock_irq(&mdev->req_lock);
- schedule();
- finish_wait(&mdev->misc_wait, &wait);
- spin_lock_irq(&mdev->req_lock);
- }
- atomic_add(count, &mdev->ap_bio_cnt);
- spin_unlock_irq(&mdev->req_lock);
+ wait_event(mdev->misc_wait, _inc_ap_bio_cond(mdev, count));
}
static inline void dec_ap_bio(struct drbd_conf *mdev)