aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/fuse/dev.c9
-rw-r--r--fs/fuse/dir.c84
-rw-r--r--fs/fuse/file.c38
-rw-r--r--fs/fuse/fuse_i.h22
-rw-r--r--include/linux/fuse.h10
5 files changed, 73 insertions, 90 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index ca6fc0e96d7c..e4ada021d087 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -731,13 +731,6 @@ static struct fuse_req *request_find(struct fuse_conn *fc, u64 unique)
731 return NULL; 731 return NULL;
732} 732}
733 733
734/* fget() needs to be done in this context */
735static void process_getdir(struct fuse_req *req)
736{
737 struct fuse_getdir_out_i *arg = req->out.args[0].value;
738 arg->file = fget(arg->fd);
739}
740
741static int copy_out_args(struct fuse_copy_state *cs, struct fuse_out *out, 734static int copy_out_args(struct fuse_copy_state *cs, struct fuse_out *out,
742 unsigned nbytes) 735 unsigned nbytes)
743{ 736{
@@ -817,8 +810,6 @@ static ssize_t fuse_dev_writev(struct file *file, const struct iovec *iov,
817 if (!err) { 810 if (!err) {
818 if (req->interrupted) 811 if (req->interrupted)
819 err = -ENOENT; 812 err = -ENOENT;
820 else if (req->in.h.opcode == FUSE_GETDIR && !oh.error)
821 process_getdir(req);
822 } else if (!req->interrupted) 813 } else if (!req->interrupted)
823 req->out.h.error = -EIO; 814 req->out.h.error = -EIO;
824 request_end(fc, req); 815 request_end(fc, req);
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 65da6e1b6de5..cf5d1faed7af 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -519,70 +519,40 @@ static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
519 return 0; 519 return 0;
520} 520}
521 521
522static int fuse_checkdir(struct file *cfile, struct file *file) 522static inline size_t fuse_send_readdir(struct fuse_req *req, struct file *file,
523 struct inode *inode, loff_t pos,
524 size_t count)
523{ 525{
524 struct inode *inode; 526 return fuse_send_read_common(req, file, inode, pos, count, 1);
525 if (!cfile)
526 return -EIO;
527 inode = cfile->f_dentry->d_inode;
528 if (!S_ISREG(inode->i_mode)) {
529 fput(cfile);
530 return -EIO;
531 }
532
533 file->private_data = cfile;
534 return 0;
535} 527}
536 528
537static int fuse_getdir(struct file *file) 529static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
538{ 530{
531 int err;
532 size_t nbytes;
533 struct page *page;
539 struct inode *inode = file->f_dentry->d_inode; 534 struct inode *inode = file->f_dentry->d_inode;
540 struct fuse_conn *fc = get_fuse_conn(inode); 535 struct fuse_conn *fc = get_fuse_conn(inode);
541 struct fuse_req *req = fuse_get_request(fc); 536 struct fuse_req *req = fuse_get_request_nonint(fc);
542 struct fuse_getdir_out_i outarg;
543 int err;
544
545 if (!req) 537 if (!req)
546 return -ERESTARTNOINTR; 538 return -EINTR;
547 539
548 req->in.h.opcode = FUSE_GETDIR; 540 page = alloc_page(GFP_KERNEL);
549 req->in.h.nodeid = get_node_id(inode); 541 if (!page) {
550 req->inode = inode; 542 fuse_put_request(fc, req);
551 req->out.numargs = 1; 543 return -ENOMEM;
552 req->out.args[0].size = sizeof(struct fuse_getdir_out); 544 }
553 req->out.args[0].value = &outarg; 545 req->num_pages = 1;
554 request_send(fc, req); 546 req->pages[0] = page;
547 nbytes = fuse_send_readdir(req, file, inode, file->f_pos, PAGE_SIZE);
555 err = req->out.h.error; 548 err = req->out.h.error;
556 fuse_put_request(fc, req); 549 fuse_put_request(fc, req);
557 if (!err) 550 if (!err)
558 err = fuse_checkdir(outarg.file, file); 551 err = parse_dirfile(page_address(page), nbytes, file, dstbuf,
559 return err; 552 filldir);
560}
561
562static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
563{
564 struct file *cfile = file->private_data;
565 char *buf;
566 int ret;
567
568 if (!cfile) {
569 ret = fuse_getdir(file);
570 if (ret)
571 return ret;
572
573 cfile = file->private_data;
574 }
575 553
576 buf = (char *) __get_free_page(GFP_KERNEL); 554 __free_page(page);
577 if (!buf) 555 return err;
578 return -ENOMEM;
579
580 ret = kernel_read(cfile, file->f_pos, buf, PAGE_SIZE);
581 if (ret > 0)
582 ret = parse_dirfile(buf, ret, file, dstbuf, filldir);
583
584 free_page((unsigned long) buf);
585 return ret;
586} 556}
587 557
588static char *read_link(struct dentry *dentry) 558static char *read_link(struct dentry *dentry)
@@ -637,18 +607,12 @@ static void fuse_put_link(struct dentry *dentry, struct nameidata *nd, void *c)
637 607
638static int fuse_dir_open(struct inode *inode, struct file *file) 608static int fuse_dir_open(struct inode *inode, struct file *file)
639{ 609{
640 file->private_data = NULL; 610 return fuse_open_common(inode, file, 1);
641 return 0;
642} 611}
643 612
644static int fuse_dir_release(struct inode *inode, struct file *file) 613static int fuse_dir_release(struct inode *inode, struct file *file)
645{ 614{
646 struct file *cfile = file->private_data; 615 return fuse_release_common(inode, file, 1);
647
648 if (cfile)
649 fput(cfile);
650
651 return 0;
652} 616}
653 617
654static unsigned iattr_to_fattr(struct iattr *iattr, struct fuse_attr *fattr) 618static unsigned iattr_to_fattr(struct iattr *iattr, struct fuse_attr *fattr)
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 6bc3fb26de39..224453557cf6 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -12,7 +12,7 @@
12#include <linux/slab.h> 12#include <linux/slab.h>
13#include <linux/kernel.h> 13#include <linux/kernel.h>
14 14
15static int fuse_open(struct inode *inode, struct file *file) 15int fuse_open_common(struct inode *inode, struct file *file, int isdir)
16{ 16{
17 struct fuse_conn *fc = get_fuse_conn(inode); 17 struct fuse_conn *fc = get_fuse_conn(inode);
18 struct fuse_req *req; 18 struct fuse_req *req;
@@ -56,7 +56,7 @@ static int fuse_open(struct inode *inode, struct file *file)
56 56
57 memset(&inarg, 0, sizeof(inarg)); 57 memset(&inarg, 0, sizeof(inarg));
58 inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC); 58 inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
59 req->in.h.opcode = FUSE_OPEN; 59 req->in.h.opcode = isdir ? FUSE_OPENDIR : FUSE_OPEN;
60 req->in.h.nodeid = get_node_id(inode); 60 req->in.h.nodeid = get_node_id(inode);
61 req->inode = inode; 61 req->inode = inode;
62 req->in.numargs = 1; 62 req->in.numargs = 1;
@@ -85,7 +85,7 @@ static int fuse_open(struct inode *inode, struct file *file)
85 return err; 85 return err;
86} 86}
87 87
88static int fuse_release(struct inode *inode, struct file *file) 88int fuse_release_common(struct inode *inode, struct file *file, int isdir)
89{ 89{
90 struct fuse_conn *fc = get_fuse_conn(inode); 90 struct fuse_conn *fc = get_fuse_conn(inode);
91 struct fuse_file *ff = file->private_data; 91 struct fuse_file *ff = file->private_data;
@@ -94,7 +94,7 @@ static int fuse_release(struct inode *inode, struct file *file)
94 94
95 inarg->fh = ff->fh; 95 inarg->fh = ff->fh;
96 inarg->flags = file->f_flags & ~O_EXCL; 96 inarg->flags = file->f_flags & ~O_EXCL;
97 req->in.h.opcode = FUSE_RELEASE; 97 req->in.h.opcode = isdir ? FUSE_RELEASEDIR : FUSE_RELEASE;
98 req->in.h.nodeid = get_node_id(inode); 98 req->in.h.nodeid = get_node_id(inode);
99 req->inode = inode; 99 req->inode = inode;
100 req->in.numargs = 1; 100 req->in.numargs = 1;
@@ -107,6 +107,16 @@ static int fuse_release(struct inode *inode, struct file *file)
107 return 0; 107 return 0;
108} 108}
109 109
110static int fuse_open(struct inode *inode, struct file *file)
111{
112 return fuse_open_common(inode, file, 0);
113}
114
115static int fuse_release(struct inode *inode, struct file *file)
116{
117 return fuse_release_common(inode, file, 0);
118}
119
110static int fuse_flush(struct file *file) 120static int fuse_flush(struct file *file)
111{ 121{
112 struct inode *inode = file->f_dentry->d_inode; 122 struct inode *inode = file->f_dentry->d_inode;
@@ -178,8 +188,9 @@ static int fuse_fsync(struct file *file, struct dentry *de, int datasync)
178 return err; 188 return err;
179} 189}
180 190
181static ssize_t fuse_send_read(struct fuse_req *req, struct file *file, 191size_t fuse_send_read_common(struct fuse_req *req, struct file *file,
182 struct inode *inode, loff_t pos, size_t count) 192 struct inode *inode, loff_t pos, size_t count,
193 int isdir)
183{ 194{
184 struct fuse_conn *fc = get_fuse_conn(inode); 195 struct fuse_conn *fc = get_fuse_conn(inode);
185 struct fuse_file *ff = file->private_data; 196 struct fuse_file *ff = file->private_data;
@@ -189,7 +200,7 @@ static ssize_t fuse_send_read(struct fuse_req *req, struct file *file,
189 inarg.fh = ff->fh; 200 inarg.fh = ff->fh;
190 inarg.offset = pos; 201 inarg.offset = pos;
191 inarg.size = count; 202 inarg.size = count;
192 req->in.h.opcode = FUSE_READ; 203 req->in.h.opcode = isdir ? FUSE_READDIR : FUSE_READ;
193 req->in.h.nodeid = get_node_id(inode); 204 req->in.h.nodeid = get_node_id(inode);
194 req->inode = inode; 205 req->inode = inode;
195 req->file = file; 206 req->file = file;
@@ -204,6 +215,13 @@ static ssize_t fuse_send_read(struct fuse_req *req, struct file *file,
204 return req->out.args[0].size; 215 return req->out.args[0].size;
205} 216}
206 217
218static inline size_t fuse_send_read(struct fuse_req *req, struct file *file,
219 struct inode *inode, loff_t pos,
220 size_t count)
221{
222 return fuse_send_read_common(req, file, inode, pos, count, 0);
223}
224
207static int fuse_readpage(struct file *file, struct page *page) 225static int fuse_readpage(struct file *file, struct page *page)
208{ 226{
209 struct inode *inode = page->mapping->host; 227 struct inode *inode = page->mapping->host;
@@ -293,8 +311,8 @@ static int fuse_readpages(struct file *file, struct address_space *mapping,
293 return err; 311 return err;
294} 312}
295 313
296static ssize_t fuse_send_write(struct fuse_req *req, struct file *file, 314static size_t fuse_send_write(struct fuse_req *req, struct file *file,
297 struct inode *inode, loff_t pos, size_t count) 315 struct inode *inode, loff_t pos, size_t count)
298{ 316{
299 struct fuse_conn *fc = get_fuse_conn(inode); 317 struct fuse_conn *fc = get_fuse_conn(inode);
300 struct fuse_file *ff = file->private_data; 318 struct fuse_file *ff = file->private_data;
@@ -332,7 +350,7 @@ static int fuse_commit_write(struct file *file, struct page *page,
332 unsigned offset, unsigned to) 350 unsigned offset, unsigned to)
333{ 351{
334 int err; 352 int err;
335 ssize_t nres; 353 size_t nres;
336 unsigned count = to - offset; 354 unsigned count = to - offset;
337 struct inode *inode = page->mapping->host; 355 struct inode *inode = page->mapping->host;
338 struct fuse_conn *fc = get_fuse_conn(inode); 356 struct fuse_conn *fc = get_fuse_conn(inode);
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 0af1ac646927..8593d5bae7a6 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -273,11 +273,6 @@ struct fuse_conn {
273 struct backing_dev_info bdi; 273 struct backing_dev_info bdi;
274}; 274};
275 275
276struct fuse_getdir_out_i {
277 int fd;
278 void *file; /* Used by kernel only */
279};
280
281static inline struct fuse_conn **get_fuse_conn_super_p(struct super_block *sb) 276static inline struct fuse_conn **get_fuse_conn_super_p(struct super_block *sb)
282{ 277{
283 return (struct fuse_conn **) &sb->s_fs_info; 278 return (struct fuse_conn **) &sb->s_fs_info;
@@ -334,6 +329,23 @@ void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req,
334 unsigned long nodeid, u64 nlookup); 329 unsigned long nodeid, u64 nlookup);
335 330
336/** 331/**
332 * Send READ or READDIR request
333 */
334size_t fuse_send_read_common(struct fuse_req *req, struct file *file,
335 struct inode *inode, loff_t pos, size_t count,
336 int isdir);
337
338/**
339 * Send OPEN or OPENDIR request
340 */
341int fuse_open_common(struct inode *inode, struct file *file, int isdir);
342
343/**
344 * Send RELEASE or RELEASEDIR request
345 */
346int fuse_release_common(struct inode *inode, struct file *file, int isdir);
347
348/**
337 * Initialise file operations on a regular file 349 * Initialise file operations on a regular file
338 */ 350 */
339void fuse_init_file_inode(struct inode *inode); 351void fuse_init_file_inode(struct inode *inode);
diff --git a/include/linux/fuse.h b/include/linux/fuse.h
index e9b814e16c58..cdfaa51b9018 100644
--- a/include/linux/fuse.h
+++ b/include/linux/fuse.h
@@ -70,7 +70,6 @@ enum fuse_opcode {
70 FUSE_SETATTR = 4, 70 FUSE_SETATTR = 4,
71 FUSE_READLINK = 5, 71 FUSE_READLINK = 5,
72 FUSE_SYMLINK = 6, 72 FUSE_SYMLINK = 6,
73 FUSE_GETDIR = 7,
74 FUSE_MKNOD = 8, 73 FUSE_MKNOD = 8,
75 FUSE_MKDIR = 9, 74 FUSE_MKDIR = 9,
76 FUSE_UNLINK = 10, 75 FUSE_UNLINK = 10,
@@ -88,7 +87,10 @@ enum fuse_opcode {
88 FUSE_LISTXATTR = 23, 87 FUSE_LISTXATTR = 23,
89 FUSE_REMOVEXATTR = 24, 88 FUSE_REMOVEXATTR = 24,
90 FUSE_FLUSH = 25, 89 FUSE_FLUSH = 25,
91 FUSE_INIT = 26 90 FUSE_INIT = 26,
91 FUSE_OPENDIR = 27,
92 FUSE_READDIR = 28,
93 FUSE_RELEASEDIR = 29
92}; 94};
93 95
94/* Conservative buffer size for the client */ 96/* Conservative buffer size for the client */
@@ -120,10 +122,6 @@ struct fuse_attr_out {
120 struct fuse_attr attr; 122 struct fuse_attr attr;
121}; 123};
122 124
123struct fuse_getdir_out {
124 __u32 fd;
125};
126
127struct fuse_mknod_in { 125struct fuse_mknod_in {
128 __u32 mode; 126 __u32 mode;
129 __u32 rdev; 127 __u32 rdev;