diff options
| -rw-r--r-- | fs/fuse/dev.c | 83 | ||||
| -rw-r--r-- | fs/fuse/dir.c | 57 | ||||
| -rw-r--r-- | fs/fuse/file.c | 2 | ||||
| -rw-r--r-- | fs/fuse/fuse_i.h | 27 | ||||
| -rw-r--r-- | fs/fuse/inode.c | 68 | ||||
| -rw-r--r-- | include/linux/fuse.h | 36 |
6 files changed, 262 insertions, 11 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 8fed2ed12f3..f58ecbc416c 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c | |||
| @@ -849,6 +849,81 @@ err: | |||
| 849 | return err; | 849 | return err; |
| 850 | } | 850 | } |
| 851 | 851 | ||
| 852 | static int fuse_notify_inval_inode(struct fuse_conn *fc, unsigned int size, | ||
| 853 | struct fuse_copy_state *cs) | ||
| 854 | { | ||
| 855 | struct fuse_notify_inval_inode_out outarg; | ||
| 856 | int err = -EINVAL; | ||
| 857 | |||
| 858 | if (size != sizeof(outarg)) | ||
| 859 | goto err; | ||
| 860 | |||
| 861 | err = fuse_copy_one(cs, &outarg, sizeof(outarg)); | ||
| 862 | if (err) | ||
| 863 | goto err; | ||
| 864 | fuse_copy_finish(cs); | ||
| 865 | |||
| 866 | down_read(&fc->killsb); | ||
| 867 | err = -ENOENT; | ||
| 868 | if (!fc->sb) | ||
| 869 | goto err_unlock; | ||
| 870 | |||
| 871 | err = fuse_reverse_inval_inode(fc->sb, outarg.ino, | ||
| 872 | outarg.off, outarg.len); | ||
| 873 | |||
| 874 | err_unlock: | ||
| 875 | up_read(&fc->killsb); | ||
| 876 | return err; | ||
| 877 | |||
| 878 | err: | ||
| 879 | fuse_copy_finish(cs); | ||
| 880 | return err; | ||
| 881 | } | ||
| 882 | |||
| 883 | static int fuse_notify_inval_entry(struct fuse_conn *fc, unsigned int size, | ||
| 884 | struct fuse_copy_state *cs) | ||
| 885 | { | ||
| 886 | struct fuse_notify_inval_entry_out outarg; | ||
| 887 | int err = -EINVAL; | ||
| 888 | char buf[FUSE_NAME_MAX+1]; | ||
| 889 | struct qstr name; | ||
| 890 | |||
| 891 | if (size < sizeof(outarg)) | ||
| 892 | goto err; | ||
| 893 | |||
| 894 | err = fuse_copy_one(cs, &outarg, sizeof(outarg)); | ||
| 895 | if (err) | ||
| 896 | goto err; | ||
| 897 | |||
| 898 | err = -ENAMETOOLONG; | ||
| 899 | if (outarg.namelen > FUSE_NAME_MAX) | ||
| 900 | goto err; | ||
| 901 | |||
| 902 | name.name = buf; | ||
| 903 | name.len = outarg.namelen; | ||
| 904 | err = fuse_copy_one(cs, buf, outarg.namelen + 1); | ||
| 905 | if (err) | ||
| 906 | goto err; | ||
| 907 | fuse_copy_finish(cs); | ||
| 908 | buf[outarg.namelen] = 0; | ||
| 909 | name.hash = full_name_hash(name.name, name.len); | ||
| 910 | |||
| 911 | down_read(&fc->killsb); | ||
| 912 | err = -ENOENT; | ||
| 913 | if (!fc->sb) | ||
| 914 | goto err_unlock; | ||
| 915 | |||
| 916 | err = fuse_reverse_inval_entry(fc->sb, outarg.parent, &name); | ||
| 917 | |||
| 918 | err_unlock: | ||
| 919 | up_read(&fc->killsb); | ||
| 920 | return err; | ||
| 921 | |||
| 922 | err: | ||
| 923 | fuse_copy_finish(cs); | ||
| 924 | return err; | ||
| 925 | } | ||
| 926 | |||
| 852 | static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code, | 927 | static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code, |
| 853 | unsigned int size, struct fuse_copy_state *cs) | 928 | unsigned int size, struct fuse_copy_state *cs) |
| 854 | { | 929 | { |
| @@ -856,6 +931,12 @@ static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code, | |||
| 856 | case FUSE_NOTIFY_POLL: | 931 | case FUSE_NOTIFY_POLL: |
| 857 | return fuse_notify_poll(fc, size, cs); | 932 | return fuse_notify_poll(fc, size, cs); |
| 858 | 933 | ||
| 934 | case FUSE_NOTIFY_INVAL_INODE: | ||
| 935 | return fuse_notify_inval_inode(fc, size, cs); | ||
| 936 | |||
| 937 | case FUSE_NOTIFY_INVAL_ENTRY: | ||
| 938 | return fuse_notify_inval_entry(fc, size, cs); | ||
| 939 | |||
| 859 | default: | 940 | default: |
| 860 | fuse_copy_finish(cs); | 941 | fuse_copy_finish(cs); |
| 861 | return -EINVAL; | 942 | return -EINVAL; |
| @@ -910,7 +991,7 @@ static ssize_t fuse_dev_write(struct kiocb *iocb, const struct iovec *iov, | |||
| 910 | unsigned long nr_segs, loff_t pos) | 991 | unsigned long nr_segs, loff_t pos) |
| 911 | { | 992 | { |
| 912 | int err; | 993 | int err; |
| 913 | unsigned nbytes = iov_length(iov, nr_segs); | 994 | size_t nbytes = iov_length(iov, nr_segs); |
| 914 | struct fuse_req *req; | 995 | struct fuse_req *req; |
| 915 | struct fuse_out_header oh; | 996 | struct fuse_out_header oh; |
| 916 | struct fuse_copy_state cs; | 997 | struct fuse_copy_state cs; |
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index b3089a083d3..e703654e7f4 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
| @@ -375,7 +375,7 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode, | |||
| 375 | struct fuse_conn *fc = get_fuse_conn(dir); | 375 | struct fuse_conn *fc = get_fuse_conn(dir); |
| 376 | struct fuse_req *req; | 376 | struct fuse_req *req; |
| 377 | struct fuse_req *forget_req; | 377 | struct fuse_req *forget_req; |
| 378 | struct fuse_open_in inarg; | 378 | struct fuse_create_in inarg; |
| 379 | struct fuse_open_out outopen; | 379 | struct fuse_open_out outopen; |
| 380 | struct fuse_entry_out outentry; | 380 | struct fuse_entry_out outentry; |
| 381 | struct fuse_file *ff; | 381 | struct fuse_file *ff; |
| @@ -399,15 +399,20 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode, | |||
| 399 | if (!ff) | 399 | if (!ff) |
| 400 | goto out_put_request; | 400 | goto out_put_request; |
| 401 | 401 | ||
| 402 | if (!fc->dont_mask) | ||
| 403 | mode &= ~current_umask(); | ||
| 404 | |||
| 402 | flags &= ~O_NOCTTY; | 405 | flags &= ~O_NOCTTY; |
| 403 | memset(&inarg, 0, sizeof(inarg)); | 406 | memset(&inarg, 0, sizeof(inarg)); |
| 404 | memset(&outentry, 0, sizeof(outentry)); | 407 | memset(&outentry, 0, sizeof(outentry)); |
| 405 | inarg.flags = flags; | 408 | inarg.flags = flags; |
| 406 | inarg.mode = mode; | 409 | inarg.mode = mode; |
| 410 | inarg.umask = current_umask(); | ||
| 407 | req->in.h.opcode = FUSE_CREATE; | 411 | req->in.h.opcode = FUSE_CREATE; |
| 408 | req->in.h.nodeid = get_node_id(dir); | 412 | req->in.h.nodeid = get_node_id(dir); |
| 409 | req->in.numargs = 2; | 413 | req->in.numargs = 2; |
| 410 | req->in.args[0].size = sizeof(inarg); | 414 | req->in.args[0].size = fc->minor < 12 ? sizeof(struct fuse_open_in) : |
| 415 | sizeof(inarg); | ||
| 411 | req->in.args[0].value = &inarg; | 416 | req->in.args[0].value = &inarg; |
| 412 | req->in.args[1].size = entry->d_name.len + 1; | 417 | req->in.args[1].size = entry->d_name.len + 1; |
| 413 | req->in.args[1].value = entry->d_name.name; | 418 | req->in.args[1].value = entry->d_name.name; |
| @@ -546,12 +551,17 @@ static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode, | |||
| 546 | if (IS_ERR(req)) | 551 | if (IS_ERR(req)) |
| 547 | return PTR_ERR(req); | 552 | return PTR_ERR(req); |
| 548 | 553 | ||
| 554 | if (!fc->dont_mask) | ||
| 555 | mode &= ~current_umask(); | ||
| 556 | |||
| 549 | memset(&inarg, 0, sizeof(inarg)); | 557 | memset(&inarg, 0, sizeof(inarg)); |
| 550 | inarg.mode = mode; | 558 | inarg.mode = mode; |
| 551 | inarg.rdev = new_encode_dev(rdev); | 559 | inarg.rdev = new_encode_dev(rdev); |
| 560 | inarg.umask = current_umask(); | ||
| 552 | req->in.h.opcode = FUSE_MKNOD; | 561 | req->in.h.opcode = FUSE_MKNOD; |
| 553 | req->in.numargs = 2; | 562 | req->in.numargs = 2; |
| 554 | req->in.args[0].size = sizeof(inarg); | 563 | req->in.args[0].size = fc->minor < 12 ? FUSE_COMPAT_MKNOD_IN_SIZE : |
| 564 | sizeof(inarg); | ||
| 555 | req->in.args[0].value = &inarg; | 565 | req->in.args[0].value = &inarg; |
| 556 | req->in.args[1].size = entry->d_name.len + 1; | 566 | req->in.args[1].size = entry->d_name.len + 1; |
| 557 | req->in.args[1].value = entry->d_name.name; | 567 | req->in.args[1].value = entry->d_name.name; |
| @@ -578,8 +588,12 @@ static int fuse_mkdir(struct inode *dir, struct dentry *entry, int mode) | |||
| 578 | if (IS_ERR(req)) | 588 | if (IS_ERR(req)) |
| 579 | return PTR_ERR(req); | 589 | return PTR_ERR(req); |
| 580 | 590 | ||
| 591 | if (!fc->dont_mask) | ||
| 592 | mode &= ~current_umask(); | ||
| 593 | |||
| 581 | memset(&inarg, 0, sizeof(inarg)); | 594 | memset(&inarg, 0, sizeof(inarg)); |
| 582 | inarg.mode = mode; | 595 | inarg.mode = mode; |
| 596 | inarg.umask = current_umask(); | ||
| 583 | req->in.h.opcode = FUSE_MKDIR; | 597 | req->in.h.opcode = FUSE_MKDIR; |
| 584 | req->in.numargs = 2; | 598 | req->in.numargs = 2; |
| 585 | req->in.args[0].size = sizeof(inarg); | 599 | req->in.args[0].size = sizeof(inarg); |
| @@ -845,6 +859,43 @@ int fuse_update_attributes(struct inode *inode, struct kstat *stat, | |||
| 845 | return err; | 859 | return err; |
| 846 | } | 860 | } |
| 847 | 861 | ||
| 862 | int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid, | ||
| 863 | struct qstr *name) | ||
| 864 | { | ||
| 865 | int err = -ENOTDIR; | ||
| 866 | struct inode *parent; | ||
| 867 | struct dentry *dir; | ||
| 868 | struct dentry *entry; | ||
| 869 | |||
| 870 | parent = ilookup5(sb, parent_nodeid, fuse_inode_eq, &parent_nodeid); | ||
| 871 | if (!parent) | ||
| 872 | return -ENOENT; | ||
| 873 | |||
| 874 | mutex_lock(&parent->i_mutex); | ||
| 875 | if (!S_ISDIR(parent->i_mode)) | ||
| 876 | goto unlock; | ||
| 877 | |||
| 878 | err = -ENOENT; | ||
| 879 | dir = d_find_alias(parent); | ||
| 880 | if (!dir) | ||
| 881 | goto unlock; | ||
| 882 | |||
| 883 | entry = d_lookup(dir, name); | ||
| 884 | dput(dir); | ||
| 885 | if (!entry) | ||
| 886 | goto unlock; | ||
| 887 | |||
| 888 | fuse_invalidate_attr(parent); | ||
| 889 | fuse_invalidate_entry(entry); | ||
| 890 | dput(entry); | ||
| 891 | err = 0; | ||
| 892 | |||
| 893 | unlock: | ||
| 894 | mutex_unlock(&parent->i_mutex); | ||
| 895 | iput(parent); | ||
| 896 | return err; | ||
| 897 | } | ||
| 898 | |||
| 848 | /* | 899 | /* |
| 849 | * Calling into a user-controlled filesystem gives the filesystem | 900 | * Calling into a user-controlled filesystem gives the filesystem |
| 850 | * daemon ptrace-like capabilities over the requester process. This | 901 | * daemon ptrace-like capabilities over the requester process. This |
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index fce6ce694fd..cbc464043b6 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
| @@ -1922,7 +1922,7 @@ unsigned fuse_file_poll(struct file *file, poll_table *wait) | |||
| 1922 | 1922 | ||
| 1923 | req = fuse_get_req(fc); | 1923 | req = fuse_get_req(fc); |
| 1924 | if (IS_ERR(req)) | 1924 | if (IS_ERR(req)) |
| 1925 | return PTR_ERR(req); | 1925 | return POLLERR; |
| 1926 | 1926 | ||
| 1927 | req->in.h.opcode = FUSE_POLL; | 1927 | req->in.h.opcode = FUSE_POLL; |
| 1928 | req->in.h.nodeid = ff->nodeid; | 1928 | req->in.h.nodeid = ff->nodeid; |
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index aaf2f9ff970..52b641fc0fa 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h | |||
| @@ -446,6 +446,9 @@ struct fuse_conn { | |||
| 446 | /** Do multi-page cached writes */ | 446 | /** Do multi-page cached writes */ |
| 447 | unsigned big_writes:1; | 447 | unsigned big_writes:1; |
| 448 | 448 | ||
| 449 | /** Don't apply umask to creation modes */ | ||
| 450 | unsigned dont_mask:1; | ||
| 451 | |||
| 449 | /** The number of requests waiting for completion */ | 452 | /** The number of requests waiting for completion */ |
| 450 | atomic_t num_waiting; | 453 | atomic_t num_waiting; |
| 451 | 454 | ||
| @@ -481,6 +484,12 @@ struct fuse_conn { | |||
| 481 | 484 | ||
| 482 | /** Called on final put */ | 485 | /** Called on final put */ |
| 483 | void (*release)(struct fuse_conn *); | 486 | void (*release)(struct fuse_conn *); |
| 487 | |||
| 488 | /** Super block for this connection. */ | ||
| 489 | struct super_block *sb; | ||
| 490 | |||
| 491 | /** Read/write semaphore to hold when accessing sb. */ | ||
| 492 | struct rw_semaphore killsb; | ||
| 484 | }; | 493 | }; |
| 485 | 494 | ||
| 486 | static inline struct fuse_conn *get_fuse_conn_super(struct super_block *sb) | 495 | static inline struct fuse_conn *get_fuse_conn_super(struct super_block *sb) |
| @@ -509,6 +518,11 @@ extern const struct file_operations fuse_dev_operations; | |||
| 509 | extern const struct dentry_operations fuse_dentry_operations; | 518 | extern const struct dentry_operations fuse_dentry_operations; |
| 510 | 519 | ||
| 511 | /** | 520 | /** |
| 521 | * Inode to nodeid comparison. | ||
| 522 | */ | ||
| 523 | int fuse_inode_eq(struct inode *inode, void *_nodeidp); | ||
| 524 | |||
| 525 | /** | ||
| 512 | * Get a filled in inode | 526 | * Get a filled in inode |
| 513 | */ | 527 | */ |
| 514 | struct inode *fuse_iget(struct super_block *sb, u64 nodeid, | 528 | struct inode *fuse_iget(struct super_block *sb, u64 nodeid, |
| @@ -708,6 +722,19 @@ void fuse_release_nowrite(struct inode *inode); | |||
| 708 | 722 | ||
| 709 | u64 fuse_get_attr_version(struct fuse_conn *fc); | 723 | u64 fuse_get_attr_version(struct fuse_conn *fc); |
| 710 | 724 | ||
| 725 | /** | ||
| 726 | * File-system tells the kernel to invalidate cache for the given node id. | ||
| 727 | */ | ||
| 728 | int fuse_reverse_inval_inode(struct super_block *sb, u64 nodeid, | ||
| 729 | loff_t offset, loff_t len); | ||
| 730 | |||
| 731 | /** | ||
| 732 | * File-system tells the kernel to invalidate parent attributes and | ||
| 733 | * the dentry matching parent/name. | ||
| 734 | */ | ||
| 735 | int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid, | ||
| 736 | struct qstr *name); | ||
| 737 | |||
| 711 | int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file, | 738 | int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file, |
| 712 | bool isdir); | 739 | bool isdir); |
| 713 | ssize_t fuse_direct_io(struct file *file, const char __user *buf, | 740 | ssize_t fuse_direct_io(struct file *file, const char __user *buf, |
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index d8673ccf90b..f91ccc4a189 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 | ||
diff --git a/include/linux/fuse.h b/include/linux/fuse.h index d41ed593f79..cf593bf9fd3 100644 --- a/include/linux/fuse.h +++ b/include/linux/fuse.h | |||
| @@ -25,6 +25,11 @@ | |||
| 25 | * - add IOCTL message | 25 | * - add IOCTL message |
| 26 | * - add unsolicited notification support | 26 | * - add unsolicited notification support |
| 27 | * - add POLL message and NOTIFY_POLL notification | 27 | * - add POLL message and NOTIFY_POLL notification |
| 28 | * | ||
| 29 | * 7.12 | ||
| 30 | * - add umask flag to input argument of open, mknod and mkdir | ||
| 31 | * - add notification messages for invalidation of inodes and | ||
| 32 | * directory entries | ||
| 28 | */ | 33 | */ |
| 29 | 34 | ||
| 30 | #ifndef _LINUX_FUSE_H | 35 | #ifndef _LINUX_FUSE_H |
| @@ -36,7 +41,7 @@ | |||
| 36 | #define FUSE_KERNEL_VERSION 7 | 41 | #define FUSE_KERNEL_VERSION 7 |
| 37 | 42 | ||
| 38 | /** Minor version number of this interface */ | 43 | /** Minor version number of this interface */ |
| 39 | #define FUSE_KERNEL_MINOR_VERSION 11 | 44 | #define FUSE_KERNEL_MINOR_VERSION 12 |
| 40 | 45 | ||
| 41 | /** The node ID of the root inode */ | 46 | /** The node ID of the root inode */ |
| 42 | #define FUSE_ROOT_ID 1 | 47 | #define FUSE_ROOT_ID 1 |
| @@ -112,6 +117,7 @@ struct fuse_file_lock { | |||
| 112 | * INIT request/reply flags | 117 | * INIT request/reply flags |
| 113 | * | 118 | * |
| 114 | * FUSE_EXPORT_SUPPORT: filesystem handles lookups of "." and ".." | 119 | * FUSE_EXPORT_SUPPORT: filesystem handles lookups of "." and ".." |
| 120 | * FUSE_DONT_MASK: don't apply umask to file mode on create operations | ||
| 115 | */ | 121 | */ |
| 116 | #define FUSE_ASYNC_READ (1 << 0) | 122 | #define FUSE_ASYNC_READ (1 << 0) |
| 117 | #define FUSE_POSIX_LOCKS (1 << 1) | 123 | #define FUSE_POSIX_LOCKS (1 << 1) |
| @@ -119,6 +125,7 @@ struct fuse_file_lock { | |||
| 119 | #define FUSE_ATOMIC_O_TRUNC (1 << 3) | 125 | #define FUSE_ATOMIC_O_TRUNC (1 << 3) |
| 120 | #define FUSE_EXPORT_SUPPORT (1 << 4) | 126 | #define FUSE_EXPORT_SUPPORT (1 << 4) |
| 121 | #define FUSE_BIG_WRITES (1 << 5) | 127 | #define FUSE_BIG_WRITES (1 << 5) |
| 128 | #define FUSE_DONT_MASK (1 << 6) | ||
| 122 | 129 | ||
| 123 | /** | 130 | /** |
| 124 | * CUSE INIT request/reply flags | 131 | * CUSE INIT request/reply flags |
| @@ -224,6 +231,8 @@ enum fuse_opcode { | |||
| 224 | 231 | ||
| 225 | enum fuse_notify_code { | 232 | enum fuse_notify_code { |
| 226 | FUSE_NOTIFY_POLL = 1, | 233 | FUSE_NOTIFY_POLL = 1, |
| 234 | FUSE_NOTIFY_INVAL_INODE = 2, | ||
| 235 | FUSE_NOTIFY_INVAL_ENTRY = 3, | ||
| 227 | FUSE_NOTIFY_CODE_MAX, | 236 | FUSE_NOTIFY_CODE_MAX, |
| 228 | }; | 237 | }; |
| 229 | 238 | ||
| @@ -262,14 +271,18 @@ struct fuse_attr_out { | |||
| 262 | struct fuse_attr attr; | 271 | struct fuse_attr attr; |
| 263 | }; | 272 | }; |
| 264 | 273 | ||
| 274 | #define FUSE_COMPAT_MKNOD_IN_SIZE 8 | ||
| 275 | |||
| 265 | struct fuse_mknod_in { | 276 | struct fuse_mknod_in { |
| 266 | __u32 mode; | 277 | __u32 mode; |
| 267 | __u32 rdev; | 278 | __u32 rdev; |
| 279 | __u32 umask; | ||
| 280 | __u32 padding; | ||
| 268 | }; | 281 | }; |
| 269 | 282 | ||
| 270 | struct fuse_mkdir_in { | 283 | struct fuse_mkdir_in { |
| 271 | __u32 mode; | 284 | __u32 mode; |
| 272 | __u32 padding; | 285 | __u32 umask; |
| 273 | }; | 286 | }; |
| 274 | 287 | ||
| 275 | struct fuse_rename_in { | 288 | struct fuse_rename_in { |
| @@ -301,7 +314,14 @@ struct fuse_setattr_in { | |||
| 301 | 314 | ||
| 302 | struct fuse_open_in { | 315 | struct fuse_open_in { |
| 303 | __u32 flags; | 316 | __u32 flags; |
| 317 | __u32 unused; | ||
| 318 | }; | ||
| 319 | |||
| 320 | struct fuse_create_in { | ||
| 321 | __u32 flags; | ||
| 304 | __u32 mode; | 322 | __u32 mode; |
| 323 | __u32 umask; | ||
| 324 | __u32 padding; | ||
| 305 | }; | 325 | }; |
| 306 | 326 | ||
| 307 | struct fuse_open_out { | 327 | struct fuse_open_out { |
| @@ -508,4 +528,16 @@ struct fuse_dirent { | |||
| 508 | #define FUSE_DIRENT_SIZE(d) \ | 528 | #define FUSE_DIRENT_SIZE(d) \ |
| 509 | FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + (d)->namelen) | 529 | FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + (d)->namelen) |
| 510 | 530 | ||
| 531 | struct fuse_notify_inval_inode_out { | ||
| 532 | __u64 ino; | ||
| 533 | __s64 off; | ||
| 534 | __s64 len; | ||
| 535 | }; | ||
| 536 | |||
| 537 | struct fuse_notify_inval_entry_out { | ||
| 538 | __u64 parent; | ||
| 539 | __u32 namelen; | ||
| 540 | __u32 padding; | ||
| 541 | }; | ||
| 542 | |||
| 511 | #endif /* _LINUX_FUSE_H */ | 543 | #endif /* _LINUX_FUSE_H */ |
