locks: break delegations on any attribute modification
NFSv4 uses leases to guarantee that clients can cache metadata as well as data. Cc: Mikulas Patocka <mikulas@artax.karlin.mff.cuni.cz> Cc: David Howells <dhowells@redhat.com> Cc: Tyler Hicks <tyhicks@canonical.com> Cc: Dustin Kirkland <dustin.kirkland@gazzang.com> Acked-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
22
fs/open.c
22
fs/open.c
@@ -57,7 +57,8 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
|
||||
newattrs.ia_valid |= ret | ATTR_FORCE;
|
||||
|
||||
mutex_lock(&dentry->d_inode->i_mutex);
|
||||
ret = notify_change(dentry, &newattrs);
|
||||
/* Note any delegations or leases have already been broken: */
|
||||
ret = notify_change(dentry, &newattrs, NULL);
|
||||
mutex_unlock(&dentry->d_inode->i_mutex);
|
||||
return ret;
|
||||
}
|
||||
@@ -464,21 +465,28 @@ out:
|
||||
static int chmod_common(struct path *path, umode_t mode)
|
||||
{
|
||||
struct inode *inode = path->dentry->d_inode;
|
||||
struct inode *delegated_inode = NULL;
|
||||
struct iattr newattrs;
|
||||
int error;
|
||||
|
||||
error = mnt_want_write(path->mnt);
|
||||
if (error)
|
||||
return error;
|
||||
retry_deleg:
|
||||
mutex_lock(&inode->i_mutex);
|
||||
error = security_path_chmod(path, mode);
|
||||
if (error)
|
||||
goto out_unlock;
|
||||
newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
|
||||
newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
|
||||
error = notify_change(path->dentry, &newattrs);
|
||||
error = notify_change(path->dentry, &newattrs, &delegated_inode);
|
||||
out_unlock:
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
if (delegated_inode) {
|
||||
error = break_deleg_wait(&delegated_inode);
|
||||
if (!error)
|
||||
goto retry_deleg;
|
||||
}
|
||||
mnt_drop_write(path->mnt);
|
||||
return error;
|
||||
}
|
||||
@@ -522,6 +530,7 @@ SYSCALL_DEFINE2(chmod, const char __user *, filename, umode_t, mode)
|
||||
static int chown_common(struct path *path, uid_t user, gid_t group)
|
||||
{
|
||||
struct inode *inode = path->dentry->d_inode;
|
||||
struct inode *delegated_inode = NULL;
|
||||
int error;
|
||||
struct iattr newattrs;
|
||||
kuid_t uid;
|
||||
@@ -546,12 +555,17 @@ static int chown_common(struct path *path, uid_t user, gid_t group)
|
||||
if (!S_ISDIR(inode->i_mode))
|
||||
newattrs.ia_valid |=
|
||||
ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
|
||||
retry_deleg:
|
||||
mutex_lock(&inode->i_mutex);
|
||||
error = security_path_chown(path, uid, gid);
|
||||
if (!error)
|
||||
error = notify_change(path->dentry, &newattrs);
|
||||
error = notify_change(path->dentry, &newattrs, &delegated_inode);
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
|
||||
if (delegated_inode) {
|
||||
error = break_deleg_wait(&delegated_inode);
|
||||
if (!error)
|
||||
goto retry_deleg;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user