drbd: Move write_ordering from mdev to tconn
authorPhilipp Reisner <philipp.reisner@linbit.com>
Wed, 9 Nov 2011 19:12:34 +0000 (20:12 +0100)
committerPhilipp Reisner <philipp.reisner@linbit.com>
Thu, 8 Nov 2012 15:58:07 +0000 (16:58 +0100)
This is necessary in order to prepare the move of the (receiver side)
epoch list from the device (mdev) to the connection (tconn) objects.

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

index e391330..4736946 100644 (file)
@@ -858,6 +858,8 @@ struct drbd_tconn {                 /* is a resource from the config file */
        void *int_dig_in;
        void *int_dig_vv;
 
+       enum write_ordering_e write_ordering;
+
        struct drbd_thread receiver;
        struct drbd_thread worker;
        struct drbd_thread asender;
@@ -962,7 +964,7 @@ struct drbd_conf {
        struct drbd_epoch *current_epoch;
        spinlock_t epoch_lock;
        unsigned int epochs;
-       enum write_ordering_e write_ordering;
+
        struct list_head active_ee; /* IO in progress (P_DATA gets written to disk) */
        struct list_head sync_ee;   /* IO in progress (P_RS_DATA_REPLY gets written to disk) */
        struct list_head done_ee;   /* need to send P_WRITE_ACK */
@@ -1539,7 +1541,7 @@ static inline void drbd_tcp_quickack(struct socket *sock)
                        (char*)&val, sizeof(val));
 }
 
-void drbd_bump_write_ordering(struct drbd_conf *mdev, enum write_ordering_e wo);
+void drbd_bump_write_ordering(struct drbd_tconn *tconn, enum write_ordering_e wo);
 
 /* drbd_proc.c */
 extern struct proc_dir_entry *drbd_proc;
index e123406..7b1cad8 100644 (file)
@@ -2130,7 +2130,6 @@ void drbd_init_set_defaults(struct drbd_conf *mdev)
        init_waitqueue_head(&mdev->al_wait);
        init_waitqueue_head(&mdev->seq_wait);
 
-       mdev->write_ordering = WO_bdev_flush;
        mdev->resync_wenr = LC_FREE;
        mdev->peer_max_bio_size = DRBD_MAX_BIO_SIZE_SAFE;
        mdev->local_max_bio_size = DRBD_MAX_BIO_SIZE_SAFE;
@@ -2625,6 +2624,8 @@ struct drbd_tconn *conn_create(const char *name, struct res_opts *res_opts)
        if (!tl_init(tconn))
                goto fail;
 
+       tconn->write_ordering = WO_bdev_flush;
+
        tconn->cstate = C_STANDALONE;
        mutex_init(&tconn->cstate_mutex);
        spin_lock_init(&tconn->req_lock);
index b342c95..b369dd1 100644 (file)
@@ -1497,8 +1497,7 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
        new_disk_conf = NULL;
        new_plan = NULL;
 
-       mdev->write_ordering = WO_bdev_flush;
-       drbd_bump_write_ordering(mdev, WO_bdev_flush);
+       drbd_bump_write_ordering(mdev->tconn, WO_bdev_flush);
 
        if (drbd_md_test_flag(mdev->ldev, MDF_CRASHED_PRIMARY))
                set_bit(CRASHED_PRIMARY, &mdev->flags);
index 7e68d99..1321192 100644 (file)
@@ -272,7 +272,7 @@ static int drbd_seq_show(struct seq_file *seq, void *v)
                           atomic_read(&mdev->unacked_cnt),
                           atomic_read(&mdev->ap_bio_cnt),
                           mdev->epochs,
