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); |
