]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
drbd: Allow to wait for the completion of an epoch entry as well
authorAndreas Gruenbacher <agruen@linbit.com>
Fri, 28 Jan 2011 09:31:04 +0000 (10:31 +0100)
committerPhilipp Reisner <philipp.reisner@linbit.com>
Wed, 28 Sep 2011 08:26:31 +0000 (10:26 +0200)
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
drivers/block/drbd/drbd_interval.h
drivers/block/drbd/drbd_receiver.c
drivers/block/drbd/drbd_req.c
drivers/block/drbd/drbd_req.h

index a847b4a07b250d53a91165e58a2489fcfcd75d9a..9d1e5eb2d7eb6ebe37daa707b274fc6559c8f6a7 100644 (file)
@@ -9,6 +9,7 @@ struct drbd_interval {
        sector_t sector;        /* start sector of the interval */
        unsigned int size;      /* size in bytes */
        sector_t end;           /* highest interval end in subtree */
+       int waiting:1;
 };
 
 static inline void drbd_clear_interval(struct drbd_interval *i)
index d9f3f7fd9bb21436f78853f3fc0c70fe4395b863..b84a9c9fd3f84321762b1d786b402c8f3bba3660 100644 (file)
@@ -334,13 +334,15 @@ struct drbd_epoch_entry *drbd_alloc_ee(struct drbd_conf *mdev,
                goto fail;
 
        drbd_clear_interval(&e->i);
+       e->i.size = data_size;
+       e->i.sector = sector;
+       e->i.waiting = false;
+
        e->epoch = NULL;
        e->mdev = mdev;
        e->pages = page;
        atomic_set(&e->pending_bios, 0);
-       e->i.size = data_size;
        e->flags = 0;
-       e->i.sector = sector;
        /*
         * The block_id is opaque to the receiver.  It is not endianness
         * converted, and sent back to the sender unchanged.
@@ -1172,6 +1174,19 @@ fail:
        return err;
 }
 
+static void drbd_remove_epoch_entry_interval(struct drbd_conf *mdev,
+                                            struct drbd_epoch_entry *e)
+{
+       struct drbd_interval *i = &e->i;
+
+       drbd_remove_interval(&mdev->write_requests, i);
+       drbd_clear_interval(i);
+
+       /* Wake up any processes waiting for this epoch entry to complete.  */
+       if (i->waiting)
+               wake_up(&mdev->misc_wait);
+}
+
 static int receive_Barrier(struct drbd_conf *mdev, enum drbd_packet cmd,
                           unsigned int data_size)
 {
@@ -1591,8 +1606,7 @@ static int e_end_block(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
        if (mdev->tconn->net_conf->two_primaries) {
                spin_lock_irq(&mdev->tconn->req_lock);
                D_ASSERT(!drbd_interval_empty(&e->i));
-               drbd_remove_interval(&mdev->epoch_entries, &e->i);
-               drbd_clear_interval(&e->i);
+               drbd_remove_epoch_entry_interval(mdev, e);
                spin_unlock_irq(&mdev->tconn->req_lock);
        } else
                D_ASSERT(drbd_interval_empty(&e->i));
@@ -1612,8 +1626,7 @@ static int e_send_discard_ack(struct drbd_conf *mdev, struct drbd_work *w, int u
 
        spin_lock_irq(&mdev->tconn->req_lock);
        D_ASSERT(!drbd_interval_empty(&e->i));
-       drbd_remove_interval(&mdev->epoch_entries, &e->i);
-       drbd_clear_interval(&e->i);
+       drbd_remove_epoch_entry_interval(mdev, e);
        spin_unlock_irq(&mdev->tconn->req_lock);
 
        dec_unacked(mdev);
@@ -1860,17 +1873,14 @@ static int receive_Data(struct drbd_conf *mdev, enum drbd_packet cmd,
                        }
 
                        if (signal_pending(current)) {
-                               drbd_remove_interval(&mdev->epoch_entries, &e->i);
-                               drbd_clear_interval(&e->i);
-
+                               drbd_remove_epoch_entry_interval(mdev, e);
                                spin_unlock_irq(&mdev->tconn->req_lock);
-
                                finish_wait(&mdev->misc_wait, &wait);
                                goto out_interrupted;
                        }
 
                        /* Indicate to wake up mdev->misc_wait upon completion.  */
-                       req2->rq_state |= RQ_COLLISION;
+                       i->waiting = true;
 
                        spin_unlock_irq(&mdev->tconn->req_lock);
                        if (first) {
@@ -1922,8 +1932,7 @@ static int receive_Data(struct drbd_conf *mdev, enum drbd_packet cmd,
        dev_err(DEV, "submit failed, triggering re-connect\n");
        spin_lock_irq(&mdev->tconn->req_lock);
        list_del(&e->w.list);
-       drbd_remove_interval(&mdev->epoch_entries, &e->i);
-       drbd_clear_interval(&e->i);
+       drbd_remove_epoch_entry_interval(mdev, e);
        spin_unlock_irq(&mdev->tconn->req_lock);
        if (e->flags & EE_CALL_AL_COMPLETE_IO)
                drbd_al_complete_io(mdev, e->i.sector);
index 8b4ba94538bdb026af8d8c84410ab7b6ea3f2f92..078f77ba68fb29dc09a3d9b25d946ea5a34070a2 100644 (file)
@@ -70,9 +70,12 @@ static struct drbd_request *drbd_req_new(struct drbd_conf *mdev,
        req->mdev        = mdev;
        req->master_bio  = bio_src;
        req->epoch       = 0;
+
        drbd_clear_interval(&req->i);
        req->i.sector     = bio_src->bi_sector;
        req->i.size      = bio_src->bi_size;
+       req->i.waiting = false;
+
        INIT_LIST_HEAD(&req->tl_requests);
        INIT_LIST_HEAD(&req->w.list);
 
@@ -175,10 +178,6 @@ static void _about_to_complete_local_write(struct drbd_conf *mdev,
            (s & RQ_NET_SENT) != 0 &&
            req->epoch == mdev->tconn->newest_tle->br_number)
                queue_barrier(mdev);
-
-       /* Wake up any processes waiting for this request to complete.  */
-       if ((s & RQ_NET_DONE) && (s & RQ_COLLISION))
-               wake_up(&mdev->misc_wait);
 }
 
 void complete_master_bio(struct drbd_conf *mdev,
@@ -188,6 +187,20 @@ void complete_master_bio(struct drbd_conf *mdev,
        dec_ap_bio(mdev);
 }
 
+
+static void drbd_remove_request_interval(struct rb_root *root,
+                                        struct drbd_request *req)
+{
+       struct drbd_conf *mdev = req->mdev;
+       struct drbd_interval *i = &req->i;
+
+       drbd_remove_interval(root, i);
+
+       /* Wake up any processes waiting for this request to complete.  */
+       if (i->waiting)
+               wake_up(&mdev->misc_wait);
+}
+
 /* Helper for __req_mod().
  * Set m->bio to the master bio, if it is fit to be completed,
  * or leave it alone (it is initialized to NULL in __req_mod),
@@ -251,7 +264,7 @@ void _req_may_be_done(struct drbd_request *req, struct bio_and_error *m)
                                root = &mdev->write_requests;
                        else
                                root = &mdev->read_requests;
-                       drbd_remove_interval(root, &req->i);
+                       drbd_remove_request_interval(root, req);
                } else
                        D_ASSERT((s & (RQ_NET_MASK & ~RQ_NET_DONE)) == 0);
 
index 7a7464a2b3a63d5b6e153db0d2f89f126fe76004..431e3f962c3a88faccde36f0d0247fa3ce285218 100644 (file)
@@ -194,12 +194,6 @@ enum drbd_req_state_bits {
 
        /* Should call drbd_al_complete_io() for this request... */
        __RQ_IN_ACT_LOG,
-
-       /*
-        * Set when a processes puts itself to sleep to wait for this request
-        * to complete.
-        */
-       __RQ_COLLISION,
 };
 
 #define RQ_LOCAL_PENDING   (1UL << __RQ_LOCAL_PENDING)
@@ -220,7 +214,6 @@ enum drbd_req_state_bits {
 
 #define RQ_WRITE           (1UL << __RQ_WRITE)
 #define RQ_IN_ACT_LOG      (1UL << __RQ_IN_ACT_LOG)
-#define RQ_COLLISION      (1UL << __RQ_COLLISION)
 
 /* For waking up the frozen transfer log mod_req() has to return if the request
    should be counted in the epoch object*/