drbd: Move write_ordering from mdev to tconn
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>
This commit is contained in:
parent
6936fcb49a
commit
4b0007c0e8
5 changed files with 48 additions and 31 deletions
|
@ -858,6 +858,8 @@ struct drbd_tconn { /* is a resource from the config file */
|
||||||
void *int_dig_in;
|
void *int_dig_in;
|
||||||
void *int_dig_vv;
|
void *int_dig_vv;
|
||||||
|
|
||||||
|
enum write_ordering_e write_ordering;
|
||||||
|
|
||||||
struct drbd_thread receiver;
|
struct drbd_thread receiver;
|
||||||
struct drbd_thread worker;
|
struct drbd_thread worker;
|
||||||
struct drbd_thread asender;
|
struct drbd_thread asender;
|
||||||
|
@ -962,7 +964,7 @@ struct drbd_conf {
|
||||||
struct drbd_epoch *current_epoch;
|
struct drbd_epoch *current_epoch;
|
||||||
spinlock_t epoch_lock;
|
spinlock_t epoch_lock;
|
||||||
unsigned int epochs;
|
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 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 sync_ee; /* IO in progress (P_RS_DATA_REPLY gets written to disk) */
|
||||||
struct list_head done_ee; /* need to send P_WRITE_ACK */
|
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));
|
(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 */
|
/* drbd_proc.c */
|
||||||
extern struct proc_dir_entry *drbd_proc;
|
extern struct proc_dir_entry *drbd_proc;
|
||||||
|
|
|
@ -2130,7 +2130,6 @@ void drbd_init_set_defaults(struct drbd_conf *mdev)
|
||||||
init_waitqueue_head(&mdev->al_wait);
|
init_waitqueue_head(&mdev->al_wait);
|
||||||
init_waitqueue_head(&mdev->seq_wait);
|
init_waitqueue_head(&mdev->seq_wait);
|
||||||
|
|
||||||
mdev->write_ordering = WO_bdev_flush;
|
|
||||||
mdev->resync_wenr = LC_FREE;
|
mdev->resync_wenr = LC_FREE;
|
||||||
mdev->peer_max_bio_size = DRBD_MAX_BIO_SIZE_SAFE;
|
mdev->peer_max_bio_size = DRBD_MAX_BIO_SIZE_SAFE;
|
||||||
mdev->local_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))
|
if (!tl_init(tconn))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
tconn->write_ordering = WO_bdev_flush;
|
||||||
|
|
||||||
tconn->cstate = C_STANDALONE;
|
tconn->cstate = C_STANDALONE;
|
||||||
mutex_init(&tconn->cstate_mutex);
|
mutex_init(&tconn->cstate_mutex);
|
||||||
spin_lock_init(&tconn->req_lock);
|
spin_lock_init(&tconn->req_lock);
|
||||||
|
|
|
@ -1497,8 +1497,7 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
|
||||||
new_disk_conf = NULL;
|
new_disk_conf = NULL;
|
||||||
new_plan = NULL;
|
new_plan = NULL;
|
||||||
|
|
||||||
mdev->write_ordering = WO_bdev_flush;
|
drbd_bump_write_ordering(mdev->tconn, WO_bdev_flush);
|
||||||
drbd_bump_write_ordering(mdev, WO_bdev_flush);
|
|
||||||
|
|
||||||
if (drbd_md_test_flag(mdev->ldev, MDF_CRASHED_PRIMARY))
|
if (drbd_md_test_flag(mdev->ldev, MDF_CRASHED_PRIMARY))
|
||||||
set_bit(CRASHED_PRIMARY, &mdev->flags);
|
set_bit(CRASHED_PRIMARY, &mdev->flags);
|
||||||
|
|
|
@ -272,7 +272,7 @@ static int drbd_seq_show(struct seq_file *seq, void *v)
|
||||||
atomic_read(&mdev->unacked_cnt),
|
atomic_read(&mdev->unacked_cnt),
|
||||||
atomic_read(&mdev->ap_bio_cnt),
|
atomic_read(&mdev->ap_bio_cnt),
|
||||||
mdev->epochs,
|
mdev->epochs,
|
||||||
write_ordering_chars[mdev->write_ordering]
|
write_ordering_chars[mdev->tconn->write_ordering]
|
||||||
);
|
);
|
||||||
seq_printf(seq, " oos:%llu\n",
|
seq_printf(seq, " oos:%llu\n",
|
||||||
Bit2KB((unsigned long long)
|
Bit2KB((unsigned long long)
|
||||||
|
|
|
@ -1089,21 +1089,29 @@ static int drbd_recv_header(struct drbd_tconn *tconn, struct packet_info *pi)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void drbd_flush(struct drbd_conf *mdev)
|
static void drbd_flush(struct drbd_tconn *tconn)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
struct drbd_conf *mdev;
|
||||||
|
int vnr;
|
||||||
|
|
||||||
if (mdev->write_ordering >= WO_bdev_flush && get_ldev(mdev)) {
|
if (tconn->write_ordering >= WO_bdev_flush) {
|
||||||
rv = blkdev_issue_flush(mdev->ldev->backing_bdev, GFP_KERNEL,
|
idr_for_each_entry(&tconn->volumes, mdev, vnr) {
|
||||||
NULL);
|
if (get_ldev(mdev)) {
|
||||||
if (rv) {
|
rv = blkdev_issue_flush(mdev->ldev->backing_bdev, GFP_KERNEL,
|
||||||
dev_info(DEV, "local disk flush failed with status %d\n", rv);
|
NULL);
|
||||||
/* would rather check on EOPNOTSUPP, but that is not reliable.
|
put_ldev(mdev);
|
||||||
* don't try again for ANY return value != 0
|
|
||||||
* if (rv == -EOPNOTSUPP) */
|
if (rv) {
|
||||||
drbd_bump_write_ordering(mdev, WO_drain_io);
|
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
|
* drbd_bump_write_ordering() - Fall back to an other write ordering method
|
||||||
* @mdev: DRBD device.
|
* @tconn: DRBD connection.
|
||||||
* @wo: Write ordering method to try.
|
* @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 disk_conf *dc;
|
||||||
|
struct drbd_conf *mdev;
|
||||||
enum write_ordering_e pwo;
|
enum write_ordering_e pwo;
|
||||||
|
int vnr;
|
||||||
static char *write_ordering_str[] = {
|
static char *write_ordering_str[] = {
|
||||||
[WO_none] = "none",
|
[WO_none] = "none",
|
||||||
[WO_drain_io] = "drain",
|
[WO_drain_io] = "drain",
|
||||||
[WO_bdev_flush] = "flush",
|
[WO_bdev_flush] = "flush",
|
||||||
};
|
};
|
||||||
|
|
||||||
pwo = mdev->write_ordering;
|
pwo = tconn->write_ordering;
|
||||||
wo = min(pwo, wo);
|
wo = min(pwo, wo);
|
||||||
rcu_read_lock();
|
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)
|
if (wo == WO_bdev_flush && !dc->disk_flushes)
|
||||||
wo = WO_drain_io;
|
wo = WO_drain_io;
|
||||||
if (wo == WO_drain_io && !dc->disk_drain)
|
if (wo == WO_drain_io && !dc->disk_drain)
|
||||||
wo = WO_none;
|
wo = WO_none;
|
||||||
|
put_ldev(mdev);
|
||||||
|
}
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
mdev->write_ordering = wo;
|
tconn->write_ordering = wo;
|
||||||
if (pwo != mdev->write_ordering || wo == WO_bdev_flush)
|
if (pwo != tconn->write_ordering || wo == WO_bdev_flush)
|
||||||
dev_info(DEV, "Method to ensure write ordering: %s\n", write_ordering_str[mdev->write_ordering]);
|
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.
|
* R_PRIMARY crashes now.
|
||||||
* Therefore we must send the barrier_ack after the barrier request was
|
* Therefore we must send the barrier_ack after the barrier request was
|
||||||
* completed. */
|
* completed. */
|
||||||
switch (mdev->write_ordering) {
|
switch (tconn->write_ordering) {
|
||||||
case WO_none:
|
case WO_none:
|
||||||
if (rv == FE_RECYCLED)
|
if (rv == FE_RECYCLED)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1358,7 +1373,7 @@ static int receive_Barrier(struct drbd_tconn *tconn, struct packet_info *pi)
|
||||||
case WO_bdev_flush:
|
case WO_bdev_flush:
|
||||||
case WO_drain_io:
|
case WO_drain_io:
|
||||||
drbd_wait_ee_list_empty(mdev, &mdev->active_ee);
|
drbd_wait_ee_list_empty(mdev, &mdev->active_ee);
|
||||||
drbd_flush(mdev);
|
drbd_flush(tconn);
|
||||||
|
|
||||||
if (atomic_read(&mdev->current_epoch->epoch_size)) {
|
if (atomic_read(&mdev->current_epoch->epoch_size)) {
|
||||||
epoch = kmalloc(sizeof(struct drbd_epoch), GFP_NOIO);
|
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;
|
return 0;
|
||||||
default:
|
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;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue