diff options
author | Maxim Patlasov <mpatlasov@parallels.com> | 2012-10-26 11:48:07 -0400 |
---|---|---|
committer | Miklos Szeredi <mszeredi@suse.cz> | 2013-01-24 10:21:25 -0500 |
commit | 4250c0668ea10a19f3d37b1733f54ce6c8a37234 (patch) | |
tree | 4f0e6bd382fa5c9cba0d584298c38b19bcdd1841 /fs/fuse | |
parent | 0b05b18381eea98c9c9ada95629bf659a88c9374 (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.c | 47 | ||||
-rw-r--r-- | fs/fuse/file.c | 4 | ||||
-rw-r--r-- | fs/fuse/fuse_i.h | 15 | ||||
-rw-r--r-- | fs/fuse/inode.c | 4 |
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 | ||
37 | static void fuse_request_init(struct fuse_req *req) | 37 | static 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 | ||
46 | struct fuse_req *fuse_request_alloc(void) | 50 | static 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 | |||
71 | struct fuse_req *fuse_request_alloc(unsigned npages) | ||
72 | { | ||
73 | return __fuse_request_alloc(npages, GFP_KERNEL); | ||
74 | } | ||
53 | EXPORT_SYMBOL_GPL(fuse_request_alloc); | 75 | EXPORT_SYMBOL_GPL(fuse_request_alloc); |
54 | 76 | ||
55 | struct fuse_req *fuse_request_alloc_nofs(void) | 77 | struct 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 | ||
63 | void fuse_request_free(struct fuse_req *req) | 82 | void 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 */ |
48 | extern struct list_head fuse_conn_list; | 51 | extern 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 | */ |
667 | struct fuse_req *fuse_request_alloc(void); | 676 | struct fuse_req *fuse_request_alloc(unsigned npages); |
668 | 677 | ||
669 | struct fuse_req *fuse_request_alloc_nofs(void); | 678 | struct 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 | } |