History

fuse: allocate page array more efficiently

When allocating page array for a request the array for the page pointers and the array for page descriptors are allocated by two separate kmalloc() calls. Merge these into one allocation. Also instead of initializing the request and the page arrays with memset(), use the zeroing allocation variants. Reserved requests never carry pages (page array size is zero). Make that explicit by initializing the page array pointers to NULL and make sure the assumption remains true by adding a WARN_ON().

Miklos Szeredi committed 8 years ago

Commit 8a7aa281 parent ab2257e1 file · +18 −26Browse files

Unified · Split

fs/fuse/dev.c+18−26
@@ -44,9 +44,6 @@ static void fuse_request_init(struct fuse_req *req, struct page **pages, · 43 unmodified lines
44 struct fuse_page_desc *page_descs,44 struct fuse_page_desc *page_descs,
45 unsigned npages)45 unsigned npages)
46{46{
47 memset(req, 0, sizeof(*req));
48 memset(pages, 0, sizeof(*pages) * npages);
49 memset(page_descs, 0, sizeof(*page_descs) * npages);
50 INIT_LIST_HEAD(&req->list);47 INIT_LIST_HEAD(&req->list);
51 INIT_LIST_HEAD(&req->intr_entry);48 INIT_LIST_HEAD(&req->intr_entry);
52 init_waitqueue_head(&req->waitq);49 init_waitqueue_head(&req->waitq);
@@ -59,28 +56,22 @@ static void fuse_request_init(struct fuse_req *req, struct page **pages, · 6 unmodified lines
59 56
60static struct fuse_req *__fuse_request_alloc(unsigned npages, gfp_t flags)57static struct fuse_req *__fuse_request_alloc(unsigned npages, gfp_t flags)
61{58{
62 struct fuse_req *req = kmem_cache_alloc(fuse_req_cachep, flags);59 struct fuse_req *req = kmem_cache_zalloc(fuse_req_cachep, flags);
63 if (req) {60 if (req) {
64 struct page **pages;61 struct page **pages = NULL;
65 struct fuse_page_desc *page_descs;62 struct fuse_page_desc *page_descs = NULL;
66 63
67 if (npages <= FUSE_REQ_INLINE_PAGES) {64 if (npages > FUSE_REQ_INLINE_PAGES) {
65 pages = kzalloc(npages * (sizeof(*pages) +
66 sizeof(*page_descs)), flags);
67 if (!pages) {
68 kmem_cache_free(fuse_req_cachep, req);
69 return NULL;
70 }
71 page_descs = (void *) pages + npages * sizeof(*pages);
72 } else if (npages) {
68 pages = req->inline_pages;73 pages = req->inline_pages;
69 page_descs = req->inline_page_descs;74 page_descs = req->inline_page_descs;
70 } else {
71 pages = kmalloc_array(npages, sizeof(struct page *),
72 flags);
73 page_descs =
74 kmalloc_array(npages,
75 sizeof(struct fuse_page_desc),
76 flags);
77 }
78
79 if (!pages || !page_descs) {
80 kfree(pages);
81 kfree(page_descs);
82 kmem_cache_free(fuse_req_cachep, req);
83 return NULL;
84 }75 }
85 76
86 fuse_request_init(req, pages, page_descs, npages);77 fuse_request_init(req, pages, page_descs, npages);
@@ -101,10 +92,9 @@ struct fuse_req *fuse_request_alloc_nofs(unsigned npages) · 14 unmodified lines
101 92
102void fuse_request_free(struct fuse_req *req)93void fuse_request_free(struct fuse_req *req)
103{94{
104 if (req->pages != req->inline_pages) {95 if (req->pages != req->inline_pages)
105 kfree(req->pages);96 kfree(req->pages);
106 kfree(req->page_descs);97
107 }
108 kmem_cache_free(fuse_req_cachep, req);98 kmem_cache_free(fuse_req_cachep, req);
109}99}
110 100
@@ -239,8 +229,10 @@ static void put_reserved_req(struct fuse_conn *fc, struct fuse_req *req) · 128 unmodified lines
239 struct file *file = req->stolen_file;229 struct file *file = req->stolen_file;
240 struct fuse_file *ff = file->private_data;230 struct fuse_file *ff = file->private_data;
241 231
232 WARN_ON(req->max_pages);
242 spin_lock(&fc->lock);233 spin_lock(&fc->lock);
243 fuse_request_init(req, req->pages, req->page_descs, req->max_pages);234 memset(req, 0, sizeof(*req));
235 fuse_request_init(req, NULL, NULL, 0);
244 BUG_ON(ff->reserved_req);236 BUG_ON(ff->reserved_req);
245 ff->reserved_req = req;237 ff->reserved_req = req;
246 wake_up_all(&fc->reserved_req_waitq);238 wake_up_all(&fc->reserved_req_waitq);