aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fuse/dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/fuse/dir.c')
-rw-r--r--fs/fuse/dir.c84
1 files changed, 24 insertions, 60 deletions
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)