aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fuse
diff options
context:
space:
mode:
authorMaxim Patlasov <mpatlasov@parallels.com>2012-10-26 11:48:07 -0400
committerMiklos Szeredi <mszeredi@suse.cz>2013-01-24 10:21:25 -0500
commit4250c0668ea10a19f3d37b1733f54ce6c8a37234 (patch)
tree4f0e6bd382fa5c9cba0d584298c38b19bcdd1841 /fs/fuse
parent0b05b18381eea98c9c9ada95629bf659a88c9374 (diff)
fuse: general infrastructure for pages[] of variable size
The patch removes inline array of FUSE_MAX_PAGES_PER_REQ page pointers from fuse_req. Instead of that, req->pages may now point either to small inline array or to an array allocated dynamically. This essentially means that all callers of fuse_request_alloc[_nofs] should pass the number of pages needed explicitly. The patch doesn't make any logic changes. Signed-off-by: Maxim Patlasov <mpatlasov@parallels.com> Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Diffstat (limited to 'fs/fuse')
-rw-r--r--fs/fuse/dev.c47
-rw-r--r--fs/fuse/file.c4
-rw-r--r--fs/fuse/fuse_i.h15
-rw-r--r--fs/fuse/inode.c4
4 files changed, 50 insertions, 20 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 05c3eec298f2..af37ae138252 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -34,34 +34,55 @@ static struct fuse_conn *fuse_get_conn(struct file *file)
34 return file->private_data; 34 return file->private_data;
35} 35}
36 36
37static void fuse_request_init(struct fuse_req *req) 37static void fuse_request_init(struct fuse_req *req, struct page **pages,
38 unsigned npages)
38{ 39{
39 memset(req, 0, sizeof(*req)); 40 memset(req, 0, sizeof(*req));
41 memset(pages, 0, sizeof(*pages) * npages);
40 INIT_LIST_HEAD(&req->list); 42 INIT_LIST_HEAD(&req->list);
41 INIT_LIST_HEAD(&req->intr_entry); 43 INIT_LIST_HEAD(&req->intr_entry);
42 init_waitqueue_head(&req->waitq); 44 init_waitqueue_head(&req->waitq);
43 atomic_set(&req->count, 1); 45 atomic_set(&req->count, 1);
46 req->pages = pages;
47 req->max_pages = npages;
44} 48}
45 49
46struct fuse_req *fuse_request_alloc(void) 50static struct fuse_req *__fuse_request_alloc(unsigned npages, gfp_t flags)
47{ 51{
48 struct fuse_req *req = kmem_cache_alloc(fuse_req_cachep, GFP_KERNEL); 52 struct fuse_req *req = kmem_cache_alloc(fuse_req_cachep, flags);
49 if (req) 53 if (req) {
50 fuse_request_init(req); 54 struct page **pages;
55
56 if (npages <= FUSE_REQ_INLINE_PAGES)
57 pages = req->inline_pages;
58 else
59 pages = kmalloc(sizeof(struct page *) * npages, flags);
60
61 if (!pages) {
62 kmem_cache_free(fuse_req_cachep, req);
63 return NULL;
64 }
65
66 fuse_request_init(req, pages, npages);
67 }
51 return req; 68 return req;
52} 69}
70
71struct fuse_req *fuse_request_alloc(unsigned npages)
72{
73 return __fuse_request_alloc(npages, GFP_KERNEL);
74}
53EXPORT_SYMBOL_GPL(fuse_request_alloc); 75EXPORT_SYMBOL_GPL(fuse_request_alloc);
54 76
55struct fuse_req *fuse_request_alloc_nofs(void) 77struct fuse_req *fuse_request_alloc_nofs(unsigned npages)
56{ 78{
57 struct fuse_req *req = kmem_cache_alloc(fuse_req_cachep, GFP_NOFS); 79 return __fuse_request_alloc(npages, GFP_NOFS);
58 if (req)
59 fuse_request_init(req);
60 return req;
61} 80}
62 81
63void fuse_request_free(struct fuse_req *req) 82void fuse_request_free(struct fuse_req *req)
64{ 83{
84 if (req->pages != req->inline_pages)
85 kfree(req->pages);
65 kmem_cache_free(fuse_req_cachep, req); 86 kmem_cache_free(fuse_req_cachep, req);
66} 87}
67 88
@@ -116,7 +137,7 @@ struct fuse_req *fuse_get_req(struct fuse_conn *fc)
116 if (!fc->connected) 137 if (!fc->connected)
117 goto out; 138 goto out;
118 139
119 req = fuse_request_alloc(); 140 req = fuse_request_alloc(FUSE_MAX_PAGES_PER_REQ);
120 err = -ENOMEM; 141 err = -ENOMEM;
121 if (!req) 142 if (!req)
122 goto out; 143 goto out;
@@ -165,7 +186,7 @@ static void put_reserved_req(struct fuse_conn *fc, struct fuse_req *req)
165 struct fuse_file *ff = file->private_data; 186 struct fuse_file *ff = file->private_data;
166 187
167 spin_lock(&fc->lock); 188 spin_lock(&fc->lock);
168 fuse_request_init(req); 189 fuse_request_init(req, req->pages, req->max_pages);
169 BUG_ON(ff->reserved_req); 190 BUG_ON(ff->reserved_req);
170 ff->reserved_req = req; 191 ff->reserved_req = req;
171 wake_up_all(&fc->reserved_req_waitq); 192 wake_up_all(&fc->reserved_req_waitq);
@@ -192,7 +213,7 @@ struct fuse_req *fuse_get_req_nofail(struct fuse_conn *fc, struct file *file)
192 213
193 atomic_inc(&fc->num_waiting); 214 atomic_inc(&fc->num_waiting);
194 wait_event(fc->blocked_waitq, !fc->blocked); 215 wait_event(fc->blocked_waitq, !fc->blocked);
195 req = fuse_request_alloc(); 216 req = fuse_request_alloc(FUSE_MAX_PAGES_PER_REQ);
196 if (!req) 217 if (!req)
197 req = get_reserved_req(fc, file); 218 req = get_reserved_req(fc, file);
198 219
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index f3ab824fa302..2565f635c04f 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -57,7 +57,7 @@ struct fuse_file *fuse_file_alloc(struct fuse_conn *fc)
57 return NULL; 57 return NULL;
58 58
59 ff->fc = fc; 59 ff->fc = fc;
60 ff->reserved_req = fuse_request_alloc(); 60 ff->reserved_req = fuse_request_alloc(0);
61 if (unlikely(!ff->reserved_req)) { 61 if (unlikely(!ff->reserved_req)) {
62 kfree(ff); 62 kfree(ff);
63 return NULL; 63 return NULL;
@@ -1272,7 +1272,7 @@ static int fuse_writepage_locked(struct page *page)
1272 1272
1273 set_page_writeback(page); 1273 set_page_writeback(page);
1274 1274
1275 req = fuse_request_alloc_nofs(); 1275 req = fuse_request_alloc_nofs(1);
1276 if (!req) 1276 if (!req)
1277 goto err; 1277 goto err;
1278 1278
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 5c5055306d3c..0c5b9310f930 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -44,6 +44,9 @@
44 doing the mount will be allowed to access the filesystem */ 44 doing the mount will be allowed to access the filesystem */
45#define FUSE_ALLOW_OTHER (1 << 1) 45#define FUSE_ALLOW_OTHER (1 << 1)
46 46
47/** Number of page pointers embedded in fuse_req */
48#define FUSE_REQ_INLINE_PAGES 1
49
47/** List of active connections */ 50/** List of active connections */
48extern struct list_head fuse_conn_list; 51extern struct list_head fuse_conn_list;
49 52
@@ -291,7 +294,13 @@ struct fuse_req {
291 } misc; 294 } misc;
292 295
293 /** page vector */ 296 /** page vector */
294 struct page *pages[FUSE_MAX_PAGES_PER_REQ]; 297 struct page **pages;
298
299 /** size of the 'pages' array */
300 unsigned max_pages;
301
302 /** inline page vector */
303 struct page *inline_pages[FUSE_REQ_INLINE_PAGES];
295 304
296 /** number of pages in vector */ 305 /** number of pages in vector */
297 unsigned num_pages; 306 unsigned num_pages;
@@ -664,9 +673,9 @@ void fuse_ctl_cleanup(void);
664/** 673/**
665 * Allocate a request 674 * Allocate a request
666 */ 675 */
667struct fuse_req *fuse_request_alloc(void); 676struct fuse_req *fuse_request_alloc(unsigned npages);
668 677
669struct fuse_req *fuse_request_alloc_nofs(void); 678struct fuse_req *fuse_request_alloc_nofs(unsigned npages);
670 679
671/** 680/**
672 * Free a request 681 * Free a request
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 6f7d5746bf52..9a937f0239e8 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -1037,12 +1037,12 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
1037 /* only now - we want root dentry with NULL ->d_op */ 1037 /* only now - we want root dentry with NULL ->d_op */
1038 sb->s_d_op = &fuse_dentry_operations; 1038 sb->s_d_op = &fuse_dentry_operations;
1039 1039
1040 init_req = fuse_request_alloc(); 1040 init_req = fuse_request_alloc(0);
1041 if (!init_req) 1041 if (!init_req)
1042 goto err_put_root; 1042 goto err_put_root;
1043 1043
1044 if (is_bdev) { 1044 if (is_bdev) {
1045 fc->destroy_req = fuse_request_alloc(); 1045 fc->destroy_req = fuse_request_alloc(0);
1046 if (!fc->destroy_req) 1046 if (!fc->destroy_req)
1047 goto err_free_init_req; 1047 goto err_free_init_req;
1048 } 1048 }