]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
kclient: use a mempool for page vector in writepages
authorSage Weil <sage@newdream.net>
Thu, 23 Jul 2009 19:50:34 +0000 (12:50 -0700)
committerSage Weil <sage@newdream.net>
Thu, 23 Jul 2009 19:50:34 +0000 (12:50 -0700)
src/kernel/addr.c
src/kernel/osd_client.h
src/kernel/super.c
src/kernel/super.h

index 2c1c422894e3b70cde2b1c1f898753a5fc72e852..682552961c3bad50e6b6ff4a08362441d4c0b60d 100644 (file)
@@ -538,10 +538,35 @@ static void writepages_finish(struct ceph_osd_request *req)
        ceph_put_wrbuffer_cap_refs(ci, req->r_num_pages, snapc);
 
        ceph_release_pages(req->r_pages, req->r_num_pages);
-       kfree(req->r_pages);
+       if (req->r_pages_from_pool)
+               mempool_free(req->r_pages,
+                            ceph_client(inode->i_sb)->wb_pagevec_pool);
+       else
+               kfree(req->r_pages);
        ceph_osdc_put_request(req);
 }
 
+/*
+ * allocate a page vec, either directly, or if necessary, via a the
+ * mempool.  we avoid the mempool if we can because req->r_num_pages
+ * may be less than the maximum write size.
+ */
+static int alloc_page_vec(struct ceph_client *client,
+                         struct ceph_osd_request *req)
+{
+       req->r_pages = kmalloc(sizeof(struct page *) * req->r_num_pages,
+                              GFP_NOFS);
+       if (req->r_pages) {
+               req->r_pages_from_pool = 0;
+               return 0;
+       }
+
+       req->r_pages = mempool_alloc(client->wb_pagevec_pool, GFP_NOFS);
+       req->r_pages_from_pool = 1;
+       WARN_ON(!req->r_pages);
+       return -ENOMEM;
+}
+
 /*
  * initiate async writeback
  */
@@ -744,10 +769,8 @@ get_more_pages:
                                            &inode->i_mtime);
                                max_pages = req->r_num_pages;
 
-                               rc = -ENOMEM;
-                               req->r_pages = kmalloc(sizeof(*req->r_pages) *
-                                                      max_pages, GFP_NOFS);
-                               if (req->r_pages == NULL)
+                               rc = alloc_page_vec(client, req);
+                               if (rc)
                                        goto out;
                                req->r_callback = writepages_finish;
                                req->r_inode = inode;
index 53822ac39eb618879e01728a6f2e91bb27bbcd50..7634b1f8497b187d9dee1ea713932f14fa7c016c 100644 (file)
@@ -45,6 +45,7 @@ struct ceph_osd_request {
        struct ceph_snap_context *r_snapc;    /* snap context for writes */
        unsigned          r_num_pages;        /* size of page array (follows) */
        struct page     **r_pages;            /* pages for data payload */
+       int               r_pages_from_pool;
        int               r_own_pages;        /* if true, i own page list */
 };
 
index 16d674caeef7bd4545b66e427d442d5ee66bc783..8439888c6eb098992da93219b158cfd46e94fcfe 100644 (file)
@@ -724,6 +724,8 @@ static void ceph_destroy_client(struct ceph_client *client)
                destroy_workqueue(client->trunc_wq);
        if (client->msgr)
                ceph_messenger_destroy(client->msgr);
+       if (client->wb_pagevec_pool)
+               mempool_destroy(client->wb_pagevec_pool);
        kfree(client);
        dout("destroy_client %p done\n", client);
 }
@@ -975,6 +977,13 @@ static int ceph_set_super(struct super_block *s, void *data)
 
        s->s_time_gran = 1000;  /* 1000 ns == 1 us */
 
+       /* set up mempools */
+       ret = -ENOMEM;
+       client->wb_pagevec_pool = mempool_create_kmalloc_pool(10,
+                             client->mount_args.wsize >> PAGE_CACHE_SHIFT);
+       if (!client->wb_pagevec_pool)
+               goto fail;
+
        ret = set_anon_super(s, NULL);  /* what is that second arg for? */
        if (ret != 0)
                goto fail;
index 3f9e3e59c27071dfd029c9a7a0334ee47a6d07b2..07d6aa41d4fe285870b1eae645a063118ef2aed3 100644 (file)
@@ -2,12 +2,13 @@
 #define _FS_CEPH_SUPER_H
 
 #include <asm/unaligned.h>
-#include <linux/fs.h>
-#include <linux/wait.h>
+#include <linux/backing-dev.h>
 #include <linux/completion.h>
-#include <linux/pagemap.h>
 #include <linux/exportfs.h>
-#include <linux/backing-dev.h>
+#include <linux/fs.h>
+#include <linux/mempool.h>
+#include <linux/pagemap.h>
+#include <linux/wait.h>
 
 #include "types.h"
 #include "ceph_debug.h"
@@ -132,6 +133,7 @@ struct ceph_client {
        struct ceph_osd_client osdc;
 
        /* writeback */
+       mempool_t *wb_pagevec_pool;
        struct workqueue_struct *wb_wq;
        struct workqueue_struct *pg_inv_wq;
        struct workqueue_struct *trunc_wq;