diff options
-rw-r--r-- | drivers/block/drbd/drbd_int.h | 6 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_main.c | 3 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_nl.c | 3 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_proc.c | 2 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_receiver.c | 65 |
5 files changed, 48 insertions, 31 deletions
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index e3913307e3d0..473694605da6 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -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; diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index e1234065954f..7b1cad895d16 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -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); diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index b342c95b724b..b369dd112df6 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c @@ -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); diff --git a/drivers/block/drbd/drbd_proc.c b/drivers/block/drbd/drbd_proc.c index 7e68d99e9c93..1321192b377d 100644 --- a/drivers/block/drbd/drbd_proc.c +++ b/drivers/block/drbd/drbd_proc.c @@ -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) diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 4cdf8a75d71b..f6d1ff2e3ab9 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -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; } |