diff options
Diffstat (limited to 'fs/nfs/dir.c')
-rw-r--r-- | fs/nfs/dir.c | 67 |
1 files changed, 31 insertions, 36 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 2df639f143e8..8272ed3fc707 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -532,6 +532,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
532 | my_entry.eof = 0; | 532 | my_entry.eof = 0; |
533 | my_entry.fh = &fh; | 533 | my_entry.fh = &fh; |
534 | my_entry.fattr = &fattr; | 534 | my_entry.fattr = &fattr; |
535 | nfs_fattr_init(&fattr); | ||
535 | desc->entry = &my_entry; | 536 | desc->entry = &my_entry; |
536 | 537 | ||
537 | while(!desc->entry->eof) { | 538 | while(!desc->entry->eof) { |
@@ -565,8 +566,6 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
565 | } | 566 | } |
566 | } | 567 | } |
567 | unlock_kernel(); | 568 | unlock_kernel(); |
568 | if (desc->error < 0) | ||
569 | return desc->error; | ||
570 | if (res < 0) | 569 | if (res < 0) |
571 | return res; | 570 | return res; |
572 | return 0; | 571 | return 0; |
@@ -803,6 +802,7 @@ static int nfs_dentry_delete(struct dentry *dentry) | |||
803 | */ | 802 | */ |
804 | static void nfs_dentry_iput(struct dentry *dentry, struct inode *inode) | 803 | static void nfs_dentry_iput(struct dentry *dentry, struct inode *inode) |
805 | { | 804 | { |
805 | nfs_inode_return_delegation(inode); | ||
806 | if (dentry->d_flags & DCACHE_NFSFS_RENAMED) { | 806 | if (dentry->d_flags & DCACHE_NFSFS_RENAMED) { |
807 | lock_kernel(); | 807 | lock_kernel(); |
808 | inode->i_nlink--; | 808 | inode->i_nlink--; |
@@ -853,12 +853,6 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru | |||
853 | dentry->d_op = NFS_PROTO(dir)->dentry_ops; | 853 | dentry->d_op = NFS_PROTO(dir)->dentry_ops; |
854 | 854 | ||
855 | lock_kernel(); | 855 | lock_kernel(); |
856 | /* Revalidate parent directory attribute cache */ | ||
857 | error = nfs_revalidate_inode(NFS_SERVER(dir), dir); | ||
858 | if (error < 0) { | ||
859 | res = ERR_PTR(error); | ||
860 | goto out_unlock; | ||
861 | } | ||
862 | 856 | ||
863 | /* If we're doing an exclusive create, optimize away the lookup */ | 857 | /* If we're doing an exclusive create, optimize away the lookup */ |
864 | if (nfs_is_exclusive_create(dir, nd)) | 858 | if (nfs_is_exclusive_create(dir, nd)) |
@@ -916,7 +910,6 @@ static int is_atomic_open(struct inode *dir, struct nameidata *nd) | |||
916 | static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | 910 | static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) |
917 | { | 911 | { |
918 | struct dentry *res = NULL; | 912 | struct dentry *res = NULL; |
919 | struct inode *inode = NULL; | ||
920 | int error; | 913 | int error; |
921 | 914 | ||
922 | /* Check that we are indeed trying to open this file */ | 915 | /* Check that we are indeed trying to open this file */ |
@@ -930,8 +923,10 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry | |||
930 | dentry->d_op = NFS_PROTO(dir)->dentry_ops; | 923 | dentry->d_op = NFS_PROTO(dir)->dentry_ops; |
931 | 924 | ||
932 | /* Let vfs_create() deal with O_EXCL */ | 925 | /* Let vfs_create() deal with O_EXCL */ |
933 | if (nd->intent.open.flags & O_EXCL) | 926 | if (nd->intent.open.flags & O_EXCL) { |
934 | goto no_entry; | 927 | d_add(dentry, NULL); |
928 | goto out; | ||
929 | } | ||
935 | 930 | ||
936 | /* Open the file on the server */ | 931 | /* Open the file on the server */ |
937 | lock_kernel(); | 932 | lock_kernel(); |
@@ -945,32 +940,30 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry | |||
945 | 940 | ||
946 | if (nd->intent.open.flags & O_CREAT) { | 941 | if (nd->intent.open.flags & O_CREAT) { |
947 | nfs_begin_data_update(dir); | 942 | nfs_begin_data_update(dir); |
948 | inode = nfs4_atomic_open(dir, dentry, nd); | 943 | res = nfs4_atomic_open(dir, dentry, nd); |
949 | nfs_end_data_update(dir); | 944 | nfs_end_data_update(dir); |
950 | } else | 945 | } else |
951 | inode = nfs4_atomic_open(dir, dentry, nd); | 946 | res = nfs4_atomic_open(dir, dentry, nd); |
952 | unlock_kernel(); | 947 | unlock_kernel(); |
953 | if (IS_ERR(inode)) { | 948 | if (IS_ERR(res)) { |
954 | error = PTR_ERR(inode); | 949 | error = PTR_ERR(res); |
955 | switch (error) { | 950 | switch (error) { |
956 | /* Make a negative dentry */ | 951 | /* Make a negative dentry */ |
957 | case -ENOENT: | 952 | case -ENOENT: |
958 | inode = NULL; | 953 | res = NULL; |
959 | break; | 954 | goto out; |
960 | /* This turned out not to be a regular file */ | 955 | /* This turned out not to be a regular file */ |
956 | case -EISDIR: | ||
957 | case -ENOTDIR: | ||
958 | goto no_open; | ||
961 | case -ELOOP: | 959 | case -ELOOP: |
962 | if (!(nd->intent.open.flags & O_NOFOLLOW)) | 960 | if (!(nd->intent.open.flags & O_NOFOLLOW)) |
963 | goto no_open; | 961 | goto no_open; |
964 | /* case -EISDIR: */ | ||
965 | /* case -EINVAL: */ | 962 | /* case -EINVAL: */ |
966 | default: | 963 | default: |
967 | res = ERR_PTR(error); | ||
968 | goto out; | 964 | goto out; |
969 | } | 965 | } |
970 | } | 966 | } else if (res != NULL) |
971 | no_entry: | ||
972 | res = d_add_unique(dentry, inode); | ||
973 | if (res != NULL) | ||
974 | dentry = res; | 967 | dentry = res; |
975 | nfs_renew_times(dentry); | 968 | nfs_renew_times(dentry); |
976 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 969 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
@@ -1014,7 +1007,7 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
1014 | */ | 1007 | */ |
1015 | lock_kernel(); | 1008 | lock_kernel(); |
1016 | verifier = nfs_save_change_attribute(dir); | 1009 | verifier = nfs_save_change_attribute(dir); |
1017 | ret = nfs4_open_revalidate(dir, dentry, openflags); | 1010 | ret = nfs4_open_revalidate(dir, dentry, openflags, nd); |
1018 | if (!ret) | 1011 | if (!ret) |
1019 | nfs_set_verifier(dentry, verifier); | 1012 | nfs_set_verifier(dentry, verifier); |
1020 | unlock_kernel(); | 1013 | unlock_kernel(); |
@@ -1137,7 +1130,7 @@ static int nfs_create(struct inode *dir, struct dentry *dentry, int mode, | |||
1137 | 1130 | ||
1138 | lock_kernel(); | 1131 | lock_kernel(); |
1139 | nfs_begin_data_update(dir); | 1132 | nfs_begin_data_update(dir); |
1140 | error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags); | 1133 | error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, nd); |
1141 | nfs_end_data_update(dir); | 1134 | nfs_end_data_update(dir); |
1142 | if (error != 0) | 1135 | if (error != 0) |
1143 | goto out_err; | 1136 | goto out_err; |
@@ -1332,6 +1325,7 @@ static int nfs_safe_remove(struct dentry *dentry) | |||
1332 | 1325 | ||
1333 | nfs_begin_data_update(dir); | 1326 | nfs_begin_data_update(dir); |
1334 | if (inode != NULL) { | 1327 | if (inode != NULL) { |
1328 | nfs_inode_return_delegation(inode); | ||
1335 | nfs_begin_data_update(inode); | 1329 | nfs_begin_data_update(inode); |
1336 | error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); | 1330 | error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); |
1337 | /* The VFS may want to delete this inode */ | 1331 | /* The VFS may want to delete this inode */ |
@@ -1438,17 +1432,14 @@ nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) | |||
1438 | old_dentry->d_parent->d_name.name, old_dentry->d_name.name, | 1432 | old_dentry->d_parent->d_name.name, old_dentry->d_name.name, |
1439 | dentry->d_parent->d_name.name, dentry->d_name.name); | 1433 | dentry->d_parent->d_name.name, dentry->d_name.name); |
1440 | 1434 | ||
1441 | /* | ||
1442 | * Drop the dentry in advance to force a new lookup. | ||
1443 | * Since nfs_proc_link doesn't return a file handle, | ||
1444 | * we can't use the existing dentry. | ||
1445 | */ | ||
1446 | lock_kernel(); | 1435 | lock_kernel(); |
1447 | d_drop(dentry); | ||
1448 | |||
1449 | nfs_begin_data_update(dir); | 1436 | nfs_begin_data_update(dir); |
1450 | nfs_begin_data_update(inode); | 1437 | nfs_begin_data_update(inode); |
1451 | error = NFS_PROTO(dir)->link(inode, dir, &dentry->d_name); | 1438 | error = NFS_PROTO(dir)->link(inode, dir, &dentry->d_name); |
1439 | if (error == 0) { | ||
1440 | atomic_inc(&inode->i_count); | ||
1441 | d_instantiate(dentry, inode); | ||
1442 | } | ||
1452 | nfs_end_data_update(inode); | 1443 | nfs_end_data_update(inode); |
1453 | nfs_end_data_update(dir); | 1444 | nfs_end_data_update(dir); |
1454 | unlock_kernel(); | 1445 | unlock_kernel(); |
@@ -1512,9 +1503,11 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
1512 | */ | 1503 | */ |
1513 | if (!new_inode) | 1504 | if (!new_inode) |
1514 | goto go_ahead; | 1505 | goto go_ahead; |
1515 | if (S_ISDIR(new_inode->i_mode)) | 1506 | if (S_ISDIR(new_inode->i_mode)) { |
1516 | goto out; | 1507 | error = -EISDIR; |
1517 | else if (atomic_read(&new_dentry->d_count) > 2) { | 1508 | if (!S_ISDIR(old_inode->i_mode)) |
1509 | goto out; | ||
1510 | } else if (atomic_read(&new_dentry->d_count) > 2) { | ||
1518 | int err; | 1511 | int err; |
1519 | /* copy the target dentry's name */ | 1512 | /* copy the target dentry's name */ |
1520 | dentry = d_alloc(new_dentry->d_parent, | 1513 | dentry = d_alloc(new_dentry->d_parent, |
@@ -1539,7 +1532,8 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
1539 | #endif | 1532 | #endif |
1540 | goto out; | 1533 | goto out; |
1541 | } | 1534 | } |
1542 | } | 1535 | } else |
1536 | new_inode->i_nlink--; | ||
1543 | 1537 | ||
1544 | go_ahead: | 1538 | go_ahead: |
1545 | /* | 1539 | /* |
@@ -1549,6 +1543,7 @@ go_ahead: | |||
1549 | nfs_wb_all(old_inode); | 1543 | nfs_wb_all(old_inode); |
1550 | shrink_dcache_parent(old_dentry); | 1544 | shrink_dcache_parent(old_dentry); |
1551 | } | 1545 | } |
1546 | nfs_inode_return_delegation(old_inode); | ||
1552 | 1547 | ||
1553 | if (new_inode) | 1548 | if (new_inode) |
1554 | d_delete(new_dentry); | 1549 | d_delete(new_dentry); |