-                          write_ordering_chars[mdev->write_ordering]
+                          write_ordering_chars[mdev->tconn->write_ordering]
                        );
                        seq_printf(seq, " oos:%llu\n",
                                   Bit2KB((unsigned long long)
index 4cdf8a7..f6d1ff2 100644 (file)
@@ -1089,21 +1089,29 @@ static int drbd_recv_header(struct drbd_tconn *tconn, struct packet_info *pi)
        return err;
 }
 
-static void drbd_flush(struct drbd_conf *mdev)
+static void drbd_flush(struct drbd_tconn *tconn)
 {
        int rv;
+       struct drbd_conf *mdev;
+       int vnr;
+
+       if (tconn->write_ordering >= WO_bdev_flush) {
+               idr_for_each_entry(&tconn->volumes, mdev, vnr) {
+                       if (get_ldev(mdev)) {
+                               rv = blkdev_issue_flush(mdev->ldev->backing_bdev, GFP_KERNEL,
+                                                       NULL);
+                               put_ldev(mdev);
 
-       if (mdev->write_ordering >= WO_bdev_flush && get_ldev(mdev)) {
-               rv = blkdev_issue_flush(mdev->ldev->backing_bdev, GFP_KERNEL,
-                                       NULL);
-               if (rv) {
-                       dev_info(DEV, "local disk flush failed with status %d\n", rv);
-                       /* would rather check on EOPNOTSUPP, but that is not reliable.
-                        * don't try again for ANY return value != 0
-                        * if (rv == -EOPNOTSUPP) */
-                       drbd_bump_write_ordering(mdev, WO_drain_io);
+                               if (rv) {
+                                       dev_info(DEV, "local disk flush failed with status %d\n", rv);
+                                       /* would rather check on EOPNOTSUPP, but that is not reliable.
+                                        * don't try again for ANY return value != 0
+                                        * if (rv == -EOPNOTSUPP) */
+                                       drbd_bump_write_ordering(tconn, WO_drain_io);
+                                       break;
+                               }
+                       }
                }
-               put_ldev(mdev);
        }
 }
 
@@ -1182,32 +1190,39 @@ static enum finish_epoch drbd_may_finish_epoch(struct drbd_conf *mdev,
 
 /**
  * drbd_bump_write_ordering() - Fall back to an other write ordering method
- * @mdev:      DRBD device.
+ * @tconn:     DRBD connection.
  * @wo:                Write ordering method to try.
  */
-void drbd_bump_write_ordering(struct drbd_conf *mdev, enum write_ordering_e wo) __must_hold(local)
+void drbd_bump_write_ordering(struct drbd_tconn *tconn, enum write_ordering_e wo)
 {
        struct disk_conf *dc;
+       struct drbd_conf *mdev;
        enum write_ordering_e pwo;
+       int vnr;
        static char *write_ordering_str[] = {
                [WO_none] = "none",
                [WO_drain_io] = "drain",
                [WO_bdev_flush] = "flush",
        };
 
-       pwo = mdev->write_ordering;
+       pwo = tconn->write_ordering;
        wo = min(pwo, wo);
        rcu_read_lock();
-       dc = rcu_dereference(mdev->ldev->disk_conf);
+       idr_for_each_entry(&tconn->volumes, mdev, vnr) {
+               if (!get_ldev(mdev))
+                       continue;
+               dc = rcu_dereference(mdev->ldev->disk_conf);
 
-       if (wo == WO_bdev_flush && !dc->disk_flushes)
-               wo = WO_drain_io;
-       if (wo == WO_drain_io && !dc->disk_drain)
-               wo = WO_none;
+               if (wo == WO_bdev_flush && !dc->disk_flushes)
+                       wo = WO_drain_io;
+               if (wo == WO_drain_io && !dc->disk_drain)
+                       wo = WO_none;
+               put_ldev(mdev);
+       }
        rcu_read_unlock();
-       mdev->write_ordering = wo;
-       if (pwo != mdev->write_ordering || wo == WO_bdev_flush)
-               dev_info(DEV, "Method to ensure write ordering: %s\n", write_ordering_str[mdev->write_ordering]);
+       tconn->write_ordering = wo;
+       if (pwo != tconn->write_ordering || wo == WO_bdev_flush)
+               conn_info(tconn, "Method to ensure write ordering: %s\n", write_ordering_str[tconn->write_ordering]);
 }
 
 /**
@@ -1341,7 +1356,7 @@ static int receive_Barrier(struct drbd_tconn *tconn, struct packet_info *pi)
         * R_PRIMARY crashes now.
         * Therefore we must send the barrier_ack after the barrier request was
         * completed. */
-       switch (mdev->write_ordering) {
+       switch (tconn->write_ordering) {
        case WO_none:
                if (rv == FE_RECYCLED)
                        return 0;
@@ -1358,7 +1373,7 @@ static int receive_Barrier(struct drbd_tconn *tconn, struct packet_info *pi)
        case WO_bdev_flush:
        case WO_drain_io:
                drbd_wait_ee_list_empty(mdev, &mdev->active_ee);
-               drbd_flush(mdev);
+               drbd_flush(tconn);
 
                if (atomic_read(&mdev->current_epoch->epoch_size)) {
                        epoch = kmalloc(sizeof(struct drbd_epoch), GFP_NOIO);
@@ -1374,7 +1389,7 @@ static int receive_Barrier(struct drbd_tconn *tconn, struct packet_info *pi)
 
                return 0;
        default:
-               dev_err(DEV, "Strangeness in mdev->write_ordering %d\n", mdev->write_ordering);
+               dev_err(DEV, "Strangeness in tconn->write_ordering %d\n", tconn->write_ordering);
                return -EIO;
        }