@@ -4048,11 +4048,9 @@ static long do_unlinkat(int dfd, const char __user *pathname)
if (inode)
iput(inode); /* truncate the inode here */
inode = NULL;
- if (delegated_inode) {
- error = break_deleg_wait(&delegated_inode);
- if (!error)
- goto retry_deleg;
- }
+ error = break_deleg_wait(&delegated_inode, error);
+ if (error == DELEG_RETRY)
+ goto retry_deleg;
mnt_drop_write(path.mnt);
exit1:
path_put(&path);
@@ -4283,12 +4281,10 @@ SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname,
error = vfs_link(old_path.dentry, new_path.dentry->d_inode, new_dentry, &delegated_inode);
out_dput:
done_path_create(&new_path, new_dentry);
- if (delegated_inode) {
- error = break_deleg_wait(&delegated_inode);
- if (!error) {
- path_put(&old_path);
- goto retry;
- }
+ error = break_deleg_wait(&delegated_inode, error);
+ if (error == DELEG_RETRY) {
+ path_put(&old_path);
+ goto retry;
}
if (retry_estale(error, how)) {
path_put(&old_path);
@@ -4601,11 +4597,9 @@ SYSCALL_DEFINE5(renameat2, int, olddfd, const char __user *, oldname,
dput(old_dentry);
exit3:
unlock_rename(new_path.dentry, old_path.dentry);
- if (delegated_inode) {
- error = break_deleg_wait(&delegated_inode);
- if (!error)
- goto retry_deleg;
- }
+ error = break_deleg_wait(&delegated_inode, error);
+ if (error == DELEG_RETRY)
+ goto retry_deleg;
mnt_drop_write(old_path.mnt);
exit2:
if (retry_estale(error, lookup_flags))
@@ -532,11 +532,9 @@ static int chmod_common(const struct path *path, umode_t mode)
error = notify_change(path->dentry, &newattrs, &delegated_inode);
out_unlock:
inode_unlock(inode);
- if (delegated_inode) {
- error = break_deleg_wait(&delegated_inode);
- if (!error)
- goto retry_deleg;
- }
+ error = break_deleg_wait(&delegated_inode, error);
+ if (error == DELEG_RETRY)
+ goto retry_deleg;
mnt_drop_write(path->mnt);
return error;
}
@@ -611,11 +609,9 @@ static int chown_common(const struct path *path, uid_t user, gid_t group)
if (!error)
error = notify_change(path->dentry, &newattrs, &delegated_inode);
inode_unlock(inode);
- if (delegated_inode) {
- error = break_deleg_wait(&delegated_inode);
- if (!error)
- goto retry_deleg;
- }
+ error = break_deleg_wait(&delegated_inode, error);
+ if (error == DELEG_RETRY)
+ goto retry_deleg;
return error;
}
@@ -89,11 +89,9 @@ static int utimes_common(const struct path *path, struct timespec *times)
inode_lock(inode);
error = notify_change(path->dentry, &newattrs, &delegated_inode);
inode_unlock(inode);
- if (delegated_inode) {
- error = break_deleg_wait(&delegated_inode);
- if (!error)
- goto retry_deleg;
- }
+ error = break_deleg_wait(&delegated_inode, error);
+ if (error == DELEG_RETRY)
+ goto retry_deleg;
mnt_drop_write(path->mnt);
out:
@@ -2288,14 +2288,16 @@ static inline int try_break_deleg(struct inode *inode, struct inode **delegated_
return ret;
}
-static inline int break_deleg_wait(struct inode **delegated_inode)
-{
- int ret;
+#define DELEG_RETRY 1
- ret = break_deleg(*delegated_inode, O_WRONLY);
+static inline int break_deleg_wait(struct inode **delegated_inode, int error)
+{
+ if (!*delegated_inode)
+ return error;
+ error = break_deleg(*delegated_inode, O_WRONLY);
iput(*delegated_inode);
*delegated_inode = NULL;
- return ret;
+ return error ? error : DELEG_RETRY;
}
static inline int break_layout(struct inode *inode, bool wait)