History

NFS: nfs_rename() - revalidate directories on -ERESTARTSYS

An interrupted rename will leave the old dentry behind if the rename succeeds. Fix this by forcing a lookup the next time through ->d_revalidate. A previous attempt at solving this problem took the approach to complete the work of the rename asynchronously, however that approach was wrong since it would allow the d_move() to occur after the directory's i_mutex had been dropped by the original process.

Benjamin Coddington committed 9 years ago

Commit 818a8db1 parent a7a3b1e3 files · +19 −1Browse files

Unified · Split

3 files
  1. fs/nfs/dir.c +5 −1
  2. fs/nfs/unlink.c +13 −0
  3. include/linux/nfs_xdr.h +1 −0
fs/nfs/dir.c+5−1
@@ -2056,7 +2056,11 @@ int nfs_rename(struct inode *old_dir, struct dentry *old_dentry, · 2055 unmodified lines
2056 }2056 }
2057 2057
2058 error = rpc_wait_for_completion_task(task);2058 error = rpc_wait_for_completion_task(task);
2059 if (error == 0)2059 if (error != 0) {
2060 ((struct nfs_renamedata *)task->tk_calldata)->cancelled = 1;
2061 /* Paired with the atomic_dec_and_test() barrier in rpc_do_put_task() */
2062 smp_wmb();
2063 } else
2060 error = task->tk_status;2064 error = task->tk_status;
2061 rpc_put_task(task);2065 rpc_put_task(task);
2062out:2066out:
fs/nfs/unlink.c+13−0
@@ -288,6 +288,19 @@ static void nfs_async_rename_release(void *calldata) · 287 unmodified lines
288 if (d_really_is_positive(data->old_dentry))288 if (d_really_is_positive(data->old_dentry))
289 nfs_mark_for_revalidate(d_inode(data->old_dentry));289 nfs_mark_for_revalidate(d_inode(data->old_dentry));
290 290
291 /* The result of the rename is unknown. Play it safe by
292 * forcing a new lookup */
293 if (data->cancelled) {
294 spin_lock(&data->old_dir->i_lock);
295 nfs_force_lookup_revalidate(data->old_dir);
296 spin_unlock(&data->old_dir->i_lock);
297 if (data->new_dir != data->old_dir) {
298 spin_lock(&data->new_dir->i_lock);
299 nfs_force_lookup_revalidate(data->new_dir);
300 spin_unlock(&data->new_dir->i_lock);
301 }
302 }
303
291 dput(data->old_dentry);304 dput(data->old_dentry);
292 dput(data->new_dentry);305 dput(data->new_dentry);
293 iput(data->old_dir);306 iput(data->old_dir);
include/linux/nfs_xdr.h+1−0
@@ -1533,6 +1533,7 @@ struct nfs_renamedata { · 1532 unmodified lines
1533 struct nfs_fattr new_fattr;1533 struct nfs_fattr new_fattr;
1534 void (*complete)(struct rpc_task *, struct nfs_renamedata *);1534 void (*complete)(struct rpc_task *, struct nfs_renamedata *);
1535 long timeout;1535 long timeout;
1536 bool cancelled;
1536};1537};
1537 1538
1538struct nfs_access_entry;1539struct nfs_access_entry;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t