From: Sage Weil Date: Thu, 23 Jul 2009 19:50:34 +0000 (-0700) Subject: kclient: use a mempool for page vector in writepages X-Git-Tag: v0.12~90 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=aca6d39d8a06b72ab0a20a2d90c075239de4c69e;p=ceph.git kclient: use a mempool for page vector in writepages --- diff --git a/src/kernel/addr.c b/src/kernel/addr.c index 2c1c422894e3..682552961c3b 100644 --- a/src/kernel/addr.c +++ b/src/kernel/addr.c @@ -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; diff --git a/src/kernel/osd_client.h b/src/kernel/osd_client.h index 53822ac39eb6..7634b1f8497b 100644 --- a/src/kernel/osd_client.h +++ b/src/kernel/osd_client.h @@ -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 */ }; diff --git a/src/kernel/super.c b/src/kernel/super.c index 16d674caeef7..8439888c6eb0 100644 --- a/src/kernel/super.c +++ b/src/kernel/super.c @@ -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; diff --git a/src/kernel/super.h b/src/kernel/super.h index 3f9e3e59c270..07d6aa41d4fe 100644 --- a/src/kernel/super.h +++ b/src/kernel/super.h @@ -2,12 +2,13 @@ #define _FS_CEPH_SUPER_H #include -#include -#include +#include #include -#include #include -#include +#include +#include +#include +#include #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;