From 01a33259dbbeb380104d185073f8802eee743f98 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Fri, 14 Nov 2008 12:08:55 -0800 Subject: [PATCH] kclient: use generic timeout/retry code for various monitor request types --- src/kernel/mon_client.c | 129 ++++++++++++++++++++-------------------- src/kernel/mon_client.h | 23 ++++--- 2 files changed, 78 insertions(+), 74 deletions(-) diff --git a/src/kernel/mon_client.c b/src/kernel/mon_client.c index 11619bb9f70e9..9026d41878973 100644 --- a/src/kernel/mon_client.c +++ b/src/kernel/mon_client.c @@ -80,15 +80,49 @@ static int pick_mon(struct ceph_mon_client *monc, int newmon) } /* - * Delay work with exponential backoff. + * Generic timeout mechanism for monitor requests */ -static void reschedule_timeout(struct delayed_work *dwork, unsigned long *delay) +static void reschedule_timeout(struct ceph_mon_request_type *req) { - schedule_delayed_work(dwork, *delay); - if (*delay < MAX_DELAY_INTERVAL) - *delay *= 2; + schedule_delayed_work(&req->delayed_work, req->delay); + if (req->delay < MAX_DELAY_INTERVAL) + req->delay *= 2; else - *delay = MAX_DELAY_INTERVAL; + req->delay = MAX_DELAY_INTERVAL; +} + +static void retry_request(struct work_struct *work) +{ + struct ceph_mon_request_type *req = + container_of(work, struct ceph_mon_request_type, + delayed_work.work); + + /* + * if lock is contended, reschedule sooner. we can't wait for + * mutex because we cancel the timeout sync with lock held. + */ + if (mutex_trylock(&req->monc->req_mutex)) { + req->do_request(req->monc, 1); + reschedule_timeout(req); + mutex_unlock(&req->monc->req_mutex); + } else + schedule_delayed_work(&req->delayed_work, BASE_DELAY_INTERVAL); +} + +static void cancel_timeout(struct ceph_mon_request_type *req) +{ + cancel_delayed_work_sync(&req->delayed_work); + req->delay = BASE_DELAY_INTERVAL; +} + +static void init_request_type(struct ceph_mon_client *monc, + struct ceph_mon_request_type *req, + ceph_monc_request_func_t func) +{ + req->monc = monc; + INIT_DELAYED_WORK(&req->delayed_work, retry_request); + req->delay = 0; + req->do_request = func; } @@ -112,18 +146,6 @@ static void request_mdsmap(struct ceph_mon_client *monc, int newmon) ceph_msg_send(monc->client->msgr, msg, 0); } -static void retry_request_mdsmap(struct work_struct *work) -{ - struct ceph_mon_client *monc = - container_of(work, struct ceph_mon_client, - mds_delayed_work.work); - - /* keep sending request until we receive mds map */ - request_mdsmap(monc, 1); - if (monc->want_mdsmap) - reschedule_timeout(&monc->mds_delayed_work, &monc->mds_delay); -} - /* * Register our desire for an mdsmap >= epoch @want. */ @@ -132,16 +154,16 @@ void ceph_monc_request_mdsmap(struct ceph_mon_client *monc, u32 want) dout(5, "request_mdsmap want %u\n", want); mutex_lock(&monc->req_mutex); if (want > monc->want_mdsmap) { - monc->mds_delay = BASE_DELAY_INTERVAL; monc->want_mdsmap = want; + monc->mdsreq.delay = BASE_DELAY_INTERVAL; request_mdsmap(monc, 0); - reschedule_timeout(&monc->mds_delayed_work, &monc->mds_delay); + reschedule_timeout(&monc->mdsreq); } mutex_unlock(&monc->req_mutex); } /* - * Called when we receive an mds map. + * Possibly cancel our desire for a new map */ int ceph_monc_got_mdsmap(struct ceph_mon_client *monc, u32 got) { @@ -154,8 +176,7 @@ int ceph_monc_got_mdsmap(struct ceph_mon_client *monc, u32 got) } else { dout(5, "got_mdsmap %u >= wanted %u\n", got, monc->want_mdsmap); monc->want_mdsmap = 0; - cancel_delayed_work_sync(&monc->mds_delayed_work); - monc->mds_delay = BASE_DELAY_INTERVAL; + cancel_timeout(&monc->mdsreq); } mutex_unlock(&monc->req_mutex); return ret; @@ -165,7 +186,6 @@ int ceph_monc_got_mdsmap(struct ceph_mon_client *monc, u32 got) /* * osd map */ - static void request_osdmap(struct ceph_mon_client *monc, int newmon) { struct ceph_msg *msg; @@ -183,26 +203,14 @@ static void request_osdmap(struct ceph_mon_client *monc, int newmon) ceph_msg_send(monc->client->msgr, msg, 0); } -static void retry_request_osdmap(struct work_struct *work) -{ - struct ceph_mon_client *monc = - container_of(work, struct ceph_mon_client, - osd_delayed_work.work); - - /* keep sending request until we receive osd map */ - request_osdmap(monc, 1); - if (monc->want_osdmap) - reschedule_timeout(&monc->osd_delayed_work, &monc->osd_delay); -} - void ceph_monc_request_osdmap(struct ceph_mon_client *monc, u32 want) { dout(5, "request_osdmap want %u\n", want); mutex_lock(&monc->req_mutex); - monc->osd_delay = BASE_DELAY_INTERVAL; + monc->osdreq.delay = BASE_DELAY_INTERVAL; monc->want_osdmap = want; request_osdmap(monc, 0); - reschedule_timeout(&monc->osd_delayed_work, &monc->osd_delay); + reschedule_timeout(&monc->osdreq); mutex_unlock(&monc->req_mutex); } @@ -217,8 +225,7 @@ int ceph_monc_got_osdmap(struct ceph_mon_client *monc, u32 got) } else { dout(5, "got_osdmap %u >= wanted %u\n", got, monc->want_osdmap); monc->want_osdmap = 0; - cancel_delayed_work_sync(&monc->osd_delayed_work); - monc->osd_delay = BASE_DELAY_INTERVAL; + cancel_timeout(&monc->osdreq); } mutex_unlock(&monc->req_mutex); return ret; @@ -233,7 +240,7 @@ static void request_umount(struct ceph_mon_client *monc, int newmon) struct ceph_msg *msg; int mon = pick_mon(monc, newmon); - dout(5, "do_request_umount from mon%d\n", mon); + dout(5, "request_umount from mon%d\n", mon); msg = ceph_msg_new(CEPH_MSG_CLIENT_UNMOUNT, 0, 0, 0, NULL); if (IS_ERR(msg)) return; @@ -241,16 +248,6 @@ static void request_umount(struct ceph_mon_client *monc, int newmon) ceph_msg_send(monc->client->msgr, msg, 0); } -static void retry_request_umount(struct work_struct *work) -{ - struct ceph_mon_client *monc = - container_of(work, struct ceph_mon_client, - umount_delayed_work.work); - - request_umount(monc, 1); - reschedule_timeout(&monc->umount_delayed_work, &monc->umount_delay); -} - void ceph_monc_request_umount(struct ceph_mon_client *monc) { struct ceph_client *client = monc->client; @@ -260,22 +257,18 @@ void ceph_monc_request_umount(struct ceph_mon_client *monc) return; mutex_lock(&monc->req_mutex); - monc->umount_delay = BASE_DELAY_INTERVAL; + monc->umountreq.delay = BASE_DELAY_INTERVAL; request_umount(monc, 0); - reschedule_timeout(&monc->umount_delayed_work, &monc->umount_delay); + reschedule_timeout(&monc->umountreq); mutex_unlock(&monc->req_mutex); } -/* - * Handle monitor umount ack. - */ void ceph_monc_handle_umount(struct ceph_mon_client *monc, struct ceph_msg *msg) { dout(5, "handle_umount\n"); mutex_lock(&monc->req_mutex); - cancel_delayed_work_sync(&monc->umount_delayed_work); - monc->client->mount_state = CEPH_MOUNT_UNMOUNTED; + cancel_timeout(&monc->umountreq); mutex_unlock(&monc->req_mutex); wake_up(&monc->client->mount_wq); } @@ -376,6 +369,9 @@ int ceph_monc_do_statfs(struct ceph_mon_client *monc, struct ceph_statfs *buf) return req.result; } +/* + * Resend any statfs requests that have timed out. + */ static void do_statfs_check(struct work_struct *work) { struct ceph_mon_client *monc = @@ -399,7 +395,7 @@ static void do_statfs_check(struct work_struct *work) next_tid = req->tid + 1; if (time_after(jiffies, req->last_attempt + req->delay)) { req->last_attempt = jiffies; - if (req->delay < HZ*60) + if (req->delay < MAX_DELAY_INTERVAL) req->delay *= 2; send_statfs(monc, req->tid, newmon); newmon = 0; @@ -412,6 +408,7 @@ static void do_statfs_check(struct work_struct *work) round_jiffies_relative(1*HZ)); } + int ceph_monc_init(struct ceph_mon_client *monc, struct ceph_client *cl) { dout(5, "init\n"); @@ -426,11 +423,10 @@ int ceph_monc_init(struct ceph_mon_client *monc, struct ceph_client *cl) INIT_RADIX_TREE(&monc->statfs_request_tree, GFP_ATOMIC); monc->num_statfs_requests = 0; monc->last_tid = 0; - INIT_DELAYED_WORK(&monc->mds_delayed_work, retry_request_mdsmap); - INIT_DELAYED_WORK(&monc->osd_delayed_work, retry_request_osdmap); - INIT_DELAYED_WORK(&monc->umount_delayed_work, retry_request_umount); INIT_DELAYED_WORK(&monc->statfs_delayed_work, do_statfs_check); - monc->mds_delay = monc->osd_delay = monc->umount_delay = 0; + init_request_type(monc, &monc->mdsreq, request_mdsmap); + init_request_type(monc, &monc->osdreq, request_osdmap); + init_request_type(monc, &monc->umountreq, request_umount); mutex_init(&monc->req_mutex); monc->want_mdsmap = 0; monc->want_osdmap = 0; @@ -440,8 +436,9 @@ int ceph_monc_init(struct ceph_mon_client *monc, struct ceph_client *cl) void ceph_monc_stop(struct ceph_mon_client *monc) { dout(5, "stop\n"); - cancel_delayed_work_sync(&monc->mds_delayed_work); - cancel_delayed_work_sync(&monc->osd_delayed_work); - cancel_delayed_work_sync(&monc->umount_delayed_work); + cancel_timeout(&monc->mdsreq); + cancel_timeout(&monc->osdreq); + cancel_timeout(&monc->umountreq); + cancel_delayed_work_sync(&monc->statfs_delayed_work); kfree(monc->monmap); } diff --git a/src/kernel/mon_client.h b/src/kernel/mon_client.h index 9ccc106131046..9ca6880384915 100644 --- a/src/kernel/mon_client.h +++ b/src/kernel/mon_client.h @@ -35,9 +35,21 @@ struct ceph_monmap { struct ceph_entity_inst mon_inst[0]; }; +struct ceph_mon_client; + /* - * a pending statfs() request. + * Generic mechanism for resending monitor requests. */ +typedef void (*ceph_monc_request_func_t)(struct ceph_mon_client *monc, + int newmon); +struct ceph_mon_request_type { + struct ceph_mon_client *monc; + struct delayed_work delayed_work; + unsigned long delay; + ceph_monc_request_func_t do_request; +}; + +/* statfs() is done a bit differently */ struct ceph_mon_statfs_request { u64 tid; int result; @@ -56,16 +68,11 @@ struct ceph_mon_client { struct radix_tree_root statfs_request_tree; int num_statfs_requests; u64 last_tid; + struct delayed_work statfs_delayed_work; /* mds/osd map or umount requests */ - struct delayed_work mds_delayed_work; - struct delayed_work osd_delayed_work; - struct delayed_work umount_delayed_work; - struct delayed_work statfs_delayed_work; - unsigned long mds_delay; - unsigned long osd_delay; - unsigned long umount_delay; struct mutex req_mutex; + struct ceph_mon_request_type mdsreq, osdreq, umountreq; u32 want_mdsmap; u32 want_osdmap; }; -- 2.39.5