Commit 84b8c06b authored by Andreas Gruenbacher's avatar Andreas Gruenbacher Committed by Philipp Reisner

drbd: Create a dedicated struct drbd_device_work

drbd_device_work is a work item that has a reference to a device,
while drbd_work is a more generic work item that does not carry
a reference to a device.

All callbacks get a pointer to a drbd_work instance, those callbacks
that expect a drbd_device_work use the container_of macro to get it.
Signed-off-by: default avatarAndreas Gruenbacher <agruen@linbit.com>
Signed-off-by: default avatarPhilipp Reisner <philipp.reisner@linbit.com>
parent 8682eae9
......@@ -95,11 +95,13 @@ struct __packed al_transaction_on_disk {
struct update_odbm_work {
struct drbd_work w;
struct drbd_device *device;
unsigned int enr;
};
struct update_al_work {
struct drbd_work w;
struct drbd_device *device;
struct completion event;
int err;
};
......@@ -594,7 +596,7 @@ _al_write_transaction(struct drbd_device *device)
static int w_al_write_transaction(struct drbd_work *w, int unused)
{
struct update_al_work *aw = container_of(w, struct update_al_work, w);
struct drbd_device *device = w->device;
struct drbd_device *device = aw->device;
int err;
err = _al_write_transaction(device);
......@@ -613,8 +615,9 @@ static int al_write_transaction(struct drbd_device *device, bool delegate)
struct update_al_work al_work;
init_completion(&al_work.event);
al_work.w.cb = w_al_write_transaction;
al_work.w.device = device;
drbd_queue_work_front(&first_peer_device(device)->connection->sender_work, &al_work.w);
al_work.device = device;
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
......@@ -684,7 +687,7 @@ int drbd_initialize_al(struct drbd_device *device, void *buffer)
static int w_update_odbm(struct drbd_work *w, int unused)
{
struct update_odbm_work *udw = container_of(w, struct update_odbm_work, w);
struct drbd_device *device = w->device;
struct drbd_device *device = udw->device;
struct sib_info sib = { .sib_reason = SIB_SYNC_PROGRESS, };
if (!get_ldev(device)) {
......@@ -795,8 +798,9 @@ static void drbd_try_clear_on_disk_bm(struct drbd_device *device, sector_t secto
if (udw) {
udw->enr = ext->lce.lc_number;
udw->w.cb = w_update_odbm;
udw->w.device = device;
drbd_queue_work_front(&first_peer_device(device)->connection->sender_work, &udw->w);
udw->device = device;
drbd_queue_work_front(&first_peer_device(device)->connection->sender_work,
&udw->w);
} else {
drbd_warn(device, "Could not kmalloc an udw\n");
}
......
......@@ -281,10 +281,11 @@ static inline enum drbd_thread_state get_t_state(struct drbd_thread *thi)
struct drbd_work {
struct list_head list;
int (*cb)(struct drbd_work *, int cancel);
union {
};
struct drbd_device_work {
struct drbd_work w;
struct drbd_device *device;
struct drbd_connection *connection;
};
};
#include "drbd_interval.h"
......@@ -293,6 +294,7 @@ extern int drbd_wait_misc(struct drbd_device *, struct drbd_interval *);
struct drbd_request {
struct drbd_work w;
struct drbd_device *device;
/* if local IO is not allowed, will be NULL.
* if local IO _is_ allowed, holds the locally submitted bio clone,
......@@ -360,7 +362,7 @@ struct digest_info {
};
struct drbd_peer_request {
struct drbd_work w;
struct drbd_device_work dw;
struct drbd_epoch *epoch; /* for writes */
struct page *pages;
atomic_t pending_bios;
......@@ -686,11 +688,11 @@ struct drbd_device {
struct gendisk *vdisk;
unsigned long last_reattach_jif;
struct drbd_work resync_work,
unplug_work,
go_diskless,
md_sync_work,
start_resync_work;
struct drbd_work resync_work;
struct drbd_work unplug_work;
struct drbd_work go_diskless;
struct drbd_work md_sync_work;
struct drbd_work start_resync_work;
struct timer_list resync_timer;
struct timer_list md_sync_timer;
struct timer_list start_resync_timer;
......@@ -1865,7 +1867,8 @@ 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(&first_peer_device(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);
}
......@@ -2092,7 +2095,9 @@ 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(&first_peer_device(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!
......
......@@ -312,7 +312,7 @@ void tl_abort_disk_io(struct drbd_device *device)
list_for_each_entry_safe(req, r, &connection->transfer_log, tl_requests) {
if (!(req->rq_state & RQ_LOCAL_PENDING))
continue;
if (req->w.device != device)
if (req->device != device)
continue;
_req_mod(req, ABORT_DISK_IO);
}
......@@ -1917,13 +1917,6 @@ void drbd_init_set_defaults(struct drbd_device *device)
device->bm_io_work.w.cb = w_bitmap_io;
device->start_resync_work.cb = w_start_resync;
device->resync_work.device = device;
device->unplug_work.device = device;
device->go_diskless.device = device;
device->md_sync_work.device = device;
device->bm_io_work.w.device = device;
device->start_resync_work.device = device;
init_timer(&device->resync_timer);
init_timer(&device->md_sync_timer);
init_timer(&device->start_resync_timer);
......@@ -2222,7 +2215,7 @@ static void do_retry(struct work_struct *ws)
spin_unlock_irq(&retry->lock);
list_for_each_entry_safe(req, tmp, &writes, tl_requests) {
struct drbd_device *device = req->w.device;
struct drbd_device *device = req->device;
struct bio *bio = req->master_bio;
unsigned long start_time = req->start_time;
bool expected;
......@@ -2273,7 +2266,7 @@ void drbd_restart_request(struct drbd_request *req)
/* Drop the extra reference that would otherwise
* have been dropped by complete_master_bio.
* do_retry() needs to grab a new one. */
dec_ap_bio(req->w.device);
dec_ap_bio(req->device);
queue_work(retry.wq, &retry.worker);
}
......@@ -3468,8 +3461,9 @@ int drbd_bmio_clear_n_write(struct drbd_device *device)
static int w_bitmap_io(struct drbd_work *w, int unused)
{
struct bm_io_work *work = container_of(w, struct bm_io_work, w);
struct drbd_device *device = w->device;
struct drbd_device *device =
container_of(w, struct drbd_device, bm_io_work.w);
struct bm_io_work *work = &device->bm_io_work;
int rv = -EIO;
D_ASSERT(device, atomic_read(&device->ap_bio_cnt) == 0);
......@@ -3509,7 +3503,8 @@ void drbd_ldev_destroy(struct drbd_device *device)
static int w_go_diskless(struct drbd_work *w, int unused)
{
struct drbd_device *device = w->device;
struct drbd_device *device =
container_of(w, struct drbd_device, go_diskless);
D_ASSERT(device, device->state.disk == D_FAILED);
/* we cannot assert local_cnt == 0 here, as get_ldev_if_state will
......@@ -3583,7 +3578,8 @@ void drbd_queue_bitmap_io(struct drbd_device *device,
set_bit(BITMAP_IO, &device->flags);
if (atomic_read(&device->ap_bio_cnt) == 0) {
if (!test_and_set_bit(BITMAP_IO_QUEUED, &device->flags))
drbd_queue_work(&first_peer_device(device)->connection->sender_work, &device->bm_io_work.w);
drbd_queue_work(&first_peer_device(device)->connection->sender_work,
&device->bm_io_work.w);
}
spin_unlock_irq(&device->resource->req_lock);
}
......@@ -3643,12 +3639,14 @@ static void md_sync_timer_fn(unsigned long data)
/* must not double-queue! */
if (list_empty(&device->md_sync_work.list))
drbd_queue_work_front(&first_peer_device(device)->connection->sender_work, &device->md_sync_work);
drbd_queue_work_front(&first_peer_device(device)->connection->sender_work,
&device->md_sync_work);
}
static int w_md_sync(struct drbd_work *w, int unused)
{
struct drbd_device *device = w->device;
struct drbd_device *device =
container_of(w, struct drbd_device, md_sync_work);
drbd_warn(device, "md_sync_timer expired! Worker calls drbd_md_sync().\n");
#ifdef DEBUG
......
This diff is collapsed.
......@@ -72,7 +72,7 @@ static struct drbd_request *drbd_req_new(struct drbd_device *device,
drbd_req_make_private_bio(req, bio_src);
req->rq_state = bio_data_dir(bio_src) == WRITE ? RQ_WRITE : 0;
req->w.device = device;
req->device = device;
req->master_bio = bio_src;
req->epoch = 0;
......@@ -95,7 +95,7 @@ static struct drbd_request *drbd_req_new(struct drbd_device *device,
void drbd_req_destroy(struct kref *kref)
{
struct drbd_request *req = container_of(kref, struct drbd_request, kref);
struct drbd_device *device = req->w.device;
struct drbd_device *device = req->device;
const unsigned s = req->rq_state;
if ((req->master_bio && !(s & RQ_POSTPONED)) ||
......@@ -191,7 +191,7 @@ void complete_master_bio(struct drbd_device *device,
static void drbd_remove_request_interval(struct rb_root *root,
struct drbd_request *req)
{
struct drbd_device *device = req->w.device;
struct drbd_device *device = req->device;
struct drbd_interval *i = &req->i;
drbd_remove_interval(root, i);
......@@ -211,7 +211,7 @@ static
void drbd_req_complete(struct drbd_request *req, struct bio_and_error *m)
{
const unsigned s = req->rq_state;
struct drbd_device *device = req->w.device;
struct drbd_device *device = req->device;
int rw;
int error, ok;
......@@ -306,7 +306,7 @@ void drbd_req_complete(struct drbd_request *req, struct bio_and_error *m)
static int drbd_req_put_completion_ref(struct drbd_request *req, struct bio_and_error *m, int put)
{
struct drbd_device *device = req->w.device;
struct drbd_device *device = req->device;
D_ASSERT(device, m || (req->rq_state & RQ_POSTPONED));
if (!atomic_sub_and_test(put, &req->completion_ref))
......@@ -329,7 +329,7 @@ static int drbd_req_put_completion_ref(struct drbd_request *req, struct bio_and_
static void mod_rq_state(struct drbd_request *req, struct bio_and_error *m,
int clear, int set)
{
struct drbd_device *device = req->w.device;
struct drbd_device *device = req->device;
unsigned s = req->rq_state;
int c_put = 0;
int k_put = 0;
......@@ -454,7 +454,7 @@ static void drbd_report_io_error(struct drbd_device *device, struct drbd_request
int __req_mod(struct drbd_request *req, enum drbd_req_event what,
struct bio_and_error *m)
{
struct drbd_device *device = req->w.device;
struct drbd_device *device = req->device;
struct net_conf *nc;
int p, rv = 0;
......@@ -542,7 +542,8 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
D_ASSERT(device, (req->rq_state & RQ_LOCAL_MASK) == 0);
mod_rq_state(req, m, 0, RQ_NET_QUEUED);
req->w.cb = w_send_read_req;
drbd_queue_work(&first_peer_device(device)->connection->sender_work, &req->w);
drbd_queue_work(&first_peer_device(device)->connection->sender_work,
&req->w);
break;
case QUEUE_FOR_NET_WRITE:
......@@ -577,7 +578,8 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
D_ASSERT(device, req->rq_state & RQ_NET_PENDING);
mod_rq_state(req, m, 0, RQ_NET_QUEUED|RQ_EXP_BARR_ACK);
req->w.cb = w_send_dblock;
drbd_queue_work(&first_peer_device(device)->connection->sender_work, &req->w);
drbd_queue_work(&first_peer_device(device)->connection->sender_work,
&req->w);
/* close the epoch, in case it outgrew the limit */
rcu_read_lock();
......@@ -592,7 +594,8 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
case QUEUE_FOR_SEND_OOS:
mod_rq_state(req, m, 0, RQ_NET_QUEUED);
req->w.cb = w_send_out_of_sync;
drbd_queue_work(&first_peer_device(device)->connection->sender_work, &req->w);
drbd_queue_work(&first_peer_device(device)->connection->sender_work,
&req->w);
break;
case READ_RETRY_REMOTE_CANCELED:
......@@ -704,7 +707,8 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
get_ldev(device); /* always succeeds in this call path */
req->w.cb = w_restart_disk_io;
drbd_queue_work(&first_peer_device(device)->connection->sender_work, &req->w);
drbd_queue_work(&first_peer_device(device)->connection->sender_work,
&req->w);
break;
case RESEND:
......@@ -720,12 +724,13 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
Throwing them out of the TL here by pretending we got a BARRIER_ACK.
During connection handshake, we ensure that the peer was not rebooted. */
if (!(req->rq_state & RQ_NET_OK)) {
/* FIXME could this possibly be a req->w.cb == w_send_out_of_sync?
/* FIXME could this possibly be a req->dw.cb == w_send_out_of_sync?
* in that case we must not set RQ_NET_PENDING. */
mod_rq_state(req, m, RQ_COMPLETION_SUSP, RQ_NET_QUEUED|RQ_NET_PENDING);
if (req->w.cb) {
drbd_queue_work(&first_peer_device(device)->connection->sender_work, &req->w);
drbd_queue_work(&first_peer_device(device)->connection->sender_work,
&req->w);
rv = req->rq_state & RQ_WRITE ? MR_WRITE : MR_READ;
} /* else: FIXME can this happen? */
break;
......@@ -835,7 +840,7 @@ static bool remote_due_to_read_balancing(struct drbd_device *device, sector_t se
static void complete_conflicting_writes(struct drbd_request *req)
{
DEFINE_WAIT(wait);
struct drbd_device *device = req->w.device;
struct drbd_device *device = req->device;
struct drbd_interval *i;
sector_t sector = req->i.sector;
int size = req->i.size;
......@@ -915,7 +920,7 @@ static void maybe_pull_ahead(struct drbd_device *device)
*/
static bool do_remote_read(struct drbd_request *req)
{
struct drbd_device *device = req->w.device;
struct drbd_device *device = req->device;
enum drbd_read_balancing rbm;
if (req->private_bio) {
......@@ -960,7 +965,7 @@ static bool do_remote_read(struct drbd_request *req)
* which does NOT include those that we are L_AHEAD for. */
static int drbd_process_write_request(struct drbd_request *req)
{
struct drbd_device *device = req->w.device;
struct drbd_device *device = req->device;
int remote, send_oos;
remote = drbd_should_do_remote(device->state);
......@@ -997,7 +1002,7 @@ static int drbd_process_write_request(struct drbd_request *req)
static void
drbd_submit_req_private_bio(struct drbd_request *req)
{
struct drbd_device *device = req->w.device;
struct drbd_device *device = req->device;
struct bio *bio = req->private_bio;
const int rw = bio_rw(bio);
......@@ -1390,7 +1395,7 @@ void request_timer_fn(unsigned long data)
drbd_warn(device, "Remote failed to finish a request within ko-count * timeout\n");
_drbd_set_state(_NS(device, conn, C_TIMEOUT), CS_VERBOSE | CS_HARD, NULL);
}
if (dt && req->rq_state & RQ_LOCAL_PENDING && req->w.device == device &&
if (dt && req->rq_state & RQ_LOCAL_PENDING && req->device == device &&
time_after(now, req->start_time + dt) &&
!time_in_range(now, device->last_reattach_jif, device->last_reattach_jif + dt)) {
drbd_warn(device, "Local backing device failed to meet the disk-timeout\n");
......
......@@ -294,7 +294,7 @@ extern void drbd_restart_request(struct drbd_request *req);
* outside the spinlock, e.g. when walking some list on cleanup. */
static inline int _req_mod(struct drbd_request *req, enum drbd_req_event what)
{
struct drbd_device *device = req->w.device;
struct drbd_device *device = req->device;
struct bio_and_error m;
int rv;
......@@ -314,7 +314,7 @@ static inline int req_mod(struct drbd_request *req,
enum drbd_req_event what)
{
unsigned long flags;
struct drbd_device *device = req->w.device;
struct drbd_device *device = req->device;
struct bio_and_error m;
int rv;
......
......@@ -32,6 +32,7 @@
struct after_state_chg_work {
struct drbd_work w;
struct drbd_device *device;
union drbd_state os;
union drbd_state ns;
enum chg_state_flags flags;
......@@ -1145,9 +1146,10 @@ __drbd_set_state(struct drbd_device *device, union drbd_state ns,
ascw->ns = ns;
ascw->flags = flags;
ascw->w.cb = w_after_state_ch;
ascw->w.device = device;
ascw->device = device;
ascw->done = done;
drbd_queue_work(&first_peer_device(device)->connection->sender_work, &ascw->w);
drbd_queue_work(&first_peer_device(device)->connection->sender_work,
&ascw->w);
} else {
drbd_err(device, "Could not kmalloc an ascw\n");
}
......@@ -1159,7 +1161,7 @@ static int w_after_state_ch(struct drbd_work *w, int unused)
{
struct after_state_chg_work *ascw =
container_of(w, struct after_state_chg_work, w);
struct drbd_device *device = w->device;
struct drbd_device *device = ascw->device;
after_state_ch(device, ascw->os, ascw->ns, ascw->flags);
if (ascw->flags & CS_WAIT_COMPLETE)
......@@ -1528,18 +1530,19 @@ static void after_state_ch(struct drbd_device *device, union drbd_state os,
}
struct after_conn_state_chg_work {
struct drbd_work w;
struct drbd_device_work dw;
enum drbd_conns oc;
union drbd_state ns_min;
union drbd_state ns_max; /* new, max state, over all devices */
enum chg_state_flags flags;
struct drbd_connection *connection;
};
static int w_after_conn_state_ch(struct drbd_work *w, int unused)
{
struct after_conn_state_chg_work *acscw =
container_of(w, struct after_conn_state_chg_work, w);
struct drbd_connection *connection = w->connection;
container_of(w, struct after_conn_state_chg_work, dw.w);
struct drbd_connection *connection = acscw->connection;
enum drbd_conns oc = acscw->oc;
union drbd_state ns_max = acscw->ns_max;
struct drbd_peer_device *peer_device;
......@@ -1840,10 +1843,10 @@ _conn_request_state(struct drbd_connection *connection, union drbd_state mask, u
acscw->ns_min = ns_min;
acscw->ns_max = ns_max;
acscw->flags = flags;
acscw->w.cb = w_after_conn_state_ch;
acscw->dw.w.cb = w_after_conn_state_ch;
kref_get(&connection->kref);
acscw->w.connection = connection;
drbd_queue_work(&connection->sender_work, &acscw->w);
acscw->connection = connection;
drbd_queue_work(&connection->sender_work, &acscw->dw.w);
} else {
drbd_err(connection, "Could not kmalloc an acscw\n");
}
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment