drbd: announce FLUSH/FUA capability to upper layers
authorLars Ellenberg <lars.ellenberg@linbit.com>
Mon, 25 Jun 2012 17:15:38 +0000 (19:15 +0200)
committerPhilipp Reisner <philipp.reisner@linbit.com>
Tue, 24 Jul 2012 13:14:28 +0000 (15:14 +0200)
Unconditionally announce FLUSH/FUA to upper layers.
If the lower layers on either node do not actually support this,
generic_make_request() will deal with it.

If this causes performance regressions on your setup,
make sure there are no volatile caches involved,
and mount -o nobarrier or equivalent.

Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
drivers/block/drbd/drbd_actlog.c
drivers/block/drbd/drbd_main.c
drivers/block/drbd/drbd_receiver.c
drivers/block/drbd/drbd_req.c

index 6ace11e9e5a1532129ba10f46853ae3b8bf2f8e6..3fbef018ce555fe47a716a0de01c2df837a2cc9e 100644 (file)
@@ -876,7 +876,11 @@ int __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector, int size,
        unsigned int enr, count = 0;
        struct lc_element *e;
 
-       if (size <= 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_BIO_SIZE) {
+       /* this should be an empty REQ_FLUSH */
+       if (size == 0)
+               return 0;
+
+       if (size < 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_BIO_SIZE) {
                dev_err(DEV, "sector: %llus, size: %d\n",
                        (unsigned long long)sector, size);
                return 0;
index 1ee1404769c27135c7382081c3c1b9e5d4487790..2e0e7fc1dbbaf50e24d8a446a4e20aeb2239f5bb 100644 (file)
@@ -3636,6 +3636,7 @@ struct drbd_conf *drbd_new_device(unsigned int minor)
        q->backing_dev_info.congested_data = mdev;
 
        blk_queue_make_request(q, drbd_make_request);
+       blk_queue_flush(q, REQ_FLUSH | REQ_FUA);
        /* Setting the max_hw_sectors to an odd value of 8kibyte here
           This triggers a max_bio_size message upon first attach or connect */
        blk_queue_max_hw_sectors(q, DRBD_MAX_BIO_SIZE_SAFE >> 8);
index 83d99133f94b0a57c1cc4e6411a8f720b53a586a..c74ca2df7431f13553d366fd371d717b6ed1f56b 100644 (file)
@@ -277,6 +277,9 @@ static void drbd_pp_free(struct drbd_conf *mdev, struct page *page, int is_net)
        atomic_t *a = is_net ? &mdev->pp_in_use_by_net : &mdev->pp_in_use;
        int i;
 
+       if (page == NULL)
+               return;
+
        if (drbd_pp_vacant > (DRBD_MAX_BIO_SIZE/PAGE_SIZE)*minor_count)
                i = page_chain_free(page);
        else {
@@ -316,7 +319,7 @@ struct drbd_epoch_entry *drbd_alloc_ee(struct drbd_conf *mdev,
                                     gfp_t gfp_mask) __must_hold(local)
 {
        struct drbd_epoch_entry *e;
-       struct page *page;
+       struct page *page = NULL;
        unsigned nr_pages = (data_size + PAGE_SIZE -1) >> PAGE_SHIFT;
 
        if (drbd_insert_fault(mdev, DRBD_FAULT_AL_EE))
@@ -329,9 +332,11 @@ struct drbd_epoch_entry *drbd_alloc_ee(struct drbd_conf *mdev,
                return NULL;
        }
 
-       page = drbd_pp_alloc(mdev, nr_pages, (gfp_mask & __GFP_WAIT));
-       if (!page)
-               goto fail;
+       if (data_size) {
+               page = drbd_pp_alloc(mdev, nr_pages, (gfp_mask & __GFP_WAIT));
+               if (!page)
+                       goto fail;
+       }
 
        INIT_HLIST_NODE(&e->collision);
        e->epoch = NULL;
@@ -1270,7 +1275,6 @@ read_in_block(struct drbd_conf *mdev, u64 id, sector_t sector, int data_size) __
 
        data_size -= dgs;
 
-       ERR_IF(data_size == 0) return NULL;
        ERR_IF(data_size &  0x1ff) return NULL;
        ERR_IF(data_size >  DRBD_MAX_BIO_SIZE) return NULL;
 
@@ -1291,6 +1295,9 @@ read_in_block(struct drbd_conf *mdev, u64 id, sector_t sector, int data_size) __
        if (!e)
                return NULL;
 
+       if (!data_size)
+               return e;
+
        ds = data_size;
        page = e->pages;
        page_chain_for_each(page) {
@@ -1715,6 +1722,10 @@ static int receive_Data(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned
 
        dp_flags = be32_to_cpu(p->dp_flags);
        rw |= wire_flags_to_bio(mdev, dp_flags);
+       if (e->pages == NULL) {
+               D_ASSERT(e->size == 0);
+               D_ASSERT(dp_flags & DP_FLUSH);
+       }
 
        if (dp_flags & DP_MAY_SET_IN_SYNC)
                e->flags |= EE_MAY_SET_IN_SYNC;
index 1f4b2dbb7d4afc93ea2261b58c786fedab41e1a2..910335c30927f0429a4c4b0fddcfe74033c45e8d 100644 (file)
@@ -1111,13 +1111,12 @@ void drbd_make_request(struct request_queue *q, struct bio *bio)
        /*
         * what we "blindly" assume:
         */
-       D_ASSERT(bio->bi_size > 0);
        D_ASSERT((bio->bi_size & 0x1ff) == 0);
 
        /* to make some things easier, force alignment of requests within the
         * granularity of our hash tables */
        s_enr = bio->bi_sector >> HT_SHIFT;
-       e_enr = (bio->bi_sector+(bio->bi_size>>9)-1) >> HT_SHIFT;
+       e_enr = bio->bi_size ? (bio->bi_sector+(bio->bi_size>>9)-1) >> HT_SHIFT : s_enr;
 
        if (likely(s_enr == e_enr)) {
                do {