diff options
Diffstat (limited to 'fs/utimes.c')
| -rw-r--r-- | fs/utimes.c | 27 | 
1 files changed, 19 insertions, 8 deletions
diff --git a/fs/utimes.c b/fs/utimes.c index 179b5869065..aa138d64560 100644 --- a/fs/utimes.c +++ b/fs/utimes.c @@ -53,6 +53,7 @@ static int utimes_common(struct path *path, struct timespec *times)  	int error;  	struct iattr newattrs;  	struct inode *inode = path->dentry->d_inode; +	struct inode *delegated_inode = NULL;  	error = mnt_want_write(path->mnt);  	if (error) @@ -95,15 +96,21 @@ static int utimes_common(struct path *path, struct timespec *times)                  if (IS_IMMUTABLE(inode))  			goto mnt_drop_write_and_out; -		if (!is_owner_or_cap(inode)) { +		if (!inode_owner_or_capable(inode)) {  			error = inode_permission(inode, MAY_WRITE);  			if (error)  				goto mnt_drop_write_and_out;  		}  	} +retry_deleg:  	mutex_lock(&inode->i_mutex); -	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; +	}  mnt_drop_write_and_out:  	mnt_drop_write(path->mnt); @@ -140,31 +147,35 @@ long do_utimes(int dfd, const char __user *filename, struct timespec *times,  		goto out;  	if (filename == NULL && dfd != AT_FDCWD) { -		struct file *file; +		struct fd f;  		if (flags & AT_SYMLINK_NOFOLLOW)  			goto out; -		file = fget(dfd); +		f = fdget(dfd);  		error = -EBADF; -		if (!file) +		if (!f.file)  			goto out; -		error = utimes_common(&file->f_path, times); -		fput(file); +		error = utimes_common(&f.file->f_path, times); +		fdput(f);  	} else {  		struct path path;  		int lookup_flags = 0;  		if (!(flags & AT_SYMLINK_NOFOLLOW))  			lookup_flags |= LOOKUP_FOLLOW; - +retry:  		error = user_path_at(dfd, filename, lookup_flags, &path);  		if (error)  			goto out;  		error = utimes_common(&path, times);  		path_put(&path); +		if (retry_estale(error, lookup_flags)) { +			lookup_flags |= LOOKUP_REVAL; +			goto retry; +		}  	}  out:  | 
