aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@suse.cz>2007-10-18 06:06:58 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-18 17:37:30 -0400
commit1fb69e7817296da8a6824804bb206ca1e7f31425 (patch)
tree51f8ac8ab4f06207a406cb9e917a48d71616235c
parente57ac68378a287d6336d187b26971f35f7ee7251 (diff)
fuse: fix race between getattr and write
Getattr and lookup operations can be running in parallel to attribute changing operations, such as write and setattr. This means, that if for example getattr was slower than a write, the cached size attribute could be set to a stale value. To prevent this race, introduce a per-filesystem attribute version counter. This counter is incremented whenever cached attributes are modified, and the incremented value stored in the inode. Before storing new attributes in the cache, getattr and lookup check, using the version number, whether the attributes have been modified during the request's lifetime. If so, the returned attributes are not cached, because they might be stale. Thanks to Jakub Bogusz for the bug report and test program. [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> Cc: Jakub Bogusz <jakub.bogusz@gemius.pl> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--fs/fuse/dir.c125
-rw-r--r--fs/fuse/file.c2
-rw-r--r--fs/fuse/fuse_i.h12
-rw-r--r--fs/fuse/inode.c22
4 files changed, 111 insertions, 50 deletions
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index b18e06daeffb..a058b664859c 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -63,13 +63,21 @@ static u64 time_to_jiffies(unsigned long sec, unsigned long nsec)
63 * Set dentry and possibly attribute timeouts from the lookup/mk* 63 * Set dentry and possibly attribute timeouts from the lookup/mk*
64 * replies 64 * replies
65 */ 65 */
66static void fuse_change_timeout(struct dentry *entry, struct fuse_entry_out *o) 66static void fuse_change_entry_timeout(struct dentry *entry,
67 struct fuse_entry_out *o)
67{ 68{
68 fuse_dentry_settime(entry, 69 fuse_dentry_settime(entry,
69 time_to_jiffies(o->entry_valid, o->entry_valid_nsec)); 70 time_to_jiffies(o->entry_valid, o->entry_valid_nsec));
70 if (entry->d_inode) 71}
71 get_fuse_inode(entry->d_inode)->i_time = 72
72 time_to_jiffies(o->attr_valid, o->attr_valid_nsec); 73static u64 attr_timeout(struct fuse_attr_out *o)
74{
75 return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
76}
77
78static u64 entry_attr_timeout(struct fuse_entry_out *o)
79{
80 return time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
73} 81}
74 82
75/* 83/*
@@ -140,6 +148,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
140 struct fuse_req *req; 148 struct fuse_req *req;
141 struct fuse_req *forget_req; 149 struct fuse_req *forget_req;
142 struct dentry *parent; 150 struct dentry *parent;
151 u64 attr_version;
143 152
144 /* For negative dentries, always do a fresh lookup */ 153 /* For negative dentries, always do a fresh lookup */
145 if (!inode) 154 if (!inode)
@@ -156,6 +165,10 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
156 return 0; 165 return 0;
157 } 166 }
158 167
168 spin_lock(&fc->lock);
169 attr_version = fc->attr_version;
170 spin_unlock(&fc->lock);
171
159 parent = dget_parent(entry); 172 parent = dget_parent(entry);
160 fuse_lookup_init(req, parent->d_inode, entry, &outarg); 173 fuse_lookup_init(req, parent->d_inode, entry, &outarg);
161 request_send(fc, req); 174 request_send(fc, req);
@@ -180,8 +193,10 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
180 if (err || (outarg.attr.mode ^ inode->i_mode) & S_IFMT) 193 if (err || (outarg.attr.mode ^ inode->i_mode) & S_IFMT)
181 return 0; 194 return 0;
182 195
183 fuse_change_attributes(inode, &outarg.attr); 196 fuse_change_attributes(inode, &outarg.attr,
184 fuse_change_timeout(entry, &outarg); 197 entry_attr_timeout(&outarg),
198 attr_version);
199 fuse_change_entry_timeout(entry, &outarg);
185 } 200 }
186 return 1; 201 return 1;
187} 202}
@@ -228,6 +243,7 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
228 struct fuse_conn *fc = get_fuse_conn(dir); 243 struct fuse_conn *fc = get_fuse_conn(dir);
229 struct fuse_req *req; 244 struct fuse_req *req;
230 struct fuse_req *forget_req; 245 struct fuse_req *forget_req;
246 u64 attr_version;
231 247
232 if (entry->d_name.len > FUSE_NAME_MAX) 248 if (entry->d_name.len > FUSE_NAME_MAX)
233 return ERR_PTR(-ENAMETOOLONG); 249 return ERR_PTR(-ENAMETOOLONG);
@@ -242,6 +258,10 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
242 return ERR_PTR(PTR_ERR(forget_req)); 258 return ERR_PTR(PTR_ERR(forget_req));
243 } 259 }
244 260
261 spin_lock(&fc->lock);
262 attr_version = fc->attr_version;
263 spin_unlock(&fc->lock);
264
245 fuse_lookup_init(req, dir, entry, &outarg); 265 fuse_lookup_init(req, dir, entry, &outarg);
246 request_send(fc, req); 266 request_send(fc, req);
247 err = req->out.h.error; 267 err = req->out.h.error;
@@ -253,7 +273,8 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
253 err = -EIO; 273 err = -EIO;
254 if (!err && outarg.nodeid) { 274 if (!err && outarg.nodeid) {
255 inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, 275 inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
256 &outarg.attr); 276 &outarg.attr, entry_attr_timeout(&outarg),
277 attr_version);
257 if (!inode) { 278 if (!inode) {
258 fuse_send_forget(fc, forget_req, outarg.nodeid, 1); 279 fuse_send_forget(fc, forget_req, outarg.nodeid, 1);
259 return ERR_PTR(-ENOMEM); 280 return ERR_PTR(-ENOMEM);
@@ -276,7 +297,7 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
276 297
277 entry->d_op = &fuse_dentry_operations; 298 entry->d_op = &fuse_dentry_operations;
278 if (!err) 299 if (!err)
279 fuse_change_timeout(entry, &outarg); 300 fuse_change_entry_timeout(entry, &outarg);
280 else 301 else
281 fuse_invalidate_entry_cache(entry); 302 fuse_invalidate_entry_cache(entry);
282 return NULL; 303 return NULL;
@@ -363,7 +384,7 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode,
363 384
364 fuse_put_request(fc, req); 385 fuse_put_request(fc, req);
365 inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation, 386 inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation,
366 &outentry.attr); 387 &outentry.attr, entry_attr_timeout(&outentry), 0);
367 if (!inode) { 388 if (!inode) {
368 flags &= ~(O_CREAT | O_EXCL | O_TRUNC); 389 flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
369 ff->fh = outopen.fh; 390 ff->fh = outopen.fh;
@@ -373,7 +394,7 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode,
373 } 394 }
374 fuse_put_request(fc, forget_req); 395 fuse_put_request(fc, forget_req);
375 d_instantiate(entry, inode); 396 d_instantiate(entry, inode);
376 fuse_change_timeout(entry, &outentry); 397 fuse_change_entry_timeout(entry, &outentry);
377 file = lookup_instantiate_filp(nd, entry, generic_file_open); 398 file = lookup_instantiate_filp(nd, entry, generic_file_open);
378 if (IS_ERR(file)) { 399 if (IS_ERR(file)) {
379 ff->fh = outopen.fh; 400 ff->fh = outopen.fh;
@@ -428,7 +449,7 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
428 goto out_put_forget_req; 449 goto out_put_forget_req;
429 450
430 inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, 451 inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
431 &outarg.attr); 452 &outarg.attr, entry_attr_timeout(&outarg), 0);
432 if (!inode) { 453 if (!inode) {
433 fuse_send_forget(fc, forget_req, outarg.nodeid, 1); 454 fuse_send_forget(fc, forget_req, outarg.nodeid, 1);
434 return -ENOMEM; 455 return -ENOMEM;
@@ -451,7 +472,7 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req,
451 } else 472 } else
452 d_instantiate(entry, inode); 473 d_instantiate(entry, inode);
453 474
454 fuse_change_timeout(entry, &outarg); 475 fuse_change_entry_timeout(entry, &outarg);
455 fuse_invalidate_attr(dir); 476 fuse_invalidate_attr(dir);
456 return 0; 477 return 0;
457 478
@@ -663,15 +684,43 @@ static int fuse_link(struct dentry *entry, struct inode *newdir,
663 return err; 684 return err;
664} 685}
665 686
666static int fuse_do_getattr(struct inode *inode) 687static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr,
688 struct kstat *stat)
689{
690 stat->dev = inode->i_sb->s_dev;
691 stat->ino = attr->ino;
692 stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
693 stat->nlink = attr->nlink;
694 stat->uid = attr->uid;
695 stat->gid = attr->gid;
696 stat->rdev = inode->i_rdev;
697 stat->atime.tv_sec = attr->atime;
698 stat->atime.tv_nsec = attr->atimensec;
699 stat->mtime.tv_sec = attr->mtime;
700 stat->mtime.tv_nsec = attr->mtimensec;
701 stat->ctime.tv_sec = attr->ctime;
702 stat->ctime.tv_nsec = attr->ctimensec;
703 stat->size = attr->size;
704 stat->blocks = attr->blocks;
705 stat->blksize = (1 << inode->i_blkbits);
706}
707
708static int fuse_do_getattr(struct inode *inode, struct kstat *stat)
667{ 709{
668 int err; 710 int err;
669 struct fuse_attr_out arg; 711 struct fuse_attr_out arg;
670 struct fuse_conn *fc = get_fuse_conn(inode); 712 struct fuse_conn *fc = get_fuse_conn(inode);
671 struct fuse_req *req = fuse_get_req(fc); 713 struct fuse_req *req;
714 u64 attr_version;
715
716 req = fuse_get_req(fc);
672 if (IS_ERR(req)) 717 if (IS_ERR(req))
673 return PTR_ERR(req); 718 return PTR_ERR(req);
674 719
720 spin_lock(&fc->lock);
721 attr_version = fc->attr_version;
722 spin_unlock(&fc->lock);
723
675 req->in.h.opcode = FUSE_GETATTR; 724 req->in.h.opcode = FUSE_GETATTR;
676 req->in.h.nodeid = get_node_id(inode); 725 req->in.h.nodeid = get_node_id(inode);
677 req->out.numargs = 1; 726 req->out.numargs = 1;
@@ -685,30 +734,17 @@ static int fuse_do_getattr(struct inode *inode)
685 make_bad_inode(inode); 734 make_bad_inode(inode);
686 err = -EIO; 735 err = -EIO;
687 } else { 736 } else {
688 struct fuse_inode *fi = get_fuse_inode(inode); 737 fuse_change_attributes(inode, &arg.attr,
689 fuse_change_attributes(inode, &arg.attr); 738 attr_timeout(&arg),
690 fi->i_time = time_to_jiffies(arg.attr_valid, 739 attr_version);
691 arg.attr_valid_nsec); 740 if (stat)
741 fuse_fillattr(inode, &arg.attr, stat);
692 } 742 }
693 } 743 }
694 return err; 744 return err;
695} 745}
696 746
697/* 747/*
698 * Check if attributes are still valid, and if not send a GETATTR
699 * request to refresh them.
700 */
701static int fuse_refresh_attributes(struct inode *inode)
702{
703 struct fuse_inode *fi = get_fuse_inode(inode);
704
705 if (fi->i_time < get_jiffies_64())
706 return fuse_do_getattr(inode);
707 else
708 return 0;
709}
710
711/*
712 * Calling into a user-controlled filesystem gives the filesystem 748 * Calling into a user-controlled filesystem gives the filesystem
713 * daemon ptrace-like capabilities over the requester process. This 749 * daemon ptrace-like capabilities over the requester process. This
714 * means, that the filesystem daemon is able to record the exact 750 * means, that the filesystem daemon is able to record the exact
@@ -795,11 +831,14 @@ static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd)
795 */ 831 */
796 if ((fc->flags & FUSE_DEFAULT_PERMISSIONS) || 832 if ((fc->flags & FUSE_DEFAULT_PERMISSIONS) ||
797 ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) { 833 ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) {
798 err = fuse_refresh_attributes(inode); 834 struct fuse_inode *fi = get_fuse_inode(inode);
799 if (err) 835 if (fi->i_time < get_jiffies_64()) {
800 return err; 836 err = fuse_do_getattr(inode, NULL);
837 if (err)
838 return err;
801 839
802 refreshed = true; 840 refreshed = true;
841 }
803 } 842 }
804 843
805 if (fc->flags & FUSE_DEFAULT_PERMISSIONS) { 844 if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
@@ -809,7 +848,7 @@ static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd)
809 attributes. This is also needed, because the root 848 attributes. This is also needed, because the root
810 node will at first have no permissions */ 849 node will at first have no permissions */
811 if (err == -EACCES && !refreshed) { 850 if (err == -EACCES && !refreshed) {
812 err = fuse_do_getattr(inode); 851 err = fuse_do_getattr(inode, NULL);
813 if (!err) 852 if (!err)
814 err = generic_permission(inode, mask, NULL); 853 err = generic_permission(inode, mask, NULL);
815 } 854 }
@@ -825,7 +864,7 @@ static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd)
825 if (refreshed) 864 if (refreshed)
826 return -EACCES; 865 return -EACCES;
827 866
828 err = fuse_do_getattr(inode); 867 err = fuse_do_getattr(inode, NULL);
829 if (!err && !(inode->i_mode & S_IXUGO)) 868 if (!err && !(inode->i_mode & S_IXUGO))
830 return -EACCES; 869 return -EACCES;
831 } 870 }
@@ -999,7 +1038,6 @@ static int fuse_setattr(struct dentry *entry, struct iattr *attr)
999{ 1038{
1000 struct inode *inode = entry->d_inode; 1039 struct inode *inode = entry->d_inode;
1001 struct fuse_conn *fc = get_fuse_conn(inode); 1040 struct fuse_conn *fc = get_fuse_conn(inode);
1002 struct fuse_inode *fi = get_fuse_inode(inode);
1003 struct fuse_req *req; 1041 struct fuse_req *req;
1004 struct fuse_setattr_in inarg; 1042 struct fuse_setattr_in inarg;
1005 struct fuse_attr_out outarg; 1043 struct fuse_attr_out outarg;
@@ -1053,8 +1091,7 @@ static int fuse_setattr(struct dentry *entry, struct iattr *attr)
1053 return -EIO; 1091 return -EIO;
1054 } 1092 }
1055 1093
1056 fuse_change_attributes(inode, &outarg.attr); 1094 fuse_change_attributes(inode, &outarg.attr, attr_timeout(&outarg), 0);
1057 fi->i_time = time_to_jiffies(outarg.attr_valid, outarg.attr_valid_nsec);
1058 return 0; 1095 return 0;
1059} 1096}
1060 1097
@@ -1069,8 +1106,10 @@ static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
1069 if (!fuse_allow_task(fc, current)) 1106 if (!fuse_allow_task(fc, current))
1070 return -EACCES; 1107 return -EACCES;
1071 1108
1072 err = fuse_refresh_attributes(inode); 1109 if (fi->i_time < get_jiffies_64())
1073 if (!err) { 1110 err = fuse_do_getattr(inode, stat);
1111 else {
1112 err = 0;
1074 generic_fillattr(inode, stat); 1113 generic_fillattr(inode, stat);
1075 stat->mode = fi->orig_i_mode; 1114 stat->mode = fi->orig_i_mode;
1076 } 1115 }
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index c4b98c03a46e..4a28c3d37732 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -478,6 +478,7 @@ static int fuse_buffered_write(struct file *file, struct inode *inode,
478 int err; 478 int err;
479 size_t nres; 479 size_t nres;
480 struct fuse_conn *fc = get_fuse_conn(inode); 480 struct fuse_conn *fc = get_fuse_conn(inode);
481 struct fuse_inode *fi = get_fuse_inode(inode);
481 unsigned offset = pos & (PAGE_CACHE_SIZE - 1); 482 unsigned offset = pos & (PAGE_CACHE_SIZE - 1);
482 struct fuse_req *req; 483 struct fuse_req *req;
483 484
@@ -499,6 +500,7 @@ static int fuse_buffered_write(struct file *file, struct inode *inode,
499 if (!err) { 500 if (!err) {
500 pos += nres; 501 pos += nres;
501 spin_lock(&fc->lock); 502 spin_lock(&fc->lock);
503 fi->attr_version = ++fc->attr_version;
502 if (pos > inode->i_size) 504 if (pos > inode->i_size)
503 i_size_write(inode, pos); 505 i_size_write(inode, pos);
504 spin_unlock(&fc->lock); 506 spin_unlock(&fc->lock);
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index e7464b8ebbfb..ffbcadaa7d67 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -67,6 +67,9 @@ struct fuse_inode {
67 /** The sticky bit in inode->i_mode may have been removed, so 67 /** The sticky bit in inode->i_mode may have been removed, so
68 preserve the original mode */ 68 preserve the original mode */
69 mode_t orig_i_mode; 69 mode_t orig_i_mode;
70
71 /** Version of last attribute change */
72 u64 attr_version;
70}; 73};
71 74
72/** FUSE specific file data */ 75/** FUSE specific file data */
@@ -387,6 +390,9 @@ struct fuse_conn {
387 390
388 /** Reserved request for the DESTROY message */ 391 /** Reserved request for the DESTROY message */
389 struct fuse_req *destroy_req; 392 struct fuse_req *destroy_req;
393
394 /** Version counter for attribute changes */
395 u64 attr_version;
390}; 396};
391 397
392static inline struct fuse_conn *get_fuse_conn_super(struct super_block *sb) 398static inline struct fuse_conn *get_fuse_conn_super(struct super_block *sb)
@@ -416,7 +422,8 @@ extern const struct file_operations fuse_dev_operations;
416 * Get a filled in inode 422 * Get a filled in inode
417 */ 423 */
418struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid, 424struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid,
419 int generation, struct fuse_attr *attr); 425 int generation, struct fuse_attr *attr,
426 u64 attr_valid, u64 attr_version);
420 427
421/** 428/**
422 * Send FORGET command 429 * Send FORGET command
@@ -477,7 +484,8 @@ void fuse_init_symlink(struct inode *inode);
477/** 484/**
478 * Change attributes of an inode 485 * Change attributes of an inode
479 */ 486 */
480void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr); 487void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
488 u64 attr_valid, u64 attr_version);
481 489
482/** 490/**
483 * Initialize the client device 491 * Initialize the client device
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 00bb5a255ded..2167fc4fcab8 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -117,12 +117,22 @@ static void fuse_truncate(struct address_space *mapping, loff_t offset)
117 unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1); 117 unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
118} 118}
119 119
120void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr) 120
121void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
122 u64 attr_valid, u64 attr_version)
121{ 123{
122 struct fuse_conn *fc = get_fuse_conn(inode); 124 struct fuse_conn *fc = get_fuse_conn(inode);
123 struct fuse_inode *fi = get_fuse_inode(inode); 125 struct fuse_inode *fi = get_fuse_inode(inode);
124 loff_t oldsize; 126 loff_t oldsize;
125 127
128 spin_lock(&fc->lock);
129 if (attr_version != 0 && fi->attr_version > attr_version) {
130 spin_unlock(&fc->lock);
131 return;
132 }
133 fi->attr_version = ++fc->attr_version;
134 fi->i_time = attr_valid;
135
126 inode->i_ino = attr->ino; 136 inode->i_ino = attr->ino;
127 inode->i_mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777); 137 inode->i_mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
128 inode->i_nlink = attr->nlink; 138 inode->i_nlink = attr->nlink;
@@ -145,7 +155,6 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr)
145 if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS)) 155 if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS))
146 inode->i_mode &= ~S_ISVTX; 156 inode->i_mode &= ~S_ISVTX;
147 157
148 spin_lock(&fc->lock);
149 oldsize = inode->i_size; 158 oldsize = inode->i_size;
150 i_size_write(inode, attr->size); 159 i_size_write(inode, attr->size);
151 spin_unlock(&fc->lock); 160 spin_unlock(&fc->lock);
@@ -194,7 +203,8 @@ static int fuse_inode_set(struct inode *inode, void *_nodeidp)
194} 203}
195 204
196struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid, 205struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid,
197 int generation, struct fuse_attr *attr) 206 int generation, struct fuse_attr *attr,
207 u64 attr_valid, u64 attr_version)
198{ 208{
199 struct inode *inode; 209 struct inode *inode;
200 struct fuse_inode *fi; 210 struct fuse_inode *fi;
@@ -222,7 +232,8 @@ struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid,
222 spin_lock(&fc->lock); 232 spin_lock(&fc->lock);
223 fi->nlookup ++; 233 fi->nlookup ++;
224 spin_unlock(&fc->lock); 234 spin_unlock(&fc->lock);
225 fuse_change_attributes(inode, attr); 235 fuse_change_attributes(inode, attr, attr_valid, attr_version);
236
226 return inode; 237 return inode;
227} 238}
228 239
@@ -457,6 +468,7 @@ static struct fuse_conn *new_conn(void)
457 } 468 }
458 fc->reqctr = 0; 469 fc->reqctr = 0;
459 fc->blocked = 1; 470 fc->blocked = 1;
471 fc->attr_version = 1;
460 get_random_bytes(&fc->scramble_key, sizeof(fc->scramble_key)); 472 get_random_bytes(&fc->scramble_key, sizeof(fc->scramble_key));
461 } 473 }
462out: 474out:
@@ -488,7 +500,7 @@ static struct inode *get_root_inode(struct super_block *sb, unsigned mode)
488 attr.mode = mode; 500 attr.mode = mode;
489 attr.ino = FUSE_ROOT_ID; 501 attr.ino = FUSE_ROOT_ID;
490 attr.nlink = 1; 502 attr.nlink = 1;
491 return fuse_iget(sb, 1, 0, &attr); 503 return fuse_iget(sb, 1, 0, &attr, 0, 0);
492} 504}
493 505
494static const struct super_operations fuse_super_operations = { 506static const struct super_operations fuse_super_operations = {