Skip to content

Commit

Permalink
drbd: Move write_ordering from mdev to tconn
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Philipp Reisner committed Nov 8, 2012
1 parent 6936fcb commit 4b0007c
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 31 deletions.
6 changes: 4 additions & 2 deletions drivers/block/drbd/drbd_int.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion drivers/block/drbd/drbd_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
3 changes: 1 addition & 2 deletions drivers/block/drbd/drbd_nl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion drivers/block/drbd/drbd_proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
65 changes: 40 additions & 25 deletions drivers/block/drbd/drbd_receiver.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand Down Expand Up @@ -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]);
}

/**
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand All @@ -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;
}

Expand Down

0 comments on commit 4b0007c

Please sign in to comment.