Skip to content

Commit

Permalink
drbd: Introduce "peer_device" object between "device" and "connection"
Browse files Browse the repository at this point in the history
In a setup where a device (aka volume) can replicate to multiple peers and one
connection can be shared between multiple devices, we need separate objects to
represent devices on peer nodes and network connections.

As a first step to introduce multiple connections per device, give each
drbd_device object a single drbd_peer_device object which connects it to a
drbd_connection object.

Signed-off-by: Andreas Gruenbacher <agruen@linbit.com>
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
  • Loading branch information
Andreas Gruenbacher authored and Philipp Reisner committed Feb 17, 2014
1 parent bde89a9 commit a6b32bc
Show file tree
Hide file tree
Showing 11 changed files with 416 additions and 377 deletions.
8 changes: 4 additions & 4 deletions drivers/block/drbd/drbd_actlog.c
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ void drbd_al_begin_io_commit(struct drbd_device *device, bool delegate)
{
bool locked = false;

BUG_ON(delegate && current == device->connection->worker.task);
BUG_ON(delegate && current == first_peer_device(device)->connection->worker.task);

/* Serialize multiple transactions.
* This uses test_and_set_bit, memory barrier is implicit.
Expand Down Expand Up @@ -354,7 +354,7 @@ void drbd_al_begin_io_commit(struct drbd_device *device, bool delegate)
*/
void drbd_al_begin_io(struct drbd_device *device, struct drbd_interval *i, bool delegate)
{
BUG_ON(delegate && current == device->connection->worker.task);
BUG_ON(delegate && current == first_peer_device(device)->connection->worker.task);

if (drbd_al_begin_io_prepare(device, i))
drbd_al_begin_io_commit(device, delegate);
Expand Down Expand Up @@ -614,7 +614,7 @@ static int al_write_transaction(struct drbd_device *device, bool delegate)
init_completion(&al_work.event);
al_work.w.cb = w_al_write_transaction;
al_work.w.device = device;
drbd_queue_work_front(&device->connection->sender_work, &al_work.w);
drbd_queue_work_front(&first_peer_device(device)->connection->sender_work, &al_work.w);
wait_for_completion(&al_work.event);
return al_work.err;
} else
Expand Down Expand Up @@ -796,7 +796,7 @@ static void drbd_try_clear_on_disk_bm(struct drbd_device *device, sector_t secto
udw->enr = ext->lce.lc_number;
udw->w.cb = w_update_odbm;
udw->w.device = device;
drbd_queue_work_front(&device->connection->sender_work, &udw->w);
drbd_queue_work_front(&first_peer_device(device)->connection->sender_work, &udw->w);
} else {
dev_warn(DEV, "Could not kmalloc an udw\n");
}
Expand Down
8 changes: 4 additions & 4 deletions drivers/block/drbd/drbd_bitmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,9 @@ static void __bm_print_lock_info(struct drbd_device *device, const char *func)
if (!__ratelimit(&drbd_ratelimit_state))
return;
dev_err(DEV, "FIXME %s in %s, bitmap locked for '%s' by %s\n",
drbd_task_to_thread_name(device->connection, current),
drbd_task_to_thread_name(first_peer_device(device)->connection, current),
func, b->bm_why ?: "?",
drbd_task_to_thread_name(device->connection, b->bm_task));
drbd_task_to_thread_name(first_peer_device(device)->connection, b->bm_task));
}

void drbd_bm_lock(struct drbd_device *device, char *why, enum bm_flag flags)
Expand All @@ -138,9 +138,9 @@ void drbd_bm_lock(struct drbd_device *device, char *why, enum bm_flag flags)

