diff options
Diffstat (limited to 'fs/fuse/inode.c')
| -rw-r--r-- | fs/fuse/inode.c | 68 |
1 files changed, 64 insertions, 4 deletions
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index d8673ccf90b7..f91ccc4a189d 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c | |||
| @@ -206,7 +206,7 @@ static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr) | |||
| 206 | BUG(); | 206 | BUG(); |
| 207 | } | 207 | } |
| 208 | 208 | ||
| 209 | static int fuse_inode_eq(struct inode *inode, void *_nodeidp) | 209 | int fuse_inode_eq(struct inode *inode, void *_nodeidp) |
| 210 | { | 210 | { |
| 211 | u64 nodeid = *(u64 *) _nodeidp; | 211 | u64 nodeid = *(u64 *) _nodeidp; |
| 212 | if (get_node_id(inode) == nodeid) | 212 | if (get_node_id(inode) == nodeid) |
| @@ -257,6 +257,31 @@ struct inode *fuse_iget(struct super_block *sb, u64 nodeid, | |||
| 257 | return inode; | 257 | return inode; |
| 258 | } | 258 | } |
| 259 | 259 | ||
| 260 | int fuse_reverse_inval_inode(struct super_block *sb, u64 nodeid, | ||
| 261 | loff_t offset, loff_t len) | ||
| 262 | { | ||
| 263 | struct inode *inode; | ||
| 264 | pgoff_t pg_start; | ||
| 265 | pgoff_t pg_end; | ||
| 266 | |||
| 267 | inode = ilookup5(sb, nodeid, fuse_inode_eq, &nodeid); | ||
| 268 | if (!inode) | ||
| 269 | return -ENOENT; | ||
| 270 | |||
| 271 | fuse_invalidate_attr(inode); | ||
| 272 | if (offset >= 0) { | ||
| 273 | pg_start = offset >> PAGE_CACHE_SHIFT; | ||
| 274 | if (len <= 0) | ||
| 275 | pg_end = -1; | ||
| 276 | else | ||
| 277 | pg_end = (offset + len - 1) >> PAGE_CACHE_SHIFT; | ||
| 278 | invalidate_inode_pages2_range(inode->i_mapping, | ||
| 279 | pg_start, pg_end); | ||
| 280 | } | ||
| 281 | iput(inode); | ||
| 282 | return 0; | ||
| 283 | } | ||
| 284 | |||
| 260 | static void fuse_umount_begin(struct super_block *sb) | 285 | static void fuse_umount_begin(struct super_block *sb) |
| 261 | { | 286 | { |
| 262 | fuse_abort_conn(get_fuse_conn_super(sb)); | 287 | fuse_abort_conn(get_fuse_conn_super(sb)); |
| @@ -480,6 +505,7 @@ void fuse_conn_init(struct fuse_conn *fc) | |||
| 480 | memset(fc, 0, sizeof(*fc)); | 505 | memset(fc, 0, sizeof(*fc)); |
| 481 | spin_lock_init(&fc->lock); | 506 | spin_lock_init(&fc->lock); |
| 482 | mutex_init(&fc->inst_mutex); | 507 | mutex_init(&fc->inst_mutex); |
| 508 | init_rwsem(&fc->killsb); | ||
| 483 | atomic_set(&fc->count, 1); | 509 | atomic_set(&fc->count, 1); |
| 484 | init_waitqueue_head(&fc->waitq); | 510 | init_waitqueue_head(&fc->waitq); |
| 485 | init_waitqueue_head(&fc->blocked_waitq); | 511 | init_waitqueue_head(&fc->blocked_waitq); |
| @@ -725,6 +751,8 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req) | |||
| 725 | } | 751 | } |
| 726 | if (arg->flags & FUSE_BIG_WRITES) | 752 | if (arg->flags & FUSE_BIG_WRITES) |
| 727 | fc->big_writes = 1; | 753 | fc->big_writes = 1; |
| 754 | if (arg->flags & FUSE_DONT_MASK) | ||
| 755 | fc->dont_mask = 1; | ||
| 728 | } else { | 756 | } else { |
| 729 | ra_pages = fc->max_read / PAGE_CACHE_SIZE; | 757 | ra_pages = fc->max_read / PAGE_CACHE_SIZE; |
| 730 | fc->no_lock = 1; | 758 | fc->no_lock = 1; |
| @@ -748,7 +776,7 @@ static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req) | |||
| 748 | arg->minor = FUSE_KERNEL_MINOR_VERSION; | 776 | arg->minor = FUSE_KERNEL_MINOR_VERSION; |
| 749 | arg->max_readahead = fc->bdi.ra_pages * PAGE_CACHE_SIZE; | 777 | arg->max_readahead = fc->bdi.ra_pages * PAGE_CACHE_SIZE; |
| 750 | arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC | | 778 | arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC | |
| 751 | FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES; | 779 | FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES | FUSE_DONT_MASK; |
| 752 | req->in.h.opcode = FUSE_INIT; | 780 | req->in.h.opcode = FUSE_INIT; |
| 753 | req->in.numargs = 1; | 781 | req->in.numargs = 1; |
| 754 | req->in.args[0].size = sizeof(*arg); | 782 | req->in.args[0].size = sizeof(*arg); |
| @@ -860,10 +888,16 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) | |||
| 860 | fuse_conn_init(fc); | 888 | fuse_conn_init(fc); |
| 861 | 889 | ||
| 862 | fc->dev = sb->s_dev; | 890 | fc->dev = sb->s_dev; |
| 891 | fc->sb = sb; | ||
| 863 | err = fuse_bdi_init(fc, sb); | 892 | err = fuse_bdi_init(fc, sb); |
| 864 | if (err) | 893 | if (err) |
| 865 | goto err_put_conn; | 894 | goto err_put_conn; |
| 866 | 895 | ||
| 896 | /* Handle umasking inside the fuse code */ | ||
| 897 | if (sb->s_flags & MS_POSIXACL) | ||
| 898 | fc->dont_mask = 1; | ||
| 899 | sb->s_flags |= MS_POSIXACL; | ||
| 900 | |||
| 867 | fc->release = fuse_free_conn; | 901 | fc->release = fuse_free_conn; |
| 868 | fc->flags = d.flags; | 902 | fc->flags = d.flags; |
| 869 | fc->user_id = d.user_id; | 903 | fc->user_id = d.user_id; |
| @@ -941,12 +975,25 @@ static int fuse_get_sb(struct file_system_type *fs_type, | |||
| 941 | return get_sb_nodev(fs_type, flags, raw_data, fuse_fill_super, mnt); | 975 | return get_sb_nodev(fs_type, flags, raw_data, fuse_fill_super, mnt); |
| 942 | } | 976 | } |
| 943 | 977 | ||
| 978 | static void fuse_kill_sb_anon(struct super_block *sb) | ||
| 979 | { | ||
| 980 | struct fuse_conn *fc = get_fuse_conn_super(sb); | ||
| 981 | |||
| 982 | if (fc) { | ||
| 983 | down_write(&fc->killsb); | ||
| 984 | fc->sb = NULL; | ||
| 985 | up_write(&fc->killsb); | ||
| 986 | } | ||
| 987 | |||
| 988 | kill_anon_super(sb); | ||
| 989 | } | ||
| 990 | |||
| 944 | static struct file_system_type fuse_fs_type = { | 991 | static struct file_system_type fuse_fs_type = { |
| 945 | .owner = THIS_MODULE, | 992 | .owner = THIS_MODULE, |
| 946 | .name = "fuse", | 993 | .name = "fuse", |
| 947 | .fs_flags = FS_HAS_SUBTYPE, | 994 | .fs_flags = FS_HAS_SUBTYPE, |
| 948 | .get_sb = fuse_get_sb, | 995 | .get_sb = fuse_get_sb, |
| 949 | .kill_sb = kill_anon_super, | 996 | .kill_sb = fuse_kill_sb_anon, |
| 950 | }; | 997 | }; |
| 951 | 998 | ||
| 952 | #ifdef CONFIG_BLOCK | 999 | #ifdef CONFIG_BLOCK |
| @@ -958,11 +1005,24 @@ static int fuse_get_sb_blk(struct file_system_type *fs_type, | |||
| 958 | mnt); | 1005 | mnt); |
| 959 | } | 1006 | } |
| 960 | 1007 | ||
| 1008 | static void fuse_kill_sb_blk(struct super_block *sb) | ||
| 1009 | { | ||
| 1010 | struct fuse_conn *fc = get_fuse_conn_super(sb); | ||
| 1011 | |||
| 1012 | if (fc) { | ||
| 1013 | down_write(&fc->killsb); | ||
| 1014 | fc->sb = NULL; | ||
| 1015 | up_write(&fc->killsb); | ||
| 1016 | } | ||
| 1017 | |||
| 1018 | kill_block_super(sb); | ||
| 1019 | } | ||
| 1020 | |||
| 961 | static struct file_system_type fuseblk_fs_type = { | 1021 | static struct file_system_type fuseblk_fs_type = { |
| 962 | .owner = THIS_MODULE, | 1022 | .owner = THIS_MODULE, |
| 963 | .name = "fuseblk", | 1023 | .name = "fuseblk", |
| 964 | .get_sb = fuse_get_sb_blk, | 1024 | .get_sb = fuse_get_sb_blk, |
| 965 | .kill_sb = kill_block_super, | 1025 | .kill_sb = fuse_kill_sb_blk, |
| 966 | .fs_flags = FS_REQUIRES_DEV | FS_HAS_SUBTYPE, | 1026 | .fs_flags = FS_REQUIRES_DEV | FS_HAS_SUBTYPE, |
| 967 | }; | 1027 | }; |
| 968 | 1028 | ||
