From: Miklos Szeredi mszeredi@redhat.com
commit 371e8fd02969383204b1f6023451125dbc20dfbd upstream.
Logically it belongs there since attributes are invalidated due to the updated ctime. This is a cleanup and should not change behavior.
Signed-off-by: Miklos Szeredi mszeredi@redhat.com Signed-off-by: Dmitriy Privalov d.privalov@omp.ru --- v2: Add 371e8fd02969 and cefd1b83275d to backport
fs/fuse/dir.c | 9 ++------- fs/fuse/xattr.c | 10 ++++------ 2 files changed, 6 insertions(+), 13 deletions(-)
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 4488a53a192d..38c3bc68d080 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -809,6 +809,7 @@ void fuse_flush_time_update(struct inode *inode)
void fuse_update_ctime(struct inode *inode) { + fuse_invalidate_attr(inode); if (!IS_NOCMTIME(inode)) { inode->i_ctime = current_time(inode); mark_inode_dirty_sync(inode); @@ -846,7 +847,6 @@ static int fuse_unlink(struct inode *dir, struct dentry *entry) if (inode->i_nlink > 0) drop_nlink(inode); spin_unlock(&fi->lock); - fuse_invalidate_attr(inode); fuse_dir_changed(dir); fuse_invalidate_entry_cache(entry); fuse_update_ctime(inode); @@ -903,13 +903,10 @@ static int fuse_rename_common(struct inode *olddir, struct dentry *oldent, err = fuse_simple_request(fm, &args); if (!err) { /* ctime changes */ - fuse_invalidate_attr(d_inode(oldent)); fuse_update_ctime(d_inode(oldent));
- if (flags & RENAME_EXCHANGE) { - fuse_invalidate_attr(d_inode(newent)); + if (flags & RENAME_EXCHANGE) fuse_update_ctime(d_inode(newent)); - }
fuse_dir_changed(olddir); if (olddir != newdir) @@ -917,7 +914,6 @@ static int fuse_rename_common(struct inode *olddir, struct dentry *oldent,
/* newent will end up negative */ if (!(flags & RENAME_EXCHANGE) && d_really_is_positive(newent)) { - fuse_invalidate_attr(d_inode(newent)); fuse_invalidate_entry_cache(newent); fuse_update_ctime(d_inode(newent)); } @@ -1000,7 +996,6 @@ static int fuse_link(struct dentry *entry, struct inode *newdir, if (likely(inode->i_nlink < UINT_MAX)) inc_nlink(inode); spin_unlock(&fi->lock); - fuse_invalidate_attr(inode); fuse_update_ctime(inode); } else if (err == -EINTR) { fuse_invalidate_attr(inode); diff --git a/fs/fuse/xattr.c b/fs/fuse/xattr.c index 314e460ce679..27d7ea5e4176 100644 --- a/fs/fuse/xattr.c +++ b/fs/fuse/xattr.c @@ -39,10 +39,9 @@ int fuse_setxattr(struct inode *inode, const char *name, const void *value, fm->fc->no_setxattr = 1; err = -EOPNOTSUPP; } - if (!err) { - fuse_invalidate_attr(inode); + if (!err) fuse_update_ctime(inode); - } + return err; }
@@ -170,10 +169,9 @@ int fuse_removexattr(struct inode *inode, const char *name) fm->fc->no_removexattr = 1; err = -EOPNOTSUPP; } - if (!err) { - fuse_invalidate_attr(inode); + if (!err) fuse_update_ctime(inode); - } + return err; }
From: Miklos Szeredi mszeredi@redhat.com
commit cefd1b83275d4c587bdeb2fe7aed07908642f875 upstream.
Rename didn't decrement/clear nlink on overwritten target inode.
Create a common helper fuse_entry_unlinked() that handles this for unlink, rmdir and rename.
Signed-off-by: Miklos Szeredi mszeredi@redhat.com Signed-off-by: Dmitriy Privalov d.privalov@omp.ru --- v2: Add 371e8fd02969 and cefd1b83275d to backport
fs/fuse/dir.c | 49 +++++++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 22 deletions(-)
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 38c3bc68d080..f8b444674c14 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -817,6 +817,29 @@ void fuse_update_ctime(struct inode *inode) } }
+static void fuse_entry_unlinked(struct dentry *entry) +{ + struct inode *inode = d_inode(entry); + struct fuse_conn *fc = get_fuse_conn(inode); + struct fuse_inode *fi = get_fuse_inode(inode); + + spin_lock(&fi->lock); + fi->attr_version = atomic64_inc_return(&fc->attr_version); + /* + * If i_nlink == 0 then unlink doesn't make sense, yet this can + * happen if userspace filesystem is careless. It would be + * difficult to enforce correct nlink usage so just ignore this + * condition here + */ + if (S_ISDIR(inode->i_mode)) + clear_nlink(inode); + else if (inode->i_nlink > 0) + drop_nlink(inode); + spin_unlock(&fi->lock); + fuse_invalidate_entry_cache(entry); + fuse_update_ctime(inode); +} + static int fuse_unlink(struct inode *dir, struct dentry *entry) { int err; @@ -833,23 +856,8 @@ static int fuse_unlink(struct inode *dir, struct dentry *entry) args.in_args[0].value = entry->d_name.name; err = fuse_simple_request(fm, &args); if (!err) { - struct inode *inode = d_inode(entry); - struct fuse_inode *fi = get_fuse_inode(inode); - - spin_lock(&fi->lock); - fi->attr_version = atomic64_inc_return(&fm->fc->attr_version); - /* - * If i_nlink == 0 then unlink doesn't make sense, yet this can - * happen if userspace filesystem is careless. It would be - * difficult to enforce correct nlink usage so just ignore this - * condition here - */ - if (inode->i_nlink > 0) - drop_nlink(inode); - spin_unlock(&fi->lock); fuse_dir_changed(dir); - fuse_invalidate_entry_cache(entry); - fuse_update_ctime(inode); + fuse_entry_unlinked(entry); } else if (err == -EINTR) fuse_invalidate_entry(entry); return err; @@ -871,9 +879,8 @@ static int fuse_rmdir(struct inode *dir, struct dentry *entry) args.in_args[0].value = entry->d_name.name; err = fuse_simple_request(fm, &args); if (!err) { - clear_nlink(d_inode(entry)); fuse_dir_changed(dir); - fuse_invalidate_entry_cache(entry); + fuse_entry_unlinked(entry); } else if (err == -EINTR) fuse_invalidate_entry(entry); return err; @@ -913,10 +920,8 @@ static int fuse_rename_common(struct inode *olddir, struct dentry *oldent, fuse_dir_changed(newdir);
/* newent will end up negative */ - if (!(flags & RENAME_EXCHANGE) && d_really_is_positive(newent)) { - fuse_invalidate_entry_cache(newent); - fuse_update_ctime(d_inode(newent)); - } + if (!(flags & RENAME_EXCHANGE) && d_really_is_positive(newent)) + fuse_entry_unlinked(newent); } else if (err == -EINTR) { /* If request was interrupted, DEITY only knows if the rename actually took place. If the invalidation
From: Miklos Szeredi mszeredi@redhat.com
commit 97f044f690bac2b094bfb7fb2d177ef946c85880 upstream.
The fuse_iget() call in create_new_entry() already updated the inode with all the new attributes and incremented the attribute version.
Incrementing the nlink will result in the wrong count. This wasn't noticed because the attributes were invalidated right after this.
Updating ctime is still needed for the writeback case when the ctime is not refreshed.
Signed-off-by: Miklos Szeredi mszeredi@redhat.com Signed-off-by: Dmitriy Privalov d.privalov@omp.ru --- v2: Add 371e8fd02969 and cefd1b83275d to backport
fs/fuse/dir.c | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-)
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index f8b444674c14..08ede7f7d8dc 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -807,9 +807,8 @@ void fuse_flush_time_update(struct inode *inode) mapping_set_error(inode->i_mapping, err); }
-void fuse_update_ctime(struct inode *inode) +static void fuse_update_ctime_in_cache(struct inode *inode) { - fuse_invalidate_attr(inode); if (!IS_NOCMTIME(inode)) { inode->i_ctime = current_time(inode); mark_inode_dirty_sync(inode); @@ -817,6 +816,12 @@ void fuse_update_ctime(struct inode *inode) } }
+void fuse_update_ctime(struct inode *inode) +{ + fuse_invalidate_attr(inode); + fuse_update_ctime_in_cache(inode); +} + static void fuse_entry_unlinked(struct dentry *entry) { struct inode *inode = d_inode(entry); @@ -987,24 +992,11 @@ static int fuse_link(struct dentry *entry, struct inode *newdir, args.in_args[1].size = newent->d_name.len + 1; args.in_args[1].value = newent->d_name.name; err = create_new_entry(fm, &args, newdir, newent, inode->i_mode); - /* Contrary to "normal" filesystems it can happen that link - makes two "logical" inodes point to the same "physical" - inode. We invalidate the attributes of the old one, so it - will reflect changes in the backing inode (link count, - etc.) - */ - if (!err) { - struct fuse_inode *fi = get_fuse_inode(inode); - - spin_lock(&fi->lock); - fi->attr_version = atomic64_inc_return(&fm->fc->attr_version); - if (likely(inode->i_nlink < UINT_MAX)) - inc_nlink(inode); - spin_unlock(&fi->lock); - fuse_update_ctime(inode); - } else if (err == -EINTR) { + if (!err) + fuse_update_ctime_in_cache(inode); + else if (err == -EINTR) fuse_invalidate_attr(inode); - } + return err; }
linux-stable-mirror@lists.linaro.org