mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 15:22:21 -04:00
cifs: invalidate cfid on unlink/rename/rmdir
Today we do not invalidate the cached_dirent or the entire parent cfid when a dentry in a dir has been removed/moved. This change invalidates the parent cfid so that we don't serve directory contents from the cache. Cc: <stable@vger.kernel.org> Signed-off-by: Shyam Prasad N <sprasad@microsoft.com> Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
committed by
Steve French
parent
8cd9520d35
commit
f71d68d2b4
@@ -28,6 +28,23 @@
|
||||
#include "cached_dir.h"
|
||||
#include "reparse.h"
|
||||
|
||||
static void cifs_invalidate_cached_dir(struct cifs_tcon *tcon,
|
||||
struct dentry *parent)
|
||||
{
|
||||
struct cached_fid *parent_cfid = NULL;
|
||||
|
||||
if (!tcon || !parent)
|
||||
return;
|
||||
|
||||
if (!open_cached_dir_by_dentry(tcon, parent, &parent_cfid)) {
|
||||
mutex_lock(&parent_cfid->dirents.de_mutex);
|
||||
parent_cfid->dirents.is_valid = false;
|
||||
parent_cfid->dirents.is_failed = true;
|
||||
mutex_unlock(&parent_cfid->dirents.de_mutex);
|
||||
close_cached_dir(parent_cfid);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set parameters for the netfs library
|
||||
*/
|
||||
@@ -2067,6 +2084,9 @@ static int __cifs_unlink(struct inode *dir, struct dentry *dentry, bool sillyren
|
||||
cifs_set_file_info(inode, attrs, xid, full_path, origattr);
|
||||
|
||||
out_reval:
|
||||
if (!rc && dentry->d_parent)
|
||||
cifs_invalidate_cached_dir(tcon, dentry->d_parent);
|
||||
|
||||
if (inode) {
|
||||
cifs_inode = CIFS_I(inode);
|
||||
cifs_inode->time = 0; /* will force revalidate to get info
|
||||
@@ -2378,7 +2398,6 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
|
||||
}
|
||||
|
||||
rc = server->ops->rmdir(xid, tcon, full_path, cifs_sb);
|
||||
cifs_put_tlink(tlink);
|
||||
|
||||
cifsInode = CIFS_I(d_inode(direntry));
|
||||
|
||||
@@ -2388,6 +2407,8 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
|
||||
i_size_write(d_inode(direntry), 0);
|
||||
clear_nlink(d_inode(direntry));
|
||||
spin_unlock(&d_inode(direntry)->i_lock);
|
||||
if (direntry->d_parent)
|
||||
cifs_invalidate_cached_dir(tcon, direntry->d_parent);
|
||||
}
|
||||
|
||||
/* force revalidate to go get info when needed */
|
||||
@@ -2402,6 +2423,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
|
||||
|
||||
inode_set_ctime_current(d_inode(direntry));
|
||||
inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode));
|
||||
cifs_put_tlink(tlink);
|
||||
|
||||
rmdir_exit:
|
||||
free_dentry_path(page);
|
||||
@@ -2668,6 +2690,12 @@ cifs_rename2(struct mnt_idmap *idmap, struct inode *source_dir,
|
||||
}
|
||||
|
||||
/* force revalidate to go get info when needed */
|
||||
if (!rc) {
|
||||
cifs_invalidate_cached_dir(tcon, source_dentry->d_parent);
|
||||
if (target_dentry->d_parent != source_dentry->d_parent)
|
||||
cifs_invalidate_cached_dir(tcon, target_dentry->d_parent);
|
||||
}
|
||||
|
||||
CIFS_I(source_dir)->time = CIFS_I(target_dir)->time = 0;
|
||||
|
||||
cifs_rename_exit:
|
||||
|
||||
Reference in New Issue
Block a user