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
*/
&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;
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 */
};
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);
}
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;
#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"
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;