]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
kclient: reuse osd struct when possible
authorSage Weil <sage@newdream.net>
Tue, 1 Sep 2009 22:48:32 +0000 (15:48 -0700)
committerSage Weil <sage@newdream.net>
Tue, 1 Sep 2009 22:48:32 +0000 (15:48 -0700)
src/kernel/osd_client.c

index cb77848c7064ce3df8c0c1133d2b3e06218d7b68..32f23784590cf45406ae1219cbf419eb11cc88a4 100644 (file)
@@ -329,9 +329,10 @@ static void destroy_osd(struct ceph_osd_client *osdc, struct ceph_osd *osd)
        dout("destroy_osd %p\n", osd);
        BUG_ON(!list_empty(&osd->o_requests));
        rb_erase(&osd->o_node, &osdc->osds);
+       osd->o_con->private = NULL;
        ceph_con_close(osd->o_con);
        osd->o_con->ops->put(osd->o_con);
-       kfree(osd);
+       osd->o_con = NULL;
 }
 
 static int reset_osd(struct ceph_osd_client *osdc, struct ceph_osd *osd)
@@ -341,9 +342,11 @@ static int reset_osd(struct ceph_osd_client *osdc, struct ceph_osd *osd)
        dout("reset_osd %p osd%d\n", osd, osd->o_osd);
        if (list_empty(&osd->o_requests)) {
                destroy_osd(osdc, osd);
+               kfree(osd);
        } else {
                ceph_con_close(osd->o_con);
                osd->o_con->ops->put(osd->o_con);
+               osd->o_con = NULL;
                ret = open_osd_session(osdc, osd);
        }
        return ret;
@@ -432,8 +435,10 @@ static void __unregister_request(struct ceph_osd_client *osdc,
        osdc->num_requests--;
 
        list_del_init(&req->r_osd_item);
-       if (list_empty(&req->r_osd->o_requests))
+       if (list_empty(&req->r_osd->o_requests)) {
                destroy_osd(osdc, req->r_osd);
+               kfree(req->r_osd);
+       }
        req->r_osd = NULL;
 
        ceph_osdc_put_request(req);
@@ -458,20 +463,22 @@ static void __unregister_request(struct ceph_osd_client *osdc,
 
 
 /*
- * Pick an osd (the first 'up' osd in the pg), and put result in
- * req->r_last_osd[_addr].  If none, set to -1.
+ * Pick an osd (the first 'up' osd in the pg), allocate the osd struct
+ * (as needed), and set the request r_osd appropriately.  If there is
+ * no up osd, set r_osd to NULL.
  *
- * Caller should hold map_sem for read.
+ * Return 0 if unchanged, 1 if changed, or negative on error.
  *
- * return 0 if unchanged, 1 if changed.
+ * Caller should hold map_sem for read and request_mutex.
  */
-static int map_osds(struct ceph_osd_client *osdc,
-                   struct ceph_osd_request *req)
+static int __map_osds(struct ceph_osd_client *osdc,
+                     struct ceph_osd_request *req)
 {
        struct ceph_osd_request_head *reqhead = req->r_request->front.iov_base;
        union ceph_pg pgid;
        int o = -1;
        int err;
+       struct ceph_osd *newosd = NULL;
 
        err = ceph_calc_object_layout(&reqhead->layout, req->r_oid,
                                      &req->r_file_layout, osdc->osdmap);
@@ -480,33 +487,45 @@ static int map_osds(struct ceph_osd_client *osdc,
        pgid.pg64 = le64_to_cpu(reqhead->layout.ol_pgid);
        o = ceph_calc_pg_primary(osdc->osdmap, pgid);
 
-       if (req->r_osd && req->r_osd->o_osd == o)
-               return 0;
+       if ((req->r_osd && req->r_osd->o_osd == o) ||
+           (req->r_osd == NULL && o == -1))
+               return 0;  /* no change */
 
        dout("map_osds tid %llu pgid %llx pool %d osd%d (was osd%d)\n",
             req->r_tid, pgid.pg64, pgid.pg.pool, o,
             req->r_osd ? req->r_osd->o_osd : -1);
 
-       /* XXX FIXME: try to reuse r_osd where possible */
        if (req->r_osd) {
                list_del_init(&req->r_osd_item);
-               if (list_empty(&req->r_osd->o_requests))
-                       destroy_osd(osdc, req->r_osd);
+               if (list_empty(&req->r_osd->o_requests)) {
+                       /* try to re-use r_osd if possible */
+                       newosd = req->r_osd;
+                       destroy_osd(osdc, newosd);
+               }
                req->r_osd = NULL;
        }
 
        req->r_osd = __lookup_osd(osdc, o);
-       if (!req->r_osd) {
-               req->r_osd = kmalloc(sizeof(*req->r_osd), GFP_NOFS);
-               if (!req->r_osd)
-                       return -ENOMEM;
+       if (!req->r_osd && o >= 0) {
+               if (newosd) {
+                       req->r_osd = newosd;
+                       newosd = NULL;
+               } else {
+                       err = -ENOMEM;
+                       req->r_osd = kmalloc(sizeof(*req->r_osd), GFP_NOFS);
+                       if (!req->r_osd)
+                               goto out;
+               }
                init_osd(osdc, req->r_osd, o);
-#warning check return value
-               open_osd_session(osdc, req->r_osd);
                __insert_osd(osdc, req->r_osd);
        }
+
        list_add(&req->r_osd_item, &req->r_osd->o_requests);
-       return 1;
+       err = 1;   /* osd changed */
+
+out:
+       kfree(newosd);
+       return err;
 }
 
 /*