diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/fuse/dev.c | 51 | ||||
-rw-r--r-- | fs/fuse/dir.c | 41 | ||||
-rw-r--r-- | fs/fuse/file.c | 8 | ||||
-rw-r--r-- | fs/fuse/inode.c | 22 |
4 files changed, 69 insertions, 53 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 098f97bdcf1b..ca887314aba9 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c | |||
@@ -643,9 +643,8 @@ struct fuse_copy_state { | |||
643 | unsigned long seglen; | 643 | unsigned long seglen; |
644 | unsigned long addr; | 644 | unsigned long addr; |
645 | struct page *pg; | 645 | struct page *pg; |
646 | void *mapaddr; | ||
647 | void *buf; | ||
648 | unsigned len; | 646 | unsigned len; |
647 | unsigned offset; | ||
649 | unsigned move_pages:1; | 648 | unsigned move_pages:1; |
650 | }; | 649 | }; |
651 | 650 | ||
@@ -666,23 +665,17 @@ static void fuse_copy_finish(struct fuse_copy_state *cs) | |||
666 | if (cs->currbuf) { | 665 | if (cs->currbuf) { |
667 | struct pipe_buffer *buf = cs->currbuf; | 666 | struct pipe_buffer *buf = cs->currbuf; |
668 | 667 | ||
669 | if (!cs->write) { | 668 | if (cs->write) |
670 | kunmap_atomic(cs->mapaddr); | ||
671 | } else { | ||
672 | kunmap_atomic(cs->mapaddr); | ||
673 | buf->len = PAGE_SIZE - cs->len; | 669 | buf->len = PAGE_SIZE - cs->len; |
674 | } | ||
675 | cs->currbuf = NULL; | 670 | cs->currbuf = NULL; |
676 | cs->mapaddr = NULL; | 671 | } else if (cs->pg) { |
677 | } else if (cs->mapaddr) { | ||
678 | kunmap_atomic(cs->mapaddr); | ||
679 | if (cs->write) { | 672 | if (cs->write) { |
680 | flush_dcache_page(cs->pg); | 673 | flush_dcache_page(cs->pg); |
681 | set_page_dirty_lock(cs->pg); | 674 | set_page_dirty_lock(cs->pg); |
682 | } | 675 | } |
683 | put_page(cs->pg); | 676 | put_page(cs->pg); |
684 | cs->mapaddr = NULL; | ||
685 | } | 677 | } |
678 | cs->pg = NULL; | ||
686 | } | 679 | } |
687 | 680 | ||
688 | /* | 681 | /* |
@@ -691,7 +684,7 @@ static void fuse_copy_finish(struct fuse_copy_state *cs) | |||
691 | */ | 684 | */ |
692 | static int fuse_copy_fill(struct fuse_copy_state *cs) | 685 | static int fuse_copy_fill(struct fuse_copy_state *cs) |
693 | { | 686 | { |
694 | unsigned long offset; | 687 | struct page *page; |
695 | int err; | 688 | int err; |
696 | 689 | ||
697 | unlock_request(cs->fc, cs->req); | 690 | unlock_request(cs->fc, cs->req); |
@@ -706,14 +699,12 @@ static int fuse_copy_fill(struct fuse_copy_state *cs) | |||
706 | 699 | ||
707 | BUG_ON(!cs->nr_segs); | 700 | BUG_ON(!cs->nr_segs); |
708 | cs->currbuf = buf; | 701 | cs->currbuf = buf; |
709 | cs->mapaddr = kmap_atomic(buf->page); | 702 | cs->pg = buf->page; |
703 | cs->offset = buf->offset; | ||
710 | cs->len = buf->len; | 704 | cs->len = buf->len; |
711 | cs->buf = cs->mapaddr + buf->offset; | ||
712 | cs->pipebufs++; | 705 | cs->pipebufs++; |
713 | cs->nr_segs--; | 706 | cs->nr_segs--; |
714 | } else { | 707 | } else { |
715 | struct page *page; | ||
716 | |||
717 | if (cs->nr_segs == cs->pipe->buffers) | 708 | if (cs->nr_segs == cs->pipe->buffers) |
718 | return -EIO; | 709 | return -EIO; |
719 | 710 | ||
@@ -726,8 +717,8 @@ static int fuse_copy_fill(struct fuse_copy_state *cs) | |||
726 | buf->len = 0; | 717 | buf->len = 0; |
727 | 718 | ||
728 | cs->currbuf = buf; | 719 | cs->currbuf = buf; |
729 | cs->mapaddr = kmap_atomic(page); | 720 | cs->pg = page; |
730 | cs->buf = cs->mapaddr; | 721 | cs->offset = 0; |
731 | cs->len = PAGE_SIZE; | 722 | cs->len = PAGE_SIZE; |
732 | cs->pipebufs++; | 723 | cs->pipebufs++; |
733 | cs->nr_segs++; | 724 | cs->nr_segs++; |
@@ -740,14 +731,13 @@ static int fuse_copy_fill(struct fuse_copy_state *cs) | |||
740 | cs->iov++; | 731 | cs->iov++; |
741 | cs->nr_segs--; | 732 | cs->nr_segs--; |
742 | } | 733 | } |
743 | err = get_user_pages_fast(cs->addr, 1, cs->write, &cs->pg); | 734 | err = get_user_pages_fast(cs->addr, 1, cs->write, &page); |
744 | if (err < 0) | 735 | if (err < 0) |
745 | return err; | 736 | return err; |
746 | BUG_ON(err != 1); | 737 | BUG_ON(err != 1); |
747 | offset = cs->addr % PAGE_SIZE; | 738 | cs->pg = page; |
748 | cs->mapaddr = kmap_atomic(cs->pg); | 739 | cs->offset = cs->addr % PAGE_SIZE; |
749 | cs->buf = cs->mapaddr + offset; | 740 | cs->len = min(PAGE_SIZE - cs->offset, cs->seglen); |
750 | cs->len = min(PAGE_SIZE - offset, cs->seglen); | ||
751 | cs->seglen -= cs->len; | 741 | cs->seglen -= cs->len; |
752 | cs->addr += cs->len; | 742 | cs->addr += cs->len; |
753 | } | 743 | } |
@@ -760,15 +750,20 @@ static int fuse_copy_do(struct fuse_copy_state *cs, void **val, unsigned *size) | |||
760 | { | 750 | { |
761 | unsigned ncpy = min(*size, cs->len); | 751 | unsigned ncpy = min(*size, cs->len); |
762 | if (val) { | 752 | if (val) { |
753 | void *pgaddr = kmap_atomic(cs->pg); | ||
754 | void *buf = pgaddr + cs->offset; | ||
755 | |||
763 | if (cs->write) | 756 | if (cs->write) |
764 | memcpy(cs->buf, *val, ncpy); | 757 | memcpy(buf, *val, ncpy); |
765 | else | 758 | else |
766 | memcpy(*val, cs->buf, ncpy); | 759 | memcpy(*val, buf, ncpy); |
760 | |||
761 | kunmap_atomic(pgaddr); | ||
767 | *val += ncpy; | 762 | *val += ncpy; |
768 | } | 763 | } |
769 | *size -= ncpy; | 764 | *size -= ncpy; |
770 | cs->len -= ncpy; | 765 | cs->len -= ncpy; |
771 | cs->buf += ncpy; | 766 | cs->offset += ncpy; |
772 | return ncpy; | 767 | return ncpy; |
773 | } | 768 | } |
774 | 769 | ||
@@ -874,8 +869,8 @@ static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep) | |||
874 | out_fallback_unlock: | 869 | out_fallback_unlock: |
875 | unlock_page(newpage); | 870 | unlock_page(newpage); |
876 | out_fallback: | 871 | out_fallback: |
877 | cs->mapaddr = kmap_atomic(buf->page); | 872 | cs->pg = buf->page; |
878 | cs->buf = cs->mapaddr + buf->offset; | 873 | cs->offset = buf->offset; |
879 | 874 | ||
880 | err = lock_request(cs->fc, cs->req); | 875 | err = lock_request(cs->fc, cs->req); |
881 | if (err) | 876 | if (err) |
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 42198359fa1b..0c6048247a34 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
@@ -198,7 +198,8 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags) | |||
198 | inode = ACCESS_ONCE(entry->d_inode); | 198 | inode = ACCESS_ONCE(entry->d_inode); |
199 | if (inode && is_bad_inode(inode)) | 199 | if (inode && is_bad_inode(inode)) |
200 | goto invalid; | 200 | goto invalid; |
201 | else if (fuse_dentry_time(entry) < get_jiffies_64()) { | 201 | else if (time_before64(fuse_dentry_time(entry), get_jiffies_64()) || |
202 | (flags & LOOKUP_REVAL)) { | ||
202 | int err; | 203 | int err; |
203 | struct fuse_entry_out outarg; | 204 | struct fuse_entry_out outarg; |
204 | struct fuse_req *req; | 205 | struct fuse_req *req; |
@@ -814,13 +815,6 @@ static int fuse_rename_common(struct inode *olddir, struct dentry *oldent, | |||
814 | return err; | 815 | return err; |
815 | } | 816 | } |
816 | 817 | ||
817 | static int fuse_rename(struct inode *olddir, struct dentry *oldent, | ||
818 | struct inode *newdir, struct dentry *newent) | ||
819 | { | ||
820 | return fuse_rename_common(olddir, oldent, newdir, newent, 0, | ||
821 | FUSE_RENAME, sizeof(struct fuse_rename_in)); | ||
822 | } | ||
823 | |||
824 | static int fuse_rename2(struct inode *olddir, struct dentry *oldent, | 818 | static int fuse_rename2(struct inode *olddir, struct dentry *oldent, |
825 | struct inode *newdir, struct dentry *newent, | 819 | struct inode *newdir, struct dentry *newent, |
826 | unsigned int flags) | 820 | unsigned int flags) |
@@ -831,17 +825,30 @@ static int fuse_rename2(struct inode *olddir, struct dentry *oldent, | |||
831 | if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE)) | 825 | if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE)) |
832 | return -EINVAL; | 826 | return -EINVAL; |
833 | 827 | ||
834 | if (fc->no_rename2 || fc->minor < 23) | 828 | if (flags) { |
835 | return -EINVAL; | 829 | if (fc->no_rename2 || fc->minor < 23) |
830 | return -EINVAL; | ||
836 | 831 | ||
837 | err = fuse_rename_common(olddir, oldent, newdir, newent, flags, | 832 | err = fuse_rename_common(olddir, oldent, newdir, newent, flags, |
838 | FUSE_RENAME2, sizeof(struct fuse_rename2_in)); | 833 | FUSE_RENAME2, |
839 | if (err == -ENOSYS) { | 834 | sizeof(struct fuse_rename2_in)); |
840 | fc->no_rename2 = 1; | 835 | if (err == -ENOSYS) { |
841 | err = -EINVAL; | 836 | fc->no_rename2 = 1; |
837 | err = -EINVAL; | ||
838 | } | ||
839 | } else { | ||
840 | err = fuse_rename_common(olddir, oldent, newdir, newent, 0, | ||
841 | FUSE_RENAME, | ||
842 | sizeof(struct fuse_rename_in)); | ||
842 | } | 843 | } |
844 | |||
843 | return err; | 845 | return err; |
846 | } | ||
844 | 847 | ||
848 | static int fuse_rename(struct inode *olddir, struct dentry *oldent, | ||
849 | struct inode *newdir, struct dentry *newent) | ||
850 | { | ||
851 | return fuse_rename2(olddir, oldent, newdir, newent, 0); | ||
845 | } | 852 | } |
846 | 853 | ||
847 | static int fuse_link(struct dentry *entry, struct inode *newdir, | 854 | static int fuse_link(struct dentry *entry, struct inode *newdir, |
@@ -985,7 +992,7 @@ int fuse_update_attributes(struct inode *inode, struct kstat *stat, | |||
985 | int err; | 992 | int err; |
986 | bool r; | 993 | bool r; |
987 | 994 | ||
988 | if (fi->i_time < get_jiffies_64()) { | 995 | if (time_before64(fi->i_time, get_jiffies_64())) { |
989 | r = true; | 996 | r = true; |
990 | err = fuse_do_getattr(inode, stat, file); | 997 | err = fuse_do_getattr(inode, stat, file); |
991 | } else { | 998 | } else { |
@@ -1171,7 +1178,7 @@ static int fuse_permission(struct inode *inode, int mask) | |||
1171 | ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) { | 1178 | ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) { |
1172 | struct fuse_inode *fi = get_fuse_inode(inode); | 1179 | struct fuse_inode *fi = get_fuse_inode(inode); |
1173 | 1180 | ||
1174 | if (fi->i_time < get_jiffies_64()) { | 1181 | if (time_before64(fi->i_time, get_jiffies_64())) { |
1175 | refreshed = true; | 1182 | refreshed = true; |
1176 | 1183 | ||
1177 | err = fuse_perm_getattr(inode, mask); | 1184 | err = fuse_perm_getattr(inode, mask); |
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 6e16dad13e9b..40ac2628ddcf 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -1687,7 +1687,7 @@ static int fuse_writepage_locked(struct page *page) | |||
1687 | error = -EIO; | 1687 | error = -EIO; |
1688 | req->ff = fuse_write_file_get(fc, fi); | 1688 | req->ff = fuse_write_file_get(fc, fi); |
1689 | if (!req->ff) | 1689 | if (!req->ff) |
1690 | goto err_free; | 1690 | goto err_nofile; |
1691 | 1691 | ||
1692 | fuse_write_fill(req, req->ff, page_offset(page), 0); | 1692 | fuse_write_fill(req, req->ff, page_offset(page), 0); |
1693 | 1693 | ||
@@ -1715,6 +1715,8 @@ static int fuse_writepage_locked(struct page *page) | |||
1715 | 1715 | ||
1716 | return 0; | 1716 | return 0; |
1717 | 1717 | ||
1718 | err_nofile: | ||
1719 | __free_page(tmp_page); | ||
1718 | err_free: | 1720 | err_free: |
1719 | fuse_request_free(req); | 1721 | fuse_request_free(req); |
1720 | err: | 1722 | err: |
@@ -1955,8 +1957,8 @@ static int fuse_writepages(struct address_space *mapping, | |||
1955 | data.ff = NULL; | 1957 | data.ff = NULL; |
1956 | 1958 | ||
1957 | err = -ENOMEM; | 1959 | err = -ENOMEM; |
1958 | data.orig_pages = kzalloc(sizeof(struct page *) * | 1960 | data.orig_pages = kcalloc(FUSE_MAX_PAGES_PER_REQ, |
1959 | FUSE_MAX_PAGES_PER_REQ, | 1961 | sizeof(struct page *), |
1960 | GFP_NOFS); | 1962 | GFP_NOFS); |
1961 | if (!data.orig_pages) | 1963 | if (!data.orig_pages) |
1962 | goto out; | 1964 | goto out; |
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 754dcf23de8a..8474028d7848 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c | |||
@@ -478,6 +478,17 @@ static const match_table_t tokens = { | |||
478 | {OPT_ERR, NULL} | 478 | {OPT_ERR, NULL} |
479 | }; | 479 | }; |
480 | 480 | ||
481 | static int fuse_match_uint(substring_t *s, unsigned int *res) | ||
482 | { | ||
483 | int err = -ENOMEM; | ||
484 | char *buf = match_strdup(s); | ||
485 | if (buf) { | ||
486 | err = kstrtouint(buf, 10, res); | ||
487 | kfree(buf); | ||
488 | } | ||
489 | return err; | ||
490 | } | ||
491 | |||
481 | static int parse_fuse_opt(char *opt, struct fuse_mount_data *d, int is_bdev) | 492 | static int parse_fuse_opt(char *opt, struct fuse_mount_data *d, int is_bdev) |
482 | { | 493 | { |
483 | char *p; | 494 | char *p; |
@@ -488,6 +499,7 @@ static int parse_fuse_opt(char *opt, struct fuse_mount_data *d, int is_bdev) | |||
488 | while ((p = strsep(&opt, ",")) != NULL) { | 499 | while ((p = strsep(&opt, ",")) != NULL) { |
489 | int token; | 500 | int token; |
490 | int value; | 501 | int value; |
502 | unsigned uv; | ||
491 | substring_t args[MAX_OPT_ARGS]; | 503 | substring_t args[MAX_OPT_ARGS]; |
492 | if (!*p) | 504 | if (!*p) |
493 | continue; | 505 | continue; |
@@ -511,18 +523,18 @@ static int parse_fuse_opt(char *opt, struct fuse_mount_data *d, int is_bdev) | |||
511 | break; | 523 | break; |
512 | 524 | ||
513 | case OPT_USER_ID: | 525 | case OPT_USER_ID: |
514 | if (match_int(&args[0], &value)) | 526 | if (fuse_match_uint(&args[0], &uv)) |
515 | return 0; | 527 | return 0; |
516 | d->user_id = make_kuid(current_user_ns(), value); | 528 | d->user_id = make_kuid(current_user_ns(), uv); |
517 | if (!uid_valid(d->user_id)) | 529 | if (!uid_valid(d->user_id)) |
518 | return 0; | 530 | return 0; |
519 | d->user_id_present = 1; | 531 | d->user_id_present = 1; |
520 | break; | 532 | break; |
521 | 533 | ||
522 | case OPT_GROUP_ID: | 534 | case OPT_GROUP_ID: |
523 | if (match_int(&args[0], &value)) | 535 | if (fuse_match_uint(&args[0], &uv)) |
524 | return 0; | 536 | return 0; |
525 | d->group_id = make_kgid(current_user_ns(), value); | 537 | d->group_id = make_kgid(current_user_ns(), uv); |
526 | if (!gid_valid(d->group_id)) | 538 | if (!gid_valid(d->group_id)) |
527 | return 0; | 539 | return 0; |
528 | d->group_id_present = 1; | 540 | d->group_id_present = 1; |
@@ -1006,7 +1018,7 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) | |||
1006 | 1018 | ||
1007 | sb->s_flags &= ~(MS_NOSEC | MS_I_VERSION); | 1019 | sb->s_flags &= ~(MS_NOSEC | MS_I_VERSION); |
1008 | 1020 | ||
1009 | if (!parse_fuse_opt((char *) data, &d, is_bdev)) | 1021 | if (!parse_fuse_opt(data, &d, is_bdev)) |
1010 | goto err; | 1022 | goto err; |
1011 | 1023 | ||
1012 | if (is_bdev) { | 1024 | if (is_bdev) { |