diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2008-01-28 19:43:18 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2008-01-30 02:05:22 -0500 |
commit | d45b9d8baf41acb177abbbe6746b1dea094b8a28 (patch) | |
tree | 2bb90613fb21865b6b23c676c00073d3c4729929 | |
parent | 609005c319bc6062b95ed82e132884ed7e22cdb9 (diff) |
NFS: Handle -ENOENT errors in unlink()/rmdir()/rename()
If the server returns an ENOENT error, we still need to do a d_delete() in
order to ensure that the dentry is deleted.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r-- | fs/nfs/dir.c | 15 |
1 files changed, 13 insertions, 2 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index d9abdb1d6a2a..06f26d40b4fe 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -1267,6 +1267,12 @@ out_err: | |||
1267 | return error; | 1267 | return error; |
1268 | } | 1268 | } |
1269 | 1269 | ||
1270 | static void nfs_dentry_handle_enoent(struct dentry *dentry) | ||
1271 | { | ||
1272 | if (dentry->d_inode != NULL && !d_unhashed(dentry)) | ||
1273 | d_delete(dentry); | ||
1274 | } | ||
1275 | |||
1270 | static int nfs_rmdir(struct inode *dir, struct dentry *dentry) | 1276 | static int nfs_rmdir(struct inode *dir, struct dentry *dentry) |
1271 | { | 1277 | { |
1272 | int error; | 1278 | int error; |
@@ -1279,6 +1285,8 @@ static int nfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
1279 | /* Ensure the VFS deletes this inode */ | 1285 | /* Ensure the VFS deletes this inode */ |
1280 | if (error == 0 && dentry->d_inode != NULL) | 1286 | if (error == 0 && dentry->d_inode != NULL) |
1281 | clear_nlink(dentry->d_inode); | 1287 | clear_nlink(dentry->d_inode); |
1288 | else if (error == -ENOENT) | ||
1289 | nfs_dentry_handle_enoent(dentry); | ||
1282 | unlock_kernel(); | 1290 | unlock_kernel(); |
1283 | 1291 | ||
1284 | return error; | 1292 | return error; |
@@ -1385,6 +1393,8 @@ static int nfs_safe_remove(struct dentry *dentry) | |||
1385 | nfs_mark_for_revalidate(inode); | 1393 | nfs_mark_for_revalidate(inode); |
1386 | } else | 1394 | } else |
1387 | error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); | 1395 | error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); |
1396 | if (error == -ENOENT) | ||
1397 | nfs_dentry_handle_enoent(dentry); | ||
1388 | out: | 1398 | out: |
1389 | return error; | 1399 | return error; |
1390 | } | 1400 | } |
@@ -1421,7 +1431,7 @@ static int nfs_unlink(struct inode *dir, struct dentry *dentry) | |||
1421 | spin_unlock(&dentry->d_lock); | 1431 | spin_unlock(&dentry->d_lock); |
1422 | spin_unlock(&dcache_lock); | 1432 | spin_unlock(&dcache_lock); |
1423 | error = nfs_safe_remove(dentry); | 1433 | error = nfs_safe_remove(dentry); |
1424 | if (!error) { | 1434 | if (!error || error == -ENOENT) { |
1425 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 1435 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
1426 | } else if (need_rehash) | 1436 | } else if (need_rehash) |
1427 | d_rehash(dentry); | 1437 | d_rehash(dentry); |
@@ -1634,7 +1644,8 @@ out: | |||
1634 | d_move(old_dentry, new_dentry); | 1644 | d_move(old_dentry, new_dentry); |
1635 | nfs_set_verifier(new_dentry, | 1645 | nfs_set_verifier(new_dentry, |
1636 | nfs_save_change_attribute(new_dir)); | 1646 | nfs_save_change_attribute(new_dir)); |
1637 | } | 1647 | } else if (error == -ENOENT) |
1648 | nfs_dentry_handle_enoent(old_dentry); | ||
1638 | 1649 | ||
1639 | /* new dentry created? */ | 1650 | /* new dentry created? */ |
1640 | if (dentry) | 1651 | if (dentry) |