]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
kclient: use generic timeout/retry code for various monitor request types
authorSage Weil <sage@newdream.net>
Fri, 14 Nov 2008 20:08:55 +0000 (12:08 -0800)
committerSage Weil <sage@newdream.net>
Fri, 14 Nov 2008 20:08:55 +0000 (12:08 -0800)
src/kernel/mon_client.c
src/kernel/mon_client.h

index 11619bb9f70e9404f95004acbeb86c93679a466a..9026d41878973128b38e00700c949f5da06d4808 100644 (file)
@@ -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);
 }
index 9ccc1061310468534c79ee8f877019589b89e4bd..9ca6880384915b981fbc31f2f3f5f20c1db17bef 100644 (file)
@@ -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;
 };