diff options
Diffstat (limited to 'fs/fuse')
-rw-r--r-- | fs/fuse/dev.c | 73 | ||||
-rw-r--r-- | fs/fuse/dir.c | 118 | ||||
-rw-r--r-- | fs/fuse/file.c | 48 | ||||
-rw-r--r-- | fs/fuse/fuse_i.h | 26 | ||||
-rw-r--r-- | fs/fuse/inode.c | 54 |
5 files changed, 111 insertions, 208 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 6b8843d4ad8c..4dc104c0e95d 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c | |||
@@ -72,10 +72,8 @@ static void restore_sigs(sigset_t *oldset) | |||
72 | */ | 72 | */ |
73 | void fuse_reset_request(struct fuse_req *req) | 73 | void fuse_reset_request(struct fuse_req *req) |
74 | { | 74 | { |
75 | int preallocated = req->preallocated; | ||
76 | BUG_ON(atomic_read(&req->count) != 1); | 75 | BUG_ON(atomic_read(&req->count) != 1); |
77 | fuse_request_init(req); | 76 | fuse_request_init(req); |
78 | req->preallocated = preallocated; | ||
79 | } | 77 | } |
80 | 78 | ||
81 | static void __fuse_get_request(struct fuse_req *req) | 79 | static void __fuse_get_request(struct fuse_req *req) |
@@ -90,71 +88,28 @@ static void __fuse_put_request(struct fuse_req *req) | |||
90 | atomic_dec(&req->count); | 88 | atomic_dec(&req->count); |
91 | } | 89 | } |
92 | 90 | ||
93 | static struct fuse_req *do_get_request(struct fuse_conn *fc) | 91 | struct fuse_req *fuse_get_req(struct fuse_conn *fc) |
94 | { | 92 | { |
95 | struct fuse_req *req; | 93 | struct fuse_req *req = fuse_request_alloc(); |
94 | if (!req) | ||
95 | return ERR_PTR(-ENOMEM); | ||
96 | 96 | ||
97 | spin_lock(&fc->lock); | 97 | atomic_inc(&fc->num_waiting); |
98 | BUG_ON(list_empty(&fc->unused_list)); | ||
99 | req = list_entry(fc->unused_list.next, struct fuse_req, list); | ||
100 | list_del_init(&req->list); | ||
101 | spin_unlock(&fc->lock); | ||
102 | fuse_request_init(req); | 98 | fuse_request_init(req); |
103 | req->preallocated = 1; | ||
104 | req->in.h.uid = current->fsuid; | 99 | req->in.h.uid = current->fsuid; |
105 | req->in.h.gid = current->fsgid; | 100 | req->in.h.gid = current->fsgid; |
106 | req->in.h.pid = current->pid; | 101 | req->in.h.pid = current->pid; |
107 | return req; | 102 | return req; |
108 | } | 103 | } |
109 | 104 | ||
110 | /* This can return NULL, but only in case it's interrupted by a SIGKILL */ | ||
111 | struct fuse_req *fuse_get_request(struct fuse_conn *fc) | ||
112 | { | ||
113 | int intr; | ||
114 | sigset_t oldset; | ||
115 | |||
116 | atomic_inc(&fc->num_waiting); | ||
117 | block_sigs(&oldset); | ||
118 | intr = down_interruptible(&fc->outstanding_sem); | ||
119 | restore_sigs(&oldset); | ||
120 | if (intr) { | ||
121 | atomic_dec(&fc->num_waiting); | ||
122 | return NULL; | ||
123 | } | ||
124 | return do_get_request(fc); | ||
125 | } | ||
126 | |||
127 | /* Must be called with fc->lock held */ | ||
128 | static void fuse_putback_request(struct fuse_conn *fc, struct fuse_req *req) | ||
129 | { | ||
130 | if (req->preallocated) { | ||
131 | atomic_dec(&fc->num_waiting); | ||
132 | list_add(&req->list, &fc->unused_list); | ||
133 | } else | ||
134 | fuse_request_free(req); | ||
135 | |||
136 | /* If we are in debt decrease that first */ | ||
137 | if (fc->outstanding_debt) | ||
138 | fc->outstanding_debt--; | ||
139 | else | ||
140 | up(&fc->outstanding_sem); | ||
141 | } | ||
142 | |||
143 | void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req) | 105 | void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req) |
144 | { | 106 | { |
145 | if (atomic_dec_and_test(&req->count)) { | 107 | if (atomic_dec_and_test(&req->count)) { |
146 | spin_lock(&fc->lock); | 108 | atomic_dec(&fc->num_waiting); |
147 | fuse_putback_request(fc, req); | 109 | fuse_request_free(req); |
148 | spin_unlock(&fc->lock); | ||
149 | } | 110 | } |
150 | } | 111 | } |
151 | 112 | ||
152 | static void fuse_put_request_locked(struct fuse_conn *fc, struct fuse_req *req) | ||
153 | { | ||
154 | if (atomic_dec_and_test(&req->count)) | ||
155 | fuse_putback_request(fc, req); | ||
156 | } | ||
157 | |||
158 | void fuse_release_background(struct fuse_conn *fc, struct fuse_req *req) | 113 | void fuse_release_background(struct fuse_conn *fc, struct fuse_req *req) |
159 | { | 114 | { |
160 | iput(req->inode); | 115 | iput(req->inode); |
@@ -189,9 +144,9 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req) | |||
189 | list_del(&req->list); | 144 | list_del(&req->list); |
190 | req->state = FUSE_REQ_FINISHED; | 145 | req->state = FUSE_REQ_FINISHED; |
191 | if (!req->background) { | 146 | if (!req->background) { |
192 | wake_up(&req->waitq); | ||
193 | fuse_put_request_locked(fc, req); | ||
194 | spin_unlock(&fc->lock); | 147 | spin_unlock(&fc->lock); |
148 | wake_up(&req->waitq); | ||
149 | fuse_put_request(fc, req); | ||
195 | } else { | 150 | } else { |
196 | void (*end) (struct fuse_conn *, struct fuse_req *) = req->end; | 151 | void (*end) (struct fuse_conn *, struct fuse_req *) = req->end; |
197 | req->end = NULL; | 152 | req->end = NULL; |
@@ -302,16 +257,6 @@ static void queue_request(struct fuse_conn *fc, struct fuse_req *req) | |||
302 | req->in.h.unique = fc->reqctr; | 257 | req->in.h.unique = fc->reqctr; |
303 | req->in.h.len = sizeof(struct fuse_in_header) + | 258 | req->in.h.len = sizeof(struct fuse_in_header) + |
304 | len_args(req->in.numargs, (struct fuse_arg *) req->in.args); | 259 | len_args(req->in.numargs, (struct fuse_arg *) req->in.args); |
305 | if (!req->preallocated) { | ||
306 | /* If request is not preallocated (either FORGET or | ||
307 | RELEASE), then still decrease outstanding_sem, so | ||
308 | user can't open infinite number of files while not | ||
309 | processing the RELEASE requests. However for | ||
310 | efficiency do it without blocking, so if down() | ||
311 | would block, just increase the debt instead */ | ||
312 | if (down_trylock(&fc->outstanding_sem)) | ||
313 | fc->outstanding_debt++; | ||
314 | } | ||
315 | list_add_tail(&req->list, &fc->pending); | 260 | list_add_tail(&req->list, &fc->pending); |
316 | req->state = FUSE_REQ_PENDING; | 261 | req->state = FUSE_REQ_PENDING; |
317 | wake_up(&fc->waitq); | 262 | wake_up(&fc->waitq); |
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 256355b80256..8d7546e832e8 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
@@ -117,8 +117,8 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd) | |||
117 | return 0; | 117 | return 0; |
118 | 118 | ||
119 | fc = get_fuse_conn(inode); | 119 | fc = get_fuse_conn(inode); |
120 | req = fuse_get_request(fc); | 120 | req = fuse_get_req(fc); |
121 | if (!req) | 121 | if (IS_ERR(req)) |
122 | return 0; | 122 | return 0; |
123 | 123 | ||
124 | fuse_lookup_init(req, entry->d_parent->d_inode, entry, &outarg); | 124 | fuse_lookup_init(req, entry->d_parent->d_inode, entry, &outarg); |
@@ -188,9 +188,9 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, | |||
188 | if (entry->d_name.len > FUSE_NAME_MAX) | 188 | if (entry->d_name.len > FUSE_NAME_MAX) |
189 | return ERR_PTR(-ENAMETOOLONG); | 189 | return ERR_PTR(-ENAMETOOLONG); |
190 | 190 | ||
191 | req = fuse_get_request(fc); | 191 | req = fuse_get_req(fc); |
192 | if (!req) | 192 | if (IS_ERR(req)) |
193 | return ERR_PTR(-EINTR); | 193 | return ERR_PTR(PTR_ERR(req)); |
194 | 194 | ||
195 | fuse_lookup_init(req, dir, entry, &outarg); | 195 | fuse_lookup_init(req, dir, entry, &outarg); |
196 | request_send(fc, req); | 196 | request_send(fc, req); |
@@ -244,15 +244,14 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode, | |||
244 | struct file *file; | 244 | struct file *file; |
245 | int flags = nd->intent.open.flags - 1; | 245 | int flags = nd->intent.open.flags - 1; |
246 | 246 | ||
247 | err = -ENOSYS; | ||
248 | if (fc->no_create) | 247 | if (fc->no_create) |
249 | goto out; | 248 | return -ENOSYS; |
250 | 249 | ||
251 | err = -EINTR; | 250 | req = fuse_get_req(fc); |
252 | req = fuse_get_request(fc); | 251 | if (IS_ERR(req)) |
253 | if (!req) | 252 | return PTR_ERR(req); |
254 | goto out; | ||
255 | 253 | ||
254 | err = -ENOMEM; | ||
256 | ff = fuse_file_alloc(); | 255 | ff = fuse_file_alloc(); |
257 | if (!ff) | 256 | if (!ff) |
258 | goto out_put_request; | 257 | goto out_put_request; |
@@ -314,7 +313,6 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode, | |||
314 | fuse_file_free(ff); | 313 | fuse_file_free(ff); |
315 | out_put_request: | 314 | out_put_request: |
316 | fuse_put_request(fc, req); | 315 | fuse_put_request(fc, req); |
317 | out: | ||
318 | return err; | 316 | return err; |
319 | } | 317 | } |
320 | 318 | ||
@@ -375,9 +373,9 @@ static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode, | |||
375 | { | 373 | { |
376 | struct fuse_mknod_in inarg; | 374 | struct fuse_mknod_in inarg; |
377 | struct fuse_conn *fc = get_fuse_conn(dir); | 375 | struct fuse_conn *fc = get_fuse_conn(dir); |
378 | struct fuse_req *req = fuse_get_request(fc); | 376 | struct fuse_req *req = fuse_get_req(fc); |
379 | if (!req) | 377 | if (IS_ERR(req)) |
380 | return -EINTR; | 378 | return PTR_ERR(req); |
381 | 379 | ||
382 | memset(&inarg, 0, sizeof(inarg)); | 380 | memset(&inarg, 0, sizeof(inarg)); |
383 | inarg.mode = mode; | 381 | inarg.mode = mode; |
@@ -407,9 +405,9 @@ static int fuse_mkdir(struct inode *dir, struct dentry *entry, int mode) | |||
407 | { | 405 | { |
408 | struct fuse_mkdir_in inarg; | 406 | struct fuse_mkdir_in inarg; |
409 | struct fuse_conn *fc = get_fuse_conn(dir); | 407 | struct fuse_conn *fc = get_fuse_conn(dir); |
410 | struct fuse_req *req = fuse_get_request(fc); | 408 | struct fuse_req *req = fuse_get_req(fc); |
411 | if (!req) | 409 | if (IS_ERR(req)) |
412 | return -EINTR; | 410 | return PTR_ERR(req); |
413 | 411 | ||
414 | memset(&inarg, 0, sizeof(inarg)); | 412 | memset(&inarg, 0, sizeof(inarg)); |
415 | inarg.mode = mode; | 413 | inarg.mode = mode; |
@@ -427,9 +425,9 @@ static int fuse_symlink(struct inode *dir, struct dentry *entry, | |||
427 | { | 425 | { |
428 | struct fuse_conn *fc = get_fuse_conn(dir); | 426 | struct fuse_conn *fc = get_fuse_conn(dir); |
429 | unsigned len = strlen(link) + 1; | 427 | unsigned len = strlen(link) + 1; |
430 | struct fuse_req *req = fuse_get_request(fc); | 428 | struct fuse_req *req = fuse_get_req(fc); |
431 | if (!req) | 429 | if (IS_ERR(req)) |
432 | return -EINTR; | 430 | return PTR_ERR(req); |
433 | 431 | ||
434 | req->in.h.opcode = FUSE_SYMLINK; | 432 | req->in.h.opcode = FUSE_SYMLINK; |
435 | req->in.numargs = 2; | 433 | req->in.numargs = 2; |
@@ -444,9 +442,9 @@ static int fuse_unlink(struct inode *dir, struct dentry *entry) | |||
444 | { | 442 | { |
445 | int err; | 443 | int err; |
446 | struct fuse_conn *fc = get_fuse_conn(dir); | 444 | struct fuse_conn *fc = get_fuse_conn(dir); |
447 | struct fuse_req *req = fuse_get_request(fc); | 445 | struct fuse_req *req = fuse_get_req(fc); |
448 | if (!req) | 446 | if (IS_ERR(req)) |
449 | return -EINTR; | 447 | return PTR_ERR(req); |
450 | 448 | ||
451 | req->in.h.opcode = FUSE_UNLINK; | 449 | req->in.h.opcode = FUSE_UNLINK; |
452 | req->in.h.nodeid = get_node_id(dir); | 450 | req->in.h.nodeid = get_node_id(dir); |
@@ -476,9 +474,9 @@ static int fuse_rmdir(struct inode *dir, struct dentry *entry) | |||
476 | { | 474 | { |
477 | int err; | 475 | int err; |
478 | struct fuse_conn *fc = get_fuse_conn(dir); | 476 | struct fuse_conn *fc = get_fuse_conn(dir); |
479 | struct fuse_req *req = fuse_get_request(fc); | 477 | struct fuse_req *req = fuse_get_req(fc); |
480 | if (!req) | 478 | if (IS_ERR(req)) |
481 | return -EINTR; | 479 | return PTR_ERR(req); |
482 | 480 | ||
483 | req->in.h.opcode = FUSE_RMDIR; | 481 | req->in.h.opcode = FUSE_RMDIR; |
484 | req->in.h.nodeid = get_node_id(dir); | 482 | req->in.h.nodeid = get_node_id(dir); |
@@ -504,9 +502,9 @@ static int fuse_rename(struct inode *olddir, struct dentry *oldent, | |||
504 | int err; | 502 | int err; |
505 | struct fuse_rename_in inarg; | 503 | struct fuse_rename_in inarg; |
506 | struct fuse_conn *fc = get_fuse_conn(olddir); | 504 | struct fuse_conn *fc = get_fuse_conn(olddir); |
507 | struct fuse_req *req = fuse_get_request(fc); | 505 | struct fuse_req *req = fuse_get_req(fc); |
508 | if (!req) | 506 | if (IS_ERR(req)) |
509 | return -EINTR; | 507 | return PTR_ERR(req); |
510 | 508 | ||
511 | memset(&inarg, 0, sizeof(inarg)); | 509 | memset(&inarg, 0, sizeof(inarg)); |
512 | inarg.newdir = get_node_id(newdir); | 510 | inarg.newdir = get_node_id(newdir); |
@@ -553,9 +551,9 @@ static int fuse_link(struct dentry *entry, struct inode *newdir, | |||
553 | struct fuse_link_in inarg; | 551 | struct fuse_link_in inarg; |
554 | struct inode *inode = entry->d_inode; | 552 | struct inode *inode = entry->d_inode; |
555 | struct fuse_conn *fc = get_fuse_conn(inode); | 553 | struct fuse_conn *fc = get_fuse_conn(inode); |
556 | struct fuse_req *req = fuse_get_request(fc); | 554 | struct fuse_req *req = fuse_get_req(fc); |
557 | if (!req) | 555 | if (IS_ERR(req)) |
558 | return -EINTR; | 556 | return PTR_ERR(req); |
559 | 557 | ||
560 | memset(&inarg, 0, sizeof(inarg)); | 558 | memset(&inarg, 0, sizeof(inarg)); |
561 | inarg.oldnodeid = get_node_id(inode); | 559 | inarg.oldnodeid = get_node_id(inode); |
@@ -583,9 +581,9 @@ int fuse_do_getattr(struct inode *inode) | |||
583 | int err; | 581 | int err; |
584 | struct fuse_attr_out arg; | 582 | struct fuse_attr_out arg; |
585 | struct fuse_conn *fc = get_fuse_conn(inode); | 583 | struct fuse_conn *fc = get_fuse_conn(inode); |
586 | struct fuse_req *req = fuse_get_request(fc); | 584 | struct fuse_req *req = fuse_get_req(fc); |
587 | if (!req) | 585 | if (IS_ERR(req)) |
588 | return -EINTR; | 586 | return PTR_ERR(req); |
589 | 587 | ||
590 | req->in.h.opcode = FUSE_GETATTR; | 588 | req->in.h.opcode = FUSE_GETATTR; |
591 | req->in.h.nodeid = get_node_id(inode); | 589 | req->in.h.nodeid = get_node_id(inode); |
@@ -673,9 +671,9 @@ static int fuse_access(struct inode *inode, int mask) | |||
673 | if (fc->no_access) | 671 | if (fc->no_access) |
674 | return 0; | 672 | return 0; |
675 | 673 | ||
676 | req = fuse_get_request(fc); | 674 | req = fuse_get_req(fc); |
677 | if (!req) | 675 | if (IS_ERR(req)) |
678 | return -EINTR; | 676 | return PTR_ERR(req); |
679 | 677 | ||
680 | memset(&inarg, 0, sizeof(inarg)); | 678 | memset(&inarg, 0, sizeof(inarg)); |
681 | inarg.mask = mask; | 679 | inarg.mask = mask; |
@@ -780,9 +778,9 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir) | |||
780 | if (is_bad_inode(inode)) | 778 | if (is_bad_inode(inode)) |
781 | return -EIO; | 779 | return -EIO; |
782 | 780 | ||
783 | req = fuse_get_request(fc); | 781 | req = fuse_get_req(fc); |
784 | if (!req) | 782 | if (IS_ERR(req)) |
785 | return -EINTR; | 783 | return PTR_ERR(req); |
786 | 784 | ||
787 | page = alloc_page(GFP_KERNEL); | 785 | page = alloc_page(GFP_KERNEL); |
788 | if (!page) { | 786 | if (!page) { |
@@ -809,11 +807,11 @@ static char *read_link(struct dentry *dentry) | |||
809 | { | 807 | { |
810 | struct inode *inode = dentry->d_inode; | 808 | struct inode *inode = dentry->d_inode; |
811 | struct fuse_conn *fc = get_fuse_conn(inode); | 809 | struct fuse_conn *fc = get_fuse_conn(inode); |
812 | struct fuse_req *req = fuse_get_request(fc); | 810 | struct fuse_req *req = fuse_get_req(fc); |
813 | char *link; | 811 | char *link; |
814 | 812 | ||
815 | if (!req) | 813 | if (IS_ERR(req)) |
816 | return ERR_PTR(-EINTR); | 814 | return ERR_PTR(PTR_ERR(req)); |
817 | 815 | ||
818 | link = (char *) __get_free_page(GFP_KERNEL); | 816 | link = (char *) __get_free_page(GFP_KERNEL); |
819 | if (!link) { | 817 | if (!link) { |
@@ -933,9 +931,9 @@ static int fuse_setattr(struct dentry *entry, struct iattr *attr) | |||
933 | } | 931 | } |
934 | } | 932 | } |
935 | 933 | ||
936 | req = fuse_get_request(fc); | 934 | req = fuse_get_req(fc); |
937 | if (!req) | 935 | if (IS_ERR(req)) |
938 | return -EINTR; | 936 | return PTR_ERR(req); |
939 | 937 | ||
940 | memset(&inarg, 0, sizeof(inarg)); | 938 | memset(&inarg, 0, sizeof(inarg)); |
941 | iattr_to_fattr(attr, &inarg); | 939 | iattr_to_fattr(attr, &inarg); |
@@ -995,9 +993,9 @@ static int fuse_setxattr(struct dentry *entry, const char *name, | |||
995 | if (fc->no_setxattr) | 993 | if (fc->no_setxattr) |
996 | return -EOPNOTSUPP; | 994 | return -EOPNOTSUPP; |
997 | 995 | ||
998 | req = fuse_get_request(fc); | 996 | req = fuse_get_req(fc); |
999 | if (!req) | 997 | if (IS_ERR(req)) |
1000 | return -EINTR; | 998 | return PTR_ERR(req); |
1001 | 999 | ||
1002 | memset(&inarg, 0, sizeof(inarg)); | 1000 | memset(&inarg, 0, sizeof(inarg)); |
1003 | inarg.size = size; | 1001 | inarg.size = size; |
@@ -1035,9 +1033,9 @@ static ssize_t fuse_getxattr(struct dentry *entry, const char *name, | |||
1035 | if (fc->no_getxattr) | 1033 | if (fc->no_getxattr) |
1036 | return -EOPNOTSUPP; | 1034 | return -EOPNOTSUPP; |
1037 | 1035 | ||
1038 | req = fuse_get_request(fc); | 1036 | req = fuse_get_req(fc); |
1039 | if (!req) | 1037 | if (IS_ERR(req)) |
1040 | return -EINTR; | 1038 | return PTR_ERR(req); |
1041 | 1039 | ||
1042 | memset(&inarg, 0, sizeof(inarg)); | 1040 | memset(&inarg, 0, sizeof(inarg)); |
1043 | inarg.size = size; | 1041 | inarg.size = size; |
@@ -1085,9 +1083,9 @@ static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size) | |||
1085 | if (fc->no_listxattr) | 1083 | if (fc->no_listxattr) |
1086 | return -EOPNOTSUPP; | 1084 | return -EOPNOTSUPP; |
1087 | 1085 | ||
1088 | req = fuse_get_request(fc); | 1086 | req = fuse_get_req(fc); |
1089 | if (!req) | 1087 | if (IS_ERR(req)) |
1090 | return -EINTR; | 1088 | return PTR_ERR(req); |
1091 | 1089 | ||
1092 | memset(&inarg, 0, sizeof(inarg)); | 1090 | memset(&inarg, 0, sizeof(inarg)); |
1093 | inarg.size = size; | 1091 | inarg.size = size; |
@@ -1131,9 +1129,9 @@ static int fuse_removexattr(struct dentry *entry, const char *name) | |||
1131 | if (fc->no_removexattr) | 1129 | if (fc->no_removexattr) |
1132 | return -EOPNOTSUPP; | 1130 | return -EOPNOTSUPP; |
1133 | 1131 | ||
1134 | req = fuse_get_request(fc); | 1132 | req = fuse_get_req(fc); |
1135 | if (!req) | 1133 | if (IS_ERR(req)) |
1136 | return -EINTR; | 1134 | return PTR_ERR(req); |
1137 | 1135 | ||
1138 | req->in.h.opcode = FUSE_REMOVEXATTR; | 1136 | req->in.h.opcode = FUSE_REMOVEXATTR; |
1139 | req->in.h.nodeid = get_node_id(inode); | 1137 | req->in.h.nodeid = get_node_id(inode); |
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 3ac39c0288de..e4f041a11bb5 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -22,9 +22,9 @@ static int fuse_send_open(struct inode *inode, struct file *file, int isdir, | |||
22 | struct fuse_req *req; | 22 | struct fuse_req *req; |
23 | int err; | 23 | int err; |
24 | 24 | ||
25 | req = fuse_get_request(fc); | 25 | req = fuse_get_req(fc); |
26 | if (!req) | 26 | if (IS_ERR(req)) |
27 | return -EINTR; | 27 | return PTR_ERR(req); |
28 | 28 | ||
29 | memset(&inarg, 0, sizeof(inarg)); | 29 | memset(&inarg, 0, sizeof(inarg)); |
30 | inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC); | 30 | inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC); |
@@ -184,9 +184,9 @@ static int fuse_flush(struct file *file) | |||
184 | if (fc->no_flush) | 184 | if (fc->no_flush) |
185 | return 0; | 185 | return 0; |
186 | 186 | ||
187 | req = fuse_get_request(fc); | 187 | req = fuse_get_req(fc); |
188 | if (!req) | 188 | if (IS_ERR(req)) |
189 | return -EINTR; | 189 | return PTR_ERR(req); |
190 | 190 | ||
191 | memset(&inarg, 0, sizeof(inarg)); | 191 | memset(&inarg, 0, sizeof(inarg)); |
192 | inarg.fh = ff->fh; | 192 | inarg.fh = ff->fh; |
@@ -223,9 +223,9 @@ int fuse_fsync_common(struct file *file, struct dentry *de, int datasync, | |||
223 | if ((!isdir && fc->no_fsync) || (isdir && fc->no_fsyncdir)) | 223 | if ((!isdir && fc->no_fsync) || (isdir && fc->no_fsyncdir)) |
224 | return 0; | 224 | return 0; |
225 | 225 | ||
226 | req = fuse_get_request(fc); | 226 | req = fuse_get_req(fc); |
227 | if (!req) | 227 | if (IS_ERR(req)) |
228 | return -EINTR; | 228 | return PTR_ERR(req); |
229 | 229 | ||
230 | memset(&inarg, 0, sizeof(inarg)); | 230 | memset(&inarg, 0, sizeof(inarg)); |
231 | inarg.fh = ff->fh; | 231 | inarg.fh = ff->fh; |
@@ -297,9 +297,9 @@ static int fuse_readpage(struct file *file, struct page *page) | |||
297 | if (is_bad_inode(inode)) | 297 | if (is_bad_inode(inode)) |
298 | goto out; | 298 | goto out; |
299 | 299 | ||
300 | err = -EINTR; | 300 | req = fuse_get_req(fc); |
301 | req = fuse_get_request(fc); | 301 | err = PTR_ERR(req); |
302 | if (!req) | 302 | if (IS_ERR(req)) |
303 | goto out; | 303 | goto out; |
304 | 304 | ||
305 | req->out.page_zeroing = 1; | 305 | req->out.page_zeroing = 1; |
@@ -368,10 +368,10 @@ static int fuse_readpages_fill(void *_data, struct page *page) | |||
368 | (req->num_pages + 1) * PAGE_CACHE_SIZE > fc->max_read || | 368 | (req->num_pages + 1) * PAGE_CACHE_SIZE > fc->max_read || |
369 | req->pages[req->num_pages - 1]->index + 1 != page->index)) { | 369 | req->pages[req->num_pages - 1]->index + 1 != page->index)) { |
370 | fuse_send_readpages(req, data->file, inode); | 370 | fuse_send_readpages(req, data->file, inode); |
371 | data->req = req = fuse_get_request(fc); | 371 | data->req = req = fuse_get_req(fc); |
372 | if (!req) { | 372 | if (IS_ERR(req)) { |
373 | unlock_page(page); | 373 | unlock_page(page); |
374 | return -EINTR; | 374 | return PTR_ERR(req); |
375 | } | 375 | } |
376 | } | 376 | } |
377 | req->pages[req->num_pages] = page; | 377 | req->pages[req->num_pages] = page; |
@@ -392,9 +392,9 @@ static int fuse_readpages(struct file *file, struct address_space *mapping, | |||
392 | 392 | ||
393 | data.file = file; | 393 | data.file = file; |
394 | data.inode = inode; | 394 | data.inode = inode; |
395 | data.req = fuse_get_request(fc); | 395 | data.req = fuse_get_req(fc); |
396 | if (!data.req) | 396 | if (IS_ERR(data.req)) |
397 | return -EINTR; | 397 | return PTR_ERR(data.req); |
398 | 398 | ||
399 | err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data); | 399 | err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data); |
400 | if (!err) { | 400 | if (!err) { |
@@ -455,9 +455,9 @@ static int fuse_commit_write(struct file *file, struct page *page, | |||
455 | if (is_bad_inode(inode)) | 455 | if (is_bad_inode(inode)) |
456 | return -EIO; | 456 | return -EIO; |
457 | 457 | ||
458 | req = fuse_get_request(fc); | 458 | req = fuse_get_req(fc); |
459 | if (!req) | 459 | if (IS_ERR(req)) |
460 | return -EINTR; | 460 | return PTR_ERR(req); |
461 | 461 | ||
462 | req->num_pages = 1; | 462 | req->num_pages = 1; |
463 | req->pages[0] = page; | 463 | req->pages[0] = page; |
@@ -532,9 +532,9 @@ static ssize_t fuse_direct_io(struct file *file, const char __user *buf, | |||
532 | if (is_bad_inode(inode)) | 532 | if (is_bad_inode(inode)) |
533 | return -EIO; | 533 | return -EIO; |
534 | 534 | ||
535 | req = fuse_get_request(fc); | 535 | req = fuse_get_req(fc); |
536 | if (!req) | 536 | if (IS_ERR(req)) |
537 | return -EINTR; | 537 | return PTR_ERR(req); |
538 | 538 | ||
539 | while (count) { | 539 | while (count) { |
540 | size_t nres; | 540 | size_t nres; |
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 6ed812fd6200..242e69cb1251 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h | |||
@@ -18,9 +18,6 @@ | |||
18 | /** Max number of pages that can be used in a single read request */ | 18 | /** Max number of pages that can be used in a single read request */ |
19 | #define FUSE_MAX_PAGES_PER_REQ 32 | 19 | #define FUSE_MAX_PAGES_PER_REQ 32 |
20 | 20 | ||
21 | /** If more requests are outstanding, then the operation will block */ | ||
22 | #define FUSE_MAX_OUTSTANDING 10 | ||
23 | |||
24 | /** It could be as large as PATH_MAX, but would that have any uses? */ | 21 | /** It could be as large as PATH_MAX, but would that have any uses? */ |
25 | #define FUSE_NAME_MAX 1024 | 22 | #define FUSE_NAME_MAX 1024 |
26 | 23 | ||
@@ -131,8 +128,8 @@ struct fuse_conn; | |||
131 | * A request to the client | 128 | * A request to the client |
132 | */ | 129 | */ |
133 | struct fuse_req { | 130 | struct fuse_req { |
134 | /** This can be on either unused_list, pending processing or | 131 | /** This can be on either pending processing or io lists in |
135 | io lists in fuse_conn */ | 132 | fuse_conn */ |
136 | struct list_head list; | 133 | struct list_head list; |
137 | 134 | ||
138 | /** Entry on the background list */ | 135 | /** Entry on the background list */ |
@@ -150,9 +147,6 @@ struct fuse_req { | |||
150 | /** True if the request has reply */ | 147 | /** True if the request has reply */ |
151 | unsigned isreply:1; | 148 | unsigned isreply:1; |
152 | 149 | ||
153 | /** The request is preallocated */ | ||
154 | unsigned preallocated:1; | ||
155 | |||
156 | /** The request was interrupted */ | 150 | /** The request was interrupted */ |
157 | unsigned interrupted:1; | 151 | unsigned interrupted:1; |
158 | 152 | ||
@@ -247,19 +241,9 @@ struct fuse_conn { | |||
247 | interrupted request) */ | 241 | interrupted request) */ |
248 | struct list_head background; | 242 | struct list_head background; |
249 | 243 | ||
250 | /** Controls the maximum number of outstanding requests */ | ||
251 | struct semaphore outstanding_sem; | ||
252 | |||
253 | /** This counts the number of outstanding requests if | ||
254 | outstanding_sem would go negative */ | ||
255 | unsigned outstanding_debt; | ||
256 | |||
257 | /** RW semaphore for exclusion with fuse_put_super() */ | 244 | /** RW semaphore for exclusion with fuse_put_super() */ |
258 | struct rw_semaphore sbput_sem; | 245 | struct rw_semaphore sbput_sem; |
259 | 246 | ||
260 | /** The list of unused requests */ | ||
261 | struct list_head unused_list; | ||
262 | |||
263 | /** The next unique request id */ | 247 | /** The next unique request id */ |
264 | u64 reqctr; | 248 | u64 reqctr; |
265 | 249 | ||
@@ -452,11 +436,11 @@ void fuse_reset_request(struct fuse_req *req); | |||
452 | /** | 436 | /** |
453 | * Reserve a preallocated request | 437 | * Reserve a preallocated request |
454 | */ | 438 | */ |
455 | struct fuse_req *fuse_get_request(struct fuse_conn *fc); | 439 | struct fuse_req *fuse_get_req(struct fuse_conn *fc); |
456 | 440 | ||
457 | /** | 441 | /** |
458 | * Decrement reference count of a request. If count goes to zero put | 442 | * Decrement reference count of a request. If count goes to zero free |
459 | * on unused list (preallocated) or free request (not preallocated). | 443 | * the request. |
460 | */ | 444 | */ |
461 | void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req); | 445 | void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req); |
462 | 446 | ||
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index cc58debeabd4..824ebbc428ed 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c | |||
@@ -243,9 +243,9 @@ static int fuse_statfs(struct super_block *sb, struct kstatfs *buf) | |||
243 | struct fuse_statfs_out outarg; | 243 | struct fuse_statfs_out outarg; |
244 | int err; | 244 | int err; |
245 | 245 | ||
246 | req = fuse_get_request(fc); | 246 | req = fuse_get_req(fc); |
247 | if (!req) | 247 | if (IS_ERR(req)) |
248 | return -EINTR; | 248 | return PTR_ERR(req); |
249 | 249 | ||
250 | memset(&outarg, 0, sizeof(outarg)); | 250 | memset(&outarg, 0, sizeof(outarg)); |
251 | req->in.numargs = 0; | 251 | req->in.numargs = 0; |
@@ -370,15 +370,7 @@ static int fuse_show_options(struct seq_file *m, struct vfsmount *mnt) | |||
370 | 370 | ||
371 | static void fuse_conn_release(struct kobject *kobj) | 371 | static void fuse_conn_release(struct kobject *kobj) |
372 | { | 372 | { |
373 | struct fuse_conn *fc = get_fuse_conn_kobj(kobj); | 373 | kfree(get_fuse_conn_kobj(kobj)); |
374 | |||
375 | while (!list_empty(&fc->unused_list)) { | ||
376 | struct fuse_req *req; | ||
377 | req = list_entry(fc->unused_list.next, struct fuse_req, list); | ||
378 | list_del(&req->list); | ||
379 | fuse_request_free(req); | ||
380 | } | ||
381 | kfree(fc); | ||
382 | } | 374 | } |
383 | 375 | ||
384 | static struct fuse_conn *new_conn(void) | 376 | static struct fuse_conn *new_conn(void) |
@@ -387,27 +379,16 @@ static struct fuse_conn *new_conn(void) | |||
387 | 379 | ||
388 | fc = kzalloc(sizeof(*fc), GFP_KERNEL); | 380 | fc = kzalloc(sizeof(*fc), GFP_KERNEL); |
389 | if (fc) { | 381 | if (fc) { |
390 | int i; | ||
391 | spin_lock_init(&fc->lock); | 382 | spin_lock_init(&fc->lock); |
392 | init_waitqueue_head(&fc->waitq); | 383 | init_waitqueue_head(&fc->waitq); |
393 | INIT_LIST_HEAD(&fc->pending); | 384 | INIT_LIST_HEAD(&fc->pending); |
394 | INIT_LIST_HEAD(&fc->processing); | 385 | INIT_LIST_HEAD(&fc->processing); |
395 | INIT_LIST_HEAD(&fc->io); | 386 | INIT_LIST_HEAD(&fc->io); |
396 | INIT_LIST_HEAD(&fc->unused_list); | ||
397 | INIT_LIST_HEAD(&fc->background); | 387 | INIT_LIST_HEAD(&fc->background); |
398 | sema_init(&fc->outstanding_sem, 1); /* One for INIT */ | ||
399 | init_rwsem(&fc->sbput_sem); | 388 | init_rwsem(&fc->sbput_sem); |
400 | kobj_set_kset_s(fc, connections_subsys); | 389 | kobj_set_kset_s(fc, connections_subsys); |
401 | kobject_init(&fc->kobj); | 390 | kobject_init(&fc->kobj); |
402 | atomic_set(&fc->num_waiting, 0); | 391 | atomic_set(&fc->num_waiting, 0); |
403 | for (i = 0; i < FUSE_MAX_OUTSTANDING; i++) { | ||
404 | struct fuse_req *req = fuse_request_alloc(); | ||
405 | if (!req) { | ||
406 | kobject_put(&fc->kobj); | ||
407 | return NULL; | ||
408 | } | ||
409 | list_add(&req->list, &fc->unused_list); | ||
410 | } | ||
411 | fc->bdi.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE; | 392 | fc->bdi.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE; |
412 | fc->bdi.unplug_io_fn = default_unplug_io_fn; | 393 | fc->bdi.unplug_io_fn = default_unplug_io_fn; |
413 | fc->reqctr = 0; | 394 | fc->reqctr = 0; |
@@ -438,7 +419,6 @@ static struct super_operations fuse_super_operations = { | |||
438 | 419 | ||
439 | static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req) | 420 | static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req) |
440 | { | 421 | { |
441 | int i; | ||
442 | struct fuse_init_out *arg = &req->misc.init_out; | 422 | struct fuse_init_out *arg = &req->misc.init_out; |
443 | 423 | ||
444 | if (req->out.h.error || arg->major != FUSE_KERNEL_VERSION) | 424 | if (req->out.h.error || arg->major != FUSE_KERNEL_VERSION) |
@@ -457,22 +437,11 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req) | |||
457 | fc->minor = arg->minor; | 437 | fc->minor = arg->minor; |
458 | fc->max_write = arg->minor < 5 ? 4096 : arg->max_write; | 438 | fc->max_write = arg->minor < 5 ? 4096 : arg->max_write; |
459 | } | 439 | } |
460 | |||
461 | /* After INIT reply is received other requests can go | ||
462 | out. So do (FUSE_MAX_OUTSTANDING - 1) number of | ||
463 | up()s on outstanding_sem. The last up() is done in | ||
464 | fuse_putback_request() */ | ||
465 | for (i = 1; i < FUSE_MAX_OUTSTANDING; i++) | ||
466 | up(&fc->outstanding_sem); | ||
467 | |||
468 | fuse_put_request(fc, req); | 440 | fuse_put_request(fc, req); |
469 | } | 441 | } |
470 | 442 | ||
471 | static void fuse_send_init(struct fuse_conn *fc) | 443 | static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req) |
472 | { | 444 | { |
473 | /* This is called from fuse_read_super() so there's guaranteed | ||
474 | to be exactly one request available */ | ||
475 | struct fuse_req *req = fuse_get_request(fc); | ||
476 | struct fuse_init_in *arg = &req->misc.init_in; | 445 | struct fuse_init_in *arg = &req->misc.init_in; |
477 | 446 | ||
478 | arg->major = FUSE_KERNEL_VERSION; | 447 | arg->major = FUSE_KERNEL_VERSION; |
@@ -508,6 +477,7 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) | |||
508 | struct fuse_mount_data d; | 477 | struct fuse_mount_data d; |
509 | struct file *file; | 478 | struct file *file; |
510 | struct dentry *root_dentry; | 479 | struct dentry *root_dentry; |
480 | struct fuse_req *init_req; | ||
511 | int err; | 481 | int err; |
512 | 482 | ||
513 | if (!parse_fuse_opt((char *) data, &d)) | 483 | if (!parse_fuse_opt((char *) data, &d)) |
@@ -554,13 +524,17 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) | |||
554 | goto err; | 524 | goto err; |
555 | } | 525 | } |
556 | 526 | ||
527 | init_req = fuse_request_alloc(); | ||
528 | if (!init_req) | ||
529 | goto err_put_root; | ||
530 | |||
557 | err = kobject_set_name(&fc->kobj, "%llu", conn_id()); | 531 | err = kobject_set_name(&fc->kobj, "%llu", conn_id()); |
558 | if (err) | 532 | if (err) |
559 | goto err_put_root; | 533 | goto err_free_req; |
560 | 534 | ||
561 | err = kobject_add(&fc->kobj); | 535 | err = kobject_add(&fc->kobj); |
562 | if (err) | 536 | if (err) |
563 | goto err_put_root; | 537 | goto err_free_req; |
564 | 538 | ||
565 | sb->s_root = root_dentry; | 539 | sb->s_root = root_dentry; |
566 | fc->mounted = 1; | 540 | fc->mounted = 1; |
@@ -574,10 +548,12 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) | |||
574 | */ | 548 | */ |
575 | fput(file); | 549 | fput(file); |
576 | 550 | ||
577 | fuse_send_init(fc); | 551 | fuse_send_init(fc, init_req); |
578 | 552 | ||
579 | return 0; | 553 | return 0; |
580 | 554 | ||
555 | err_free_req: | ||
556 | fuse_request_free(init_req); | ||
581 | err_put_root: | 557 | err_put_root: |
582 | dput(root_dentry); | 558 | dput(root_dentry); |
583 | err: | 559 | err: |