aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/fuse/dir.c37
-rw-r--r--fs/fuse/inode.c2
-rw-r--r--include/linux/fuse.h23
3 files changed, 47 insertions, 15 deletions
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index a058b664859c..8c5d156284a0 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -705,10 +705,12 @@ static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
705 stat->blksize = (1 << inode->i_blkbits); 705 stat->blksize = (1 << inode->i_blkbits);
706} 706}
707 707
708static int fuse_do_getattr(struct inode *inode, struct kstat *stat) 708static int fuse_do_getattr(struct inode *inode, struct kstat *stat,
709 struct file *file)
709{ 710{
710 int err; 711 int err;
711 struct fuse_attr_out arg; 712 struct fuse_getattr_in inarg;
713 struct fuse_attr_out outarg;
712 struct fuse_conn *fc = get_fuse_conn(inode); 714 struct fuse_conn *fc = get_fuse_conn(inode);
713 struct fuse_req *req; 715 struct fuse_req *req;
714 u64 attr_version; 716 u64 attr_version;
@@ -721,24 +723,35 @@ static int fuse_do_getattr(struct inode *inode, struct kstat *stat)
721 attr_version = fc->attr_version; 723 attr_version = fc->attr_version;
722 spin_unlock(&fc->lock); 724 spin_unlock(&fc->lock);
723 725
726 memset(&inarg, 0, sizeof(inarg));
727 /* Directories have separate file-handle space */
728 if (file && S_ISREG(inode->i_mode)) {
729 struct fuse_file *ff = file->private_data;
730
731 inarg.getattr_flags |= FUSE_GETATTR_FH;
732 inarg.fh = ff->fh;
733 }
724 req->in.h.opcode = FUSE_GETATTR; 734 req->in.h.opcode = FUSE_GETATTR;
725 req->in.h.nodeid = get_node_id(inode); 735 req->in.h.nodeid = get_node_id(inode);
736 req->in.numargs = 1;
737 req->in.args[0].size = sizeof(inarg);
738 req->in.args[0].value = &inarg;
726 req->out.numargs = 1; 739 req->out.numargs = 1;
727 req->out.args[0].size = sizeof(arg); 740 req->out.args[0].size = sizeof(outarg);
728 req->out.args[0].value = &arg; 741 req->out.args[0].value = &outarg;
729 request_send(fc, req); 742 request_send(fc, req);
730 err = req->out.h.error; 743 err = req->out.h.error;
731 fuse_put_request(fc, req); 744 fuse_put_request(fc, req);
732 if (!err) { 745 if (!err) {
733 if ((inode->i_mode ^ arg.attr.mode) & S_IFMT) { 746 if ((inode->i_mode ^ outarg.attr.mode) & S_IFMT) {
734 make_bad_inode(inode); 747 make_bad_inode(inode);
735 err = -EIO; 748 err = -EIO;
736 } else { 749 } else {
737 fuse_change_attributes(inode, &arg.attr, 750 fuse_change_attributes(inode, &outarg.attr,
738 attr_timeout(&arg), 751 attr_timeout(&outarg),
739 attr_version); 752 attr_version);
740 if (stat) 753 if (stat)
741 fuse_fillattr(inode, &arg.attr, stat); 754 fuse_fillattr(inode, &outarg.attr, stat);
742 } 755 }
743 } 756 }
744 return err; 757 return err;
@@ -833,7 +846,7 @@ static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd)
833 ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) { 846 ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) {
834 struct fuse_inode *fi = get_fuse_inode(inode); 847 struct fuse_inode *fi = get_fuse_inode(inode);
835 if (fi->i_time < get_jiffies_64()) { 848 if (fi->i_time < get_jiffies_64()) {
836 err = fuse_do_getattr(inode, NULL); 849 err = fuse_do_getattr(inode, NULL, NULL);
837 if (err) 850 if (err)
838 return err; 851 return err;
839 852
@@ -848,7 +861,7 @@ static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd)
848 attributes. This is also needed, because the root 861 attributes. This is also needed, because the root
849 node will at first have no permissions */ 862 node will at first have no permissions */
850 if (err == -EACCES && !refreshed) { 863 if (err == -EACCES && !refreshed) {
851 err = fuse_do_getattr(inode, NULL); 864 err = fuse_do_getattr(inode, NULL, NULL);
852 if (!err) 865 if (!err)
853 err = generic_permission(inode, mask, NULL); 866 err = generic_permission(inode, mask, NULL);
854 } 867 }
@@ -864,7 +877,7 @@ static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd)
864 if (refreshed) 877 if (refreshed)
865 return -EACCES; 878 return -EACCES;
866 879
867 err = fuse_do_getattr(inode, NULL); 880 err = fuse_do_getattr(inode, NULL, NULL);
868 if (!err && !(inode->i_mode & S_IXUGO)) 881 if (!err && !(inode->i_mode & S_IXUGO))
869 return -EACCES; 882 return -EACCES;
870 } 883 }
@@ -1107,7 +1120,7 @@ static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
1107 return -EACCES; 1120 return -EACCES;
1108 1121
1109 if (fi->i_time < get_jiffies_64()) 1122 if (fi->i_time < get_jiffies_64())
1110 err = fuse_do_getattr(inode, stat); 1123 err = fuse_do_getattr(inode, stat, NULL);
1111 else { 1124 else {
1112 err = 0; 1125 err = 0;
1113 generic_fillattr(inode, stat); 1126 generic_fillattr(inode, stat);
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 2167fc4fcab8..6ef3973f4048 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -553,7 +553,7 @@ static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req)
553 arg->major = FUSE_KERNEL_VERSION; 553 arg->major = FUSE_KERNEL_VERSION;
554 arg->minor = FUSE_KERNEL_MINOR_VERSION; 554 arg->minor = FUSE_KERNEL_MINOR_VERSION;
555 arg->max_readahead = fc->bdi.ra_pages * PAGE_CACHE_SIZE; 555 arg->max_readahead = fc->bdi.ra_pages * PAGE_CACHE_SIZE;
556 arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS; 556 arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_FILE_OPS;
557 req->in.h.opcode = FUSE_INIT; 557 req->in.h.opcode = FUSE_INIT;
558 req->in.numargs = 1; 558 req->in.numargs = 1;
559 req->in.args[0].size = sizeof(*arg); 559 req->in.args[0].size = sizeof(*arg);
diff --git a/include/linux/fuse.h b/include/linux/fuse.h
index 9fbe9d258e22..a50d0d9ac7ae 100644
--- a/include/linux/fuse.h
+++ b/include/linux/fuse.h
@@ -6,7 +6,14 @@
6 See the file COPYING. 6 See the file COPYING.
7*/ 7*/
8 8
9/* This file defines the kernel interface of FUSE */ 9/*
10 * This file defines the kernel interface of FUSE
11 *
12 * Protocol changelog:
13 *
14 * 7.9:
15 * - new fuse_getattr_in input argument of GETATTR
16 */
10 17
11#include <asm/types.h> 18#include <asm/types.h>
12#include <linux/major.h> 19#include <linux/major.h>
@@ -15,7 +22,7 @@
15#define FUSE_KERNEL_VERSION 7 22#define FUSE_KERNEL_VERSION 7
16 23
17/** Minor version number of this interface */ 24/** Minor version number of this interface */
18#define FUSE_KERNEL_MINOR_VERSION 8 25#define FUSE_KERNEL_MINOR_VERSION 9
19 26
20/** The node ID of the root inode */ 27/** The node ID of the root inode */
21#define FUSE_ROOT_ID 1 28#define FUSE_ROOT_ID 1
@@ -91,12 +98,18 @@ struct fuse_file_lock {
91 */ 98 */
92#define FUSE_ASYNC_READ (1 << 0) 99#define FUSE_ASYNC_READ (1 << 0)
93#define FUSE_POSIX_LOCKS (1 << 1) 100#define FUSE_POSIX_LOCKS (1 << 1)
101#define FUSE_FILE_OPS (1 << 2)
94 102
95/** 103/**
96 * Release flags 104 * Release flags
97 */ 105 */
98#define FUSE_RELEASE_FLUSH (1 << 0) 106#define FUSE_RELEASE_FLUSH (1 << 0)
99 107
108/**
109 * Getattr flags
110 */
111#define FUSE_GETATTR_FH (1 << 0)
112
100enum fuse_opcode { 113enum fuse_opcode {
101 FUSE_LOOKUP = 1, 114 FUSE_LOOKUP = 1,
102 FUSE_FORGET = 2, /* no reply */ 115 FUSE_FORGET = 2, /* no reply */
@@ -154,6 +167,12 @@ struct fuse_forget_in {
154 __u64 nlookup; 167 __u64 nlookup;
155}; 168};
156 169
170struct fuse_getattr_in {
171 __u32 getattr_flags;
172 __u32 dummy;
173 __u64 fh;
174};
175
157struct fuse_attr_out { 176struct fuse_attr_out {
158 __u64 attr_valid; /* Cache timeout for the attributes */ 177 __u64 attr_valid; /* Cache timeout for the attributes */
159 __u32 attr_valid_nsec; 178 __u32 attr_valid_nsec;