diff options
Diffstat (limited to 'fs/fuse/inode.c')
-rw-r--r-- | fs/fuse/inode.c | 22 |
1 files changed, 17 insertions, 5 deletions
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 | ||
120 | void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr) | 120 | |
121 | void 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 | ||
196 | struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid, | 205 | struct 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 | } |
462 | out: | 474 | out: |
@@ -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 | ||
494 | static const struct super_operations fuse_super_operations = { | 506 | static const struct super_operations fuse_super_operations = { |