diff options
Diffstat (limited to 'fs/fuse/file.c')
-rw-r--r-- | fs/fuse/file.c | 346 |
1 files changed, 201 insertions, 145 deletions
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 06f30e965676..fce6ce694fde 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -12,13 +12,13 @@ | |||
12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/sched.h> | 14 | #include <linux/sched.h> |
15 | #include <linux/module.h> | ||
15 | 16 | ||
16 | static const struct file_operations fuse_direct_io_file_operations; | 17 | static const struct file_operations fuse_direct_io_file_operations; |
17 | 18 | ||
18 | static int fuse_send_open(struct inode *inode, struct file *file, int isdir, | 19 | static int fuse_send_open(struct fuse_conn *fc, u64 nodeid, struct file *file, |
19 | struct fuse_open_out *outargp) | 20 | int opcode, struct fuse_open_out *outargp) |
20 | { | 21 | { |
21 | struct fuse_conn *fc = get_fuse_conn(inode); | ||
22 | struct fuse_open_in inarg; | 22 | struct fuse_open_in inarg; |
23 | struct fuse_req *req; | 23 | struct fuse_req *req; |
24 | int err; | 24 | int err; |
@@ -31,8 +31,8 @@ static int fuse_send_open(struct inode *inode, struct file *file, int isdir, | |||
31 | inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY); | 31 | inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY); |
32 | if (!fc->atomic_o_trunc) | 32 | if (!fc->atomic_o_trunc) |
33 | inarg.flags &= ~O_TRUNC; | 33 | inarg.flags &= ~O_TRUNC; |
34 | req->in.h.opcode = isdir ? FUSE_OPENDIR : FUSE_OPEN; | 34 | req->in.h.opcode = opcode; |
35 | req->in.h.nodeid = get_node_id(inode); | 35 | req->in.h.nodeid = nodeid; |
36 | req->in.numargs = 1; | 36 | req->in.numargs = 1; |
37 | req->in.args[0].size = sizeof(inarg); | 37 | req->in.args[0].size = sizeof(inarg); |
38 | req->in.args[0].value = &inarg; | 38 | req->in.args[0].value = &inarg; |
@@ -49,22 +49,27 @@ static int fuse_send_open(struct inode *inode, struct file *file, int isdir, | |||
49 | struct fuse_file *fuse_file_alloc(struct fuse_conn *fc) | 49 | struct fuse_file *fuse_file_alloc(struct fuse_conn *fc) |
50 | { | 50 | { |
51 | struct fuse_file *ff; | 51 | struct fuse_file *ff; |
52 | |||
52 | ff = kmalloc(sizeof(struct fuse_file), GFP_KERNEL); | 53 | ff = kmalloc(sizeof(struct fuse_file), GFP_KERNEL); |
53 | if (ff) { | 54 | if (unlikely(!ff)) |
54 | ff->reserved_req = fuse_request_alloc(); | 55 | return NULL; |
55 | if (!ff->reserved_req) { | 56 | |
56 | kfree(ff); | 57 | ff->fc = fc; |
57 | return NULL; | 58 | ff->reserved_req = fuse_request_alloc(); |
58 | } else { | 59 | if (unlikely(!ff->reserved_req)) { |
59 | INIT_LIST_HEAD(&ff->write_entry); | 60 | kfree(ff); |
60 | atomic_set(&ff->count, 0); | 61 | return NULL; |
61 | spin_lock(&fc->lock); | ||
62 | ff->kh = ++fc->khctr; | ||
63 | spin_unlock(&fc->lock); | ||
64 | } | ||
65 | RB_CLEAR_NODE(&ff->polled_node); | ||
66 | init_waitqueue_head(&ff->poll_wait); | ||
67 | } | 62 | } |
63 | |||
64 | INIT_LIST_HEAD(&ff->write_entry); | ||
65 | atomic_set(&ff->count, 0); | ||
66 | RB_CLEAR_NODE(&ff->polled_node); | ||
67 | init_waitqueue_head(&ff->poll_wait); | ||
68 | |||
69 | spin_lock(&fc->lock); | ||
70 | ff->kh = ++fc->khctr; | ||
71 | spin_unlock(&fc->lock); | ||
72 | |||
68 | return ff; | 73 | return ff; |
69 | } | 74 | } |
70 | 75 | ||
@@ -74,7 +79,7 @@ void fuse_file_free(struct fuse_file *ff) | |||
74 | kfree(ff); | 79 | kfree(ff); |
75 | } | 80 | } |
76 | 81 | ||
77 | static struct fuse_file *fuse_file_get(struct fuse_file *ff) | 82 | struct fuse_file *fuse_file_get(struct fuse_file *ff) |
78 | { | 83 | { |
79 | atomic_inc(&ff->count); | 84 | atomic_inc(&ff->count); |
80 | return ff; | 85 | return ff; |
@@ -82,40 +87,65 @@ static struct fuse_file *fuse_file_get(struct fuse_file *ff) | |||
82 | 87 | ||
83 | static void fuse_release_end(struct fuse_conn *fc, struct fuse_req *req) | 88 | static void fuse_release_end(struct fuse_conn *fc, struct fuse_req *req) |
84 | { | 89 | { |
85 | dput(req->misc.release.dentry); | 90 | path_put(&req->misc.release.path); |
86 | mntput(req->misc.release.vfsmount); | ||
87 | } | 91 | } |
88 | 92 | ||
89 | static void fuse_file_put(struct fuse_file *ff) | 93 | static void fuse_file_put(struct fuse_file *ff) |
90 | { | 94 | { |
91 | if (atomic_dec_and_test(&ff->count)) { | 95 | if (atomic_dec_and_test(&ff->count)) { |
92 | struct fuse_req *req = ff->reserved_req; | 96 | struct fuse_req *req = ff->reserved_req; |
93 | struct inode *inode = req->misc.release.dentry->d_inode; | 97 | |
94 | struct fuse_conn *fc = get_fuse_conn(inode); | ||
95 | req->end = fuse_release_end; | 98 | req->end = fuse_release_end; |
96 | fuse_request_send_background(fc, req); | 99 | fuse_request_send_background(ff->fc, req); |
97 | kfree(ff); | 100 | kfree(ff); |
98 | } | 101 | } |
99 | } | 102 | } |
100 | 103 | ||
101 | void fuse_finish_open(struct inode *inode, struct file *file, | 104 | int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file, |
102 | struct fuse_file *ff, struct fuse_open_out *outarg) | 105 | bool isdir) |
103 | { | 106 | { |
104 | if (outarg->open_flags & FOPEN_DIRECT_IO) | 107 | struct fuse_open_out outarg; |
108 | struct fuse_file *ff; | ||
109 | int err; | ||
110 | int opcode = isdir ? FUSE_OPENDIR : FUSE_OPEN; | ||
111 | |||
112 | ff = fuse_file_alloc(fc); | ||
113 | if (!ff) | ||
114 | return -ENOMEM; | ||
115 | |||
116 | err = fuse_send_open(fc, nodeid, file, opcode, &outarg); | ||
117 | if (err) { | ||
118 | fuse_file_free(ff); | ||
119 | return err; | ||
120 | } | ||
121 | |||
122 | if (isdir) | ||
123 | outarg.open_flags &= ~FOPEN_DIRECT_IO; | ||
124 | |||
125 | ff->fh = outarg.fh; | ||
126 | ff->nodeid = nodeid; | ||
127 | ff->open_flags = outarg.open_flags; | ||
128 | file->private_data = fuse_file_get(ff); | ||
129 | |||
130 | return 0; | ||
131 | } | ||
132 | EXPORT_SYMBOL_GPL(fuse_do_open); | ||
133 | |||
134 | void fuse_finish_open(struct inode *inode, struct file *file) | ||
135 | { | ||
136 | struct fuse_file *ff = file->private_data; | ||
137 | |||
138 | if (ff->open_flags & FOPEN_DIRECT_IO) | ||
105 | file->f_op = &fuse_direct_io_file_operations; | 139 | file->f_op = &fuse_direct_io_file_operations; |
106 | if (!(outarg->open_flags & FOPEN_KEEP_CACHE)) | 140 | if (!(ff->open_flags & FOPEN_KEEP_CACHE)) |
107 | invalidate_inode_pages2(inode->i_mapping); | 141 | invalidate_inode_pages2(inode->i_mapping); |
108 | if (outarg->open_flags & FOPEN_NONSEEKABLE) | 142 | if (ff->open_flags & FOPEN_NONSEEKABLE) |
109 | nonseekable_open(inode, file); | 143 | nonseekable_open(inode, file); |
110 | ff->fh = outarg->fh; | ||
111 | file->private_data = fuse_file_get(ff); | ||
112 | } | 144 | } |
113 | 145 | ||
114 | int fuse_open_common(struct inode *inode, struct file *file, int isdir) | 146 | int fuse_open_common(struct inode *inode, struct file *file, bool isdir) |
115 | { | 147 | { |
116 | struct fuse_conn *fc = get_fuse_conn(inode); | 148 | struct fuse_conn *fc = get_fuse_conn(inode); |
117 | struct fuse_open_out outarg; | ||
118 | struct fuse_file *ff; | ||
119 | int err; | 149 | int err; |
120 | 150 | ||
121 | /* VFS checks this, but only _after_ ->open() */ | 151 | /* VFS checks this, but only _after_ ->open() */ |
@@ -126,78 +156,85 @@ int fuse_open_common(struct inode *inode, struct file *file, int isdir) | |||
126 | if (err) | 156 | if (err) |
127 | return err; | 157 | return err; |
128 | 158 | ||
129 | ff = fuse_file_alloc(fc); | 159 | err = fuse_do_open(fc, get_node_id(inode), file, isdir); |
130 | if (!ff) | ||
131 | return -ENOMEM; | ||
132 | |||
133 | err = fuse_send_open(inode, file, isdir, &outarg); | ||
134 | if (err) | 160 | if (err) |
135 | fuse_file_free(ff); | 161 | return err; |
136 | else { | ||
137 | if (isdir) | ||
138 | outarg.open_flags &= ~FOPEN_DIRECT_IO; | ||
139 | fuse_finish_open(inode, file, ff, &outarg); | ||
140 | } | ||
141 | 162 | ||
142 | return err; | 163 | fuse_finish_open(inode, file); |
164 | |||
165 | return 0; | ||
143 | } | 166 | } |
144 | 167 | ||
145 | void fuse_release_fill(struct fuse_file *ff, u64 nodeid, int flags, int opcode) | 168 | static void fuse_prepare_release(struct fuse_file *ff, int flags, int opcode) |
146 | { | 169 | { |
170 | struct fuse_conn *fc = ff->fc; | ||
147 | struct fuse_req *req = ff->reserved_req; | 171 | struct fuse_req *req = ff->reserved_req; |
148 | struct fuse_release_in *inarg = &req->misc.release.in; | 172 | struct fuse_release_in *inarg = &req->misc.release.in; |
149 | 173 | ||
174 | spin_lock(&fc->lock); | ||
175 | list_del(&ff->write_entry); | ||
176 | if (!RB_EMPTY_NODE(&ff->polled_node)) | ||
177 | rb_erase(&ff->polled_node, &fc->polled_files); | ||
178 | spin_unlock(&fc->lock); | ||
179 | |||
180 | wake_up_interruptible_sync(&ff->poll_wait); | ||
181 | |||
150 | inarg->fh = ff->fh; | 182 | inarg->fh = ff->fh; |
151 | inarg->flags = flags; | 183 | inarg->flags = flags; |
152 | req->in.h.opcode = opcode; | 184 | req->in.h.opcode = opcode; |
153 | req->in.h.nodeid = nodeid; | 185 | req->in.h.nodeid = ff->nodeid; |
154 | req->in.numargs = 1; | 186 | req->in.numargs = 1; |
155 | req->in.args[0].size = sizeof(struct fuse_release_in); | 187 | req->in.args[0].size = sizeof(struct fuse_release_in); |
156 | req->in.args[0].value = inarg; | 188 | req->in.args[0].value = inarg; |
157 | } | 189 | } |
158 | 190 | ||
159 | int fuse_release_common(struct inode *inode, struct file *file, int isdir) | 191 | void fuse_release_common(struct file *file, int opcode) |
160 | { | 192 | { |
161 | struct fuse_file *ff = file->private_data; | 193 | struct fuse_file *ff; |
162 | if (ff) { | 194 | struct fuse_req *req; |
163 | struct fuse_conn *fc = get_fuse_conn(inode); | ||
164 | struct fuse_req *req = ff->reserved_req; | ||
165 | |||
166 | fuse_release_fill(ff, get_node_id(inode), file->f_flags, | ||
167 | isdir ? FUSE_RELEASEDIR : FUSE_RELEASE); | ||
168 | 195 | ||
169 | /* Hold vfsmount and dentry until release is finished */ | 196 | ff = file->private_data; |
170 | req->misc.release.vfsmount = mntget(file->f_path.mnt); | 197 | if (unlikely(!ff)) |
171 | req->misc.release.dentry = dget(file->f_path.dentry); | 198 | return; |
172 | 199 | ||
173 | spin_lock(&fc->lock); | 200 | req = ff->reserved_req; |
174 | list_del(&ff->write_entry); | 201 | fuse_prepare_release(ff, file->f_flags, opcode); |
175 | if (!RB_EMPTY_NODE(&ff->polled_node)) | ||
176 | rb_erase(&ff->polled_node, &fc->polled_files); | ||
177 | spin_unlock(&fc->lock); | ||
178 | 202 | ||
179 | wake_up_interruptible_sync(&ff->poll_wait); | 203 | /* Hold vfsmount and dentry until release is finished */ |
180 | /* | 204 | path_get(&file->f_path); |
181 | * Normally this will send the RELEASE request, | 205 | req->misc.release.path = file->f_path; |
182 | * however if some asynchronous READ or WRITE requests | ||
183 | * are outstanding, the sending will be delayed | ||
184 | */ | ||
185 | fuse_file_put(ff); | ||
186 | } | ||
187 | 206 | ||
188 | /* Return value is ignored by VFS */ | 207 | /* |
189 | return 0; | 208 | * Normally this will send the RELEASE request, however if |
209 | * some asynchronous READ or WRITE requests are outstanding, | ||
210 | * the sending will be delayed. | ||
211 | */ | ||
212 | fuse_file_put(ff); | ||
190 | } | 213 | } |
191 | 214 | ||
192 | static int fuse_open(struct inode *inode, struct file *file) | 215 | static int fuse_open(struct inode *inode, struct file *file) |
193 | { | 216 | { |
194 | return fuse_open_common(inode, file, 0); | 217 | return fuse_open_common(inode, file, false); |
195 | } | 218 | } |
196 | 219 | ||
197 | static int fuse_release(struct inode *inode, struct file *file) | 220 | static int fuse_release(struct inode *inode, struct file *file) |
198 | { | 221 | { |
199 | return fuse_release_common(inode, file, 0); | 222 | fuse_release_common(file, FUSE_RELEASE); |
223 | |||
224 | /* return value is ignored by VFS */ | ||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | void fuse_sync_release(struct fuse_file *ff, int flags) | ||
229 | { | ||
230 | WARN_ON(atomic_read(&ff->count) > 1); | ||
231 | fuse_prepare_release(ff, flags, FUSE_RELEASE); | ||
232 | ff->reserved_req->force = 1; | ||
233 | fuse_request_send(ff->fc, ff->reserved_req); | ||
234 | fuse_put_request(ff->fc, ff->reserved_req); | ||
235 | kfree(ff); | ||
200 | } | 236 | } |
237 | EXPORT_SYMBOL_GPL(fuse_sync_release); | ||
201 | 238 | ||
202 | /* | 239 | /* |
203 | * Scramble the ID space with XTEA, so that the value of the files_struct | 240 | * Scramble the ID space with XTEA, so that the value of the files_struct |
@@ -371,8 +408,8 @@ static int fuse_fsync(struct file *file, struct dentry *de, int datasync) | |||
371 | return fuse_fsync_common(file, de, datasync, 0); | 408 | return fuse_fsync_common(file, de, datasync, 0); |
372 | } | 409 | } |
373 | 410 | ||
374 | void fuse_read_fill(struct fuse_req *req, struct file *file, | 411 | void fuse_read_fill(struct fuse_req *req, struct file *file, loff_t pos, |
375 | struct inode *inode, loff_t pos, size_t count, int opcode) | 412 | size_t count, int opcode) |
376 | { | 413 | { |
377 | struct fuse_read_in *inarg = &req->misc.read.in; | 414 | struct fuse_read_in *inarg = &req->misc.read.in; |
378 | struct fuse_file *ff = file->private_data; | 415 | struct fuse_file *ff = file->private_data; |
@@ -382,7 +419,7 @@ void fuse_read_fill(struct fuse_req *req, struct file *file, | |||
382 | inarg->size = count; | 419 | inarg->size = count; |
383 | inarg->flags = file->f_flags; | 420 | inarg->flags = file->f_flags; |
384 | req->in.h.opcode = opcode; | 421 | req->in.h.opcode = opcode; |
385 | req->in.h.nodeid = get_node_id(inode); | 422 | req->in.h.nodeid = ff->nodeid; |
386 | req->in.numargs = 1; | 423 | req->in.numargs = 1; |
387 | req->in.args[0].size = sizeof(struct fuse_read_in); | 424 | req->in.args[0].size = sizeof(struct fuse_read_in); |
388 | req->in.args[0].value = inarg; | 425 | req->in.args[0].value = inarg; |
@@ -392,12 +429,12 @@ void fuse_read_fill(struct fuse_req *req, struct file *file, | |||
392 | } | 429 | } |
393 | 430 | ||
394 | static size_t fuse_send_read(struct fuse_req *req, struct file *file, | 431 | static size_t fuse_send_read(struct fuse_req *req, struct file *file, |
395 | struct inode *inode, loff_t pos, size_t count, | 432 | loff_t pos, size_t count, fl_owner_t owner) |
396 | fl_owner_t owner) | ||
397 | { | 433 | { |
398 | struct fuse_conn *fc = get_fuse_conn(inode); | 434 | struct fuse_file *ff = file->private_data; |
435 | struct fuse_conn *fc = ff->fc; | ||
399 | 436 | ||
400 | fuse_read_fill(req, file, inode, pos, count, FUSE_READ); | 437 | fuse_read_fill(req, file, pos, count, FUSE_READ); |
401 | if (owner != NULL) { | 438 | if (owner != NULL) { |
402 | struct fuse_read_in *inarg = &req->misc.read.in; | 439 | struct fuse_read_in *inarg = &req->misc.read.in; |
403 | 440 | ||
@@ -455,7 +492,7 @@ static int fuse_readpage(struct file *file, struct page *page) | |||
455 | req->out.argpages = 1; | 492 | req->out.argpages = 1; |
456 | req->num_pages = 1; | 493 | req->num_pages = 1; |
457 | req->pages[0] = page; | 494 | req->pages[0] = page; |
458 | num_read = fuse_send_read(req, file, inode, pos, count, NULL); | 495 | num_read = fuse_send_read(req, file, pos, count, NULL); |
459 | err = req->out.h.error; | 496 | err = req->out.h.error; |
460 | fuse_put_request(fc, req); | 497 | fuse_put_request(fc, req); |
461 | 498 | ||
@@ -504,19 +541,18 @@ static void fuse_readpages_end(struct fuse_conn *fc, struct fuse_req *req) | |||
504 | fuse_file_put(req->ff); | 541 | fuse_file_put(req->ff); |
505 | } | 542 | } |
506 | 543 | ||
507 | static void fuse_send_readpages(struct fuse_req *req, struct file *file, | 544 | static void fuse_send_readpages(struct fuse_req *req, struct file *file) |
508 | struct inode *inode) | ||
509 | { | 545 | { |
510 | struct fuse_conn *fc = get_fuse_conn(inode); | 546 | struct fuse_file *ff = file->private_data; |
547 | struct fuse_conn *fc = ff->fc; | ||
511 | loff_t pos = page_offset(req->pages[0]); | 548 | loff_t pos = page_offset(req->pages[0]); |
512 | size_t count = req->num_pages << PAGE_CACHE_SHIFT; | 549 | size_t count = req->num_pages << PAGE_CACHE_SHIFT; |
513 | 550 | ||
514 | req->out.argpages = 1; | 551 | req->out.argpages = 1; |
515 | req->out.page_zeroing = 1; | 552 | req->out.page_zeroing = 1; |
516 | fuse_read_fill(req, file, inode, pos, count, FUSE_READ); | 553 | fuse_read_fill(req, file, pos, count, FUSE_READ); |
517 | req->misc.read.attr_ver = fuse_get_attr_version(fc); | 554 | req->misc.read.attr_ver = fuse_get_attr_version(fc); |
518 | if (fc->async_read) { | 555 | if (fc->async_read) { |
519 | struct fuse_file *ff = file->private_data; | ||
520 | req->ff = fuse_file_get(ff); | 556 | req->ff = fuse_file_get(ff); |
521 | req->end = fuse_readpages_end; | 557 | req->end = fuse_readpages_end; |
522 | fuse_request_send_background(fc, req); | 558 | fuse_request_send_background(fc, req); |
@@ -546,7 +582,7 @@ static int fuse_readpages_fill(void *_data, struct page *page) | |||
546 | (req->num_pages == FUSE_MAX_PAGES_PER_REQ || | 582 | (req->num_pages == FUSE_MAX_PAGES_PER_REQ || |
547 | (req->num_pages + 1) * PAGE_CACHE_SIZE > fc->max_read || | 583 | (req->num_pages + 1) * PAGE_CACHE_SIZE > fc->max_read || |
548 | req->pages[req->num_pages - 1]->index + 1 != page->index)) { | 584 | req->pages[req->num_pages - 1]->index + 1 != page->index)) { |
549 | fuse_send_readpages(req, data->file, inode); | 585 | fuse_send_readpages(req, data->file); |
550 | data->req = req = fuse_get_req(fc); | 586 | data->req = req = fuse_get_req(fc); |
551 | if (IS_ERR(req)) { | 587 | if (IS_ERR(req)) { |
552 | unlock_page(page); | 588 | unlock_page(page); |
@@ -580,7 +616,7 @@ static int fuse_readpages(struct file *file, struct address_space *mapping, | |||
580 | err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data); | 616 | err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data); |
581 | if (!err) { | 617 | if (!err) { |
582 | if (data.req->num_pages) | 618 | if (data.req->num_pages) |
583 | fuse_send_readpages(data.req, file, inode); | 619 | fuse_send_readpages(data.req, file); |
584 | else | 620 | else |
585 | fuse_put_request(fc, data.req); | 621 | fuse_put_request(fc, data.req); |
586 | } | 622 | } |
@@ -607,24 +643,19 @@ static ssize_t fuse_file_aio_read(struct kiocb *iocb, const struct iovec *iov, | |||
607 | return generic_file_aio_read(iocb, iov, nr_segs, pos); | 643 | return generic_file_aio_read(iocb, iov, nr_segs, pos); |
608 | } | 644 | } |
609 | 645 | ||
610 | static void fuse_write_fill(struct fuse_req *req, struct file *file, | 646 | static void fuse_write_fill(struct fuse_req *req, struct fuse_file *ff, |
611 | struct fuse_file *ff, struct inode *inode, | 647 | loff_t pos, size_t count) |
612 | loff_t pos, size_t count, int writepage) | ||
613 | { | 648 | { |
614 | struct fuse_conn *fc = get_fuse_conn(inode); | ||
615 | struct fuse_write_in *inarg = &req->misc.write.in; | 649 | struct fuse_write_in *inarg = &req->misc.write.in; |
616 | struct fuse_write_out *outarg = &req->misc.write.out; | 650 | struct fuse_write_out *outarg = &req->misc.write.out; |
617 | 651 | ||
618 | memset(inarg, 0, sizeof(struct fuse_write_in)); | ||
619 | inarg->fh = ff->fh; | 652 | inarg->fh = ff->fh; |
620 | inarg->offset = pos; | 653 | inarg->offset = pos; |
621 | inarg->size = count; | 654 | inarg->size = count; |
622 | inarg->write_flags = writepage ? FUSE_WRITE_CACHE : 0; | ||
623 | inarg->flags = file ? file->f_flags : 0; | ||
624 | req->in.h.opcode = FUSE_WRITE; | 655 | req->in.h.opcode = FUSE_WRITE; |
625 | req->in.h.nodeid = get_node_id(inode); | 656 | req->in.h.nodeid = ff->nodeid; |
626 | req->in.numargs = 2; | 657 | req->in.numargs = 2; |
627 | if (fc->minor < 9) | 658 | if (ff->fc->minor < 9) |
628 | req->in.args[0].size = FUSE_COMPAT_WRITE_IN_SIZE; | 659 | req->in.args[0].size = FUSE_COMPAT_WRITE_IN_SIZE; |
629 | else | 660 | else |
630 | req->in.args[0].size = sizeof(struct fuse_write_in); | 661 | req->in.args[0].size = sizeof(struct fuse_write_in); |
@@ -636,13 +667,15 @@ static void fuse_write_fill(struct fuse_req *req, struct file *file, | |||
636 | } | 667 | } |
637 | 668 | ||
638 | static size_t fuse_send_write(struct fuse_req *req, struct file *file, | 669 | static size_t fuse_send_write(struct fuse_req *req, struct file *file, |
639 | struct inode *inode, loff_t pos, size_t count, | 670 | loff_t pos, size_t count, fl_owner_t owner) |
640 | fl_owner_t owner) | ||
641 | { | 671 | { |
642 | struct fuse_conn *fc = get_fuse_conn(inode); | 672 | struct fuse_file *ff = file->private_data; |
643 | fuse_write_fill(req, file, file->private_data, inode, pos, count, 0); | 673 | struct fuse_conn *fc = ff->fc; |
674 | struct fuse_write_in *inarg = &req->misc.write.in; | ||
675 | |||
676 | fuse_write_fill(req, ff, pos, count); | ||
677 | inarg->flags = file->f_flags; | ||
644 | if (owner != NULL) { | 678 | if (owner != NULL) { |
645 | struct fuse_write_in *inarg = &req->misc.write.in; | ||
646 | inarg->write_flags |= FUSE_WRITE_LOCKOWNER; | 679 | inarg->write_flags |= FUSE_WRITE_LOCKOWNER; |
647 | inarg->lock_owner = fuse_lock_owner_id(fc, owner); | 680 | inarg->lock_owner = fuse_lock_owner_id(fc, owner); |
648 | } | 681 | } |
@@ -700,7 +733,7 @@ static int fuse_buffered_write(struct file *file, struct inode *inode, | |||
700 | req->num_pages = 1; | 733 | req->num_pages = 1; |
701 | req->pages[0] = page; | 734 | req->pages[0] = page; |
702 | req->page_offset = offset; | 735 | req->page_offset = offset; |
703 | nres = fuse_send_write(req, file, inode, pos, count, NULL); | 736 | nres = fuse_send_write(req, file, pos, count, NULL); |
704 | err = req->out.h.error; | 737 | err = req->out.h.error; |
705 | fuse_put_request(fc, req); | 738 | fuse_put_request(fc, req); |
706 | if (!err && !nres) | 739 | if (!err && !nres) |
@@ -741,7 +774,7 @@ static size_t fuse_send_write_pages(struct fuse_req *req, struct file *file, | |||
741 | for (i = 0; i < req->num_pages; i++) | 774 | for (i = 0; i < req->num_pages; i++) |
742 | fuse_wait_on_page_writeback(inode, req->pages[i]->index); | 775 | fuse_wait_on_page_writeback(inode, req->pages[i]->index); |
743 | 776 | ||
744 | res = fuse_send_write(req, file, inode, pos, count, NULL); | 777 | res = fuse_send_write(req, file, pos, count, NULL); |
745 | 778 | ||
746 | offset = req->page_offset; | 779 | offset = req->page_offset; |
747 | count = res; | 780 | count = res; |
@@ -979,25 +1012,23 @@ static int fuse_get_user_pages(struct fuse_req *req, const char __user *buf, | |||
979 | return 0; | 1012 | return 0; |
980 | } | 1013 | } |
981 | 1014 | ||
982 | static ssize_t fuse_direct_io(struct file *file, const char __user *buf, | 1015 | ssize_t fuse_direct_io(struct file *file, const char __user *buf, |
983 | size_t count, loff_t *ppos, int write) | 1016 | size_t count, loff_t *ppos, int write) |
984 | { | 1017 | { |
985 | struct inode *inode = file->f_path.dentry->d_inode; | 1018 | struct fuse_file *ff = file->private_data; |
986 | struct fuse_conn *fc = get_fuse_conn(inode); | 1019 | struct fuse_conn *fc = ff->fc; |
987 | size_t nmax = write ? fc->max_write : fc->max_read; | 1020 | size_t nmax = write ? fc->max_write : fc->max_read; |
988 | loff_t pos = *ppos; | 1021 | loff_t pos = *ppos; |
989 | ssize_t res = 0; | 1022 | ssize_t res = 0; |
990 | struct fuse_req *req; | 1023 | struct fuse_req *req; |
991 | 1024 | ||
992 | if (is_bad_inode(inode)) | ||
993 | return -EIO; | ||
994 | |||
995 | req = fuse_get_req(fc); | 1025 | req = fuse_get_req(fc); |
996 | if (IS_ERR(req)) | 1026 | if (IS_ERR(req)) |
997 | return PTR_ERR(req); | 1027 | return PTR_ERR(req); |
998 | 1028 | ||
999 | while (count) { | 1029 | while (count) { |
1000 | size_t nres; | 1030 | size_t nres; |
1031 | fl_owner_t owner = current->files; | ||
1001 | size_t nbytes = min(count, nmax); | 1032 | size_t nbytes = min(count, nmax); |
1002 | int err = fuse_get_user_pages(req, buf, &nbytes, write); | 1033 | int err = fuse_get_user_pages(req, buf, &nbytes, write); |
1003 | if (err) { | 1034 | if (err) { |
@@ -1006,11 +1037,10 @@ static ssize_t fuse_direct_io(struct file *file, const char __user *buf, | |||
1006 | } | 1037 | } |
1007 | 1038 | ||
1008 | if (write) | 1039 | if (write) |
1009 | nres = fuse_send_write(req, file, inode, pos, nbytes, | 1040 | nres = fuse_send_write(req, file, pos, nbytes, owner); |
1010 | current->files); | ||
1011 | else | 1041 | else |
1012 | nres = fuse_send_read(req, file, inode, pos, nbytes, | 1042 | nres = fuse_send_read(req, file, pos, nbytes, owner); |
1013 | current->files); | 1043 | |
1014 | fuse_release_user_pages(req, !write); | 1044 | fuse_release_user_pages(req, !write); |
1015 | if (req->out.h.error) { | 1045 | if (req->out.h.error) { |
1016 | if (!res) | 1046 | if (!res) |
@@ -1034,20 +1064,27 @@ static ssize_t fuse_direct_io(struct file *file, const char __user *buf, | |||
1034 | } | 1064 | } |
1035 | } | 1065 | } |
1036 | fuse_put_request(fc, req); | 1066 | fuse_put_request(fc, req); |
1037 | if (res > 0) { | 1067 | if (res > 0) |
1038 | if (write) | ||
1039 | fuse_write_update_size(inode, pos); | ||
1040 | *ppos = pos; | 1068 | *ppos = pos; |
1041 | } | ||
1042 | fuse_invalidate_attr(inode); | ||
1043 | 1069 | ||
1044 | return res; | 1070 | return res; |
1045 | } | 1071 | } |
1072 | EXPORT_SYMBOL_GPL(fuse_direct_io); | ||
1046 | 1073 | ||
1047 | static ssize_t fuse_direct_read(struct file *file, char __user *buf, | 1074 | static ssize_t fuse_direct_read(struct file *file, char __user *buf, |
1048 | size_t count, loff_t *ppos) | 1075 | size_t count, loff_t *ppos) |
1049 | { | 1076 | { |
1050 | return fuse_direct_io(file, buf, count, ppos, 0); | 1077 | ssize_t res; |
1078 | struct inode *inode = file->f_path.dentry->d_inode; | ||
1079 | |||
1080 | if (is_bad_inode(inode)) | ||
1081 | return -EIO; | ||
1082 | |||
1083 | res = fuse_direct_io(file, buf, count, ppos, 0); | ||
1084 | |||
1085 | fuse_invalidate_attr(inode); | ||
1086 | |||
1087 | return res; | ||
1051 | } | 1088 | } |
1052 | 1089 | ||
1053 | static ssize_t fuse_direct_write(struct file *file, const char __user *buf, | 1090 | static ssize_t fuse_direct_write(struct file *file, const char __user *buf, |
@@ -1055,12 +1092,22 @@ static ssize_t fuse_direct_write(struct file *file, const char __user *buf, | |||
1055 | { | 1092 | { |
1056 | struct inode *inode = file->f_path.dentry->d_inode; | 1093 | struct inode *inode = file->f_path.dentry->d_inode; |
1057 | ssize_t res; | 1094 | ssize_t res; |
1095 | |||
1096 | if (is_bad_inode(inode)) | ||
1097 | return -EIO; | ||
1098 | |||
1058 | /* Don't allow parallel writes to the same file */ | 1099 | /* Don't allow parallel writes to the same file */ |
1059 | mutex_lock(&inode->i_mutex); | 1100 | mutex_lock(&inode->i_mutex); |
1060 | res = generic_write_checks(file, ppos, &count, 0); | 1101 | res = generic_write_checks(file, ppos, &count, 0); |
1061 | if (!res) | 1102 | if (!res) { |
1062 | res = fuse_direct_io(file, buf, count, ppos, 1); | 1103 | res = fuse_direct_io(file, buf, count, ppos, 1); |
1104 | if (res > 0) | ||
1105 | fuse_write_update_size(inode, *ppos); | ||
1106 | } | ||
1063 | mutex_unlock(&inode->i_mutex); | 1107 | mutex_unlock(&inode->i_mutex); |
1108 | |||
1109 | fuse_invalidate_attr(inode); | ||
1110 | |||
1064 | return res; | 1111 | return res; |
1065 | } | 1112 | } |
1066 | 1113 | ||
@@ -1177,9 +1224,10 @@ static int fuse_writepage_locked(struct page *page) | |||
1177 | req->ff = fuse_file_get(ff); | 1224 | req->ff = fuse_file_get(ff); |
1178 | spin_unlock(&fc->lock); | 1225 | spin_unlock(&fc->lock); |
1179 | 1226 | ||
1180 | fuse_write_fill(req, NULL, ff, inode, page_offset(page), 0, 1); | 1227 | fuse_write_fill(req, ff, page_offset(page), 0); |
1181 | 1228 | ||
1182 | copy_highpage(tmp_page, page); | 1229 | copy_highpage(tmp_page, page); |
1230 | req->misc.write.in.write_flags |= FUSE_WRITE_CACHE; | ||
1183 | req->in.argpages = 1; | 1231 | req->in.argpages = 1; |
1184 | req->num_pages = 1; | 1232 | req->num_pages = 1; |
1185 | req->pages[0] = tmp_page; | 1233 | req->pages[0] = tmp_page; |
@@ -1603,12 +1651,11 @@ static int fuse_ioctl_copy_user(struct page **pages, struct iovec *iov, | |||
1603 | * limits ioctl data transfers to well-formed ioctls and is the forced | 1651 | * limits ioctl data transfers to well-formed ioctls and is the forced |
1604 | * behavior for all FUSE servers. | 1652 | * behavior for all FUSE servers. |
1605 | */ | 1653 | */ |
1606 | static long fuse_file_do_ioctl(struct file *file, unsigned int cmd, | 1654 | long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg, |
1607 | unsigned long arg, unsigned int flags) | 1655 | unsigned int flags) |
1608 | { | 1656 | { |
1609 | struct inode *inode = file->f_dentry->d_inode; | ||
1610 | struct fuse_file *ff = file->private_data; | 1657 | struct fuse_file *ff = file->private_data; |
1611 | struct fuse_conn *fc = get_fuse_conn(inode); | 1658 | struct fuse_conn *fc = ff->fc; |
1612 | struct fuse_ioctl_in inarg = { | 1659 | struct fuse_ioctl_in inarg = { |
1613 | .fh = ff->fh, | 1660 | .fh = ff->fh, |
1614 | .cmd = cmd, | 1661 | .cmd = cmd, |
@@ -1627,13 +1674,6 @@ static long fuse_file_do_ioctl(struct file *file, unsigned int cmd, | |||
1627 | /* assume all the iovs returned by client always fits in a page */ | 1674 | /* assume all the iovs returned by client always fits in a page */ |
1628 | BUILD_BUG_ON(sizeof(struct iovec) * FUSE_IOCTL_MAX_IOV > PAGE_SIZE); | 1675 | BUILD_BUG_ON(sizeof(struct iovec) * FUSE_IOCTL_MAX_IOV > PAGE_SIZE); |
1629 | 1676 | ||
1630 | if (!fuse_allow_task(fc, current)) | ||
1631 | return -EACCES; | ||
1632 | |||
1633 | err = -EIO; | ||
1634 | if (is_bad_inode(inode)) | ||
1635 | goto out; | ||
1636 | |||
1637 | err = -ENOMEM; | 1677 | err = -ENOMEM; |
1638 | pages = kzalloc(sizeof(pages[0]) * FUSE_MAX_PAGES_PER_REQ, GFP_KERNEL); | 1678 | pages = kzalloc(sizeof(pages[0]) * FUSE_MAX_PAGES_PER_REQ, GFP_KERNEL); |
1639 | iov_page = alloc_page(GFP_KERNEL); | 1679 | iov_page = alloc_page(GFP_KERNEL); |
@@ -1694,7 +1734,7 @@ static long fuse_file_do_ioctl(struct file *file, unsigned int cmd, | |||
1694 | 1734 | ||
1695 | /* okay, let's send it to the client */ | 1735 | /* okay, let's send it to the client */ |
1696 | req->in.h.opcode = FUSE_IOCTL; | 1736 | req->in.h.opcode = FUSE_IOCTL; |
1697 | req->in.h.nodeid = get_node_id(inode); | 1737 | req->in.h.nodeid = ff->nodeid; |
1698 | req->in.numargs = 1; | 1738 | req->in.numargs = 1; |
1699 | req->in.args[0].size = sizeof(inarg); | 1739 | req->in.args[0].size = sizeof(inarg); |
1700 | req->in.args[0].value = &inarg; | 1740 | req->in.args[0].value = &inarg; |
@@ -1777,17 +1817,33 @@ static long fuse_file_do_ioctl(struct file *file, unsigned int cmd, | |||
1777 | 1817 | ||
1778 | return err ? err : outarg.result; | 1818 | return err ? err : outarg.result; |
1779 | } | 1819 | } |
1820 | EXPORT_SYMBOL_GPL(fuse_do_ioctl); | ||
1821 | |||
1822 | static long fuse_file_ioctl_common(struct file *file, unsigned int cmd, | ||
1823 | unsigned long arg, unsigned int flags) | ||
1824 | { | ||
1825 | struct inode *inode = file->f_dentry->d_inode; | ||
1826 | struct fuse_conn *fc = get_fuse_conn(inode); | ||
1827 | |||
1828 | if (!fuse_allow_task(fc, current)) | ||
1829 | return -EACCES; | ||
1830 | |||
1831 | if (is_bad_inode(inode)) | ||
1832 | return -EIO; | ||
1833 | |||
1834 | return fuse_do_ioctl(file, cmd, arg, flags); | ||
1835 | } | ||
1780 | 1836 | ||
1781 | static long fuse_file_ioctl(struct file *file, unsigned int cmd, | 1837 | static long fuse_file_ioctl(struct file *file, unsigned int cmd, |
1782 | unsigned long arg) | 1838 | unsigned long arg) |
1783 | { | 1839 | { |
1784 | return fuse_file_do_ioctl(file, cmd, arg, 0); | 1840 | return fuse_file_ioctl_common(file, cmd, arg, 0); |
1785 | } | 1841 | } |
1786 | 1842 | ||
1787 | static long fuse_file_compat_ioctl(struct file *file, unsigned int cmd, | 1843 | static long fuse_file_compat_ioctl(struct file *file, unsigned int cmd, |
1788 | unsigned long arg) | 1844 | unsigned long arg) |
1789 | { | 1845 | { |
1790 | return fuse_file_do_ioctl(file, cmd, arg, FUSE_IOCTL_COMPAT); | 1846 | return fuse_file_ioctl_common(file, cmd, arg, FUSE_IOCTL_COMPAT); |
1791 | } | 1847 | } |
1792 | 1848 | ||
1793 | /* | 1849 | /* |
@@ -1841,11 +1897,10 @@ static void fuse_register_polled_file(struct fuse_conn *fc, | |||
1841 | spin_unlock(&fc->lock); | 1897 | spin_unlock(&fc->lock); |
1842 | } | 1898 | } |
1843 | 1899 | ||
1844 | static unsigned fuse_file_poll(struct file *file, poll_table *wait) | 1900 | unsigned fuse_file_poll(struct file *file, poll_table *wait) |
1845 | { | 1901 | { |
1846 | struct inode *inode = file->f_dentry->d_inode; | ||
1847 | struct fuse_file *ff = file->private_data; | 1902 | struct fuse_file *ff = file->private_data; |
1848 | struct fuse_conn *fc = get_fuse_conn(inode); | 1903 | struct fuse_conn *fc = ff->fc; |
1849 | struct fuse_poll_in inarg = { .fh = ff->fh, .kh = ff->kh }; | 1904 | struct fuse_poll_in inarg = { .fh = ff->fh, .kh = ff->kh }; |
1850 | struct fuse_poll_out outarg; | 1905 | struct fuse_poll_out outarg; |
1851 | struct fuse_req *req; | 1906 | struct fuse_req *req; |
@@ -1870,7 +1925,7 @@ static unsigned fuse_file_poll(struct file *file, poll_table *wait) | |||
1870 | return PTR_ERR(req); | 1925 | return PTR_ERR(req); |
1871 | 1926 | ||
1872 | req->in.h.opcode = FUSE_POLL; | 1927 | req->in.h.opcode = FUSE_POLL; |
1873 | req->in.h.nodeid = get_node_id(inode); | 1928 | req->in.h.nodeid = ff->nodeid; |
1874 | req->in.numargs = 1; | 1929 | req->in.numargs = 1; |
1875 | req->in.args[0].size = sizeof(inarg); | 1930 | req->in.args[0].size = sizeof(inarg); |
1876 | req->in.args[0].value = &inarg; | 1931 | req->in.args[0].value = &inarg; |
@@ -1889,6 +1944,7 @@ static unsigned fuse_file_poll(struct file *file, poll_table *wait) | |||
1889 | } | 1944 | } |
1890 | return POLLERR; | 1945 | return POLLERR; |
1891 | } | 1946 | } |
1947 | EXPORT_SYMBOL_GPL(fuse_file_poll); | ||
1892 | 1948 | ||
1893 | /* | 1949 | /* |
1894 | * This is called from fuse_handle_notify() on FUSE_NOTIFY_POLL and | 1950 | * This is called from fuse_handle_notify() on FUSE_NOTIFY_POLL and |