if (trylock_failed) {
dev_warn(DEV, "%s going to '%s' but bitmap already locked for '%s' by %s\n",
drbd_task_to_thread_name(device->connection, current),
drbd_task_to_thread_name(first_peer_device(device)->connection, current),
why, b->bm_why ?: "?",
drbd_task_to_thread_name(device->connection, b->bm_task));
drbd_task_to_thread_name(first_peer_device(device)->connection, b->bm_task));
mutex_lock(&b->bm_change);
}
if (BM_LOCKED_MASK & b->bm_flags)
Expand Down
58 changes: 39 additions & 19 deletions drivers/block/drbd/drbd_int.h
Original file line number Diff line number Diff line change
Expand Up @@ -483,7 +483,7 @@ struct drbd_backing_dev {
struct block_device *backing_bdev;
struct block_device *md_bdev;
struct drbd_md md;
struct disk_conf *disk_conf; /* RCU, for updates: device->connection->conf_update */
struct disk_conf *disk_conf; /* RCU, for updates: first_peer_device(device)->connection->conf_update */
sector_t known_size; /* last known size of that backing device */
};

Expand Down Expand Up @@ -617,8 +617,14 @@ struct submit_worker {
struct list_head writes;
};

struct drbd_device {
struct drbd_peer_device {
struct list_head peer_devices;
struct drbd_device *device;
struct drbd_connection *connection;
};

struct drbd_device {
struct list_head peer_devices;
int vnr; /* volume number within the connection */
struct kref kref;

Expand Down Expand Up @@ -744,7 +750,7 @@ struct drbd_device {
struct bm_io_work bm_io_work;
u64 ed_uuid; /* UUID of the exposed data */
struct mutex own_state_mutex;
struct mutex *state_mutex; /* either own_state_mutex or device->connection->cstate_mutex */
struct mutex *state_mutex; /* either own_state_mutex or first_peer_device(device)->connection->cstate_mutex */
char congestion_reason; /* Why we where congested... */
atomic_t rs_sect_in; /* for incoming resync data rate, SyncTarget */
atomic_t rs_sect_ev; /* for submitted resync data rate, both */
Expand All @@ -768,6 +774,20 @@ static inline struct drbd_device *minor_to_device(unsigned int minor)
return (struct drbd_device *)idr_find(&minors, minor);
}

static inline struct drbd_peer_device *first_peer_device(struct drbd_device *device)
{
return list_first_entry(&device->peer_devices, struct drbd_peer_device, peer_devices);
}

#define for_each_peer_device(peer_device, device) \
list_for_each_entry(peer_device, &device->peer_devices, peer_devices)

#define for_each_peer_device_rcu(peer_device, device) \
list_for_each_entry_rcu(peer_device, &device->peer_devices, peer_devices)

#define for_each_peer_device_safe(peer_device, tmp, device) \
list_for_each_entry_safe(peer_device, tmp, &device->peer_devices, peer_devices)

static inline unsigned int device_to_minor(struct drbd_device *device)
{
return device->minor;
Expand Down Expand Up @@ -1154,7 +1174,7 @@ extern struct bio *bio_alloc_drbd(gfp_t gfp_mask);
extern rwlock_t global_state_lock;

extern int conn_lowest_minor(struct drbd_connection *connection);
enum drbd_ret_code conn_new_minor(struct drbd_connection *connection, unsigned int minor, int vnr);
enum drbd_ret_code drbd_create_minor(struct drbd_connection *connection, unsigned int minor, int vnr);
extern void drbd_minor_destroy(struct kref *kref);

extern int set_resource_options(struct drbd_connection *connection, struct res_opts *res_opts);
Expand Down Expand Up @@ -1275,7 +1295,7 @@ extern void conn_flush_workqueue(struct drbd_connection *connection);
extern int drbd_connected(struct drbd_device *device);
static inline void drbd_flush_workqueue(struct drbd_device *device)
{
conn_flush_workqueue(device->connection);
conn_flush_workqueue(first_peer_device(device)->connection);
}

/* Yes, there is kernel_setsockopt, but only since 2.6.18.
Expand Down Expand Up @@ -1421,9 +1441,9 @@ static inline union drbd_state drbd_read_state(struct drbd_device *device)
union drbd_state rv;

rv.i = device->state.i;
rv.susp = device->connection->susp;
rv.susp_nod = device->connection->susp_nod;
rv.susp_fen = device->connection->susp_fen;
rv.susp = first_peer_device(device)->connection->susp;
rv.susp_nod = first_peer_device(device)->connection->susp_nod;
rv.susp_fen = first_peer_device(device)->connection->susp_fen;

return rv;
}
Expand Down Expand Up @@ -1505,9 +1525,9 @@ static inline void drbd_chk_io_error_(struct drbd_device *device,
{
if (error) {
unsigned long flags;
spin_lock_irqsave(&device->connection->req_lock, flags);
spin_lock_irqsave(&first_peer_device(device)->connection->req_lock, flags);
__drbd_chk_io_error_(device, forcedetach, where);
spin_unlock_irqrestore(&device->connection->req_lock, flags);
spin_unlock_irqrestore(&first_peer_device(device)->connection->req_lock, flags);
}
}

Expand Down Expand Up @@ -1783,7 +1803,7 @@ static inline void put_ldev(struct drbd_device *device)
if (device->state.disk == D_FAILED) {
/* all application IO references gone. */
if (!test_and_set_bit(GO_DISKLESS, &device->flags))
drbd_queue_work(&device->connection->sender_work, &device->go_diskless);
drbd_queue_work(&first_peer_device(device)->connection->sender_work, &device->go_diskless);
}
wake_up(&device->misc_wait);
}
Expand Down Expand Up @@ -1865,7 +1885,7 @@ static inline int drbd_get_max_buffers(struct drbd_device *device)
int mxb;

rcu_read_lock();
nc = rcu_dereference(device->connection->net_conf);
nc = rcu_dereference(first_peer_device(device)->connection->net_conf);
mxb = nc ? nc->max_buffers : 1000000; /* arbitrary limit on open requests */
rcu_read_unlock();

Expand Down Expand Up @@ -1908,7 +1928,7 @@ static inline int drbd_state_is_stable(struct drbd_device *device)

/* Allow IO in BM exchange states with new protocols */
case C_WF_BITMAP_S:
if (device->connection->agreed_pro_version < 96)
if (first_peer_device(device)->connection->agreed_pro_version < 96)
return 0;
break;

Expand Down Expand Up @@ -1944,7 +1964,7 @@ static inline int drbd_state_is_stable(struct drbd_device *device)

static inline int drbd_suspended(struct drbd_device *device)
{
struct drbd_connection *connection = device->connection;
struct drbd_connection *connection = first_peer_device(device)->connection;

return connection->susp || connection->susp_fen || connection->susp_nod;
}
Expand Down Expand Up @@ -1979,11 +1999,11 @@ static inline bool inc_ap_bio_cond(struct drbd_device *device)
{
bool rv = false;

spin_lock_irq(&device->connection->req_lock);
spin_lock_irq(&first_peer_device(device)->connection->req_lock);
rv = may_inc_ap_bio(device);
if (rv)
atomic_inc(&device->ap_bio_cnt);
spin_unlock_irq(&device->connection->req_lock);
spin_unlock_irq(&first_peer_device(device)->connection->req_lock);

return rv;
}
Expand All @@ -2010,7 +2030,7 @@ static inline void dec_ap_bio(struct drbd_device *device)

if (ap_bio == 0 && test_bit(BITMAP_IO, &device->flags)) {
if (!test_and_set_bit(BITMAP_IO_QUEUED, &device->flags))
drbd_queue_work(&device->connection->sender_work, &device->bm_io_work.w);
drbd_queue_work(&first_peer_device(device)->connection->sender_work, &device->bm_io_work.w);
}

/* this currently does wake_up for every dec_ap_bio!
Expand All @@ -2022,8 +2042,8 @@ static inline void dec_ap_bio(struct drbd_device *device)

static inline bool verify_can_do_stop_sector(struct drbd_device *device)
{
return device->connection->agreed_pro_version >= 97 &&
device->connection->agreed_pro_version != 100;
return first_peer_device(device)->connection->agreed_pro_version >= 97 &&
first_peer_device(device)->connection->agreed_pro_version != 100;
}

static inline int drbd_set_ed_uuid(struct drbd_device *device, u64 val)
Expand Down
Loading

0 comments on commit a6b32bc

Please sign in to comment.