diff options
Diffstat (limited to 'fs/fuse/dir.c')
-rw-r--r-- | fs/fuse/dir.c | 84 |
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 | ||
522 | static int fuse_checkdir(struct file *cfile, struct file *file) | 522 | static 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 | ||
537 | static int fuse_getdir(struct file *file) | 529 | static 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 | |||
562 | static 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 | ||
588 | static char *read_link(struct dentry *dentry) | 558 | static 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 | ||
638 | static int fuse_dir_open(struct inode *inode, struct file *file) | 608 | static 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 | ||
644 | static int fuse_dir_release(struct inode *inode, struct file *file) | 613 | static 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 | ||
654 | static unsigned iattr_to_fattr(struct iattr *iattr, struct fuse_attr *fattr) | 618 | static unsigned iattr_to_fattr(struct iattr *iattr, struct fuse_attr *fattr) |