diff options
Diffstat (limited to 'fs/nfs')
| -rw-r--r-- | fs/nfs/delegation.c | 2 | ||||
| -rw-r--r-- | fs/nfs/delegation.h | 16 | ||||
| -rw-r--r-- | fs/nfs/dir.c | 67 | ||||
| -rw-r--r-- | fs/nfs/file.c | 31 | ||||
| -rw-r--r-- | fs/nfs/inode.c | 200 | ||||
| -rw-r--r-- | fs/nfs/nfs2xdr.c | 1 | ||||
| -rw-r--r-- | fs/nfs/nfs3proc.c | 92 | ||||
| -rw-r--r-- | fs/nfs/nfs3xdr.c | 1 | ||||
| -rw-r--r-- | fs/nfs/nfs4_fs.h | 53 | ||||
| -rw-r--r-- | fs/nfs/nfs4proc.c | 735 | ||||
| -rw-r--r-- | fs/nfs/nfs4state.c | 181 | ||||
| -rw-r--r-- | fs/nfs/nfs4xdr.c | 305 | ||||
| -rw-r--r-- | fs/nfs/proc.c | 44 | ||||
| -rw-r--r-- | fs/nfs/read.c | 1 | ||||
| -rw-r--r-- | fs/nfs/write.c | 2 |
15 files changed, 1142 insertions, 589 deletions
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index 4a36839f0bbd..44135af9894c 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c | |||
| @@ -142,7 +142,7 @@ static void nfs_msync_inode(struct inode *inode) | |||
| 142 | /* | 142 | /* |
| 143 | * Basic procedure for returning a delegation to the server | 143 | * Basic procedure for returning a delegation to the server |
| 144 | */ | 144 | */ |
| 145 | int nfs_inode_return_delegation(struct inode *inode) | 145 | int __nfs_inode_return_delegation(struct inode *inode) |
| 146 | { | 146 | { |
| 147 | struct nfs4_client *clp = NFS_SERVER(inode)->nfs4_state; | 147 | struct nfs4_client *clp = NFS_SERVER(inode)->nfs4_state; |
| 148 | struct nfs_inode *nfsi = NFS_I(inode); | 148 | struct nfs_inode *nfsi = NFS_I(inode); |
diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h index 3f6c45a29d6a..8017846b561f 100644 --- a/fs/nfs/delegation.h +++ b/fs/nfs/delegation.h | |||
| @@ -25,7 +25,7 @@ struct nfs_delegation { | |||
| 25 | 25 | ||
| 26 | int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res); | 26 | int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res); |
| 27 | void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res); | 27 | void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res); |
| 28 | int nfs_inode_return_delegation(struct inode *inode); | 28 | int __nfs_inode_return_delegation(struct inode *inode); |
| 29 | int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid); | 29 | int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid); |
| 30 | 30 | ||
| 31 | struct inode *nfs_delegation_find_inode(struct nfs4_client *clp, const struct nfs_fh *fhandle); | 31 | struct inode *nfs_delegation_find_inode(struct nfs4_client *clp, const struct nfs_fh *fhandle); |
| @@ -47,11 +47,25 @@ static inline int nfs_have_delegation(struct inode *inode, int flags) | |||
| 47 | return 1; | 47 | return 1; |
| 48 | return 0; | 48 | return 0; |
| 49 | } | 49 | } |
| 50 | |||
| 51 | static inline int nfs_inode_return_delegation(struct inode *inode) | ||
| 52 | { | ||
| 53 | int err = 0; | ||
| 54 | |||
| 55 | if (NFS_I(inode)->delegation != NULL) | ||
| 56 | err = __nfs_inode_return_delegation(inode); | ||
| 57 | return err; | ||
| 58 | } | ||
| 50 | #else | 59 | #else |
| 51 | static inline int nfs_have_delegation(struct inode *inode, int flags) | 60 | static inline int nfs_have_delegation(struct inode *inode, int flags) |
| 52 | { | 61 | { |
| 53 | return 0; | 62 | return 0; |
| 54 | } | 63 | } |
| 64 | |||
| 65 | static inline int nfs_inode_return_delegation(struct inode *inode) | ||
| 66 | { | ||
| 67 | return 0; | ||
| 68 | } | ||
| 55 | #endif | 69 | #endif |
| 56 | 70 | ||
| 57 | #endif | 71 | #endif |
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); |
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 6bdcfa95de94..57d3e77d97ee 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
| @@ -205,8 +205,8 @@ nfs_file_flush(struct file *file) | |||
| 205 | if (!status) { | 205 | if (!status) { |
| 206 | status = ctx->error; | 206 | status = ctx->error; |
| 207 | ctx->error = 0; | 207 | ctx->error = 0; |
| 208 | if (!status && !nfs_have_delegation(inode, FMODE_READ)) | 208 | if (!status) |
| 209 | __nfs_revalidate_inode(NFS_SERVER(inode), inode); | 209 | nfs_revalidate_inode(NFS_SERVER(inode), inode); |
| 210 | } | 210 | } |
| 211 | unlock_kernel(); | 211 | unlock_kernel(); |
| 212 | return status; | 212 | return status; |
| @@ -376,22 +376,31 @@ out_swapfile: | |||
| 376 | 376 | ||
| 377 | static int do_getlk(struct file *filp, int cmd, struct file_lock *fl) | 377 | static int do_getlk(struct file *filp, int cmd, struct file_lock *fl) |
| 378 | { | 378 | { |
| 379 | struct file_lock *cfl; | ||
| 379 | struct inode *inode = filp->f_mapping->host; | 380 | struct inode *inode = filp->f_mapping->host; |
| 380 | int status = 0; | 381 | int status = 0; |
| 381 | 382 | ||
| 382 | lock_kernel(); | 383 | lock_kernel(); |
| 383 | /* Use local locking if mounted with "-onolock" */ | 384 | /* Try local locking first */ |
| 384 | if (!(NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM)) | 385 | cfl = posix_test_lock(filp, fl); |
| 385 | status = NFS_PROTO(inode)->lock(filp, cmd, fl); | 386 | if (cfl != NULL) { |
| 386 | else { | 387 | locks_copy_lock(fl, cfl); |
| 387 | struct file_lock *cfl = posix_test_lock(filp, fl); | 388 | goto out; |
| 388 | |||
| 389 | fl->fl_type = F_UNLCK; | ||
| 390 | if (cfl != NULL) | ||
| 391 | memcpy(fl, cfl, sizeof(*fl)); | ||
| 392 | } | 389 | } |
| 390 | |||
| 391 | if (nfs_have_delegation(inode, FMODE_READ)) | ||
| 392 | goto out_noconflict; | ||
| 393 | |||
| 394 | if (NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM) | ||
| 395 | goto out_noconflict; | ||
| 396 | |||
| 397 | status = NFS_PROTO(inode)->lock(filp, cmd, fl); | ||
| 398 | out: | ||
| 393 | unlock_kernel(); | 399 | unlock_kernel(); |
| 394 | return status; | 400 | return status; |
| 401 | out_noconflict: | ||
| 402 | fl->fl_type = F_UNLCK; | ||
| 403 | goto out; | ||
| 395 | } | 404 | } |
| 396 | 405 | ||
| 397 | static int do_vfs_lock(struct file *file, struct file_lock *fl) | 406 | static int do_vfs_lock(struct file *file, struct file_lock *fl) |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index d4eadeea128e..f2781ca42761 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
| @@ -358,6 +358,35 @@ out_no_root: | |||
| 358 | return no_root_error; | 358 | return no_root_error; |
| 359 | } | 359 | } |
| 360 | 360 | ||
| 361 | static void nfs_init_timeout_values(struct rpc_timeout *to, int proto, unsigned int timeo, unsigned int retrans) | ||
| 362 | { | ||
| 363 | to->to_initval = timeo * HZ / 10; | ||
| 364 | to->to_retries = retrans; | ||
| 365 | if (!to->to_retries) | ||
| 366 | to->to_retries = 2; | ||
| 367 | |||
| 368 | switch (proto) { | ||
| 369 | case IPPROTO_TCP: | ||
| 370 | if (!to->to_initval) | ||
| 371 | to->to_initval = 60 * HZ; | ||
| 372 | if (to->to_initval > NFS_MAX_TCP_TIMEOUT) | ||
| 373 | to->to_initval = NFS_MAX_TCP_TIMEOUT; | ||
| 374 | to->to_increment = to->to_initval; | ||
| 375 | to->to_maxval = to->to_initval + (to->to_increment * to->to_retries); | ||
| 376 | to->to_exponential = 0; | ||
| 377 | break; | ||
| 378 | case IPPROTO_UDP: | ||
| 379 | default: | ||
| 380 | if (!to->to_initval) | ||
| 381 | to->to_initval = 11 * HZ / 10; | ||
| 382 | if (to->to_initval > NFS_MAX_UDP_TIMEOUT) | ||
| 383 | to->to_initval = NFS_MAX_UDP_TIMEOUT; | ||
| 384 | to->to_maxval = NFS_MAX_UDP_TIMEOUT; | ||
| 385 | to->to_exponential = 1; | ||
| 386 | break; | ||
| 387 | } | ||
| 388 | } | ||
| 389 | |||
| 361 | /* | 390 | /* |
| 362 | * Create an RPC client handle. | 391 | * Create an RPC client handle. |
| 363 | */ | 392 | */ |
| @@ -367,22 +396,12 @@ nfs_create_client(struct nfs_server *server, const struct nfs_mount_data *data) | |||
| 367 | struct rpc_timeout timeparms; | 396 | struct rpc_timeout timeparms; |
| 368 | struct rpc_xprt *xprt = NULL; | 397 | struct rpc_xprt *xprt = NULL; |
| 369 | struct rpc_clnt *clnt = NULL; | 398 | struct rpc_clnt *clnt = NULL; |
| 370 | int tcp = (data->flags & NFS_MOUNT_TCP); | 399 | int proto = (data->flags & NFS_MOUNT_TCP) ? IPPROTO_TCP : IPPROTO_UDP; |
| 371 | |||
| 372 | /* Initialize timeout values */ | ||
| 373 | timeparms.to_initval = data->timeo * HZ / 10; | ||
| 374 | timeparms.to_retries = data->retrans; | ||
| 375 | timeparms.to_maxval = tcp ? RPC_MAX_TCP_TIMEOUT : RPC_MAX_UDP_TIMEOUT; | ||
| 376 | timeparms.to_exponential = 1; | ||
| 377 | 400 | ||
| 378 | if (!timeparms.to_initval) | 401 | nfs_init_timeout_values(&timeparms, proto, data->timeo, data->retrans); |
| 379 | timeparms.to_initval = (tcp ? 600 : 11) * HZ / 10; | ||
| 380 | if (!timeparms.to_retries) | ||
| 381 | timeparms.to_retries = 5; | ||
| 382 | 402 | ||
| 383 | /* create transport and client */ | 403 | /* create transport and client */ |
| 384 | xprt = xprt_create_proto(tcp ? IPPROTO_TCP : IPPROTO_UDP, | 404 | xprt = xprt_create_proto(proto, &server->addr, &timeparms); |
| 385 | &server->addr, &timeparms); | ||
| 386 | if (IS_ERR(xprt)) { | 405 | if (IS_ERR(xprt)) { |
| 387 | dprintk("%s: cannot create RPC transport. Error = %ld\n", | 406 | dprintk("%s: cannot create RPC transport. Error = %ld\n", |
| 388 | __FUNCTION__, PTR_ERR(xprt)); | 407 | __FUNCTION__, PTR_ERR(xprt)); |
| @@ -576,7 +595,6 @@ static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt) | |||
| 576 | { NFS_MOUNT_SOFT, ",soft", ",hard" }, | 595 | { NFS_MOUNT_SOFT, ",soft", ",hard" }, |
| 577 | { NFS_MOUNT_INTR, ",intr", "" }, | 596 | { NFS_MOUNT_INTR, ",intr", "" }, |
| 578 | { NFS_MOUNT_POSIX, ",posix", "" }, | 597 | { NFS_MOUNT_POSIX, ",posix", "" }, |
| 579 | { NFS_MOUNT_TCP, ",tcp", ",udp" }, | ||
| 580 | { NFS_MOUNT_NOCTO, ",nocto", "" }, | 598 | { NFS_MOUNT_NOCTO, ",nocto", "" }, |
| 581 | { NFS_MOUNT_NOAC, ",noac", "" }, | 599 | { NFS_MOUNT_NOAC, ",noac", "" }, |
| 582 | { NFS_MOUNT_NONLM, ",nolock", ",lock" }, | 600 | { NFS_MOUNT_NONLM, ",nolock", ",lock" }, |
| @@ -585,6 +603,8 @@ static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt) | |||
| 585 | }; | 603 | }; |
| 586 | struct proc_nfs_info *nfs_infop; | 604 | struct proc_nfs_info *nfs_infop; |
| 587 | struct nfs_server *nfss = NFS_SB(mnt->mnt_sb); | 605 | struct nfs_server *nfss = NFS_SB(mnt->mnt_sb); |
| 606 | char buf[12]; | ||
| 607 | char *proto; | ||
| 588 | 608 | ||
| 589 | seq_printf(m, ",v%d", nfss->rpc_ops->version); | 609 | seq_printf(m, ",v%d", nfss->rpc_ops->version); |
| 590 | seq_printf(m, ",rsize=%d", nfss->rsize); | 610 | seq_printf(m, ",rsize=%d", nfss->rsize); |
| @@ -603,6 +623,18 @@ static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt) | |||
| 603 | else | 623 | else |
| 604 | seq_puts(m, nfs_infop->nostr); | 624 | seq_puts(m, nfs_infop->nostr); |
| 605 | } | 625 | } |
| 626 | switch (nfss->client->cl_xprt->prot) { | ||
| 627 | case IPPROTO_TCP: | ||
| 628 | proto = "tcp"; | ||
| 629 | break; | ||
| 630 | case IPPROTO_UDP: | ||
| 631 | proto = "udp"; | ||
| 632 | break; | ||
| 633 | default: | ||
| 634 | snprintf(buf, sizeof(buf), "%u", nfss->client->cl_xprt->prot); | ||
| 635 | proto = buf; | ||
| 636 | } | ||
| 637 | seq_printf(m, ",proto=%s", proto); | ||
| 606 | seq_puts(m, ",addr="); | 638 | seq_puts(m, ",addr="); |
| 607 | seq_escape(m, nfss->hostname, " \t\n\\"); | 639 | seq_escape(m, nfss->hostname, " \t\n\\"); |
| 608 | return 0; | 640 | return 0; |
| @@ -753,7 +785,8 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) | |||
| 753 | else | 785 | else |
| 754 | init_special_inode(inode, inode->i_mode, fattr->rdev); | 786 | init_special_inode(inode, inode->i_mode, fattr->rdev); |
| 755 | 787 | ||
| 756 | nfsi->read_cache_jiffies = fattr->timestamp; | 788 | nfsi->read_cache_jiffies = fattr->time_start; |
| 789 | nfsi->last_updated = jiffies; | ||
| 757 | inode->i_atime = fattr->atime; | 790 | inode->i_atime = fattr->atime; |
| 758 | inode->i_mtime = fattr->mtime; | 791 | inode->i_mtime = fattr->mtime; |
| 759 | inode->i_ctime = fattr->ctime; | 792 | inode->i_ctime = fattr->ctime; |
| @@ -821,6 +854,11 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
| 821 | filemap_fdatawait(inode->i_mapping); | 854 | filemap_fdatawait(inode->i_mapping); |
| 822 | nfs_wb_all(inode); | 855 | nfs_wb_all(inode); |
| 823 | } | 856 | } |
| 857 | /* | ||
| 858 | * Return any delegations if we're going to change ACLs | ||
| 859 | */ | ||
| 860 | if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) | ||
| 861 | nfs_inode_return_delegation(inode); | ||
| 824 | error = NFS_PROTO(inode)->setattr(dentry, &fattr, attr); | 862 | error = NFS_PROTO(inode)->setattr(dentry, &fattr, attr); |
| 825 | if (error == 0) | 863 | if (error == 0) |
| 826 | nfs_refresh_inode(inode, &fattr); | 864 | nfs_refresh_inode(inode, &fattr); |
| @@ -1019,15 +1057,11 @@ int nfs_open(struct inode *inode, struct file *filp) | |||
| 1019 | ctx->mode = filp->f_mode; | 1057 | ctx->mode = filp->f_mode; |
| 1020 | nfs_file_set_open_context(filp, ctx); | 1058 | nfs_file_set_open_context(filp, ctx); |
| 1021 | put_nfs_open_context(ctx); | 1059 | put_nfs_open_context(ctx); |
| 1022 | if ((filp->f_mode & FMODE_WRITE) != 0) | ||
| 1023 | nfs_begin_data_update(inode); | ||
| 1024 | return 0; | 1060 | return 0; |
| 1025 | } | 1061 | } |
| 1026 | 1062 | ||
| 1027 | int nfs_release(struct inode *inode, struct file *filp) | 1063 | int nfs_release(struct inode *inode, struct file *filp) |
| 1028 | { | 1064 | { |
| 1029 | if ((filp->f_mode & FMODE_WRITE) != 0) | ||
| 1030 | nfs_end_data_update(inode); | ||
| 1031 | nfs_file_clear_open_context(filp); | 1065 | nfs_file_clear_open_context(filp); |
| 1032 | return 0; | 1066 | return 0; |
| 1033 | } | 1067 | } |
| @@ -1083,14 +1117,15 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
| 1083 | goto out; | 1117 | goto out; |
| 1084 | } | 1118 | } |
| 1085 | 1119 | ||
| 1120 | spin_lock(&inode->i_lock); | ||
| 1086 | status = nfs_update_inode(inode, &fattr, verifier); | 1121 | status = nfs_update_inode(inode, &fattr, verifier); |
| 1087 | if (status) { | 1122 | if (status) { |
| 1123 | spin_unlock(&inode->i_lock); | ||
| 1088 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n", | 1124 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n", |
| 1089 | inode->i_sb->s_id, | 1125 | inode->i_sb->s_id, |
| 1090 | (long long)NFS_FILEID(inode), status); | 1126 | (long long)NFS_FILEID(inode), status); |
| 1091 | goto out; | 1127 | goto out; |
| 1092 | } | 1128 | } |
| 1093 | spin_lock(&inode->i_lock); | ||
| 1094 | cache_validity = nfsi->cache_validity; | 1129 | cache_validity = nfsi->cache_validity; |
| 1095 | nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE; | 1130 | nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE; |
| 1096 | 1131 | ||
| @@ -1098,7 +1133,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
| 1098 | * We may need to keep the attributes marked as invalid if | 1133 | * We may need to keep the attributes marked as invalid if |
| 1099 | * we raced with nfs_end_attr_update(). | 1134 | * we raced with nfs_end_attr_update(). |
| 1100 | */ | 1135 | */ |
| 1101 | if (verifier == nfsi->cache_change_attribute) | 1136 | if (time_after_eq(verifier, nfsi->cache_change_attribute)) |
| 1102 | nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME); | 1137 | nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME); |
| 1103 | spin_unlock(&inode->i_lock); | 1138 | spin_unlock(&inode->i_lock); |
| 1104 | 1139 | ||
| @@ -1165,7 +1200,7 @@ void nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping) | |||
| 1165 | if (S_ISDIR(inode->i_mode)) { | 1200 | if (S_ISDIR(inode->i_mode)) { |
| 1166 | memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf)); | 1201 | memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf)); |
| 1167 | /* This ensures we revalidate child dentries */ | 1202 | /* This ensures we revalidate child dentries */ |
| 1168 | nfsi->cache_change_attribute++; | 1203 | nfsi->cache_change_attribute = jiffies; |
| 1169 | } | 1204 | } |
| 1170 | spin_unlock(&inode->i_lock); | 1205 | spin_unlock(&inode->i_lock); |
| 1171 | 1206 | ||
| @@ -1197,20 +1232,19 @@ void nfs_end_data_update(struct inode *inode) | |||
| 1197 | struct nfs_inode *nfsi = NFS_I(inode); | 1232 | struct nfs_inode *nfsi = NFS_I(inode); |
| 1198 | 1233 | ||
| 1199 | if (!nfs_have_delegation(inode, FMODE_READ)) { | 1234 | if (!nfs_have_delegation(inode, FMODE_READ)) { |
| 1200 | /* Mark the attribute cache for revalidation */ | 1235 | /* Directories and symlinks: invalidate page cache */ |
| 1201 | spin_lock(&inode->i_lock); | 1236 | if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) { |
| 1202 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR; | 1237 | spin_lock(&inode->i_lock); |
| 1203 | /* Directories and symlinks: invalidate page cache too */ | ||
| 1204 | if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) | ||
| 1205 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; | 1238 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; |
| 1206 | spin_unlock(&inode->i_lock); | 1239 | spin_unlock(&inode->i_lock); |
| 1240 | } | ||
| 1207 | } | 1241 | } |
| 1208 | nfsi->cache_change_attribute ++; | 1242 | nfsi->cache_change_attribute = jiffies; |
| 1209 | atomic_dec(&nfsi->data_updates); | 1243 | atomic_dec(&nfsi->data_updates); |
| 1210 | } | 1244 | } |
| 1211 | 1245 | ||
| 1212 | /** | 1246 | /** |
| 1213 | * nfs_refresh_inode - verify consistency of the inode attribute cache | 1247 | * nfs_check_inode_attributes - verify consistency of the inode attribute cache |
| 1214 | * @inode - pointer to inode | 1248 | * @inode - pointer to inode |
| 1215 | * @fattr - updated attributes | 1249 | * @fattr - updated attributes |
| 1216 | * | 1250 | * |
| @@ -1218,13 +1252,12 @@ void nfs_end_data_update(struct inode *inode) | |||
| 1218 | * so that fattr carries weak cache consistency data, then it may | 1252 | * so that fattr carries weak cache consistency data, then it may |
| 1219 | * also update the ctime/mtime/change_attribute. | 1253 | * also update the ctime/mtime/change_attribute. |
| 1220 | */ | 1254 | */ |
| 1221 | int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) | 1255 | static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fattr) |
| 1222 | { | 1256 | { |
| 1223 | struct nfs_inode *nfsi = NFS_I(inode); | 1257 | struct nfs_inode *nfsi = NFS_I(inode); |
| 1224 | loff_t cur_size, new_isize; | 1258 | loff_t cur_size, new_isize; |
| 1225 | int data_unstable; | 1259 | int data_unstable; |
| 1226 | 1260 | ||
| 1227 | spin_lock(&inode->i_lock); | ||
| 1228 | 1261 | ||
| 1229 | /* Are we in the process of updating data on the server? */ | 1262 | /* Are we in the process of updating data on the server? */ |
| 1230 | data_unstable = nfs_caches_unstable(inode); | 1263 | data_unstable = nfs_caches_unstable(inode); |
| @@ -1288,11 +1321,67 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
| 1288 | if (!timespec_equal(&inode->i_atime, &fattr->atime)) | 1321 | if (!timespec_equal(&inode->i_atime, &fattr->atime)) |
| 1289 | nfsi->cache_validity |= NFS_INO_INVALID_ATIME; | 1322 | nfsi->cache_validity |= NFS_INO_INVALID_ATIME; |
| 1290 | 1323 | ||
| 1291 | nfsi->read_cache_jiffies = fattr->timestamp; | 1324 | nfsi->read_cache_jiffies = fattr->time_start; |
| 1292 | spin_unlock(&inode->i_lock); | ||
| 1293 | return 0; | 1325 | return 0; |
| 1294 | } | 1326 | } |
| 1295 | 1327 | ||
| 1328 | /** | ||
| 1329 | * nfs_refresh_inode - try to update the inode attribute cache | ||
| 1330 | * @inode - pointer to inode | ||
| 1331 | * @fattr - updated attributes | ||
| 1332 | * | ||
| 1333 | * Check that an RPC call that returned attributes has not overlapped with | ||
| 1334 | * other recent updates of the inode metadata, then decide whether it is | ||
| 1335 | * safe to do a full update of the inode attributes, or whether just to | ||
| 1336 | * call nfs_check_inode_attributes. | ||
| 1337 | */ | ||
| 1338 | int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) | ||
| 1339 | { | ||
| 1340 | struct nfs_inode *nfsi = NFS_I(inode); | ||
| 1341 | int status; | ||
| 1342 | |||
| 1343 | if ((fattr->valid & NFS_ATTR_FATTR) == 0) | ||
| 1344 | return 0; | ||
| 1345 | spin_lock(&inode->i_lock); | ||
| 1346 | nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE; | ||
| 1347 | if (nfs_verify_change_attribute(inode, fattr->time_start)) | ||
| 1348 | nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME); | ||
| 1349 | if (time_after(fattr->time_start, nfsi->last_updated)) | ||
| 1350 | status = nfs_update_inode(inode, fattr, fattr->time_start); | ||
| 1351 | else | ||
| 1352 | status = nfs_check_inode_attributes(inode, fattr); | ||
| 1353 | |||
| 1354 | spin_unlock(&inode->i_lock); | ||
| 1355 | return status; | ||
| 1356 | } | ||
| 1357 | |||
| 1358 | /** | ||
| 1359 | * nfs_post_op_update_inode - try to update the inode attribute cache | ||
| 1360 | * @inode - pointer to inode | ||
| 1361 | * @fattr - updated attributes | ||
| 1362 | * | ||
| 1363 | * After an operation that has changed the inode metadata, mark the | ||
| 1364 | * attribute cache as being invalid, then try to update it. | ||
| 1365 | */ | ||
| 1366 | int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr) | ||
| 1367 | { | ||
| 1368 | struct nfs_inode *nfsi = NFS_I(inode); | ||
| 1369 | int status = 0; | ||
| 1370 | |||
| 1371 | spin_lock(&inode->i_lock); | ||
| 1372 | if (unlikely((fattr->valid & NFS_ATTR_FATTR) == 0)) { | ||
| 1373 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS; | ||
| 1374 | goto out; | ||
| 1375 | } | ||
| 1376 | status = nfs_update_inode(inode, fattr, fattr->time_start); | ||
| 1377 | if (time_after_eq(fattr->time_start, nfsi->cache_change_attribute)) | ||
| 1378 | nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME|NFS_INO_REVAL_PAGECACHE); | ||
| 1379 | nfsi->cache_change_attribute = jiffies; | ||
| 1380 | out: | ||
| 1381 | spin_unlock(&inode->i_lock); | ||
| 1382 | return status; | ||
| 1383 | } | ||
| 1384 | |||
| 1296 | /* | 1385 | /* |
| 1297 | * Many nfs protocol calls return the new file attributes after | 1386 | * Many nfs protocol calls return the new file attributes after |
| 1298 | * an operation. Here we update the inode to reflect the state | 1387 | * an operation. Here we update the inode to reflect the state |
| @@ -1328,20 +1417,17 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign | |||
| 1328 | goto out_err; | 1417 | goto out_err; |
| 1329 | } | 1418 | } |
| 1330 | 1419 | ||
| 1331 | spin_lock(&inode->i_lock); | ||
| 1332 | |||
| 1333 | /* | 1420 | /* |
| 1334 | * Make sure the inode's type hasn't changed. | 1421 | * Make sure the inode's type hasn't changed. |
| 1335 | */ | 1422 | */ |
| 1336 | if ((inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) { | 1423 | if ((inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) |
| 1337 | spin_unlock(&inode->i_lock); | ||
| 1338 | goto out_changed; | 1424 | goto out_changed; |
| 1339 | } | ||
| 1340 | 1425 | ||
| 1341 | /* | 1426 | /* |
| 1342 | * Update the read time so we don't revalidate too often. | 1427 | * Update the read time so we don't revalidate too often. |
| 1343 | */ | 1428 | */ |
| 1344 | nfsi->read_cache_jiffies = fattr->timestamp; | 1429 | nfsi->read_cache_jiffies = fattr->time_start; |
| 1430 | nfsi->last_updated = jiffies; | ||
| 1345 | 1431 | ||
| 1346 | /* Are we racing with known updates of the metadata on the server? */ | 1432 | /* Are we racing with known updates of the metadata on the server? */ |
| 1347 | data_unstable = ! (nfs_verify_change_attribute(inode, verifier) || | 1433 | data_unstable = ! (nfs_verify_change_attribute(inode, verifier) || |
| @@ -1354,7 +1440,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign | |||
| 1354 | /* Do we perhaps have any outstanding writes? */ | 1440 | /* Do we perhaps have any outstanding writes? */ |
| 1355 | if (nfsi->npages == 0) { | 1441 | if (nfsi->npages == 0) { |
| 1356 | /* No, but did we race with nfs_end_data_update()? */ | 1442 | /* No, but did we race with nfs_end_data_update()? */ |
| 1357 | if (verifier == nfsi->cache_change_attribute) { | 1443 | if (time_after_eq(verifier, nfsi->cache_change_attribute)) { |
| 1358 | inode->i_size = new_isize; | 1444 | inode->i_size = new_isize; |
| 1359 | invalid |= NFS_INO_INVALID_DATA; | 1445 | invalid |= NFS_INO_INVALID_DATA; |
| 1360 | } | 1446 | } |
| @@ -1430,7 +1516,6 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign | |||
| 1430 | if (!nfs_have_delegation(inode, FMODE_READ)) | 1516 | if (!nfs_have_delegation(inode, FMODE_READ)) |
| 1431 | nfsi->cache_validity |= invalid; | 1517 | nfsi->cache_validity |= invalid; |
| 1432 | 1518 | ||
| 1433 | spin_unlock(&inode->i_lock); | ||
| 1434 | return 0; | 1519 | return 0; |
| 1435 | out_changed: | 1520 | out_changed: |
| 1436 | /* | 1521 | /* |
| @@ -1639,8 +1724,7 @@ static void nfs4_clear_inode(struct inode *inode) | |||
| 1639 | struct nfs_inode *nfsi = NFS_I(inode); | 1724 | struct nfs_inode *nfsi = NFS_I(inode); |
| 1640 | 1725 | ||
| 1641 | /* If we are holding a delegation, return it! */ | 1726 | /* If we are holding a delegation, return it! */ |
| 1642 | if (nfsi->delegation != NULL) | 1727 | nfs_inode_return_delegation(inode); |
| 1643 | nfs_inode_return_delegation(inode); | ||
| 1644 | /* First call standard NFS clear_inode() code */ | 1728 | /* First call standard NFS clear_inode() code */ |
| 1645 | nfs_clear_inode(inode); | 1729 | nfs_clear_inode(inode); |
| 1646 | /* Now clear out any remaining state */ | 1730 | /* Now clear out any remaining state */ |
| @@ -1669,7 +1753,7 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data, | |||
| 1669 | struct rpc_clnt *clnt = NULL; | 1753 | struct rpc_clnt *clnt = NULL; |
| 1670 | struct rpc_timeout timeparms; | 1754 | struct rpc_timeout timeparms; |
| 1671 | rpc_authflavor_t authflavour; | 1755 | rpc_authflavor_t authflavour; |
| 1672 | int proto, err = -EIO; | 1756 | int err = -EIO; |
| 1673 | 1757 | ||
| 1674 | sb->s_blocksize_bits = 0; | 1758 | sb->s_blocksize_bits = 0; |
| 1675 | sb->s_blocksize = 0; | 1759 | sb->s_blocksize = 0; |
| @@ -1687,30 +1771,8 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data, | |||
| 1687 | server->acdirmax = data->acdirmax*HZ; | 1771 | server->acdirmax = data->acdirmax*HZ; |
| 1688 | 1772 | ||
| 1689 | server->rpc_ops = &nfs_v4_clientops; | 1773 | server->rpc_ops = &nfs_v4_clientops; |
| 1690 | /* Initialize timeout values */ | ||
| 1691 | |||
| 1692 | timeparms.to_initval = data->timeo * HZ / 10; | ||
| 1693 | timeparms.to_retries = data->retrans; | ||
| 1694 | timeparms.to_exponential = 1; | ||
| 1695 | if (!timeparms.to_retries) | ||
| 1696 | timeparms.to_retries = 5; | ||
| 1697 | 1774 | ||
| 1698 | proto = data->proto; | 1775 | nfs_init_timeout_values(&timeparms, data->proto, data->timeo, data->retrans); |
| 1699 | /* Which IP protocol do we use? */ | ||
| 1700 | switch (proto) { | ||
| 1701 | case IPPROTO_TCP: | ||
| 1702 | timeparms.to_maxval = RPC_MAX_TCP_TIMEOUT; | ||
| 1703 | if (!timeparms.to_initval) | ||
| 1704 | timeparms.to_initval = 600 * HZ / 10; | ||
| 1705 | break; | ||
| 1706 | case IPPROTO_UDP: | ||
| 1707 | timeparms.to_maxval = RPC_MAX_UDP_TIMEOUT; | ||
| 1708 | if (!timeparms.to_initval) | ||
| 1709 | timeparms.to_initval = 11 * HZ / 10; | ||
| 1710 | break; | ||
| 1711 | default: | ||
| 1712 | return -EINVAL; | ||
| 1713 | } | ||
| 1714 | 1776 | ||
| 1715 | clp = nfs4_get_client(&server->addr.sin_addr); | 1777 | clp = nfs4_get_client(&server->addr.sin_addr); |
| 1716 | if (!clp) { | 1778 | if (!clp) { |
| @@ -1735,7 +1797,7 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data, | |||
| 1735 | 1797 | ||
| 1736 | down_write(&clp->cl_sem); | 1798 | down_write(&clp->cl_sem); |
| 1737 | if (IS_ERR(clp->cl_rpcclient)) { | 1799 | if (IS_ERR(clp->cl_rpcclient)) { |
| 1738 | xprt = xprt_create_proto(proto, &server->addr, &timeparms); | 1800 | xprt = xprt_create_proto(data->proto, &server->addr, &timeparms); |
| 1739 | if (IS_ERR(xprt)) { | 1801 | if (IS_ERR(xprt)) { |
| 1740 | up_write(&clp->cl_sem); | 1802 | up_write(&clp->cl_sem); |
| 1741 | err = PTR_ERR(xprt); | 1803 | err = PTR_ERR(xprt); |
diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c index d91b69044a4d..59049e864ca7 100644 --- a/fs/nfs/nfs2xdr.c +++ b/fs/nfs/nfs2xdr.c | |||
| @@ -143,7 +143,6 @@ xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr) | |||
| 143 | fattr->mode = (fattr->mode & ~S_IFMT) | S_IFIFO; | 143 | fattr->mode = (fattr->mode & ~S_IFMT) | S_IFIFO; |
| 144 | fattr->rdev = 0; | 144 | fattr->rdev = 0; |
| 145 | } | 145 | } |
| 146 | fattr->timestamp = jiffies; | ||
| 147 | return p; | 146 | return p; |
| 148 | } | 147 | } |
| 149 | 148 | ||
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index edc95514046d..92c870d19ccd 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c | |||
| @@ -78,7 +78,7 @@ nfs3_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, | |||
| 78 | int status; | 78 | int status; |
| 79 | 79 | ||
| 80 | dprintk("%s: call fsinfo\n", __FUNCTION__); | 80 | dprintk("%s: call fsinfo\n", __FUNCTION__); |
| 81 | info->fattr->valid = 0; | 81 | nfs_fattr_init(info->fattr); |
| 82 | status = rpc_call(server->client_sys, NFS3PROC_FSINFO, fhandle, info, 0); | 82 | status = rpc_call(server->client_sys, NFS3PROC_FSINFO, fhandle, info, 0); |
| 83 | dprintk("%s: reply fsinfo: %d\n", __FUNCTION__, status); | 83 | dprintk("%s: reply fsinfo: %d\n", __FUNCTION__, status); |
| 84 | if (!(info->fattr->valid & NFS_ATTR_FATTR)) { | 84 | if (!(info->fattr->valid & NFS_ATTR_FATTR)) { |
| @@ -98,7 +98,7 @@ nfs3_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, | |||
| 98 | int status; | 98 | int status; |
| 99 | 99 | ||
| 100 | dprintk("NFS call getattr\n"); | 100 | dprintk("NFS call getattr\n"); |
| 101 | fattr->valid = 0; | 101 | nfs_fattr_init(fattr); |
| 102 | status = rpc_call(server->client, NFS3PROC_GETATTR, | 102 | status = rpc_call(server->client, NFS3PROC_GETATTR, |
| 103 | fhandle, fattr, 0); | 103 | fhandle, fattr, 0); |
| 104 | dprintk("NFS reply getattr: %d\n", status); | 104 | dprintk("NFS reply getattr: %d\n", status); |
| @@ -117,7 +117,7 @@ nfs3_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, | |||
| 117 | int status; | 117 | int status; |
| 118 | 118 | ||
| 119 | dprintk("NFS call setattr\n"); | 119 | dprintk("NFS call setattr\n"); |
| 120 | fattr->valid = 0; | 120 | nfs_fattr_init(fattr); |
| 121 | status = rpc_call(NFS_CLIENT(inode), NFS3PROC_SETATTR, &arg, fattr, 0); | 121 | status = rpc_call(NFS_CLIENT(inode), NFS3PROC_SETATTR, &arg, fattr, 0); |
| 122 | if (status == 0) | 122 | if (status == 0) |
| 123 | nfs_setattr_update_inode(inode, sattr); | 123 | nfs_setattr_update_inode(inode, sattr); |
| @@ -143,8 +143,8 @@ nfs3_proc_lookup(struct inode *dir, struct qstr *name, | |||
| 143 | int status; | 143 | int status; |
| 144 | 144 | ||
| 145 | dprintk("NFS call lookup %s\n", name->name); | 145 | dprintk("NFS call lookup %s\n", name->name); |
| 146 | dir_attr.valid = 0; | 146 | nfs_fattr_init(&dir_attr); |
| 147 | fattr->valid = 0; | 147 | nfs_fattr_init(fattr); |
| 148 | status = rpc_call(NFS_CLIENT(dir), NFS3PROC_LOOKUP, &arg, &res, 0); | 148 | status = rpc_call(NFS_CLIENT(dir), NFS3PROC_LOOKUP, &arg, &res, 0); |
| 149 | if (status >= 0 && !(fattr->valid & NFS_ATTR_FATTR)) | 149 | if (status >= 0 && !(fattr->valid & NFS_ATTR_FATTR)) |
| 150 | status = rpc_call(NFS_CLIENT(dir), NFS3PROC_GETATTR, | 150 | status = rpc_call(NFS_CLIENT(dir), NFS3PROC_GETATTR, |
| @@ -174,7 +174,6 @@ static int nfs3_proc_access(struct inode *inode, struct nfs_access_entry *entry) | |||
| 174 | int status; | 174 | int status; |
| 175 | 175 | ||
| 176 | dprintk("NFS call access\n"); | 176 | dprintk("NFS call access\n"); |
| 177 | fattr.valid = 0; | ||
| 178 | 177 | ||
| 179 | if (mode & MAY_READ) | 178 | if (mode & MAY_READ) |
| 180 | arg.access |= NFS3_ACCESS_READ; | 179 | arg.access |= NFS3_ACCESS_READ; |
| @@ -189,6 +188,7 @@ static int nfs3_proc_access(struct inode *inode, struct nfs_access_entry *entry) | |||
| 189 | if (mode & MAY_EXEC) | 188 | if (mode & MAY_EXEC) |
| 190 | arg.access |= NFS3_ACCESS_EXECUTE; | 189 | arg.access |= NFS3_ACCESS_EXECUTE; |
| 191 | } | 190 | } |
| 191 | nfs_fattr_init(&fattr); | ||
| 192 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); | 192 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); |
| 193 | nfs_refresh_inode(inode, &fattr); | 193 | nfs_refresh_inode(inode, &fattr); |
| 194 | if (status == 0) { | 194 | if (status == 0) { |
| @@ -217,7 +217,7 @@ static int nfs3_proc_readlink(struct inode *inode, struct page *page, | |||
| 217 | int status; | 217 | int status; |
| 218 | 218 | ||
| 219 | dprintk("NFS call readlink\n"); | 219 | dprintk("NFS call readlink\n"); |
| 220 | fattr.valid = 0; | 220 | nfs_fattr_init(&fattr); |
| 221 | status = rpc_call(NFS_CLIENT(inode), NFS3PROC_READLINK, | 221 | status = rpc_call(NFS_CLIENT(inode), NFS3PROC_READLINK, |
| 222 | &args, &fattr, 0); | 222 | &args, &fattr, 0); |
| 223 | nfs_refresh_inode(inode, &fattr); | 223 | nfs_refresh_inode(inode, &fattr); |
| @@ -240,7 +240,7 @@ static int nfs3_proc_read(struct nfs_read_data *rdata) | |||
| 240 | 240 | ||
| 241 | dprintk("NFS call read %d @ %Ld\n", rdata->args.count, | 241 | dprintk("NFS call read %d @ %Ld\n", rdata->args.count, |
| 242 | (long long) rdata->args.offset); | 242 | (long long) rdata->args.offset); |
| 243 | fattr->valid = 0; | 243 | nfs_fattr_init(fattr); |
| 244 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags); | 244 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags); |
| 245 | if (status >= 0) | 245 | if (status >= 0) |
| 246 | nfs_refresh_inode(inode, fattr); | 246 | nfs_refresh_inode(inode, fattr); |
| @@ -263,10 +263,10 @@ static int nfs3_proc_write(struct nfs_write_data *wdata) | |||
| 263 | 263 | ||
| 264 | dprintk("NFS call write %d @ %Ld\n", wdata->args.count, | 264 | dprintk("NFS call write %d @ %Ld\n", wdata->args.count, |
| 265 | (long long) wdata->args.offset); | 265 | (long long) wdata->args.offset); |
| 266 | fattr->valid = 0; | 266 | nfs_fattr_init(fattr); |
| 267 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, rpcflags); | 267 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, rpcflags); |
| 268 | if (status >= 0) | 268 | if (status >= 0) |
| 269 | nfs_refresh_inode(inode, fattr); | 269 | nfs_post_op_update_inode(inode, fattr); |
| 270 | dprintk("NFS reply write: %d\n", status); | 270 | dprintk("NFS reply write: %d\n", status); |
| 271 | return status < 0? status : wdata->res.count; | 271 | return status < 0? status : wdata->res.count; |
| 272 | } | 272 | } |
| @@ -285,10 +285,10 @@ static int nfs3_proc_commit(struct nfs_write_data *cdata) | |||
| 285 | 285 | ||
| 286 | dprintk("NFS call commit %d @ %Ld\n", cdata->args.count, | 286 | dprintk("NFS call commit %d @ %Ld\n", cdata->args.count, |
| 287 | (long long) cdata->args.offset); | 287 | (long long) cdata->args.offset); |
| 288 | fattr->valid = 0; | 288 | nfs_fattr_init(fattr); |
| 289 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); | 289 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); |
| 290 | if (status >= 0) | 290 | if (status >= 0) |
| 291 | nfs_refresh_inode(inode, fattr); | 291 | nfs_post_op_update_inode(inode, fattr); |
| 292 | dprintk("NFS reply commit: %d\n", status); | 292 | dprintk("NFS reply commit: %d\n", status); |
| 293 | return status; | 293 | return status; |
| 294 | } | 294 | } |
| @@ -299,7 +299,7 @@ static int nfs3_proc_commit(struct nfs_write_data *cdata) | |||
| 299 | */ | 299 | */ |
| 300 | static int | 300 | static int |
| 301 | nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | 301 | nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, |
| 302 | int flags) | 302 | int flags, struct nameidata *nd) |
| 303 | { | 303 | { |
| 304 | struct nfs_fh fhandle; | 304 | struct nfs_fh fhandle; |
| 305 | struct nfs_fattr fattr; | 305 | struct nfs_fattr fattr; |
| @@ -329,10 +329,10 @@ nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | |||
| 329 | sattr->ia_mode &= ~current->fs->umask; | 329 | sattr->ia_mode &= ~current->fs->umask; |
| 330 | 330 | ||
| 331 | again: | 331 | again: |
| 332 | dir_attr.valid = 0; | 332 | nfs_fattr_init(&dir_attr); |
| 333 | fattr.valid = 0; | 333 | nfs_fattr_init(&fattr); |
| 334 | status = rpc_call(NFS_CLIENT(dir), NFS3PROC_CREATE, &arg, &res, 0); | 334 | status = rpc_call(NFS_CLIENT(dir), NFS3PROC_CREATE, &arg, &res, 0); |
| 335 | nfs_refresh_inode(dir, &dir_attr); | 335 | nfs_post_op_update_inode(dir, &dir_attr); |
| 336 | 336 | ||
| 337 | /* If the server doesn't support the exclusive creation semantics, | 337 | /* If the server doesn't support the exclusive creation semantics, |
| 338 | * try again with simple 'guarded' mode. */ | 338 | * try again with simple 'guarded' mode. */ |
| @@ -401,9 +401,9 @@ nfs3_proc_remove(struct inode *dir, struct qstr *name) | |||
| 401 | int status; | 401 | int status; |
| 402 | 402 | ||
| 403 | dprintk("NFS call remove %s\n", name->name); | 403 | dprintk("NFS call remove %s\n", name->name); |
| 404 | dir_attr.valid = 0; | 404 | nfs_fattr_init(&dir_attr); |
| 405 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 405 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
| 406 | nfs_refresh_inode(dir, &dir_attr); | 406 | nfs_post_op_update_inode(dir, &dir_attr); |
| 407 | dprintk("NFS reply remove: %d\n", status); | 407 | dprintk("NFS reply remove: %d\n", status); |
| 408 | return status; | 408 | return status; |
| 409 | } | 409 | } |
| @@ -422,7 +422,7 @@ nfs3_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir, struct qstr | |||
| 422 | ptr->arg.fh = NFS_FH(dir->d_inode); | 422 | ptr->arg.fh = NFS_FH(dir->d_inode); |
| 423 | ptr->arg.name = name->name; | 423 | ptr->arg.name = name->name; |
| 424 | ptr->arg.len = name->len; | 424 | ptr->arg.len = name->len; |
| 425 | ptr->res.valid = 0; | 425 | nfs_fattr_init(&ptr->res); |
| 426 | msg->rpc_proc = &nfs3_procedures[NFS3PROC_REMOVE]; | 426 | msg->rpc_proc = &nfs3_procedures[NFS3PROC_REMOVE]; |
| 427 | msg->rpc_argp = &ptr->arg; | 427 | msg->rpc_argp = &ptr->arg; |
| 428 | msg->rpc_resp = &ptr->res; | 428 | msg->rpc_resp = &ptr->res; |
| @@ -439,7 +439,7 @@ nfs3_proc_unlink_done(struct dentry *dir, struct rpc_task *task) | |||
| 439 | return 1; | 439 | return 1; |
| 440 | if (msg->rpc_argp) { | 440 | if (msg->rpc_argp) { |
| 441 | dir_attr = (struct nfs_fattr*)msg->rpc_resp; | 441 | dir_attr = (struct nfs_fattr*)msg->rpc_resp; |
| 442 | nfs_refresh_inode(dir->d_inode, dir_attr); | 442 | nfs_post_op_update_inode(dir->d_inode, dir_attr); |
| 443 | kfree(msg->rpc_argp); | 443 | kfree(msg->rpc_argp); |
| 444 | } | 444 | } |
| 445 | return 0; | 445 | return 0; |
| @@ -465,11 +465,11 @@ nfs3_proc_rename(struct inode *old_dir, struct qstr *old_name, | |||
| 465 | int status; | 465 | int status; |
| 466 | 466 | ||
| 467 | dprintk("NFS call rename %s -> %s\n", old_name->name, new_name->name); | 467 | dprintk("NFS call rename %s -> %s\n", old_name->name, new_name->name); |
| 468 | old_dir_attr.valid = 0; | 468 | nfs_fattr_init(&old_dir_attr); |
| 469 | new_dir_attr.valid = 0; | 469 | nfs_fattr_init(&new_dir_attr); |
| 470 | status = rpc_call(NFS_CLIENT(old_dir), NFS3PROC_RENAME, &arg, &res, 0); | 470 | status = rpc_call(NFS_CLIENT(old_dir), NFS3PROC_RENAME, &arg, &res, 0); |
| 471 | nfs_refresh_inode(old_dir, &old_dir_attr); | 471 | nfs_post_op_update_inode(old_dir, &old_dir_attr); |
| 472 | nfs_refresh_inode(new_dir, &new_dir_attr); | 472 | nfs_post_op_update_inode(new_dir, &new_dir_attr); |
| 473 | dprintk("NFS reply rename: %d\n", status); | 473 | dprintk("NFS reply rename: %d\n", status); |
| 474 | return status; | 474 | return status; |
| 475 | } | 475 | } |
| @@ -491,11 +491,11 @@ nfs3_proc_link(struct inode *inode, struct inode *dir, struct qstr *name) | |||
| 491 | int status; | 491 | int status; |
| 492 | 492 | ||
| 493 | dprintk("NFS call link %s\n", name->name); | 493 | dprintk("NFS call link %s\n", name->name); |
| 494 | dir_attr.valid = 0; | 494 | nfs_fattr_init(&dir_attr); |
| 495 | fattr.valid = 0; | 495 | nfs_fattr_init(&fattr); |
| 496 | status = rpc_call(NFS_CLIENT(inode), NFS3PROC_LINK, &arg, &res, 0); | 496 | status = rpc_call(NFS_CLIENT(inode), NFS3PROC_LINK, &arg, &res, 0); |
| 497 | nfs_refresh_inode(dir, &dir_attr); | 497 | nfs_post_op_update_inode(dir, &dir_attr); |
| 498 | nfs_refresh_inode(inode, &fattr); | 498 | nfs_post_op_update_inode(inode, &fattr); |
| 499 | dprintk("NFS reply link: %d\n", status); | 499 | dprintk("NFS reply link: %d\n", status); |
| 500 | return status; | 500 | return status; |
| 501 | } | 501 | } |
| @@ -524,10 +524,10 @@ nfs3_proc_symlink(struct inode *dir, struct qstr *name, struct qstr *path, | |||
| 524 | if (path->len > NFS3_MAXPATHLEN) | 524 | if (path->len > NFS3_MAXPATHLEN) |
| 525 | return -ENAMETOOLONG; | 525 | return -ENAMETOOLONG; |
| 526 | dprintk("NFS call symlink %s -> %s\n", name->name, path->name); | 526 | dprintk("NFS call symlink %s -> %s\n", name->name, path->name); |
| 527 | dir_attr.valid = 0; | 527 | nfs_fattr_init(&dir_attr); |
| 528 | fattr->valid = 0; | 528 | nfs_fattr_init(fattr); |
| 529 | status = rpc_call(NFS_CLIENT(dir), NFS3PROC_SYMLINK, &arg, &res, 0); | 529 | status = rpc_call(NFS_CLIENT(dir), NFS3PROC_SYMLINK, &arg, &res, 0); |
| 530 | nfs_refresh_inode(dir, &dir_attr); | 530 | nfs_post_op_update_inode(dir, &dir_attr); |
| 531 | dprintk("NFS reply symlink: %d\n", status); | 531 | dprintk("NFS reply symlink: %d\n", status); |
| 532 | return status; | 532 | return status; |
| 533 | } | 533 | } |
| @@ -552,13 +552,13 @@ nfs3_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr) | |||
| 552 | int status; | 552 | int status; |
| 553 | 553 | ||
| 554 | dprintk("NFS call mkdir %s\n", dentry->d_name.name); | 554 | dprintk("NFS call mkdir %s\n", dentry->d_name.name); |
| 555 | dir_attr.valid = 0; | ||
| 556 | fattr.valid = 0; | ||
| 557 | 555 | ||
| 558 | sattr->ia_mode &= ~current->fs->umask; | 556 | sattr->ia_mode &= ~current->fs->umask; |
| 559 | 557 | ||
| 558 | nfs_fattr_init(&dir_attr); | ||
| 559 | nfs_fattr_init(&fattr); | ||
| 560 | status = rpc_call(NFS_CLIENT(dir), NFS3PROC_MKDIR, &arg, &res, 0); | 560 | status = rpc_call(NFS_CLIENT(dir), NFS3PROC_MKDIR, &arg, &res, 0); |
| 561 | nfs_refresh_inode(dir, &dir_attr); | 561 | nfs_post_op_update_inode(dir, &dir_attr); |
| 562 | if (status != 0) | 562 | if (status != 0) |
| 563 | goto out; | 563 | goto out; |
| 564 | status = nfs_instantiate(dentry, &fhandle, &fattr); | 564 | status = nfs_instantiate(dentry, &fhandle, &fattr); |
| @@ -582,9 +582,9 @@ nfs3_proc_rmdir(struct inode *dir, struct qstr *name) | |||
| 582 | int status; | 582 | int status; |
| 583 | 583 | ||
| 584 | dprintk("NFS call rmdir %s\n", name->name); | 584 | dprintk("NFS call rmdir %s\n", name->name); |
| 585 | dir_attr.valid = 0; | 585 | nfs_fattr_init(&dir_attr); |
| 586 | status = rpc_call(NFS_CLIENT(dir), NFS3PROC_RMDIR, &arg, &dir_attr, 0); | 586 | status = rpc_call(NFS_CLIENT(dir), NFS3PROC_RMDIR, &arg, &dir_attr, 0); |
| 587 | nfs_refresh_inode(dir, &dir_attr); | 587 | nfs_post_op_update_inode(dir, &dir_attr); |
| 588 | dprintk("NFS reply rmdir: %d\n", status); | 588 | dprintk("NFS reply rmdir: %d\n", status); |
| 589 | return status; | 589 | return status; |
| 590 | } | 590 | } |
| @@ -634,7 +634,7 @@ nfs3_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, | |||
| 634 | dprintk("NFS call readdir%s %d\n", | 634 | dprintk("NFS call readdir%s %d\n", |
| 635 | plus? "plus" : "", (unsigned int) cookie); | 635 | plus? "plus" : "", (unsigned int) cookie); |
| 636 | 636 | ||
| 637 | dir_attr.valid = 0; | 637 | nfs_fattr_init(&dir_attr); |
| 638 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 638 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
| 639 | nfs_refresh_inode(dir, &dir_attr); | 639 | nfs_refresh_inode(dir, &dir_attr); |
| 640 | dprintk("NFS reply readdir: %d\n", status); | 640 | dprintk("NFS reply readdir: %d\n", status); |
| @@ -676,10 +676,10 @@ nfs3_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | |||
| 676 | 676 | ||
| 677 | sattr->ia_mode &= ~current->fs->umask; | 677 | sattr->ia_mode &= ~current->fs->umask; |
| 678 | 678 | ||
| 679 | dir_attr.valid = 0; | 679 | nfs_fattr_init(&dir_attr); |
| 680 | fattr.valid = 0; | 680 | nfs_fattr_init(&fattr); |
| 681 | status = rpc_call(NFS_CLIENT(dir), NFS3PROC_MKNOD, &arg, &res, 0); | 681 | status = rpc_call(NFS_CLIENT(dir), NFS3PROC_MKNOD, &arg, &res, 0); |
| 682 | nfs_refresh_inode(dir, &dir_attr); | 682 | nfs_post_op_update_inode(dir, &dir_attr); |
| 683 | if (status != 0) | 683 | if (status != 0) |
| 684 | goto out; | 684 | goto out; |
| 685 | status = nfs_instantiate(dentry, &fh, &fattr); | 685 | status = nfs_instantiate(dentry, &fh, &fattr); |
| @@ -698,7 +698,7 @@ nfs3_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, | |||
| 698 | int status; | 698 | int status; |
| 699 | 699 | ||
| 700 | dprintk("NFS call fsstat\n"); | 700 | dprintk("NFS call fsstat\n"); |
| 701 | stat->fattr->valid = 0; | 701 | nfs_fattr_init(stat->fattr); |
| 702 | status = rpc_call(server->client, NFS3PROC_FSSTAT, fhandle, stat, 0); | 702 | status = rpc_call(server->client, NFS3PROC_FSSTAT, fhandle, stat, 0); |
| 703 | dprintk("NFS reply statfs: %d\n", status); | 703 | dprintk("NFS reply statfs: %d\n", status); |
| 704 | return status; | 704 | return status; |
| @@ -711,7 +711,7 @@ nfs3_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, | |||
| 711 | int status; | 711 | int status; |
| 712 | 712 | ||
| 713 | dprintk("NFS call fsinfo\n"); | 713 | dprintk("NFS call fsinfo\n"); |
| 714 | info->fattr->valid = 0; | 714 | nfs_fattr_init(info->fattr); |
| 715 | status = rpc_call(server->client_sys, NFS3PROC_FSINFO, fhandle, info, 0); | 715 | status = rpc_call(server->client_sys, NFS3PROC_FSINFO, fhandle, info, 0); |
| 716 | dprintk("NFS reply fsinfo: %d\n", status); | 716 | dprintk("NFS reply fsinfo: %d\n", status); |
| 717 | return status; | 717 | return status; |
| @@ -724,7 +724,7 @@ nfs3_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle, | |||
| 724 | int status; | 724 | int status; |
| 725 | 725 | ||
| 726 | dprintk("NFS call pathconf\n"); | 726 | dprintk("NFS call pathconf\n"); |
| 727 | info->fattr->valid = 0; | 727 | nfs_fattr_init(info->fattr); |
| 728 | status = rpc_call(server->client, NFS3PROC_PATHCONF, fhandle, info, 0); | 728 | status = rpc_call(server->client, NFS3PROC_PATHCONF, fhandle, info, 0); |
| 729 | dprintk("NFS reply pathconf: %d\n", status); | 729 | dprintk("NFS reply pathconf: %d\n", status); |
| 730 | return status; | 730 | return status; |
| @@ -735,7 +735,7 @@ extern u32 *nfs3_decode_dirent(u32 *, struct nfs_entry *, int); | |||
| 735 | static void | 735 | static void |
| 736 | nfs3_read_done(struct rpc_task *task) | 736 | nfs3_read_done(struct rpc_task *task) |
| 737 | { | 737 | { |
| 738 | struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata; | 738 | struct nfs_read_data *data = (struct nfs_read_data *) task->tk_calldata; |
| 739 | 739 | ||
| 740 | if (nfs3_async_handle_jukebox(task)) | 740 | if (nfs3_async_handle_jukebox(task)) |
| 741 | return; | 741 | return; |
| @@ -775,7 +775,7 @@ nfs3_write_done(struct rpc_task *task) | |||
| 775 | return; | 775 | return; |
| 776 | data = (struct nfs_write_data *)task->tk_calldata; | 776 | data = (struct nfs_write_data *)task->tk_calldata; |
| 777 | if (task->tk_status >= 0) | 777 | if (task->tk_status >= 0) |
| 778 | nfs_refresh_inode(data->inode, data->res.fattr); | 778 | nfs_post_op_update_inode(data->inode, data->res.fattr); |
| 779 | nfs_writeback_done(task); | 779 | nfs_writeback_done(task); |
| 780 | } | 780 | } |
| 781 | 781 | ||
| @@ -819,7 +819,7 @@ nfs3_commit_done(struct rpc_task *task) | |||
| 819 | return; | 819 | return; |
| 820 | data = (struct nfs_write_data *)task->tk_calldata; | 820 | data = (struct nfs_write_data *)task->tk_calldata; |
| 821 | if (task->tk_status >= 0) | 821 | if (task->tk_status >= 0) |
| 822 | nfs_refresh_inode(data->inode, data->res.fattr); | 822 | nfs_post_op_update_inode(data->inode, data->res.fattr); |
| 823 | nfs_commit_done(task); | 823 | nfs_commit_done(task); |
| 824 | } | 824 | } |
| 825 | 825 | ||
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c index db4a904810a4..0498bd36602c 100644 --- a/fs/nfs/nfs3xdr.c +++ b/fs/nfs/nfs3xdr.c | |||
| @@ -174,7 +174,6 @@ xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr) | |||
| 174 | 174 | ||
| 175 | /* Update the mode bits */ | 175 | /* Update the mode bits */ |
| 176 | fattr->valid |= (NFS_ATTR_FATTR | NFS_ATTR_FATTR_V3); | 176 | fattr->valid |= (NFS_ATTR_FATTR | NFS_ATTR_FATTR_V3); |
| 177 | fattr->timestamp = jiffies; | ||
| 178 | return p; | 177 | return p; |
| 179 | } | 178 | } |
| 180 | 179 | ||
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index ec1a22d7b876..78a53f5a9f18 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h | |||
| @@ -93,25 +93,50 @@ struct nfs4_client { | |||
| 93 | }; | 93 | }; |
| 94 | 94 | ||
| 95 | /* | 95 | /* |
| 96 | * struct rpc_sequence ensures that RPC calls are sent in the exact | ||
| 97 | * order that they appear on the list. | ||
| 98 | */ | ||
| 99 | struct rpc_sequence { | ||
| 100 | struct rpc_wait_queue wait; /* RPC call delay queue */ | ||
| 101 | spinlock_t lock; /* Protects the list */ | ||
| 102 | struct list_head list; /* Defines sequence of RPC calls */ | ||
| 103 | }; | ||
| 104 | |||
| 105 | #define NFS_SEQID_CONFIRMED 1 | ||
| 106 | struct nfs_seqid_counter { | ||
| 107 | struct rpc_sequence *sequence; | ||
| 108 | int flags; | ||
| 109 | u32 counter; | ||
| 110 | }; | ||
| 111 | |||
| 112 | struct nfs_seqid { | ||
| 113 | struct nfs_seqid_counter *sequence; | ||
| 114 | struct list_head list; | ||
| 115 | }; | ||
| 116 | |||
| 117 | static inline void nfs_confirm_seqid(struct nfs_seqid_counter *seqid, int status) | ||
| 118 | { | ||
| 119 | if (seqid_mutating_err(-status)) | ||
| 120 | seqid->flags |= NFS_SEQID_CONFIRMED; | ||
| 121 | } | ||
| 122 | |||
| 123 | /* | ||
| 96 | * NFS4 state_owners and lock_owners are simply labels for ordered | 124 | * NFS4 state_owners and lock_owners are simply labels for ordered |
| 97 | * sequences of RPC calls. Their sole purpose is to provide once-only | 125 | * sequences of RPC calls. Their sole purpose is to provide once-only |
| 98 | * semantics by allowing the server to identify replayed requests. | 126 | * semantics by allowing the server to identify replayed requests. |
| 99 | * | ||
| 100 | * The ->so_sema is held during all state_owner seqid-mutating operations: | ||
| 101 | * OPEN, OPEN_DOWNGRADE, and CLOSE. Its purpose is to properly serialize | ||
| 102 | * so_seqid. | ||
| 103 | */ | 127 | */ |
| 104 | struct nfs4_state_owner { | 128 | struct nfs4_state_owner { |
| 129 | spinlock_t so_lock; | ||
| 105 | struct list_head so_list; /* per-clientid list of state_owners */ | 130 | struct list_head so_list; /* per-clientid list of state_owners */ |
| 106 | struct nfs4_client *so_client; | 131 | struct nfs4_client *so_client; |
| 107 | u32 so_id; /* 32-bit identifier, unique */ | 132 | u32 so_id; /* 32-bit identifier, unique */ |
| 108 | struct semaphore so_sema; | ||
| 109 | u32 so_seqid; /* protected by so_sema */ | ||
| 110 | atomic_t so_count; | 133 | atomic_t so_count; |
| 111 | 134 | ||
| 112 | struct rpc_cred *so_cred; /* Associated cred */ | 135 | struct rpc_cred *so_cred; /* Associated cred */ |
| 113 | struct list_head so_states; | 136 | struct list_head so_states; |
| 114 | struct list_head so_delegations; | 137 | struct list_head so_delegations; |
| 138 | struct nfs_seqid_counter so_seqid; | ||
| 139 | struct rpc_sequence so_sequence; | ||
| 115 | }; | 140 | }; |
| 116 | 141 | ||
| 117 | /* | 142 | /* |
| @@ -132,7 +157,7 @@ struct nfs4_lock_state { | |||
| 132 | fl_owner_t ls_owner; /* POSIX lock owner */ | 157 | fl_owner_t ls_owner; /* POSIX lock owner */ |
| 133 | #define NFS_LOCK_INITIALIZED 1 | 158 | #define NFS_LOCK_INITIALIZED 1 |
| 134 | int ls_flags; | 159 | int ls_flags; |
| 135 | u32 ls_seqid; | 160 | struct nfs_seqid_counter ls_seqid; |
| 136 | u32 ls_id; | 161 | u32 ls_id; |
| 137 | nfs4_stateid ls_stateid; | 162 | nfs4_stateid ls_stateid; |
| 138 | atomic_t ls_count; | 163 | atomic_t ls_count; |
| @@ -153,7 +178,6 @@ struct nfs4_state { | |||
| 153 | struct inode *inode; /* Pointer to the inode */ | 178 | struct inode *inode; /* Pointer to the inode */ |
| 154 | 179 | ||
| 155 | unsigned long flags; /* Do we hold any locks? */ | 180 | unsigned long flags; /* Do we hold any locks? */ |
| 156 | struct semaphore lock_sema; /* Serializes file locking operations */ | ||
| 157 | spinlock_t state_lock; /* Protects the lock_states list */ | 181 | spinlock_t state_lock; /* Protects the lock_states list */ |
| 158 | 182 | ||
| 159 | nfs4_stateid stateid; | 183 | nfs4_stateid stateid; |
| @@ -191,8 +215,8 @@ extern int nfs4_proc_setclientid_confirm(struct nfs4_client *); | |||
| 191 | extern int nfs4_proc_async_renew(struct nfs4_client *); | 215 | extern int nfs4_proc_async_renew(struct nfs4_client *); |
| 192 | extern int nfs4_proc_renew(struct nfs4_client *); | 216 | extern int nfs4_proc_renew(struct nfs4_client *); |
| 193 | extern int nfs4_do_close(struct inode *inode, struct nfs4_state *state, mode_t mode); | 217 | extern int nfs4_do_close(struct inode *inode, struct nfs4_state *state, mode_t mode); |
| 194 | extern struct inode *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *); | 218 | extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *); |
| 195 | extern int nfs4_open_revalidate(struct inode *, struct dentry *, int); | 219 | extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *); |
| 196 | 220 | ||
| 197 | extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops; | 221 | extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops; |
| 198 | extern struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops; | 222 | extern struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops; |
| @@ -224,12 +248,17 @@ extern struct nfs4_state * nfs4_get_open_state(struct inode *, struct nfs4_state | |||
| 224 | extern void nfs4_put_open_state(struct nfs4_state *); | 248 | extern void nfs4_put_open_state(struct nfs4_state *); |
| 225 | extern void nfs4_close_state(struct nfs4_state *, mode_t); | 249 | extern void nfs4_close_state(struct nfs4_state *, mode_t); |
| 226 | extern struct nfs4_state *nfs4_find_state(struct inode *, struct rpc_cred *, mode_t mode); | 250 | extern struct nfs4_state *nfs4_find_state(struct inode *, struct rpc_cred *, mode_t mode); |
| 227 | extern void nfs4_increment_seqid(int status, struct nfs4_state_owner *sp); | ||
| 228 | extern void nfs4_schedule_state_recovery(struct nfs4_client *); | 251 | extern void nfs4_schedule_state_recovery(struct nfs4_client *); |
| 252 | extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp); | ||
| 229 | extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl); | 253 | extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl); |
| 230 | extern void nfs4_increment_lock_seqid(int status, struct nfs4_lock_state *ls); | ||
| 231 | extern void nfs4_copy_stateid(nfs4_stateid *, struct nfs4_state *, fl_owner_t); | 254 | extern void nfs4_copy_stateid(nfs4_stateid *, struct nfs4_state *, fl_owner_t); |
| 232 | 255 | ||
| 256 | extern struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter); | ||
| 257 | extern int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task); | ||
| 258 | extern void nfs_increment_open_seqid(int status, struct nfs_seqid *seqid); | ||
| 259 | extern void nfs_increment_lock_seqid(int status, struct nfs_seqid *seqid); | ||
| 260 | extern void nfs_free_seqid(struct nfs_seqid *seqid); | ||
| 261 | |||
| 233 | extern const nfs4_stateid zero_stateid; | 262 | extern const nfs4_stateid zero_stateid; |
| 234 | 263 | ||
| 235 | /* nfs4xdr.c */ | 264 | /* nfs4xdr.c */ |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 9701ca8c9428..933e13b383f8 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
| @@ -47,6 +47,7 @@ | |||
| 47 | #include <linux/nfs_page.h> | 47 | #include <linux/nfs_page.h> |
| 48 | #include <linux/smp_lock.h> | 48 | #include <linux/smp_lock.h> |
| 49 | #include <linux/namei.h> | 49 | #include <linux/namei.h> |
| 50 | #include <linux/mount.h> | ||
| 50 | 51 | ||
| 51 | #include "nfs4_fs.h" | 52 | #include "nfs4_fs.h" |
| 52 | #include "delegation.h" | 53 | #include "delegation.h" |
| @@ -56,10 +57,11 @@ | |||
| 56 | #define NFS4_POLL_RETRY_MIN (1*HZ) | 57 | #define NFS4_POLL_RETRY_MIN (1*HZ) |
| 57 | #define NFS4_POLL_RETRY_MAX (15*HZ) | 58 | #define NFS4_POLL_RETRY_MAX (15*HZ) |
| 58 | 59 | ||
| 60 | static int _nfs4_proc_open_confirm(struct rpc_clnt *clnt, const struct nfs_fh *fh, struct nfs4_state_owner *sp, nfs4_stateid *stateid, struct nfs_seqid *seqid); | ||
| 59 | static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); | 61 | static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); |
| 60 | static int nfs4_async_handle_error(struct rpc_task *, struct nfs_server *); | 62 | static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *); |
| 61 | static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry); | 63 | static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry); |
| 62 | static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struct nfs4_exception *exception); | 64 | static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception); |
| 63 | extern u32 *nfs4_decode_dirent(u32 *p, struct nfs_entry *entry, int plus); | 65 | extern u32 *nfs4_decode_dirent(u32 *p, struct nfs_entry *entry, int plus); |
| 64 | extern struct rpc_procinfo nfs4_procedures[]; | 66 | extern struct rpc_procinfo nfs4_procedures[]; |
| 65 | 67 | ||
| @@ -185,8 +187,26 @@ static void update_changeattr(struct inode *inode, struct nfs4_change_info *cinf | |||
| 185 | { | 187 | { |
| 186 | struct nfs_inode *nfsi = NFS_I(inode); | 188 | struct nfs_inode *nfsi = NFS_I(inode); |
| 187 | 189 | ||
| 190 | spin_lock(&inode->i_lock); | ||
| 191 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR; | ||
| 188 | if (cinfo->before == nfsi->change_attr && cinfo->atomic) | 192 | if (cinfo->before == nfsi->change_attr && cinfo->atomic) |
| 189 | nfsi->change_attr = cinfo->after; | 193 | nfsi->change_attr = cinfo->after; |
| 194 | spin_unlock(&inode->i_lock); | ||
| 195 | } | ||
| 196 | |||
| 197 | /* Helper for asynchronous RPC calls */ | ||
| 198 | static int nfs4_call_async(struct rpc_clnt *clnt, rpc_action tk_begin, | ||
| 199 | rpc_action tk_exit, void *calldata) | ||
| 200 | { | ||
| 201 | struct rpc_task *task; | ||
| 202 | |||
| 203 | if (!(task = rpc_new_task(clnt, tk_exit, RPC_TASK_ASYNC))) | ||
| 204 | return -ENOMEM; | ||
| 205 | |||
| 206 | task->tk_calldata = calldata; | ||
| 207 | task->tk_action = tk_begin; | ||
| 208 | rpc_execute(task); | ||
| 209 | return 0; | ||
| 190 | } | 210 | } |
| 191 | 211 | ||
| 192 | static void update_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid, int open_flags) | 212 | static void update_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid, int open_flags) |
| @@ -195,6 +215,7 @@ static void update_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid, | |||
| 195 | 215 | ||
| 196 | open_flags &= (FMODE_READ|FMODE_WRITE); | 216 | open_flags &= (FMODE_READ|FMODE_WRITE); |
| 197 | /* Protect against nfs4_find_state() */ | 217 | /* Protect against nfs4_find_state() */ |
| 218 | spin_lock(&state->owner->so_lock); | ||
| 198 | spin_lock(&inode->i_lock); | 219 | spin_lock(&inode->i_lock); |
| 199 | state->state |= open_flags; | 220 | state->state |= open_flags; |
| 200 | /* NB! List reordering - see the reclaim code for why. */ | 221 | /* NB! List reordering - see the reclaim code for why. */ |
| @@ -204,12 +225,12 @@ static void update_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid, | |||
| 204 | state->nreaders++; | 225 | state->nreaders++; |
| 205 | memcpy(&state->stateid, stateid, sizeof(state->stateid)); | 226 | memcpy(&state->stateid, stateid, sizeof(state->stateid)); |
| 206 | spin_unlock(&inode->i_lock); | 227 | spin_unlock(&inode->i_lock); |
| 228 | spin_unlock(&state->owner->so_lock); | ||
| 207 | } | 229 | } |
| 208 | 230 | ||
| 209 | /* | 231 | /* |
| 210 | * OPEN_RECLAIM: | 232 | * OPEN_RECLAIM: |
| 211 | * reclaim state on the server after a reboot. | 233 | * reclaim state on the server after a reboot. |
| 212 | * Assumes caller is holding the sp->so_sem | ||
| 213 | */ | 234 | */ |
| 214 | static int _nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state) | 235 | static int _nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state) |
| 215 | { | 236 | { |
| @@ -218,7 +239,6 @@ static int _nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *st | |||
| 218 | struct nfs_delegation *delegation = NFS_I(inode)->delegation; | 239 | struct nfs_delegation *delegation = NFS_I(inode)->delegation; |
| 219 | struct nfs_openargs o_arg = { | 240 | struct nfs_openargs o_arg = { |
| 220 | .fh = NFS_FH(inode), | 241 | .fh = NFS_FH(inode), |
| 221 | .seqid = sp->so_seqid, | ||
| 222 | .id = sp->so_id, | 242 | .id = sp->so_id, |
| 223 | .open_flags = state->state, | 243 | .open_flags = state->state, |
| 224 | .clientid = server->nfs4_state->cl_clientid, | 244 | .clientid = server->nfs4_state->cl_clientid, |
| @@ -245,8 +265,13 @@ static int _nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *st | |||
| 245 | } | 265 | } |
| 246 | o_arg.u.delegation_type = delegation->type; | 266 | o_arg.u.delegation_type = delegation->type; |
| 247 | } | 267 | } |
| 268 | o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid); | ||
| 269 | if (o_arg.seqid == NULL) | ||
| 270 | return -ENOMEM; | ||
| 248 | status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); | 271 | status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); |
| 249 | nfs4_increment_seqid(status, sp); | 272 | /* Confirm the sequence as being established */ |
| 273 | nfs_confirm_seqid(&sp->so_seqid, status); | ||
| 274 | nfs_increment_open_seqid(status, o_arg.seqid); | ||
| 250 | if (status == 0) { | 275 | if (status == 0) { |
| 251 | memcpy(&state->stateid, &o_res.stateid, sizeof(state->stateid)); | 276 | memcpy(&state->stateid, &o_res.stateid, sizeof(state->stateid)); |
| 252 | if (o_res.delegation_type != 0) { | 277 | if (o_res.delegation_type != 0) { |
| @@ -256,6 +281,7 @@ static int _nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *st | |||
| 256 | nfs_async_inode_return_delegation(inode, &o_res.stateid); | 281 | nfs_async_inode_return_delegation(inode, &o_res.stateid); |
| 257 | } | 282 | } |
| 258 | } | 283 | } |
| 284 | nfs_free_seqid(o_arg.seqid); | ||
| 259 | clear_bit(NFS_DELEGATED_STATE, &state->flags); | 285 | clear_bit(NFS_DELEGATED_STATE, &state->flags); |
| 260 | /* Ensure we update the inode attributes */ | 286 | /* Ensure we update the inode attributes */ |
| 261 | NFS_CACHEINV(inode); | 287 | NFS_CACHEINV(inode); |
| @@ -302,23 +328,35 @@ static int _nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state | |||
| 302 | }; | 328 | }; |
| 303 | int status = 0; | 329 | int status = 0; |
| 304 | 330 | ||
| 305 | down(&sp->so_sema); | ||
| 306 | if (!test_bit(NFS_DELEGATED_STATE, &state->flags)) | 331 | if (!test_bit(NFS_DELEGATED_STATE, &state->flags)) |
| 307 | goto out; | 332 | goto out; |
| 308 | if (state->state == 0) | 333 | if (state->state == 0) |
| 309 | goto out; | 334 | goto out; |
| 310 | arg.seqid = sp->so_seqid; | 335 | arg.seqid = nfs_alloc_seqid(&sp->so_seqid); |
| 336 | status = -ENOMEM; | ||
| 337 | if (arg.seqid == NULL) | ||
| 338 | goto out; | ||
| 311 | arg.open_flags = state->state; | 339 | arg.open_flags = state->state; |
| 312 | memcpy(arg.u.delegation.data, state->stateid.data, sizeof(arg.u.delegation.data)); | 340 | memcpy(arg.u.delegation.data, state->stateid.data, sizeof(arg.u.delegation.data)); |
| 313 | status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); | 341 | status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); |
| 314 | nfs4_increment_seqid(status, sp); | 342 | nfs_increment_open_seqid(status, arg.seqid); |
| 343 | if (status != 0) | ||
| 344 | goto out_free; | ||
| 345 | if(res.rflags & NFS4_OPEN_RESULT_CONFIRM) { | ||
| 346 | status = _nfs4_proc_open_confirm(server->client, NFS_FH(inode), | ||
| 347 | sp, &res.stateid, arg.seqid); | ||
| 348 | if (status != 0) | ||
| 349 | goto out_free; | ||
| 350 | } | ||
| 351 | nfs_confirm_seqid(&sp->so_seqid, 0); | ||
| 315 | if (status >= 0) { | 352 | if (status >= 0) { |
| 316 | memcpy(state->stateid.data, res.stateid.data, | 353 | memcpy(state->stateid.data, res.stateid.data, |
| 317 | sizeof(state->stateid.data)); | 354 | sizeof(state->stateid.data)); |
| 318 | clear_bit(NFS_DELEGATED_STATE, &state->flags); | 355 | clear_bit(NFS_DELEGATED_STATE, &state->flags); |
| 319 | } | 356 | } |
| 357 | out_free: | ||
| 358 | nfs_free_seqid(arg.seqid); | ||
| 320 | out: | 359 | out: |
| 321 | up(&sp->so_sema); | ||
| 322 | dput(parent); | 360 | dput(parent); |
| 323 | return status; | 361 | return status; |
| 324 | } | 362 | } |
| @@ -345,11 +383,11 @@ int nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state) | |||
| 345 | return err; | 383 | return err; |
| 346 | } | 384 | } |
| 347 | 385 | ||
| 348 | static inline int _nfs4_proc_open_confirm(struct rpc_clnt *clnt, const struct nfs_fh *fh, struct nfs4_state_owner *sp, nfs4_stateid *stateid) | 386 | static int _nfs4_proc_open_confirm(struct rpc_clnt *clnt, const struct nfs_fh *fh, struct nfs4_state_owner *sp, nfs4_stateid *stateid, struct nfs_seqid *seqid) |
| 349 | { | 387 | { |
| 350 | struct nfs_open_confirmargs arg = { | 388 | struct nfs_open_confirmargs arg = { |
| 351 | .fh = fh, | 389 | .fh = fh, |
| 352 | .seqid = sp->so_seqid, | 390 | .seqid = seqid, |
| 353 | .stateid = *stateid, | 391 | .stateid = *stateid, |
| 354 | }; | 392 | }; |
| 355 | struct nfs_open_confirmres res; | 393 | struct nfs_open_confirmres res; |
| @@ -362,7 +400,9 @@ static inline int _nfs4_proc_open_confirm(struct rpc_clnt *clnt, const struct nf | |||
| 362 | int status; | 400 | int status; |
| 363 | 401 | ||
| 364 | status = rpc_call_sync(clnt, &msg, RPC_TASK_NOINTR); | 402 | status = rpc_call_sync(clnt, &msg, RPC_TASK_NOINTR); |
| 365 | nfs4_increment_seqid(status, sp); | 403 | /* Confirm the sequence as being established */ |
| 404 | nfs_confirm_seqid(&sp->so_seqid, status); | ||
| 405 | nfs_increment_open_seqid(status, seqid); | ||
| 366 | if (status >= 0) | 406 | if (status >= 0) |
| 367 | memcpy(stateid, &res.stateid, sizeof(*stateid)); | 407 | memcpy(stateid, &res.stateid, sizeof(*stateid)); |
| 368 | return status; | 408 | return status; |
| @@ -380,21 +420,41 @@ static int _nfs4_proc_open(struct inode *dir, struct nfs4_state_owner *sp, stru | |||
| 380 | int status; | 420 | int status; |
| 381 | 421 | ||
| 382 | /* Update sequence id. The caller must serialize! */ | 422 | /* Update sequence id. The caller must serialize! */ |
| 383 | o_arg->seqid = sp->so_seqid; | ||
| 384 | o_arg->id = sp->so_id; | 423 | o_arg->id = sp->so_id; |
| 385 | o_arg->clientid = sp->so_client->cl_clientid; | 424 | o_arg->clientid = sp->so_client->cl_clientid; |
| 386 | 425 | ||
| 387 | status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); | 426 | status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); |
| 388 | nfs4_increment_seqid(status, sp); | 427 | if (status == 0) { |
| 428 | /* OPEN on anything except a regular file is disallowed in NFSv4 */ | ||
| 429 | switch (o_res->f_attr->mode & S_IFMT) { | ||
| 430 | case S_IFREG: | ||
| 431 | break; | ||
| 432 | case S_IFLNK: | ||
| 433 | status = -ELOOP; | ||
| 434 | break; | ||
| 435 | case S_IFDIR: | ||
| 436 | status = -EISDIR; | ||
| 437 | break; | ||
| 438 | default: | ||
| 439 | status = -ENOTDIR; | ||
| 440 | } | ||
| 441 | } | ||
| 442 | |||
| 443 | nfs_increment_open_seqid(status, o_arg->seqid); | ||
| 389 | if (status != 0) | 444 | if (status != 0) |
| 390 | goto out; | 445 | goto out; |
| 391 | update_changeattr(dir, &o_res->cinfo); | 446 | if (o_arg->open_flags & O_CREAT) { |
| 447 | update_changeattr(dir, &o_res->cinfo); | ||
| 448 | nfs_post_op_update_inode(dir, o_res->dir_attr); | ||
| 449 | } else | ||
| 450 | nfs_refresh_inode(dir, o_res->dir_attr); | ||
| 392 | if(o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) { | 451 | if(o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) { |
| 393 | status = _nfs4_proc_open_confirm(server->client, &o_res->fh, | 452 | status = _nfs4_proc_open_confirm(server->client, &o_res->fh, |
| 394 | sp, &o_res->stateid); | 453 | sp, &o_res->stateid, o_arg->seqid); |
| 395 | if (status != 0) | 454 | if (status != 0) |
| 396 | goto out; | 455 | goto out; |
| 397 | } | 456 | } |
| 457 | nfs_confirm_seqid(&sp->so_seqid, 0); | ||
| 398 | if (!(o_res->f_attr->valid & NFS_ATTR_FATTR)) | 458 | if (!(o_res->f_attr->valid & NFS_ATTR_FATTR)) |
| 399 | status = server->rpc_ops->getattr(server, &o_res->fh, o_res->f_attr); | 459 | status = server->rpc_ops->getattr(server, &o_res->fh, o_res->f_attr); |
| 400 | out: | 460 | out: |
| @@ -441,9 +501,7 @@ static int _nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *st | |||
| 441 | struct inode *inode = state->inode; | 501 | struct inode *inode = state->inode; |
| 442 | struct nfs_server *server = NFS_SERVER(dir); | 502 | struct nfs_server *server = NFS_SERVER(dir); |
| 443 | struct nfs_delegation *delegation = NFS_I(inode)->delegation; | 503 | struct nfs_delegation *delegation = NFS_I(inode)->delegation; |
| 444 | struct nfs_fattr f_attr = { | 504 | struct nfs_fattr f_attr, dir_attr; |
| 445 | .valid = 0, | ||
| 446 | }; | ||
| 447 | struct nfs_openargs o_arg = { | 505 | struct nfs_openargs o_arg = { |
| 448 | .fh = NFS_FH(dir), | 506 | .fh = NFS_FH(dir), |
| 449 | .open_flags = state->state, | 507 | .open_flags = state->state, |
| @@ -453,6 +511,7 @@ static int _nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *st | |||
| 453 | }; | 511 | }; |
| 454 | struct nfs_openres o_res = { | 512 | struct nfs_openres o_res = { |
| 455 | .f_attr = &f_attr, | 513 | .f_attr = &f_attr, |
| 514 | .dir_attr = &dir_attr, | ||
| 456 | .server = server, | 515 | .server = server, |
| 457 | }; | 516 | }; |
| 458 | int status = 0; | 517 | int status = 0; |
| @@ -465,6 +524,12 @@ static int _nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *st | |||
| 465 | set_bit(NFS_DELEGATED_STATE, &state->flags); | 524 | set_bit(NFS_DELEGATED_STATE, &state->flags); |
| 466 | goto out; | 525 | goto out; |
| 467 | } | 526 | } |
| 527 | o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid); | ||
| 528 | status = -ENOMEM; | ||
| 529 | if (o_arg.seqid == NULL) | ||
| 530 | goto out; | ||
| 531 | nfs_fattr_init(&f_attr); | ||
| 532 | nfs_fattr_init(&dir_attr); | ||
| 468 | status = _nfs4_proc_open(dir, sp, &o_arg, &o_res); | 533 | status = _nfs4_proc_open(dir, sp, &o_arg, &o_res); |
| 469 | if (status != 0) | 534 | if (status != 0) |
| 470 | goto out_nodeleg; | 535 | goto out_nodeleg; |
| @@ -490,6 +555,7 @@ static int _nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *st | |||
| 490 | nfs_inode_reclaim_delegation(inode, sp->so_cred, &o_res); | 555 | nfs_inode_reclaim_delegation(inode, sp->so_cred, &o_res); |
| 491 | } | 556 | } |
| 492 | out_nodeleg: | 557 | out_nodeleg: |
| 558 | nfs_free_seqid(o_arg.seqid); | ||
| 493 | clear_bit(NFS_DELEGATED_STATE, &state->flags); | 559 | clear_bit(NFS_DELEGATED_STATE, &state->flags); |
| 494 | out: | 560 | out: |
| 495 | dput(parent); | 561 | dput(parent); |
| @@ -564,7 +630,6 @@ static int _nfs4_open_delegated(struct inode *inode, int flags, struct rpc_cred | |||
| 564 | dprintk("%s: nfs4_get_state_owner failed!\n", __FUNCTION__); | 630 | dprintk("%s: nfs4_get_state_owner failed!\n", __FUNCTION__); |
| 565 | goto out_err; | 631 | goto out_err; |
| 566 | } | 632 | } |
| 567 | down(&sp->so_sema); | ||
| 568 | state = nfs4_get_open_state(inode, sp); | 633 | state = nfs4_get_open_state(inode, sp); |
| 569 | if (state == NULL) | 634 | if (state == NULL) |
| 570 | goto out_err; | 635 | goto out_err; |
| @@ -589,7 +654,6 @@ static int _nfs4_open_delegated(struct inode *inode, int flags, struct rpc_cred | |||
| 589 | set_bit(NFS_DELEGATED_STATE, &state->flags); | 654 | set_bit(NFS_DELEGATED_STATE, &state->flags); |
| 590 | update_open_stateid(state, &delegation->stateid, open_flags); | 655 | update_open_stateid(state, &delegation->stateid, open_flags); |
| 591 | out_ok: | 656 | out_ok: |
| 592 | up(&sp->so_sema); | ||
| 593 | nfs4_put_state_owner(sp); | 657 | nfs4_put_state_owner(sp); |
| 594 | up_read(&nfsi->rwsem); | 658 | up_read(&nfsi->rwsem); |
| 595 | up_read(&clp->cl_sem); | 659 | up_read(&clp->cl_sem); |
| @@ -600,11 +664,12 @@ out_err: | |||
| 600 | if (sp != NULL) { | 664 | if (sp != NULL) { |
| 601 | if (state != NULL) | 665 | if (state != NULL) |
| 602 | nfs4_put_open_state(state); | 666 | nfs4_put_open_state(state); |
| 603 | up(&sp->so_sema); | ||
| 604 | nfs4_put_state_owner(sp); | 667 | nfs4_put_state_owner(sp); |
| 605 | } | 668 | } |
| 606 | up_read(&nfsi->rwsem); | 669 | up_read(&nfsi->rwsem); |
| 607 | up_read(&clp->cl_sem); | 670 | up_read(&clp->cl_sem); |
| 671 | if (err != -EACCES) | ||
| 672 | nfs_inode_return_delegation(inode); | ||
| 608 | return err; | 673 | return err; |
| 609 | } | 674 | } |
| 610 | 675 | ||
| @@ -635,9 +700,7 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, st | |||
| 635 | struct nfs4_client *clp = server->nfs4_state; | 700 | struct nfs4_client *clp = server->nfs4_state; |
| 636 | struct inode *inode = NULL; | 701 | struct inode *inode = NULL; |
| 637 | int status; | 702 | int status; |
| 638 | struct nfs_fattr f_attr = { | 703 | struct nfs_fattr f_attr, dir_attr; |
| 639 | .valid = 0, | ||
| 640 | }; | ||
| 641 | struct nfs_openargs o_arg = { | 704 | struct nfs_openargs o_arg = { |
| 642 | .fh = NFS_FH(dir), | 705 | .fh = NFS_FH(dir), |
| 643 | .open_flags = flags, | 706 | .open_flags = flags, |
| @@ -648,6 +711,7 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, st | |||
| 648 | }; | 711 | }; |
| 649 | struct nfs_openres o_res = { | 712 | struct nfs_openres o_res = { |
| 650 | .f_attr = &f_attr, | 713 | .f_attr = &f_attr, |
| 714 | .dir_attr = &dir_attr, | ||
| 651 | .server = server, | 715 | .server = server, |
| 652 | }; | 716 | }; |
| 653 | 717 | ||
| @@ -665,8 +729,12 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, st | |||
| 665 | } else | 729 | } else |
| 666 | o_arg.u.attrs = sattr; | 730 | o_arg.u.attrs = sattr; |
| 667 | /* Serialization for the sequence id */ | 731 | /* Serialization for the sequence id */ |
| 668 | down(&sp->so_sema); | ||
| 669 | 732 | ||
| 733 | o_arg.seqid = nfs_alloc_seqid(&sp->so_seqid); | ||
| 734 | if (o_arg.seqid == NULL) | ||
| 735 | return -ENOMEM; | ||
| 736 | nfs_fattr_init(&f_attr); | ||
| 737 | nfs_fattr_init(&dir_attr); | ||
| 670 | status = _nfs4_proc_open(dir, sp, &o_arg, &o_res); | 738 | status = _nfs4_proc_open(dir, sp, &o_arg, &o_res); |
| 671 | if (status != 0) | 739 | if (status != 0) |
| 672 | goto out_err; | 740 | goto out_err; |
| @@ -681,7 +749,7 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, st | |||
| 681 | update_open_stateid(state, &o_res.stateid, flags); | 749 | update_open_stateid(state, &o_res.stateid, flags); |
| 682 | if (o_res.delegation_type != 0) | 750 | if (o_res.delegation_type != 0) |
| 683 | nfs_inode_set_delegation(inode, cred, &o_res); | 751 | nfs_inode_set_delegation(inode, cred, &o_res); |
| 684 | up(&sp->so_sema); | 752 | nfs_free_seqid(o_arg.seqid); |
| 685 | nfs4_put_state_owner(sp); | 753 | nfs4_put_state_owner(sp); |
| 686 | up_read(&clp->cl_sem); | 754 | up_read(&clp->cl_sem); |
| 687 | *res = state; | 755 | *res = state; |
| @@ -690,7 +758,7 @@ out_err: | |||
| 690 | if (sp != NULL) { | 758 | if (sp != NULL) { |
| 691 | if (state != NULL) | 759 | if (state != NULL) |
| 692 | nfs4_put_open_state(state); | 760 | nfs4_put_open_state(state); |
| 693 | up(&sp->so_sema); | 761 | nfs_free_seqid(o_arg.seqid); |
| 694 | nfs4_put_state_owner(sp); | 762 | nfs4_put_state_owner(sp); |
| 695 | } | 763 | } |
| 696 | /* Note: clp->cl_sem must be released before nfs4_put_open_state()! */ | 764 | /* Note: clp->cl_sem must be released before nfs4_put_open_state()! */ |
| @@ -718,7 +786,7 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir, struct dentry *dentry, | |||
| 718 | * It is actually a sign of a bug on the client or on the server. | 786 | * It is actually a sign of a bug on the client or on the server. |
| 719 | * | 787 | * |
| 720 | * If we receive a BAD_SEQID error in the particular case of | 788 | * If we receive a BAD_SEQID error in the particular case of |
| 721 | * doing an OPEN, we assume that nfs4_increment_seqid() will | 789 | * doing an OPEN, we assume that nfs_increment_open_seqid() will |
| 722 | * have unhashed the old state_owner for us, and that we can | 790 | * have unhashed the old state_owner for us, and that we can |
| 723 | * therefore safely retry using a new one. We should still warn | 791 | * therefore safely retry using a new one. We should still warn |
| 724 | * the user though... | 792 | * the user though... |
| @@ -728,6 +796,16 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir, struct dentry *dentry, | |||
| 728 | exception.retry = 1; | 796 | exception.retry = 1; |
| 729 | continue; | 797 | continue; |
| 730 | } | 798 | } |
| 799 | /* | ||
| 800 | * BAD_STATEID on OPEN means that the server cancelled our | ||
| 801 | * state before it received the OPEN_CONFIRM. | ||
| 802 | * Recover by retrying the request as per the discussion | ||
| 803 | * on Page 181 of RFC3530. | ||
| 804 | */ | ||
| 805 | if (status == -NFS4ERR_BAD_STATEID) { | ||
| 806 | exception.retry = 1; | ||
| 807 | continue; | ||
| 808 | } | ||
| 731 | res = ERR_PTR(nfs4_handle_exception(NFS_SERVER(dir), | 809 | res = ERR_PTR(nfs4_handle_exception(NFS_SERVER(dir), |
| 732 | status, &exception)); | 810 | status, &exception)); |
| 733 | } while (exception.retry); | 811 | } while (exception.retry); |
| @@ -755,7 +833,7 @@ static int _nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr, | |||
| 755 | }; | 833 | }; |
| 756 | int status; | 834 | int status; |
| 757 | 835 | ||
| 758 | fattr->valid = 0; | 836 | nfs_fattr_init(fattr); |
| 759 | 837 | ||
| 760 | if (state != NULL) { | 838 | if (state != NULL) { |
| 761 | msg.rpc_cred = state->owner->so_cred; | 839 | msg.rpc_cred = state->owner->so_cred; |
| @@ -787,19 +865,30 @@ struct nfs4_closedata { | |||
| 787 | struct nfs4_state *state; | 865 | struct nfs4_state *state; |
| 788 | struct nfs_closeargs arg; | 866 | struct nfs_closeargs arg; |
| 789 | struct nfs_closeres res; | 867 | struct nfs_closeres res; |
| 868 | struct nfs_fattr fattr; | ||
| 790 | }; | 869 | }; |
| 791 | 870 | ||
| 871 | static void nfs4_free_closedata(struct nfs4_closedata *calldata) | ||
| 872 | { | ||
| 873 | struct nfs4_state *state = calldata->state; | ||
| 874 | struct nfs4_state_owner *sp = state->owner; | ||
| 875 | |||
| 876 | nfs4_put_open_state(calldata->state); | ||
| 877 | nfs_free_seqid(calldata->arg.seqid); | ||
| 878 | nfs4_put_state_owner(sp); | ||
| 879 | kfree(calldata); | ||
| 880 | } | ||
| 881 | |||
| 792 | static void nfs4_close_done(struct rpc_task *task) | 882 | static void nfs4_close_done(struct rpc_task *task) |
| 793 | { | 883 | { |
| 794 | struct nfs4_closedata *calldata = (struct nfs4_closedata *)task->tk_calldata; | 884 | struct nfs4_closedata *calldata = (struct nfs4_closedata *)task->tk_calldata; |
| 795 | struct nfs4_state *state = calldata->state; | 885 | struct nfs4_state *state = calldata->state; |
| 796 | struct nfs4_state_owner *sp = state->owner; | ||
| 797 | struct nfs_server *server = NFS_SERVER(calldata->inode); | 886 | struct nfs_server *server = NFS_SERVER(calldata->inode); |
| 798 | 887 | ||
| 799 | /* hmm. we are done with the inode, and in the process of freeing | 888 | /* hmm. we are done with the inode, and in the process of freeing |
| 800 | * the state_owner. we keep this around to process errors | 889 | * the state_owner. we keep this around to process errors |
| 801 | */ | 890 | */ |
| 802 | nfs4_increment_seqid(task->tk_status, sp); | 891 | nfs_increment_open_seqid(task->tk_status, calldata->arg.seqid); |
| 803 | switch (task->tk_status) { | 892 | switch (task->tk_status) { |
| 804 | case 0: | 893 | case 0: |
| 805 | memcpy(&state->stateid, &calldata->res.stateid, | 894 | memcpy(&state->stateid, &calldata->res.stateid, |
| @@ -816,25 +905,49 @@ static void nfs4_close_done(struct rpc_task *task) | |||
| 816 | return; | 905 | return; |
| 817 | } | 906 | } |
| 818 | } | 907 | } |
| 908 | nfs_refresh_inode(calldata->inode, calldata->res.fattr); | ||
| 819 | state->state = calldata->arg.open_flags; | 909 | state->state = calldata->arg.open_flags; |
| 820 | nfs4_put_open_state(state); | 910 | nfs4_free_closedata(calldata); |
| 821 | up(&sp->so_sema); | ||
| 822 | nfs4_put_state_owner(sp); | ||
| 823 | up_read(&server->nfs4_state->cl_sem); | ||
| 824 | kfree(calldata); | ||
| 825 | } | 911 | } |
| 826 | 912 | ||
| 827 | static inline int nfs4_close_call(struct rpc_clnt *clnt, struct nfs4_closedata *calldata) | 913 | static void nfs4_close_begin(struct rpc_task *task) |
| 828 | { | 914 | { |
| 915 | struct nfs4_closedata *calldata = (struct nfs4_closedata *)task->tk_calldata; | ||
| 916 | struct nfs4_state *state = calldata->state; | ||
| 829 | struct rpc_message msg = { | 917 | struct rpc_message msg = { |
| 830 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CLOSE], | 918 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CLOSE], |
| 831 | .rpc_argp = &calldata->arg, | 919 | .rpc_argp = &calldata->arg, |
| 832 | .rpc_resp = &calldata->res, | 920 | .rpc_resp = &calldata->res, |
| 833 | .rpc_cred = calldata->state->owner->so_cred, | 921 | .rpc_cred = state->owner->so_cred, |
| 834 | }; | 922 | }; |
| 835 | if (calldata->arg.open_flags != 0) | 923 | int mode = 0; |
| 924 | int status; | ||
| 925 | |||
| 926 | status = nfs_wait_on_sequence(calldata->arg.seqid, task); | ||
| 927 | if (status != 0) | ||
| 928 | return; | ||
| 929 | /* Don't reorder reads */ | ||
| 930 | smp_rmb(); | ||
| 931 | /* Recalculate the new open mode in case someone reopened the file | ||
| 932 | * while we were waiting in line to be scheduled. | ||
| 933 | */ | ||
| 934 | if (state->nreaders != 0) | ||
| 935 | mode |= FMODE_READ; | ||
| 936 | if (state->nwriters != 0) | ||
| 937 | mode |= FMODE_WRITE; | ||
| 938 | if (test_bit(NFS_DELEGATED_STATE, &state->flags)) | ||
| 939 | state->state = mode; | ||
| 940 | if (mode == state->state) { | ||
| 941 | nfs4_free_closedata(calldata); | ||
| 942 | task->tk_exit = NULL; | ||
| 943 | rpc_exit(task, 0); | ||
| 944 | return; | ||
| 945 | } | ||
| 946 | nfs_fattr_init(calldata->res.fattr); | ||
| 947 | if (mode != 0) | ||
| 836 | msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE]; | 948 | msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE]; |
| 837 | return rpc_call_async(clnt, &msg, 0, nfs4_close_done, calldata); | 949 | calldata->arg.open_flags = mode; |
| 950 | rpc_call_setup(task, &msg, 0); | ||
| 838 | } | 951 | } |
| 839 | 952 | ||
| 840 | /* | 953 | /* |
| @@ -850,40 +963,57 @@ static inline int nfs4_close_call(struct rpc_clnt *clnt, struct nfs4_closedata * | |||
| 850 | */ | 963 | */ |
| 851 | int nfs4_do_close(struct inode *inode, struct nfs4_state *state, mode_t mode) | 964 | int nfs4_do_close(struct inode *inode, struct nfs4_state *state, mode_t mode) |
| 852 | { | 965 | { |
| 966 | struct nfs_server *server = NFS_SERVER(inode); | ||
| 853 | struct nfs4_closedata *calldata; | 967 | struct nfs4_closedata *calldata; |
| 854 | int status; | 968 | int status = -ENOMEM; |
| 855 | 969 | ||
| 856 | /* Tell caller we're done */ | 970 | calldata = kmalloc(sizeof(*calldata), GFP_KERNEL); |
| 857 | if (test_bit(NFS_DELEGATED_STATE, &state->flags)) { | ||
| 858 | state->state = mode; | ||
| 859 | return 0; | ||
| 860 | } | ||
| 861 | calldata = (struct nfs4_closedata *)kmalloc(sizeof(*calldata), GFP_KERNEL); | ||
| 862 | if (calldata == NULL) | 971 | if (calldata == NULL) |
| 863 | return -ENOMEM; | 972 | goto out; |
| 864 | calldata->inode = inode; | 973 | calldata->inode = inode; |
| 865 | calldata->state = state; | 974 | calldata->state = state; |
| 866 | calldata->arg.fh = NFS_FH(inode); | 975 | calldata->arg.fh = NFS_FH(inode); |
| 976 | calldata->arg.stateid = &state->stateid; | ||
| 867 | /* Serialization for the sequence id */ | 977 | /* Serialization for the sequence id */ |
| 868 | calldata->arg.seqid = state->owner->so_seqid; | 978 | calldata->arg.seqid = nfs_alloc_seqid(&state->owner->so_seqid); |
| 869 | calldata->arg.open_flags = mode; | 979 | if (calldata->arg.seqid == NULL) |
| 870 | memcpy(&calldata->arg.stateid, &state->stateid, | 980 | goto out_free_calldata; |
| 871 | sizeof(calldata->arg.stateid)); | 981 | calldata->arg.bitmask = server->attr_bitmask; |
| 872 | status = nfs4_close_call(NFS_SERVER(inode)->client, calldata); | 982 | calldata->res.fattr = &calldata->fattr; |
| 873 | /* | 983 | calldata->res.server = server; |
| 874 | * Return -EINPROGRESS on success in order to indicate to the | 984 | |
| 875 | * caller that an asynchronous RPC call has been launched, and | 985 | status = nfs4_call_async(server->client, nfs4_close_begin, |
| 876 | * that it will release the semaphores on completion. | 986 | nfs4_close_done, calldata); |
| 877 | */ | 987 | if (status == 0) |
| 878 | return (status == 0) ? -EINPROGRESS : status; | 988 | goto out; |
| 989 | |||
| 990 | nfs_free_seqid(calldata->arg.seqid); | ||
| 991 | out_free_calldata: | ||
| 992 | kfree(calldata); | ||
| 993 | out: | ||
| 994 | return status; | ||
| 879 | } | 995 | } |
| 880 | 996 | ||
| 881 | struct inode * | 997 | static void nfs4_intent_set_file(struct nameidata *nd, struct dentry *dentry, struct nfs4_state *state) |
| 998 | { | ||
| 999 | struct file *filp; | ||
| 1000 | |||
| 1001 | filp = lookup_instantiate_filp(nd, dentry, NULL); | ||
| 1002 | if (!IS_ERR(filp)) { | ||
| 1003 | struct nfs_open_context *ctx; | ||
| 1004 | ctx = (struct nfs_open_context *)filp->private_data; | ||
| 1005 | ctx->state = state; | ||
| 1006 | } else | ||
| 1007 | nfs4_close_state(state, nd->intent.open.flags); | ||
| 1008 | } | ||
| 1009 | |||
| 1010 | struct dentry * | ||
| 882 | nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | 1011 | nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd) |
| 883 | { | 1012 | { |
| 884 | struct iattr attr; | 1013 | struct iattr attr; |
| 885 | struct rpc_cred *cred; | 1014 | struct rpc_cred *cred; |
| 886 | struct nfs4_state *state; | 1015 | struct nfs4_state *state; |
| 1016 | struct dentry *res; | ||
| 887 | 1017 | ||
| 888 | if (nd->flags & LOOKUP_CREATE) { | 1018 | if (nd->flags & LOOKUP_CREATE) { |
| 889 | attr.ia_mode = nd->intent.open.create_mode; | 1019 | attr.ia_mode = nd->intent.open.create_mode; |
| @@ -897,16 +1027,23 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd) | |||
| 897 | 1027 | ||
| 898 | cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, 0); | 1028 | cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, 0); |
| 899 | if (IS_ERR(cred)) | 1029 | if (IS_ERR(cred)) |
| 900 | return (struct inode *)cred; | 1030 | return (struct dentry *)cred; |
| 901 | state = nfs4_do_open(dir, dentry, nd->intent.open.flags, &attr, cred); | 1031 | state = nfs4_do_open(dir, dentry, nd->intent.open.flags, &attr, cred); |
| 902 | put_rpccred(cred); | 1032 | put_rpccred(cred); |
| 903 | if (IS_ERR(state)) | 1033 | if (IS_ERR(state)) { |
| 904 | return (struct inode *)state; | 1034 | if (PTR_ERR(state) == -ENOENT) |
| 905 | return state->inode; | 1035 | d_add(dentry, NULL); |
| 1036 | return (struct dentry *)state; | ||
| 1037 | } | ||
| 1038 | res = d_add_unique(dentry, state->inode); | ||
| 1039 | if (res != NULL) | ||
| 1040 | dentry = res; | ||
| 1041 | nfs4_intent_set_file(nd, dentry, state); | ||
| 1042 | return res; | ||
| 906 | } | 1043 | } |
| 907 | 1044 | ||
| 908 | int | 1045 | int |
| 909 | nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags) | 1046 | nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, struct nameidata *nd) |
| 910 | { | 1047 | { |
| 911 | struct rpc_cred *cred; | 1048 | struct rpc_cred *cred; |
| 912 | struct nfs4_state *state; | 1049 | struct nfs4_state *state; |
| @@ -919,18 +1056,30 @@ nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags) | |||
| 919 | if (IS_ERR(state)) | 1056 | if (IS_ERR(state)) |
| 920 | state = nfs4_do_open(dir, dentry, openflags, NULL, cred); | 1057 | state = nfs4_do_open(dir, dentry, openflags, NULL, cred); |
| 921 | put_rpccred(cred); | 1058 | put_rpccred(cred); |
| 922 | if (state == ERR_PTR(-ENOENT) && dentry->d_inode == 0) | 1059 | if (IS_ERR(state)) { |
| 923 | return 1; | 1060 | switch (PTR_ERR(state)) { |
| 924 | if (IS_ERR(state)) | 1061 | case -EPERM: |
| 925 | return 0; | 1062 | case -EACCES: |
| 1063 | case -EDQUOT: | ||
| 1064 | case -ENOSPC: | ||
| 1065 | case -EROFS: | ||
| 1066 | lookup_instantiate_filp(nd, (struct dentry *)state, NULL); | ||
| 1067 | return 1; | ||
| 1068 | case -ENOENT: | ||
| 1069 | if (dentry->d_inode == NULL) | ||
| 1070 | return 1; | ||
| 1071 | } | ||
| 1072 | goto out_drop; | ||
| 1073 | } | ||
| 926 | inode = state->inode; | 1074 | inode = state->inode; |
| 1075 | iput(inode); | ||
| 927 | if (inode == dentry->d_inode) { | 1076 | if (inode == dentry->d_inode) { |
| 928 | iput(inode); | 1077 | nfs4_intent_set_file(nd, dentry, state); |
| 929 | return 1; | 1078 | return 1; |
| 930 | } | 1079 | } |
| 931 | d_drop(dentry); | ||
| 932 | nfs4_close_state(state, openflags); | 1080 | nfs4_close_state(state, openflags); |
| 933 | iput(inode); | 1081 | out_drop: |
| 1082 | d_drop(dentry); | ||
| 934 | return 0; | 1083 | return 0; |
| 935 | } | 1084 | } |
| 936 | 1085 | ||
| @@ -974,13 +1123,12 @@ static int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fh | |||
| 974 | static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, | 1123 | static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, |
| 975 | struct nfs_fsinfo *info) | 1124 | struct nfs_fsinfo *info) |
| 976 | { | 1125 | { |
| 977 | struct nfs_fattr * fattr = info->fattr; | ||
| 978 | struct nfs4_lookup_root_arg args = { | 1126 | struct nfs4_lookup_root_arg args = { |
| 979 | .bitmask = nfs4_fattr_bitmap, | 1127 | .bitmask = nfs4_fattr_bitmap, |
| 980 | }; | 1128 | }; |
| 981 | struct nfs4_lookup_res res = { | 1129 | struct nfs4_lookup_res res = { |
| 982 | .server = server, | 1130 | .server = server, |
| 983 | .fattr = fattr, | 1131 | .fattr = info->fattr, |
| 984 | .fh = fhandle, | 1132 | .fh = fhandle, |
| 985 | }; | 1133 | }; |
| 986 | struct rpc_message msg = { | 1134 | struct rpc_message msg = { |
| @@ -988,7 +1136,7 @@ static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, | |||
| 988 | .rpc_argp = &args, | 1136 | .rpc_argp = &args, |
| 989 | .rpc_resp = &res, | 1137 | .rpc_resp = &res, |
| 990 | }; | 1138 | }; |
| 991 | fattr->valid = 0; | 1139 | nfs_fattr_init(info->fattr); |
| 992 | return rpc_call_sync(server->client, &msg, 0); | 1140 | return rpc_call_sync(server->client, &msg, 0); |
| 993 | } | 1141 | } |
| 994 | 1142 | ||
| @@ -1051,7 +1199,7 @@ static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, | |||
| 1051 | q.len = p - q.name; | 1199 | q.len = p - q.name; |
| 1052 | 1200 | ||
| 1053 | do { | 1201 | do { |
| 1054 | fattr->valid = 0; | 1202 | nfs_fattr_init(fattr); |
| 1055 | status = nfs4_handle_exception(server, | 1203 | status = nfs4_handle_exception(server, |
| 1056 | rpc_call_sync(server->client, &msg, 0), | 1204 | rpc_call_sync(server->client, &msg, 0), |
| 1057 | &exception); | 1205 | &exception); |
| @@ -1088,7 +1236,7 @@ static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, | |||
| 1088 | .rpc_resp = &res, | 1236 | .rpc_resp = &res, |
| 1089 | }; | 1237 | }; |
| 1090 | 1238 | ||
| 1091 | fattr->valid = 0; | 1239 | nfs_fattr_init(fattr); |
| 1092 | return rpc_call_sync(server->client, &msg, 0); | 1240 | return rpc_call_sync(server->client, &msg, 0); |
| 1093 | } | 1241 | } |
| 1094 | 1242 | ||
| @@ -1130,7 +1278,7 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, | |||
| 1130 | struct nfs4_state *state; | 1278 | struct nfs4_state *state; |
| 1131 | int status; | 1279 | int status; |
| 1132 | 1280 | ||
| 1133 | fattr->valid = 0; | 1281 | nfs_fattr_init(fattr); |
| 1134 | 1282 | ||
| 1135 | cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0); | 1283 | cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0); |
| 1136 | if (IS_ERR(cred)) | 1284 | if (IS_ERR(cred)) |
| @@ -1176,7 +1324,7 @@ static int _nfs4_proc_lookup(struct inode *dir, struct qstr *name, | |||
| 1176 | .rpc_resp = &res, | 1324 | .rpc_resp = &res, |
| 1177 | }; | 1325 | }; |
| 1178 | 1326 | ||
| 1179 | fattr->valid = 0; | 1327 | nfs_fattr_init(fattr); |
| 1180 | 1328 | ||
| 1181 | dprintk("NFS call lookup %s\n", name->name); | 1329 | dprintk("NFS call lookup %s\n", name->name); |
| 1182 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 1330 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
| @@ -1325,7 +1473,7 @@ static int _nfs4_proc_read(struct nfs_read_data *rdata) | |||
| 1325 | dprintk("NFS call read %d @ %Ld\n", rdata->args.count, | 1473 | dprintk("NFS call read %d @ %Ld\n", rdata->args.count, |
| 1326 | (long long) rdata->args.offset); | 1474 | (long long) rdata->args.offset); |
| 1327 | 1475 | ||
| 1328 | fattr->valid = 0; | 1476 | nfs_fattr_init(fattr); |
| 1329 | status = rpc_call_sync(server->client, &msg, flags); | 1477 | status = rpc_call_sync(server->client, &msg, flags); |
| 1330 | if (!status) | 1478 | if (!status) |
| 1331 | renew_lease(server, timestamp); | 1479 | renew_lease(server, timestamp); |
| @@ -1362,7 +1510,7 @@ static int _nfs4_proc_write(struct nfs_write_data *wdata) | |||
| 1362 | dprintk("NFS call write %d @ %Ld\n", wdata->args.count, | 1510 | dprintk("NFS call write %d @ %Ld\n", wdata->args.count, |
| 1363 | (long long) wdata->args.offset); | 1511 | (long long) wdata->args.offset); |
| 1364 | 1512 | ||
| 1365 | fattr->valid = 0; | 1513 | nfs_fattr_init(fattr); |
| 1366 | status = rpc_call_sync(server->client, &msg, rpcflags); | 1514 | status = rpc_call_sync(server->client, &msg, rpcflags); |
| 1367 | dprintk("NFS reply write: %d\n", status); | 1515 | dprintk("NFS reply write: %d\n", status); |
| 1368 | return status; | 1516 | return status; |
| @@ -1396,7 +1544,7 @@ static int _nfs4_proc_commit(struct nfs_write_data *cdata) | |||
| 1396 | dprintk("NFS call commit %d @ %Ld\n", cdata->args.count, | 1544 | dprintk("NFS call commit %d @ %Ld\n", cdata->args.count, |
| 1397 | (long long) cdata->args.offset); | 1545 | (long long) cdata->args.offset); |
| 1398 | 1546 | ||
| 1399 | fattr->valid = 0; | 1547 | nfs_fattr_init(fattr); |
| 1400 | status = rpc_call_sync(server->client, &msg, 0); | 1548 | status = rpc_call_sync(server->client, &msg, 0); |
| 1401 | dprintk("NFS reply commit: %d\n", status); | 1549 | dprintk("NFS reply commit: %d\n", status); |
| 1402 | return status; | 1550 | return status; |
| @@ -1431,7 +1579,7 @@ static int nfs4_proc_commit(struct nfs_write_data *cdata) | |||
| 1431 | 1579 | ||
| 1432 | static int | 1580 | static int |
| 1433 | nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | 1581 | nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, |
| 1434 | int flags) | 1582 | int flags, struct nameidata *nd) |
| 1435 | { | 1583 | { |
| 1436 | struct nfs4_state *state; | 1584 | struct nfs4_state *state; |
| 1437 | struct rpc_cred *cred; | 1585 | struct rpc_cred *cred; |
| @@ -1453,24 +1601,30 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | |||
| 1453 | struct nfs_fattr fattr; | 1601 | struct nfs_fattr fattr; |
| 1454 | status = nfs4_do_setattr(NFS_SERVER(dir), &fattr, | 1602 | status = nfs4_do_setattr(NFS_SERVER(dir), &fattr, |
| 1455 | NFS_FH(state->inode), sattr, state); | 1603 | NFS_FH(state->inode), sattr, state); |
| 1456 | if (status == 0) { | 1604 | if (status == 0) |
| 1457 | nfs_setattr_update_inode(state->inode, sattr); | 1605 | nfs_setattr_update_inode(state->inode, sattr); |
| 1458 | goto out; | 1606 | } |
| 1459 | } | 1607 | if (status == 0 && nd != NULL && (nd->flags & LOOKUP_OPEN)) |
| 1460 | } else if (flags != 0) | 1608 | nfs4_intent_set_file(nd, dentry, state); |
| 1461 | goto out; | 1609 | else |
| 1462 | nfs4_close_state(state, flags); | 1610 | nfs4_close_state(state, flags); |
| 1463 | out: | 1611 | out: |
| 1464 | return status; | 1612 | return status; |
| 1465 | } | 1613 | } |
| 1466 | 1614 | ||
| 1467 | static int _nfs4_proc_remove(struct inode *dir, struct qstr *name) | 1615 | static int _nfs4_proc_remove(struct inode *dir, struct qstr *name) |
| 1468 | { | 1616 | { |
| 1617 | struct nfs_server *server = NFS_SERVER(dir); | ||
| 1469 | struct nfs4_remove_arg args = { | 1618 | struct nfs4_remove_arg args = { |
| 1470 | .fh = NFS_FH(dir), | 1619 | .fh = NFS_FH(dir), |
| 1471 | .name = name, | 1620 | .name = name, |
| 1621 | .bitmask = server->attr_bitmask, | ||
| 1622 | }; | ||
| 1623 | struct nfs_fattr dir_attr; | ||
| 1624 | struct nfs4_remove_res res = { | ||
| 1625 | .server = server, | ||
| 1626 | .dir_attr = &dir_attr, | ||
| 1472 | }; | 1627 | }; |
| 1473 | struct nfs4_change_info res; | ||
| 1474 | struct rpc_message msg = { | 1628 | struct rpc_message msg = { |
| 1475 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE], | 1629 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE], |
| 1476 | .rpc_argp = &args, | 1630 | .rpc_argp = &args, |
| @@ -1478,9 +1632,12 @@ static int _nfs4_proc_remove(struct inode *dir, struct qstr *name) | |||
| 1478 | }; | 1632 | }; |
| 1479 | int status; | 1633 | int status; |
| 1480 | 1634 | ||
| 1481 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 1635 | nfs_fattr_init(res.dir_attr); |
| 1482 | if (status == 0) | 1636 | status = rpc_call_sync(server->client, &msg, 0); |
| 1483 | update_changeattr(dir, &res); | 1637 | if (status == 0) { |
| 1638 | update_changeattr(dir, &res.cinfo); | ||
| 1639 | nfs_post_op_update_inode(dir, res.dir_attr); | ||
| 1640 | } | ||
| 1484 | return status; | 1641 | return status; |
| 1485 | } | 1642 | } |
| 1486 | 1643 | ||
| @@ -1498,12 +1655,14 @@ static int nfs4_proc_remove(struct inode *dir, struct qstr *name) | |||
| 1498 | 1655 | ||
| 1499 | struct unlink_desc { | 1656 | struct unlink_desc { |
| 1500 | struct nfs4_remove_arg args; | 1657 | struct nfs4_remove_arg args; |
| 1501 | struct nfs4_change_info res; | 1658 | struct nfs4_remove_res res; |
| 1659 | struct nfs_fattr dir_attr; | ||
| 1502 | }; | 1660 | }; |
| 1503 | 1661 | ||
| 1504 | static int nfs4_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir, | 1662 | static int nfs4_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir, |
| 1505 | struct qstr *name) | 1663 | struct qstr *name) |
| 1506 | { | 1664 | { |
| 1665 | struct nfs_server *server = NFS_SERVER(dir->d_inode); | ||
| 1507 | struct unlink_desc *up; | 1666 | struct unlink_desc *up; |
| 1508 | 1667 | ||
| 1509 | up = (struct unlink_desc *) kmalloc(sizeof(*up), GFP_KERNEL); | 1668 | up = (struct unlink_desc *) kmalloc(sizeof(*up), GFP_KERNEL); |
| @@ -1512,6 +1671,9 @@ static int nfs4_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir, | |||
| 1512 | 1671 | ||
| 1513 | up->args.fh = NFS_FH(dir->d_inode); | 1672 | up->args.fh = NFS_FH(dir->d_inode); |
| 1514 | up->args.name = name; | 1673 | up->args.name = name; |
| 1674 | up->args.bitmask = server->attr_bitmask; | ||
| 1675 | up->res.server = server; | ||
| 1676 | up->res.dir_attr = &up->dir_attr; | ||
| 1515 | 1677 | ||
| 1516 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE]; | 1678 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE]; |
| 1517 | msg->rpc_argp = &up->args; | 1679 | msg->rpc_argp = &up->args; |
| @@ -1526,7 +1688,8 @@ static int nfs4_proc_unlink_done(struct dentry *dir, struct rpc_task *task) | |||
| 1526 | 1688 | ||
| 1527 | if (msg->rpc_resp != NULL) { | 1689 | if (msg->rpc_resp != NULL) { |
| 1528 | up = container_of(msg->rpc_resp, struct unlink_desc, res); | 1690 | up = container_of(msg->rpc_resp, struct unlink_desc, res); |
| 1529 | update_changeattr(dir->d_inode, &up->res); | 1691 | update_changeattr(dir->d_inode, &up->res.cinfo); |
| 1692 | nfs_post_op_update_inode(dir->d_inode, up->res.dir_attr); | ||
| 1530 | kfree(up); | 1693 | kfree(up); |
| 1531 | msg->rpc_resp = NULL; | 1694 | msg->rpc_resp = NULL; |
| 1532 | msg->rpc_argp = NULL; | 1695 | msg->rpc_argp = NULL; |
| @@ -1537,13 +1700,20 @@ static int nfs4_proc_unlink_done(struct dentry *dir, struct rpc_task *task) | |||
| 1537 | static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name, | 1700 | static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name, |
| 1538 | struct inode *new_dir, struct qstr *new_name) | 1701 | struct inode *new_dir, struct qstr *new_name) |
| 1539 | { | 1702 | { |
| 1703 | struct nfs_server *server = NFS_SERVER(old_dir); | ||
| 1540 | struct nfs4_rename_arg arg = { | 1704 | struct nfs4_rename_arg arg = { |
| 1541 | .old_dir = NFS_FH(old_dir), | 1705 | .old_dir = NFS_FH(old_dir), |
| 1542 | .new_dir = NFS_FH(new_dir), | 1706 | .new_dir = NFS_FH(new_dir), |
| 1543 | .old_name = old_name, | 1707 | .old_name = old_name, |
| 1544 | .new_name = new_name, | 1708 | .new_name = new_name, |
| 1709 | .bitmask = server->attr_bitmask, | ||
| 1710 | }; | ||
| 1711 | struct nfs_fattr old_fattr, new_fattr; | ||
| 1712 | struct nfs4_rename_res res = { | ||
| 1713 | .server = server, | ||
| 1714 | .old_fattr = &old_fattr, | ||
| 1715 | .new_fattr = &new_fattr, | ||
| 1545 | }; | 1716 | }; |
| 1546 | struct nfs4_rename_res res = { }; | ||
| 1547 | struct rpc_message msg = { | 1717 | struct rpc_message msg = { |
| 1548 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENAME], | 1718 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENAME], |
| 1549 | .rpc_argp = &arg, | 1719 | .rpc_argp = &arg, |
| @@ -1551,11 +1721,15 @@ static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name, | |||
| 1551 | }; | 1721 | }; |
| 1552 | int status; | 1722 | int status; |
| 1553 | 1723 | ||
| 1554 | status = rpc_call_sync(NFS_CLIENT(old_dir), &msg, 0); | 1724 | nfs_fattr_init(res.old_fattr); |
| 1725 | nfs_fattr_init(res.new_fattr); | ||
| 1726 | status = rpc_call_sync(server->client, &msg, 0); | ||
| 1555 | 1727 | ||
| 1556 | if (!status) { | 1728 | if (!status) { |
| 1557 | update_changeattr(old_dir, &res.old_cinfo); | 1729 | update_changeattr(old_dir, &res.old_cinfo); |
| 1730 | nfs_post_op_update_inode(old_dir, res.old_fattr); | ||
| 1558 | update_changeattr(new_dir, &res.new_cinfo); | 1731 | update_changeattr(new_dir, &res.new_cinfo); |
| 1732 | nfs_post_op_update_inode(new_dir, res.new_fattr); | ||
| 1559 | } | 1733 | } |
| 1560 | return status; | 1734 | return status; |
| 1561 | } | 1735 | } |
| @@ -1576,22 +1750,34 @@ static int nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name, | |||
| 1576 | 1750 | ||
| 1577 | static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *name) | 1751 | static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *name) |
| 1578 | { | 1752 | { |
| 1753 | struct nfs_server *server = NFS_SERVER(inode); | ||
| 1579 | struct nfs4_link_arg arg = { | 1754 | struct nfs4_link_arg arg = { |
| 1580 | .fh = NFS_FH(inode), | 1755 | .fh = NFS_FH(inode), |
| 1581 | .dir_fh = NFS_FH(dir), | 1756 | .dir_fh = NFS_FH(dir), |
| 1582 | .name = name, | 1757 | .name = name, |
| 1758 | .bitmask = server->attr_bitmask, | ||
| 1759 | }; | ||
| 1760 | struct nfs_fattr fattr, dir_attr; | ||
| 1761 | struct nfs4_link_res res = { | ||
| 1762 | .server = server, | ||
| 1763 | .fattr = &fattr, | ||
| 1764 | .dir_attr = &dir_attr, | ||
| 1583 | }; | 1765 | }; |
| 1584 | struct nfs4_change_info cinfo = { }; | ||
| 1585 | struct rpc_message msg = { | 1766 | struct rpc_message msg = { |
| 1586 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LINK], | 1767 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LINK], |
| 1587 | .rpc_argp = &arg, | 1768 | .rpc_argp = &arg, |
| 1588 | .rpc_resp = &cinfo, | 1769 | .rpc_resp = &res, |
| 1589 | }; | 1770 | }; |
| 1590 | int status; | 1771 | int status; |
| 1591 | 1772 | ||
| 1592 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); | 1773 | nfs_fattr_init(res.fattr); |
| 1593 | if (!status) | 1774 | nfs_fattr_init(res.dir_attr); |
| 1594 | update_changeattr(dir, &cinfo); | 1775 | status = rpc_call_sync(server->client, &msg, 0); |
| 1776 | if (!status) { | ||
| 1777 | update_changeattr(dir, &res.cinfo); | ||
| 1778 | nfs_post_op_update_inode(dir, res.dir_attr); | ||
| 1779 | nfs_refresh_inode(inode, res.fattr); | ||
| 1780 | } | ||
| 1595 | 1781 | ||
| 1596 | return status; | 1782 | return status; |
| 1597 | } | 1783 | } |
| @@ -1613,6 +1799,7 @@ static int _nfs4_proc_symlink(struct inode *dir, struct qstr *name, | |||
| 1613 | struct nfs_fattr *fattr) | 1799 | struct nfs_fattr *fattr) |
| 1614 | { | 1800 | { |
| 1615 | struct nfs_server *server = NFS_SERVER(dir); | 1801 | struct nfs_server *server = NFS_SERVER(dir); |
| 1802 | struct nfs_fattr dir_fattr; | ||
| 1616 | struct nfs4_create_arg arg = { | 1803 | struct nfs4_create_arg arg = { |
| 1617 | .dir_fh = NFS_FH(dir), | 1804 | .dir_fh = NFS_FH(dir), |
| 1618 | .server = server, | 1805 | .server = server, |
| @@ -1625,6 +1812,7 @@ static int _nfs4_proc_symlink(struct inode *dir, struct qstr *name, | |||
| 1625 | .server = server, | 1812 | .server = server, |
| 1626 | .fh = fhandle, | 1813 | .fh = fhandle, |
| 1627 | .fattr = fattr, | 1814 | .fattr = fattr, |
| 1815 | .dir_fattr = &dir_fattr, | ||
| 1628 | }; | 1816 | }; |
| 1629 | struct rpc_message msg = { | 1817 | struct rpc_message msg = { |
| 1630 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SYMLINK], | 1818 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SYMLINK], |
| @@ -1636,11 +1824,13 @@ static int _nfs4_proc_symlink(struct inode *dir, struct qstr *name, | |||
| 1636 | if (path->len > NFS4_MAXPATHLEN) | 1824 | if (path->len > NFS4_MAXPATHLEN) |
| 1637 | return -ENAMETOOLONG; | 1825 | return -ENAMETOOLONG; |
| 1638 | arg.u.symlink = path; | 1826 | arg.u.symlink = path; |
| 1639 | fattr->valid = 0; | 1827 | nfs_fattr_init(fattr); |
| 1828 | nfs_fattr_init(&dir_fattr); | ||
| 1640 | 1829 | ||
| 1641 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 1830 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
| 1642 | if (!status) | 1831 | if (!status) |
| 1643 | update_changeattr(dir, &res.dir_cinfo); | 1832 | update_changeattr(dir, &res.dir_cinfo); |
| 1833 | nfs_post_op_update_inode(dir, res.dir_fattr); | ||
| 1644 | return status; | 1834 | return status; |
| 1645 | } | 1835 | } |
| 1646 | 1836 | ||
| @@ -1664,7 +1854,7 @@ static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry, | |||
| 1664 | { | 1854 | { |
| 1665 | struct nfs_server *server = NFS_SERVER(dir); | 1855 | struct nfs_server *server = NFS_SERVER(dir); |
| 1666 | struct nfs_fh fhandle; | 1856 | struct nfs_fh fhandle; |
| 1667 | struct nfs_fattr fattr; | 1857 | struct nfs_fattr fattr, dir_fattr; |
| 1668 | struct nfs4_create_arg arg = { | 1858 | struct nfs4_create_arg arg = { |
| 1669 | .dir_fh = NFS_FH(dir), | 1859 | .dir_fh = NFS_FH(dir), |
| 1670 | .server = server, | 1860 | .server = server, |
| @@ -1677,6 +1867,7 @@ static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry, | |||
| 1677 | .server = server, | 1867 | .server = server, |
| 1678 | .fh = &fhandle, | 1868 | .fh = &fhandle, |
| 1679 | .fattr = &fattr, | 1869 | .fattr = &fattr, |
| 1870 | .dir_fattr = &dir_fattr, | ||
| 1680 | }; | 1871 | }; |
| 1681 | struct rpc_message msg = { | 1872 | struct rpc_message msg = { |
| 1682 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE], | 1873 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE], |
| @@ -1685,11 +1876,13 @@ static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry, | |||
| 1685 | }; | 1876 | }; |
| 1686 | int status; | 1877 | int status; |
| 1687 | 1878 | ||
| 1688 | fattr.valid = 0; | 1879 | nfs_fattr_init(&fattr); |
| 1880 | nfs_fattr_init(&dir_fattr); | ||
| 1689 | 1881 | ||
| 1690 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 1882 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
| 1691 | if (!status) { | 1883 | if (!status) { |
| 1692 | update_changeattr(dir, &res.dir_cinfo); | 1884 | update_changeattr(dir, &res.dir_cinfo); |
| 1885 | nfs_post_op_update_inode(dir, res.dir_fattr); | ||
| 1693 | status = nfs_instantiate(dentry, &fhandle, &fattr); | 1886 | status = nfs_instantiate(dentry, &fhandle, &fattr); |
| 1694 | } | 1887 | } |
| 1695 | return status; | 1888 | return status; |
| @@ -1762,7 +1955,7 @@ static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, | |||
| 1762 | { | 1955 | { |
| 1763 | struct nfs_server *server = NFS_SERVER(dir); | 1956 | struct nfs_server *server = NFS_SERVER(dir); |
| 1764 | struct nfs_fh fh; | 1957 | struct nfs_fh fh; |
| 1765 | struct nfs_fattr fattr; | 1958 | struct nfs_fattr fattr, dir_fattr; |
| 1766 | struct nfs4_create_arg arg = { | 1959 | struct nfs4_create_arg arg = { |
| 1767 | .dir_fh = NFS_FH(dir), | 1960 | .dir_fh = NFS_FH(dir), |
| 1768 | .server = server, | 1961 | .server = server, |
| @@ -1774,6 +1967,7 @@ static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, | |||
| 1774 | .server = server, | 1967 | .server = server, |
| 1775 | .fh = &fh, | 1968 | .fh = &fh, |
| 1776 | .fattr = &fattr, | 1969 | .fattr = &fattr, |
| 1970 | .dir_fattr = &dir_fattr, | ||
| 1777 | }; | 1971 | }; |
| 1778 | struct rpc_message msg = { | 1972 | struct rpc_message msg = { |
| 1779 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE], | 1973 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE], |
| @@ -1783,7 +1977,8 @@ static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, | |||
| 1783 | int status; | 1977 | int status; |
| 1784 | int mode = sattr->ia_mode; | 1978 | int mode = sattr->ia_mode; |
| 1785 | 1979 | ||
| 1786 | fattr.valid = 0; | 1980 | nfs_fattr_init(&fattr); |
| 1981 | nfs_fattr_init(&dir_fattr); | ||
| 1787 | 1982 | ||
| 1788 | BUG_ON(!(sattr->ia_valid & ATTR_MODE)); | 1983 | BUG_ON(!(sattr->ia_valid & ATTR_MODE)); |
| 1789 | BUG_ON(!S_ISFIFO(mode) && !S_ISBLK(mode) && !S_ISCHR(mode) && !S_ISSOCK(mode)); | 1984 | BUG_ON(!S_ISFIFO(mode) && !S_ISBLK(mode) && !S_ISCHR(mode) && !S_ISSOCK(mode)); |
| @@ -1805,6 +2000,7 @@ static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, | |||
| 1805 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 2000 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
| 1806 | if (status == 0) { | 2001 | if (status == 0) { |
| 1807 | update_changeattr(dir, &res.dir_cinfo); | 2002 | update_changeattr(dir, &res.dir_cinfo); |
| 2003 | nfs_post_op_update_inode(dir, res.dir_fattr); | ||
| 1808 | status = nfs_instantiate(dentry, &fh, &fattr); | 2004 | status = nfs_instantiate(dentry, &fh, &fattr); |
| 1809 | } | 2005 | } |
| 1810 | return status; | 2006 | return status; |
| @@ -1836,7 +2032,7 @@ static int _nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, | |||
| 1836 | .rpc_resp = fsstat, | 2032 | .rpc_resp = fsstat, |
| 1837 | }; | 2033 | }; |
| 1838 | 2034 | ||
| 1839 | fsstat->fattr->valid = 0; | 2035 | nfs_fattr_init(fsstat->fattr); |
| 1840 | return rpc_call_sync(server->client, &msg, 0); | 2036 | return rpc_call_sync(server->client, &msg, 0); |
| 1841 | } | 2037 | } |
| 1842 | 2038 | ||
| @@ -1883,7 +2079,7 @@ static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, str | |||
| 1883 | 2079 | ||
| 1884 | static int nfs4_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo) | 2080 | static int nfs4_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo) |
| 1885 | { | 2081 | { |
| 1886 | fsinfo->fattr->valid = 0; | 2082 | nfs_fattr_init(fsinfo->fattr); |
| 1887 | return nfs4_do_fsinfo(server, fhandle, fsinfo); | 2083 | return nfs4_do_fsinfo(server, fhandle, fsinfo); |
| 1888 | } | 2084 | } |
| 1889 | 2085 | ||
| @@ -1906,7 +2102,7 @@ static int _nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle | |||
| 1906 | return 0; | 2102 | return 0; |
| 1907 | } | 2103 | } |
| 1908 | 2104 | ||
| 1909 | pathconf->fattr->valid = 0; | 2105 | nfs_fattr_init(pathconf->fattr); |
| 1910 | return rpc_call_sync(server->client, &msg, 0); | 2106 | return rpc_call_sync(server->client, &msg, 0); |
| 1911 | } | 2107 | } |
| 1912 | 2108 | ||
| @@ -1973,8 +2169,10 @@ nfs4_write_done(struct rpc_task *task) | |||
| 1973 | rpc_restart_call(task); | 2169 | rpc_restart_call(task); |
| 1974 | return; | 2170 | return; |
| 1975 | } | 2171 | } |
| 1976 | if (task->tk_status >= 0) | 2172 | if (task->tk_status >= 0) { |
| 1977 | renew_lease(NFS_SERVER(inode), data->timestamp); | 2173 | renew_lease(NFS_SERVER(inode), data->timestamp); |
| 2174 | nfs_post_op_update_inode(inode, data->res.fattr); | ||
| 2175 | } | ||
| 1978 | /* Call back common NFS writeback processing */ | 2176 | /* Call back common NFS writeback processing */ |
| 1979 | nfs_writeback_done(task); | 2177 | nfs_writeback_done(task); |
| 1980 | } | 2178 | } |
| @@ -1990,6 +2188,7 @@ nfs4_proc_write_setup(struct nfs_write_data *data, int how) | |||
| 1990 | .rpc_cred = data->cred, | 2188 | .rpc_cred = data->cred, |
| 1991 | }; | 2189 | }; |
| 1992 | struct inode *inode = data->inode; | 2190 | struct inode *inode = data->inode; |
| 2191 | struct nfs_server *server = NFS_SERVER(inode); | ||
| 1993 | int stable; | 2192 | int stable; |
| 1994 | int flags; | 2193 | int flags; |
| 1995 | 2194 | ||
| @@ -2001,6 +2200,8 @@ nfs4_proc_write_setup(struct nfs_write_data *data, int how) | |||
| 2001 | } else | 2200 | } else |
| 2002 | stable = NFS_UNSTABLE; | 2201 | stable = NFS_UNSTABLE; |
| 2003 | data->args.stable = stable; | 2202 | data->args.stable = stable; |
| 2203 | data->args.bitmask = server->attr_bitmask; | ||
| 2204 | data->res.server = server; | ||
| 2004 | 2205 | ||
| 2005 | data->timestamp = jiffies; | 2206 | data->timestamp = jiffies; |
| 2006 | 2207 | ||
| @@ -2022,6 +2223,8 @@ nfs4_commit_done(struct rpc_task *task) | |||
| 2022 | rpc_restart_call(task); | 2223 | rpc_restart_call(task); |
| 2023 | return; | 2224 | return; |
| 2024 | } | 2225 | } |
| 2226 | if (task->tk_status >= 0) | ||
| 2227 | nfs_post_op_update_inode(inode, data->res.fattr); | ||
| 2025 | /* Call back common NFS writeback processing */ | 2228 | /* Call back common NFS writeback processing */ |
| 2026 | nfs_commit_done(task); | 2229 | nfs_commit_done(task); |
| 2027 | } | 2230 | } |
| @@ -2037,8 +2240,12 @@ nfs4_proc_commit_setup(struct nfs_write_data *data, int how) | |||
| 2037 | .rpc_cred = data->cred, | 2240 | .rpc_cred = data->cred, |
| 2038 | }; | 2241 | }; |
| 2039 | struct inode *inode = data->inode; | 2242 | struct inode *inode = data->inode; |
| 2243 | struct nfs_server *server = NFS_SERVER(inode); | ||
| 2040 | int flags; | 2244 | int flags; |
| 2041 | 2245 | ||
| 2246 | data->args.bitmask = server->attr_bitmask; | ||
| 2247 | data->res.server = server; | ||
| 2248 | |||
| 2042 | /* Set the initial flags for the task. */ | 2249 | /* Set the initial flags for the task. */ |
| 2043 | flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; | 2250 | flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; |
| 2044 | 2251 | ||
| @@ -2106,65 +2313,6 @@ nfs4_proc_renew(struct nfs4_client *clp) | |||
| 2106 | return 0; | 2313 | return 0; |
| 2107 | } | 2314 | } |
| 2108 | 2315 | ||
| 2109 | /* | ||
| 2110 | * We will need to arrange for the VFS layer to provide an atomic open. | ||
| 2111 | * Until then, this open method is prone to inefficiency and race conditions | ||
| 2112 | * due to the lookup, potential create, and open VFS calls from sys_open() | ||
| 2113 | * placed on the wire. | ||
| 2114 | */ | ||
| 2115 | static int | ||
| 2116 | nfs4_proc_file_open(struct inode *inode, struct file *filp) | ||
| 2117 | { | ||
| 2118 | struct dentry *dentry = filp->f_dentry; | ||
| 2119 | struct nfs_open_context *ctx; | ||
| 2120 | struct nfs4_state *state = NULL; | ||
| 2121 | struct rpc_cred *cred; | ||
| 2122 | int status = -ENOMEM; | ||
| 2123 | |||
| 2124 | dprintk("nfs4_proc_file_open: starting on (%.*s/%.*s)\n", | ||
| 2125 | (int)dentry->d_parent->d_name.len, | ||
| 2126 | dentry->d_parent->d_name.name, | ||
| 2127 | (int)dentry->d_name.len, dentry->d_name.name); | ||
| 2128 | |||
| 2129 | |||
| 2130 | /* Find our open stateid */ | ||
| 2131 | cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0); | ||
| 2132 | if (IS_ERR(cred)) | ||
| 2133 | return PTR_ERR(cred); | ||
| 2134 | ctx = alloc_nfs_open_context(dentry, cred); | ||
| 2135 | put_rpccred(cred); | ||
| 2136 | if (unlikely(ctx == NULL)) | ||
| 2137 | return -ENOMEM; | ||
| 2138 | status = -EIO; /* ERACE actually */ | ||
| 2139 | state = nfs4_find_state(inode, cred, filp->f_mode); | ||
| 2140 | if (unlikely(state == NULL)) | ||
| 2141 | goto no_state; | ||
| 2142 | ctx->state = state; | ||
| 2143 | nfs4_close_state(state, filp->f_mode); | ||
| 2144 | ctx->mode = filp->f_mode; | ||
| 2145 | nfs_file_set_open_context(filp, ctx); | ||
| 2146 | put_nfs_open_context(ctx); | ||
| 2147 | if (filp->f_mode & FMODE_WRITE) | ||
| 2148 | nfs_begin_data_update(inode); | ||
| 2149 | return 0; | ||
| 2150 | no_state: | ||
| 2151 | printk(KERN_WARNING "NFS: v4 raced in function %s\n", __FUNCTION__); | ||
| 2152 | put_nfs_open_context(ctx); | ||
| 2153 | return status; | ||
| 2154 | } | ||
| 2155 | |||
| 2156 | /* | ||
| 2157 | * Release our state | ||
| 2158 | */ | ||
| 2159 | static int | ||
| 2160 | nfs4_proc_file_release(struct inode *inode, struct file *filp) | ||
| 2161 | { | ||
| 2162 | if (filp->f_mode & FMODE_WRITE) | ||
| 2163 | nfs_end_data_update(inode); | ||
| 2164 | nfs_file_clear_open_context(filp); | ||
| 2165 | return 0; | ||
| 2166 | } | ||
| 2167 | |||
| 2168 | static inline int nfs4_server_supports_acls(struct nfs_server *server) | 2316 | static inline int nfs4_server_supports_acls(struct nfs_server *server) |
| 2169 | { | 2317 | { |
| 2170 | return (server->caps & NFS_CAP_ACLS) | 2318 | return (server->caps & NFS_CAP_ACLS) |
| @@ -2285,7 +2433,7 @@ static inline ssize_t nfs4_get_acl_uncached(struct inode *inode, void *buf, size | |||
| 2285 | return -ENOMEM; | 2433 | return -ENOMEM; |
| 2286 | args.acl_pages[0] = localpage; | 2434 | args.acl_pages[0] = localpage; |
| 2287 | args.acl_pgbase = 0; | 2435 | args.acl_pgbase = 0; |
| 2288 | args.acl_len = PAGE_SIZE; | 2436 | resp_len = args.acl_len = PAGE_SIZE; |
| 2289 | } else { | 2437 | } else { |
| 2290 | resp_buf = buf; | 2438 | resp_buf = buf; |
| 2291 | buf_to_pages(buf, buflen, args.acl_pages, &args.acl_pgbase); | 2439 | buf_to_pages(buf, buflen, args.acl_pages, &args.acl_pgbase); |
| @@ -2345,6 +2493,7 @@ static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen | |||
| 2345 | 2493 | ||
| 2346 | if (!nfs4_server_supports_acls(server)) | 2494 | if (!nfs4_server_supports_acls(server)) |
| 2347 | return -EOPNOTSUPP; | 2495 | return -EOPNOTSUPP; |
| 2496 | nfs_inode_return_delegation(inode); | ||
| 2348 | buf_to_pages(buf, buflen, arg.acl_pages, &arg.acl_pgbase); | 2497 | buf_to_pages(buf, buflen, arg.acl_pages, &arg.acl_pgbase); |
| 2349 | ret = rpc_call_sync(NFS_SERVER(inode)->client, &msg, 0); | 2498 | ret = rpc_call_sync(NFS_SERVER(inode)->client, &msg, 0); |
| 2350 | if (ret == 0) | 2499 | if (ret == 0) |
| @@ -2353,7 +2502,7 @@ static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen | |||
| 2353 | } | 2502 | } |
| 2354 | 2503 | ||
| 2355 | static int | 2504 | static int |
| 2356 | nfs4_async_handle_error(struct rpc_task *task, struct nfs_server *server) | 2505 | nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server) |
| 2357 | { | 2506 | { |
| 2358 | struct nfs4_client *clp = server->nfs4_state; | 2507 | struct nfs4_client *clp = server->nfs4_state; |
| 2359 | 2508 | ||
| @@ -2431,7 +2580,7 @@ static int nfs4_delay(struct rpc_clnt *clnt, long *timeout) | |||
| 2431 | /* This is the error handling routine for processes that are allowed | 2580 | /* This is the error handling routine for processes that are allowed |
| 2432 | * to sleep. | 2581 | * to sleep. |
| 2433 | */ | 2582 | */ |
| 2434 | int nfs4_handle_exception(struct nfs_server *server, int errorcode, struct nfs4_exception *exception) | 2583 | int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception) |
| 2435 | { | 2584 | { |
| 2436 | struct nfs4_client *clp = server->nfs4_state; | 2585 | struct nfs4_client *clp = server->nfs4_state; |
| 2437 | int ret = errorcode; | 2586 | int ret = errorcode; |
| @@ -2632,7 +2781,6 @@ static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock | |||
| 2632 | 2781 | ||
| 2633 | down_read(&clp->cl_sem); | 2782 | down_read(&clp->cl_sem); |
| 2634 | nlo.clientid = clp->cl_clientid; | 2783 | nlo.clientid = clp->cl_clientid; |
| 2635 | down(&state->lock_sema); | ||
| 2636 | status = nfs4_set_lock_state(state, request); | 2784 | status = nfs4_set_lock_state(state, request); |
| 2637 | if (status != 0) | 2785 | if (status != 0) |
| 2638 | goto out; | 2786 | goto out; |
| @@ -2659,7 +2807,6 @@ static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock | |||
| 2659 | status = 0; | 2807 | status = 0; |
| 2660 | } | 2808 | } |
| 2661 | out: | 2809 | out: |
| 2662 | up(&state->lock_sema); | ||
| 2663 | up_read(&clp->cl_sem); | 2810 | up_read(&clp->cl_sem); |
| 2664 | return status; | 2811 | return status; |
| 2665 | } | 2812 | } |
| @@ -2696,79 +2843,149 @@ static int do_vfs_lock(struct file *file, struct file_lock *fl) | |||
| 2696 | return res; | 2843 | return res; |
| 2697 | } | 2844 | } |
| 2698 | 2845 | ||
| 2699 | static int _nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request) | 2846 | struct nfs4_unlockdata { |
| 2847 | struct nfs_lockargs arg; | ||
| 2848 | struct nfs_locku_opargs luargs; | ||
| 2849 | struct nfs_lockres res; | ||
| 2850 | struct nfs4_lock_state *lsp; | ||
| 2851 | struct nfs_open_context *ctx; | ||
| 2852 | atomic_t refcount; | ||
| 2853 | struct completion completion; | ||
| 2854 | }; | ||
| 2855 | |||
| 2856 | static void nfs4_locku_release_calldata(struct nfs4_unlockdata *calldata) | ||
| 2700 | { | 2857 | { |
| 2701 | struct inode *inode = state->inode; | 2858 | if (atomic_dec_and_test(&calldata->refcount)) { |
| 2702 | struct nfs_server *server = NFS_SERVER(inode); | 2859 | nfs_free_seqid(calldata->luargs.seqid); |
| 2703 | struct nfs4_client *clp = server->nfs4_state; | 2860 | nfs4_put_lock_state(calldata->lsp); |
| 2704 | struct nfs_lockargs arg = { | 2861 | put_nfs_open_context(calldata->ctx); |
| 2705 | .fh = NFS_FH(inode), | 2862 | kfree(calldata); |
| 2706 | .type = nfs4_lck_type(cmd, request), | 2863 | } |
| 2707 | .offset = request->fl_start, | 2864 | } |
| 2708 | .length = nfs4_lck_length(request), | 2865 | |
| 2709 | }; | 2866 | static void nfs4_locku_complete(struct nfs4_unlockdata *calldata) |
| 2710 | struct nfs_lockres res = { | 2867 | { |
| 2711 | .server = server, | 2868 | complete(&calldata->completion); |
| 2712 | }; | 2869 | nfs4_locku_release_calldata(calldata); |
| 2870 | } | ||
| 2871 | |||
| 2872 | static void nfs4_locku_done(struct rpc_task *task) | ||
| 2873 | { | ||
| 2874 | struct nfs4_unlockdata *calldata = (struct nfs4_unlockdata *)task->tk_calldata; | ||
| 2875 | |||
| 2876 | nfs_increment_lock_seqid(task->tk_status, calldata->luargs.seqid); | ||
| 2877 | switch (task->tk_status) { | ||
| 2878 | case 0: | ||
| 2879 | memcpy(calldata->lsp->ls_stateid.data, | ||
| 2880 | calldata->res.u.stateid.data, | ||
| 2881 | sizeof(calldata->lsp->ls_stateid.data)); | ||
| 2882 | break; | ||
| 2883 | case -NFS4ERR_STALE_STATEID: | ||
| 2884 | case -NFS4ERR_EXPIRED: | ||
| 2885 | nfs4_schedule_state_recovery(calldata->res.server->nfs4_state); | ||
| 2886 | break; | ||
| 2887 | default: | ||
| 2888 | if (nfs4_async_handle_error(task, calldata->res.server) == -EAGAIN) { | ||
| 2889 | rpc_restart_call(task); | ||
| 2890 | return; | ||
| 2891 | } | ||
| 2892 | } | ||
| 2893 | nfs4_locku_complete(calldata); | ||
| 2894 | } | ||
| 2895 | |||
| 2896 | static void nfs4_locku_begin(struct rpc_task *task) | ||
| 2897 | { | ||
| 2898 | struct nfs4_unlockdata *calldata = (struct nfs4_unlockdata *)task->tk_calldata; | ||
| 2713 | struct rpc_message msg = { | 2899 | struct rpc_message msg = { |
| 2714 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCKU], | 2900 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCKU], |
| 2715 | .rpc_argp = &arg, | 2901 | .rpc_argp = &calldata->arg, |
| 2716 | .rpc_resp = &res, | 2902 | .rpc_resp = &calldata->res, |
| 2717 | .rpc_cred = state->owner->so_cred, | 2903 | .rpc_cred = calldata->lsp->ls_state->owner->so_cred, |
| 2718 | }; | 2904 | }; |
| 2905 | int status; | ||
| 2906 | |||
| 2907 | status = nfs_wait_on_sequence(calldata->luargs.seqid, task); | ||
| 2908 | if (status != 0) | ||
| 2909 | return; | ||
| 2910 | if ((calldata->lsp->ls_flags & NFS_LOCK_INITIALIZED) == 0) { | ||
| 2911 | nfs4_locku_complete(calldata); | ||
| 2912 | task->tk_exit = NULL; | ||
| 2913 | rpc_exit(task, 0); | ||
| 2914 | return; | ||
| 2915 | } | ||
| 2916 | rpc_call_setup(task, &msg, 0); | ||
| 2917 | } | ||
| 2918 | |||
| 2919 | static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request) | ||
| 2920 | { | ||
| 2921 | struct nfs4_unlockdata *calldata; | ||
| 2922 | struct inode *inode = state->inode; | ||
| 2923 | struct nfs_server *server = NFS_SERVER(inode); | ||
| 2719 | struct nfs4_lock_state *lsp; | 2924 | struct nfs4_lock_state *lsp; |
| 2720 | struct nfs_locku_opargs luargs; | ||
| 2721 | int status; | 2925 | int status; |
| 2722 | 2926 | ||
| 2723 | down_read(&clp->cl_sem); | ||
| 2724 | down(&state->lock_sema); | ||
| 2725 | status = nfs4_set_lock_state(state, request); | 2927 | status = nfs4_set_lock_state(state, request); |
| 2726 | if (status != 0) | 2928 | if (status != 0) |
| 2727 | goto out; | 2929 | return status; |
| 2728 | lsp = request->fl_u.nfs4_fl.owner; | 2930 | lsp = request->fl_u.nfs4_fl.owner; |
| 2729 | /* We might have lost the locks! */ | 2931 | /* We might have lost the locks! */ |
| 2730 | if ((lsp->ls_flags & NFS_LOCK_INITIALIZED) == 0) | 2932 | if ((lsp->ls_flags & NFS_LOCK_INITIALIZED) == 0) |
| 2731 | goto out; | 2933 | return 0; |
| 2732 | luargs.seqid = lsp->ls_seqid; | 2934 | calldata = kmalloc(sizeof(*calldata), GFP_KERNEL); |
| 2733 | memcpy(&luargs.stateid, &lsp->ls_stateid, sizeof(luargs.stateid)); | 2935 | if (calldata == NULL) |
| 2734 | arg.u.locku = &luargs; | 2936 | return -ENOMEM; |
| 2735 | status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); | 2937 | calldata->luargs.seqid = nfs_alloc_seqid(&lsp->ls_seqid); |
| 2736 | nfs4_increment_lock_seqid(status, lsp); | 2938 | if (calldata->luargs.seqid == NULL) { |
| 2737 | 2939 | kfree(calldata); | |
| 2738 | if (status == 0) | 2940 | return -ENOMEM; |
| 2739 | memcpy(&lsp->ls_stateid, &res.u.stateid, | 2941 | } |
| 2740 | sizeof(lsp->ls_stateid)); | 2942 | calldata->luargs.stateid = &lsp->ls_stateid; |
| 2741 | out: | 2943 | calldata->arg.fh = NFS_FH(inode); |
| 2742 | up(&state->lock_sema); | 2944 | calldata->arg.type = nfs4_lck_type(cmd, request); |
| 2945 | calldata->arg.offset = request->fl_start; | ||
| 2946 | calldata->arg.length = nfs4_lck_length(request); | ||
| 2947 | calldata->arg.u.locku = &calldata->luargs; | ||
| 2948 | calldata->res.server = server; | ||
| 2949 | calldata->lsp = lsp; | ||
| 2950 | atomic_inc(&lsp->ls_count); | ||
| 2951 | |||
| 2952 | /* Ensure we don't close file until we're done freeing locks! */ | ||
| 2953 | calldata->ctx = get_nfs_open_context((struct nfs_open_context*)request->fl_file->private_data); | ||
| 2954 | |||
| 2955 | atomic_set(&calldata->refcount, 2); | ||
| 2956 | init_completion(&calldata->completion); | ||
| 2957 | |||
| 2958 | status = nfs4_call_async(NFS_SERVER(inode)->client, nfs4_locku_begin, | ||
| 2959 | nfs4_locku_done, calldata); | ||
| 2743 | if (status == 0) | 2960 | if (status == 0) |
| 2744 | do_vfs_lock(request->fl_file, request); | 2961 | wait_for_completion_interruptible(&calldata->completion); |
| 2745 | up_read(&clp->cl_sem); | 2962 | do_vfs_lock(request->fl_file, request); |
| 2963 | nfs4_locku_release_calldata(calldata); | ||
| 2746 | return status; | 2964 | return status; |
| 2747 | } | 2965 | } |
| 2748 | 2966 | ||
| 2749 | static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request) | ||
| 2750 | { | ||
| 2751 | struct nfs4_exception exception = { }; | ||
| 2752 | int err; | ||
| 2753 | |||
| 2754 | do { | ||
| 2755 | err = nfs4_handle_exception(NFS_SERVER(state->inode), | ||
| 2756 | _nfs4_proc_unlck(state, cmd, request), | ||
| 2757 | &exception); | ||
| 2758 | } while (exception.retry); | ||
| 2759 | return err; | ||
| 2760 | } | ||
| 2761 | |||
| 2762 | static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *request, int reclaim) | 2967 | static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *request, int reclaim) |
| 2763 | { | 2968 | { |
| 2764 | struct inode *inode = state->inode; | 2969 | struct inode *inode = state->inode; |
| 2765 | struct nfs_server *server = NFS_SERVER(inode); | 2970 | struct nfs_server *server = NFS_SERVER(inode); |
| 2766 | struct nfs4_lock_state *lsp = request->fl_u.nfs4_fl.owner; | 2971 | struct nfs4_lock_state *lsp = request->fl_u.nfs4_fl.owner; |
| 2972 | struct nfs_lock_opargs largs = { | ||
| 2973 | .lock_stateid = &lsp->ls_stateid, | ||
| 2974 | .open_stateid = &state->stateid, | ||
| 2975 | .lock_owner = { | ||
| 2976 | .clientid = server->nfs4_state->cl_clientid, | ||
| 2977 | .id = lsp->ls_id, | ||
| 2978 | }, | ||
| 2979 | .reclaim = reclaim, | ||
| 2980 | }; | ||
| 2767 | struct nfs_lockargs arg = { | 2981 | struct nfs_lockargs arg = { |
| 2768 | .fh = NFS_FH(inode), | 2982 | .fh = NFS_FH(inode), |
| 2769 | .type = nfs4_lck_type(cmd, request), | 2983 | .type = nfs4_lck_type(cmd, request), |
| 2770 | .offset = request->fl_start, | 2984 | .offset = request->fl_start, |
| 2771 | .length = nfs4_lck_length(request), | 2985 | .length = nfs4_lck_length(request), |
| 2986 | .u = { | ||
| 2987 | .lock = &largs, | ||
| 2988 | }, | ||
| 2772 | }; | 2989 | }; |
| 2773 | struct nfs_lockres res = { | 2990 | struct nfs_lockres res = { |
| 2774 | .server = server, | 2991 | .server = server, |
| @@ -2779,53 +2996,39 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *r | |||
| 2779 | .rpc_resp = &res, | 2996 | .rpc_resp = &res, |
| 2780 | .rpc_cred = state->owner->so_cred, | 2997 | .rpc_cred = state->owner->so_cred, |
| 2781 | }; | 2998 | }; |
| 2782 | struct nfs_lock_opargs largs = { | 2999 | int status = -ENOMEM; |
| 2783 | .reclaim = reclaim, | ||
| 2784 | .new_lock_owner = 0, | ||
| 2785 | }; | ||
| 2786 | int status; | ||
| 2787 | 3000 | ||
| 2788 | if (!(lsp->ls_flags & NFS_LOCK_INITIALIZED)) { | 3001 | largs.lock_seqid = nfs_alloc_seqid(&lsp->ls_seqid); |
| 3002 | if (largs.lock_seqid == NULL) | ||
| 3003 | return -ENOMEM; | ||
| 3004 | if (!(lsp->ls_seqid.flags & NFS_SEQID_CONFIRMED)) { | ||
| 2789 | struct nfs4_state_owner *owner = state->owner; | 3005 | struct nfs4_state_owner *owner = state->owner; |
| 2790 | struct nfs_open_to_lock otl = { | 3006 | |
| 2791 | .lock_owner = { | 3007 | largs.open_seqid = nfs_alloc_seqid(&owner->so_seqid); |
| 2792 | .clientid = server->nfs4_state->cl_clientid, | 3008 | if (largs.open_seqid == NULL) |
| 2793 | }, | 3009 | goto out; |
| 2794 | }; | ||
| 2795 | |||
| 2796 | otl.lock_seqid = lsp->ls_seqid; | ||
| 2797 | otl.lock_owner.id = lsp->ls_id; | ||
| 2798 | memcpy(&otl.open_stateid, &state->stateid, sizeof(otl.open_stateid)); | ||
| 2799 | largs.u.open_lock = &otl; | ||
| 2800 | largs.new_lock_owner = 1; | 3010 | largs.new_lock_owner = 1; |
| 2801 | arg.u.lock = &largs; | ||
| 2802 | down(&owner->so_sema); | ||
| 2803 | otl.open_seqid = owner->so_seqid; | ||
| 2804 | status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); | 3011 | status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); |
| 2805 | /* increment open_owner seqid on success, and | 3012 | /* increment open seqid on success, and seqid mutating errors */ |
| 2806 | * seqid mutating errors */ | 3013 | if (largs.new_lock_owner != 0) { |
| 2807 | nfs4_increment_seqid(status, owner); | 3014 | nfs_increment_open_seqid(status, largs.open_seqid); |
| 2808 | up(&owner->so_sema); | 3015 | if (status == 0) |
| 2809 | if (status == 0) { | 3016 | nfs_confirm_seqid(&lsp->ls_seqid, 0); |
| 2810 | lsp->ls_flags |= NFS_LOCK_INITIALIZED; | ||
| 2811 | lsp->ls_seqid++; | ||
| 2812 | } | 3017 | } |
| 2813 | } else { | 3018 | nfs_free_seqid(largs.open_seqid); |
| 2814 | struct nfs_exist_lock el = { | 3019 | } else |
| 2815 | .seqid = lsp->ls_seqid, | ||
| 2816 | }; | ||
| 2817 | memcpy(&el.stateid, &lsp->ls_stateid, sizeof(el.stateid)); | ||
| 2818 | largs.u.exist_lock = ⪙ | ||
| 2819 | arg.u.lock = &largs; | ||
| 2820 | status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); | 3020 | status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR); |
| 2821 | /* increment seqid on success, and * seqid mutating errors*/ | 3021 | /* increment lock seqid on success, and seqid mutating errors*/ |
| 2822 | nfs4_increment_lock_seqid(status, lsp); | 3022 | nfs_increment_lock_seqid(status, largs.lock_seqid); |
| 2823 | } | ||
| 2824 | /* save the returned stateid. */ | 3023 | /* save the returned stateid. */ |
| 2825 | if (status == 0) | 3024 | if (status == 0) { |
| 2826 | memcpy(&lsp->ls_stateid, &res.u.stateid, sizeof(nfs4_stateid)); | 3025 | memcpy(lsp->ls_stateid.data, res.u.stateid.data, |
| 2827 | else if (status == -NFS4ERR_DENIED) | 3026 | sizeof(lsp->ls_stateid.data)); |
| 3027 | lsp->ls_flags |= NFS_LOCK_INITIALIZED; | ||
| 3028 | } else if (status == -NFS4ERR_DENIED) | ||
| 2828 | status = -EAGAIN; | 3029 | status = -EAGAIN; |
| 3030 | out: | ||
| 3031 | nfs_free_seqid(largs.lock_seqid); | ||
| 2829 | return status; | 3032 | return status; |
| 2830 | } | 3033 | } |
| 2831 | 3034 | ||
| @@ -2865,11 +3068,9 @@ static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock | |||
| 2865 | int status; | 3068 | int status; |
| 2866 | 3069 | ||
| 2867 | down_read(&clp->cl_sem); | 3070 | down_read(&clp->cl_sem); |
| 2868 | down(&state->lock_sema); | ||
| 2869 | status = nfs4_set_lock_state(state, request); | 3071 | status = nfs4_set_lock_state(state, request); |
| 2870 | if (status == 0) | 3072 | if (status == 0) |
| 2871 | status = _nfs4_do_setlk(state, cmd, request, 0); | 3073 | status = _nfs4_do_setlk(state, cmd, request, 0); |
| 2872 | up(&state->lock_sema); | ||
| 2873 | if (status == 0) { | 3074 | if (status == 0) { |
| 2874 | /* Note: we always want to sleep here! */ | 3075 | /* Note: we always want to sleep here! */ |
| 2875 | request->fl_flags |= FL_SLEEP; | 3076 | request->fl_flags |= FL_SLEEP; |
| @@ -3024,8 +3225,8 @@ struct nfs_rpc_ops nfs_v4_clientops = { | |||
| 3024 | .read_setup = nfs4_proc_read_setup, | 3225 | .read_setup = nfs4_proc_read_setup, |
| 3025 | .write_setup = nfs4_proc_write_setup, | 3226 | .write_setup = nfs4_proc_write_setup, |
| 3026 | .commit_setup = nfs4_proc_commit_setup, | 3227 | .commit_setup = nfs4_proc_commit_setup, |
| 3027 | .file_open = nfs4_proc_file_open, | 3228 | .file_open = nfs_open, |
| 3028 | .file_release = nfs4_proc_file_release, | 3229 | .file_release = nfs_release, |
| 3029 | .lock = nfs4_proc_lock, | 3230 | .lock = nfs4_proc_lock, |
| 3030 | .clear_acl_cache = nfs4_zap_acl_attr, | 3231 | .clear_acl_cache = nfs4_zap_acl_attr, |
| 3031 | }; | 3232 | }; |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index afe587d82f1e..2d5a6a2b9dec 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
| @@ -264,13 +264,16 @@ nfs4_alloc_state_owner(void) | |||
| 264 | { | 264 | { |
| 265 | struct nfs4_state_owner *sp; | 265 | struct nfs4_state_owner *sp; |
| 266 | 266 | ||
| 267 | sp = kmalloc(sizeof(*sp),GFP_KERNEL); | 267 | sp = kzalloc(sizeof(*sp),GFP_KERNEL); |
| 268 | if (!sp) | 268 | if (!sp) |
| 269 | return NULL; | 269 | return NULL; |
| 270 | init_MUTEX(&sp->so_sema); | 270 | spin_lock_init(&sp->so_lock); |
| 271 | sp->so_seqid = 0; /* arbitrary */ | ||
| 272 | INIT_LIST_HEAD(&sp->so_states); | 271 | INIT_LIST_HEAD(&sp->so_states); |
| 273 | INIT_LIST_HEAD(&sp->so_delegations); | 272 | INIT_LIST_HEAD(&sp->so_delegations); |
| 273 | rpc_init_wait_queue(&sp->so_sequence.wait, "Seqid_waitqueue"); | ||
| 274 | sp->so_seqid.sequence = &sp->so_sequence; | ||
| 275 | spin_lock_init(&sp->so_sequence.lock); | ||
| 276 | INIT_LIST_HEAD(&sp->so_sequence.list); | ||
| 274 | atomic_set(&sp->so_count, 1); | 277 | atomic_set(&sp->so_count, 1); |
| 275 | return sp; | 278 | return sp; |
| 276 | } | 279 | } |
| @@ -359,7 +362,6 @@ nfs4_alloc_open_state(void) | |||
| 359 | memset(state->stateid.data, 0, sizeof(state->stateid.data)); | 362 | memset(state->stateid.data, 0, sizeof(state->stateid.data)); |
| 360 | atomic_set(&state->count, 1); | 363 | atomic_set(&state->count, 1); |
| 361 | INIT_LIST_HEAD(&state->lock_states); | 364 | INIT_LIST_HEAD(&state->lock_states); |
| 362 | init_MUTEX(&state->lock_sema); | ||
| 363 | spin_lock_init(&state->state_lock); | 365 | spin_lock_init(&state->state_lock); |
| 364 | return state; | 366 | return state; |
| 365 | } | 367 | } |
| @@ -437,21 +439,23 @@ nfs4_get_open_state(struct inode *inode, struct nfs4_state_owner *owner) | |||
| 437 | if (state) | 439 | if (state) |
| 438 | goto out; | 440 | goto out; |
| 439 | new = nfs4_alloc_open_state(); | 441 | new = nfs4_alloc_open_state(); |
| 442 | spin_lock(&owner->so_lock); | ||
| 440 | spin_lock(&inode->i_lock); | 443 | spin_lock(&inode->i_lock); |
| 441 | state = __nfs4_find_state_byowner(inode, owner); | 444 | state = __nfs4_find_state_byowner(inode, owner); |
| 442 | if (state == NULL && new != NULL) { | 445 | if (state == NULL && new != NULL) { |
| 443 | state = new; | 446 | state = new; |
| 444 | /* Caller *must* be holding owner->so_sem */ | ||
| 445 | /* Note: The reclaim code dictates that we add stateless | ||
| 446 | * and read-only stateids to the end of the list */ | ||
| 447 | list_add_tail(&state->open_states, &owner->so_states); | ||
| 448 | state->owner = owner; | 447 | state->owner = owner; |
| 449 | atomic_inc(&owner->so_count); | 448 | atomic_inc(&owner->so_count); |
| 450 | list_add(&state->inode_states, &nfsi->open_states); | 449 | list_add(&state->inode_states, &nfsi->open_states); |
| 451 | state->inode = igrab(inode); | 450 | state->inode = igrab(inode); |
| 452 | spin_unlock(&inode->i_lock); | 451 | spin_unlock(&inode->i_lock); |
| 452 | /* Note: The reclaim code dictates that we add stateless | ||
| 453 | * and read-only stateids to the end of the list */ | ||
| 454 | list_add_tail(&state->open_states, &owner->so_states); | ||
| 455 | spin_unlock(&owner->so_lock); | ||
| 453 | } else { | 456 | } else { |
| 454 | spin_unlock(&inode->i_lock); | 457 | spin_unlock(&inode->i_lock); |
| 458 | spin_unlock(&owner->so_lock); | ||
| 455 | if (new) | 459 | if (new) |
| 456 | nfs4_free_open_state(new); | 460 | nfs4_free_open_state(new); |
| 457 | } | 461 | } |
| @@ -461,19 +465,21 @@ out: | |||
| 461 | 465 | ||
| 462 | /* | 466 | /* |
| 463 | * Beware! Caller must be holding exactly one | 467 | * Beware! Caller must be holding exactly one |
| 464 | * reference to clp->cl_sem and owner->so_sema! | 468 | * reference to clp->cl_sem! |
| 465 | */ | 469 | */ |
| 466 | void nfs4_put_open_state(struct nfs4_state *state) | 470 | void nfs4_put_open_state(struct nfs4_state *state) |
| 467 | { | 471 | { |
| 468 | struct inode *inode = state->inode; | 472 | struct inode *inode = state->inode; |
| 469 | struct nfs4_state_owner *owner = state->owner; | 473 | struct nfs4_state_owner *owner = state->owner; |
| 470 | 474 | ||
| 471 | if (!atomic_dec_and_lock(&state->count, &inode->i_lock)) | 475 | if (!atomic_dec_and_lock(&state->count, &owner->so_lock)) |
| 472 | return; | 476 | return; |
| 477 | spin_lock(&inode->i_lock); | ||
| 473 | if (!list_empty(&state->inode_states)) | 478 | if (!list_empty(&state->inode_states)) |
| 474 | list_del(&state->inode_states); | 479 | list_del(&state->inode_states); |
| 475 | spin_unlock(&inode->i_lock); | ||
| 476 | list_del(&state->open_states); | 480 | list_del(&state->open_states); |
| 481 | spin_unlock(&inode->i_lock); | ||
| 482 | spin_unlock(&owner->so_lock); | ||
| 477 | iput(inode); | 483 | iput(inode); |
| 478 | BUG_ON (state->state != 0); | 484 | BUG_ON (state->state != 0); |
| 479 | nfs4_free_open_state(state); | 485 | nfs4_free_open_state(state); |
| @@ -481,20 +487,17 @@ void nfs4_put_open_state(struct nfs4_state *state) | |||
| 481 | } | 487 | } |
| 482 | 488 | ||
| 483 | /* | 489 | /* |
| 484 | * Beware! Caller must be holding no references to clp->cl_sem! | 490 | * Close the current file. |
| 485 | * of owner->so_sema! | ||
| 486 | */ | 491 | */ |
| 487 | void nfs4_close_state(struct nfs4_state *state, mode_t mode) | 492 | void nfs4_close_state(struct nfs4_state *state, mode_t mode) |
| 488 | { | 493 | { |
| 489 | struct inode *inode = state->inode; | 494 | struct inode *inode = state->inode; |
| 490 | struct nfs4_state_owner *owner = state->owner; | 495 | struct nfs4_state_owner *owner = state->owner; |
| 491 | struct nfs4_client *clp = owner->so_client; | ||
| 492 | int newstate; | 496 | int newstate; |
| 493 | 497 | ||
| 494 | atomic_inc(&owner->so_count); | 498 | atomic_inc(&owner->so_count); |
| 495 | down_read(&clp->cl_sem); | ||
| 496 | down(&owner->so_sema); | ||
| 497 | /* Protect against nfs4_find_state() */ | 499 | /* Protect against nfs4_find_state() */ |
| 500 | spin_lock(&owner->so_lock); | ||
| 498 | spin_lock(&inode->i_lock); | 501 | spin_lock(&inode->i_lock); |
| 499 | if (mode & FMODE_READ) | 502 | if (mode & FMODE_READ) |
| 500 | state->nreaders--; | 503 | state->nreaders--; |
| @@ -507,6 +510,7 @@ void nfs4_close_state(struct nfs4_state *state, mode_t mode) | |||
| 507 | list_move_tail(&state->open_states, &owner->so_states); | 510 | list_move_tail(&state->open_states, &owner->so_states); |
| 508 | } | 511 | } |
| 509 | spin_unlock(&inode->i_lock); | 512 | spin_unlock(&inode->i_lock); |
| 513 | spin_unlock(&owner->so_lock); | ||
| 510 | newstate = 0; | 514 | newstate = 0; |
| 511 | if (state->state != 0) { | 515 | if (state->state != 0) { |
| 512 | if (state->nreaders) | 516 | if (state->nreaders) |
| @@ -515,14 +519,16 @@ void nfs4_close_state(struct nfs4_state *state, mode_t mode) | |||
| 515 | newstate |= FMODE_WRITE; | 519 | newstate |= FMODE_WRITE; |
| 516 | if (state->state == newstate) | 520 | if (state->state == newstate) |
| 517 | goto out; | 521 | goto out; |
| 518 | if (nfs4_do_close(inode, state, newstate) == -EINPROGRESS) | 522 | if (test_bit(NFS_DELEGATED_STATE, &state->flags)) { |
| 523 | state->state = newstate; | ||
| 524 | goto out; | ||
| 525 | } | ||
| 526 | if (nfs4_do_close(inode, state, newstate) == 0) | ||
| 519 | return; | 527 | return; |
| 520 | } | 528 | } |
| 521 | out: | 529 | out: |
| 522 | nfs4_put_open_state(state); | 530 | nfs4_put_open_state(state); |
| 523 | up(&owner->so_sema); | ||
| 524 | nfs4_put_state_owner(owner); | 531 | nfs4_put_state_owner(owner); |
| 525 | up_read(&clp->cl_sem); | ||
| 526 | } | 532 | } |
| 527 | 533 | ||
| 528 | /* | 534 | /* |
| @@ -546,19 +552,16 @@ __nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t fl_owner) | |||
| 546 | * Return a compatible lock_state. If no initialized lock_state structure | 552 | * Return a compatible lock_state. If no initialized lock_state structure |
| 547 | * exists, return an uninitialized one. | 553 | * exists, return an uninitialized one. |
| 548 | * | 554 | * |
| 549 | * The caller must be holding state->lock_sema | ||
| 550 | */ | 555 | */ |
| 551 | static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, fl_owner_t fl_owner) | 556 | static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, fl_owner_t fl_owner) |
| 552 | { | 557 | { |
| 553 | struct nfs4_lock_state *lsp; | 558 | struct nfs4_lock_state *lsp; |
| 554 | struct nfs4_client *clp = state->owner->so_client; | 559 | struct nfs4_client *clp = state->owner->so_client; |
| 555 | 560 | ||
| 556 | lsp = kmalloc(sizeof(*lsp), GFP_KERNEL); | 561 | lsp = kzalloc(sizeof(*lsp), GFP_KERNEL); |
| 557 | if (lsp == NULL) | 562 | if (lsp == NULL) |
| 558 | return NULL; | 563 | return NULL; |
| 559 | lsp->ls_flags = 0; | 564 | lsp->ls_seqid.sequence = &state->owner->so_sequence; |
| 560 | lsp->ls_seqid = 0; /* arbitrary */ | ||
| 561 | memset(lsp->ls_stateid.data, 0, sizeof(lsp->ls_stateid.data)); | ||
| 562 | atomic_set(&lsp->ls_count, 1); | 565 | atomic_set(&lsp->ls_count, 1); |
| 563 | lsp->ls_owner = fl_owner; | 566 | lsp->ls_owner = fl_owner; |
| 564 | spin_lock(&clp->cl_lock); | 567 | spin_lock(&clp->cl_lock); |
| @@ -572,7 +575,7 @@ static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, f | |||
| 572 | * Return a compatible lock_state. If no initialized lock_state structure | 575 | * Return a compatible lock_state. If no initialized lock_state structure |
| 573 | * exists, return an uninitialized one. | 576 | * exists, return an uninitialized one. |
| 574 | * | 577 | * |
| 575 | * The caller must be holding state->lock_sema and clp->cl_sem | 578 | * The caller must be holding clp->cl_sem |
| 576 | */ | 579 | */ |
| 577 | static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_owner_t owner) | 580 | static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_owner_t owner) |
| 578 | { | 581 | { |
| @@ -605,7 +608,7 @@ static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_ | |||
| 605 | * Release reference to lock_state, and free it if we see that | 608 | * Release reference to lock_state, and free it if we see that |
| 606 | * it is no longer in use | 609 | * it is no longer in use |
| 607 | */ | 610 | */ |
| 608 | static void nfs4_put_lock_state(struct nfs4_lock_state *lsp) | 611 | void nfs4_put_lock_state(struct nfs4_lock_state *lsp) |
| 609 | { | 612 | { |
| 610 | struct nfs4_state *state; | 613 | struct nfs4_state *state; |
| 611 | 614 | ||
| @@ -673,29 +676,94 @@ void nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t f | |||
| 673 | nfs4_put_lock_state(lsp); | 676 | nfs4_put_lock_state(lsp); |
| 674 | } | 677 | } |
| 675 | 678 | ||
| 676 | /* | 679 | struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter) |
| 677 | * Called with state->lock_sema and clp->cl_sem held. | ||
| 678 | */ | ||
| 679 | void nfs4_increment_lock_seqid(int status, struct nfs4_lock_state *lsp) | ||
| 680 | { | 680 | { |
| 681 | if (status == NFS_OK || seqid_mutating_err(-status)) | 681 | struct nfs_seqid *new; |
| 682 | lsp->ls_seqid++; | 682 | |
| 683 | new = kmalloc(sizeof(*new), GFP_KERNEL); | ||
| 684 | if (new != NULL) { | ||
| 685 | new->sequence = counter; | ||
| 686 | INIT_LIST_HEAD(&new->list); | ||
| 687 | } | ||
| 688 | return new; | ||
| 689 | } | ||
| 690 | |||
| 691 | void nfs_free_seqid(struct nfs_seqid *seqid) | ||
| 692 | { | ||
| 693 | struct rpc_sequence *sequence = seqid->sequence->sequence; | ||
| 694 | |||
| 695 | if (!list_empty(&seqid->list)) { | ||
| 696 | spin_lock(&sequence->lock); | ||
| 697 | list_del(&seqid->list); | ||
| 698 | spin_unlock(&sequence->lock); | ||
| 699 | } | ||
| 700 | rpc_wake_up_next(&sequence->wait); | ||
| 701 | kfree(seqid); | ||
| 683 | } | 702 | } |
| 684 | 703 | ||
| 685 | /* | 704 | /* |
| 686 | * Called with sp->so_sema and clp->cl_sem held. | 705 | * Increment the seqid if the OPEN/OPEN_DOWNGRADE/CLOSE succeeded, or |
| 687 | * | 706 | * failed with a seqid incrementing error - |
| 688 | * Increment the seqid if the OPEN/OPEN_DOWNGRADE/CLOSE succeeded, or | 707 | * see comments nfs_fs.h:seqid_mutating_error() |
| 689 | * failed with a seqid incrementing error - | 708 | */ |
| 690 | * see comments nfs_fs.h:seqid_mutating_error() | 709 | static inline void nfs_increment_seqid(int status, struct nfs_seqid *seqid) |
| 691 | */ | 710 | { |
| 692 | void nfs4_increment_seqid(int status, struct nfs4_state_owner *sp) | 711 | switch (status) { |
| 693 | { | 712 | case 0: |
| 694 | if (status == NFS_OK || seqid_mutating_err(-status)) | 713 | break; |
| 695 | sp->so_seqid++; | 714 | case -NFS4ERR_BAD_SEQID: |
| 696 | /* If the server returns BAD_SEQID, unhash state_owner here */ | 715 | case -NFS4ERR_STALE_CLIENTID: |
| 697 | if (status == -NFS4ERR_BAD_SEQID) | 716 | case -NFS4ERR_STALE_STATEID: |
| 717 | case -NFS4ERR_BAD_STATEID: | ||
| 718 | case -NFS4ERR_BADXDR: | ||
| 719 | case -NFS4ERR_RESOURCE: | ||
| 720 | case -NFS4ERR_NOFILEHANDLE: | ||
| 721 | /* Non-seqid mutating errors */ | ||
| 722 | return; | ||
| 723 | }; | ||
| 724 | /* | ||
| 725 | * Note: no locking needed as we are guaranteed to be first | ||
| 726 | * on the sequence list | ||
| 727 | */ | ||
| 728 | seqid->sequence->counter++; | ||
| 729 | } | ||
| 730 | |||
| 731 | void nfs_increment_open_seqid(int status, struct nfs_seqid *seqid) | ||
| 732 | { | ||
| 733 | if (status == -NFS4ERR_BAD_SEQID) { | ||
| 734 | struct nfs4_state_owner *sp = container_of(seqid->sequence, | ||
| 735 | struct nfs4_state_owner, so_seqid); | ||
| 698 | nfs4_drop_state_owner(sp); | 736 | nfs4_drop_state_owner(sp); |
| 737 | } | ||
| 738 | return nfs_increment_seqid(status, seqid); | ||
| 739 | } | ||
| 740 | |||
| 741 | /* | ||
| 742 | * Increment the seqid if the LOCK/LOCKU succeeded, or | ||
| 743 | * failed with a seqid incrementing error - | ||
| 744 | * see comments nfs_fs.h:seqid_mutating_error() | ||
| 745 | */ | ||
| 746 | void nfs_increment_lock_seqid(int status, struct nfs_seqid *seqid) | ||
| 747 | { | ||
| 748 | return nfs_increment_seqid(status, seqid); | ||
| 749 | } | ||
| 750 | |||
| 751 | int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task) | ||
| 752 | { | ||
| 753 | struct rpc_sequence *sequence = seqid->sequence->sequence; | ||
| 754 | int status = 0; | ||
| 755 | |||
| 756 | if (sequence->list.next == &seqid->list) | ||
| 757 | goto out; | ||
| 758 | spin_lock(&sequence->lock); | ||
| 759 | if (!list_empty(&sequence->list)) { | ||
| 760 | rpc_sleep_on(&sequence->wait, task, NULL, NULL); | ||
| 761 | status = -EAGAIN; | ||
| 762 | } else | ||
| 763 | list_add(&seqid->list, &sequence->list); | ||
| 764 | spin_unlock(&sequence->lock); | ||
| 765 | out: | ||
| 766 | return status; | ||
| 699 | } | 767 | } |
| 700 | 768 | ||
| 701 | static int reclaimer(void *); | 769 | static int reclaimer(void *); |
| @@ -791,8 +859,6 @@ static int nfs4_reclaim_open_state(struct nfs4_state_recovery_ops *ops, struct n | |||
| 791 | if (state->state == 0) | 859 | if (state->state == 0) |
| 792 | continue; | 860 | continue; |
| 793 | status = ops->recover_open(sp, state); | 861 | status = ops->recover_open(sp, state); |
| 794 | list_for_each_entry(lock, &state->lock_states, ls_locks) | ||
| 795 | lock->ls_flags &= ~NFS_LOCK_INITIALIZED; | ||
| 796 | if (status >= 0) { | 862 | if (status >= 0) { |
| 797 | status = nfs4_reclaim_locks(ops, state); | 863 | status = nfs4_reclaim_locks(ops, state); |
| 798 | if (status < 0) | 864 | if (status < 0) |
| @@ -831,6 +897,28 @@ out_err: | |||
| 831 | return status; | 897 | return status; |
| 832 | } | 898 | } |
| 833 | 899 | ||
| 900 | static void nfs4_state_mark_reclaim(struct nfs4_client *clp) | ||
| 901 | { | ||
| 902 | struct nfs4_state_owner *sp; | ||
| 903 | struct nfs4_state *state; | ||
| 904 | struct nfs4_lock_state *lock; | ||
| 905 | |||
| 906 | /* Reset all sequence ids to zero */ | ||
| 907 | list_for_each_entry(sp, &clp->cl_state_owners, so_list) { | ||
| 908 | sp->so_seqid.counter = 0; | ||
| 909 | sp->so_seqid.flags = 0; | ||
| 910 | spin_lock(&sp->so_lock); | ||
| 911 | list_for_each_entry(state, &sp->so_states, open_states) { | ||
| 912 | list_for_each_entry(lock, &state->lock_states, ls_locks) { | ||
| 913 | lock->ls_seqid.counter = 0; | ||
| 914 | lock->ls_seqid.flags = 0; | ||
| 915 | lock->ls_flags &= ~NFS_LOCK_INITIALIZED; | ||
| 916 | } | ||
| 917 | } | ||
| 918 | spin_unlock(&sp->so_lock); | ||
| 919 | } | ||
| 920 | } | ||
| 921 | |||
| 834 | static int reclaimer(void *ptr) | 922 | static int reclaimer(void *ptr) |
| 835 | { | 923 | { |
| 836 | struct reclaimer_args *args = (struct reclaimer_args *)ptr; | 924 | struct reclaimer_args *args = (struct reclaimer_args *)ptr; |
| @@ -864,6 +952,7 @@ restart_loop: | |||
| 864 | default: | 952 | default: |
| 865 | ops = &nfs4_network_partition_recovery_ops; | 953 | ops = &nfs4_network_partition_recovery_ops; |
| 866 | }; | 954 | }; |
| 955 | nfs4_state_mark_reclaim(clp); | ||
| 867 | status = __nfs4_init_client(clp); | 956 | status = __nfs4_init_client(clp); |
| 868 | if (status) | 957 | if (status) |
| 869 | goto out_error; | 958 | goto out_error; |
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 6c564ef9489e..fbbace8a30c4 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
| @@ -95,6 +95,8 @@ static int nfs_stat_to_errno(int); | |||
| 95 | #define decode_getattr_maxsz (op_decode_hdr_maxsz + nfs4_fattr_maxsz) | 95 | #define decode_getattr_maxsz (op_decode_hdr_maxsz + nfs4_fattr_maxsz) |
| 96 | #define encode_savefh_maxsz (op_encode_hdr_maxsz) | 96 | #define encode_savefh_maxsz (op_encode_hdr_maxsz) |
| 97 | #define decode_savefh_maxsz (op_decode_hdr_maxsz) | 97 | #define decode_savefh_maxsz (op_decode_hdr_maxsz) |
| 98 | #define encode_restorefh_maxsz (op_encode_hdr_maxsz) | ||
| 99 | #define decode_restorefh_maxsz (op_decode_hdr_maxsz) | ||
| 98 | #define encode_fsinfo_maxsz (op_encode_hdr_maxsz + 2) | 100 | #define encode_fsinfo_maxsz (op_encode_hdr_maxsz + 2) |
| 99 | #define decode_fsinfo_maxsz (op_decode_hdr_maxsz + 11) | 101 | #define decode_fsinfo_maxsz (op_decode_hdr_maxsz + 11) |
| 100 | #define encode_renew_maxsz (op_encode_hdr_maxsz + 3) | 102 | #define encode_renew_maxsz (op_encode_hdr_maxsz + 3) |
| @@ -157,16 +159,20 @@ static int nfs_stat_to_errno(int); | |||
| 157 | op_decode_hdr_maxsz + 2) | 159 | op_decode_hdr_maxsz + 2) |
| 158 | #define NFS4_enc_write_sz (compound_encode_hdr_maxsz + \ | 160 | #define NFS4_enc_write_sz (compound_encode_hdr_maxsz + \ |
| 159 | encode_putfh_maxsz + \ | 161 | encode_putfh_maxsz + \ |
| 160 | op_encode_hdr_maxsz + 8) | 162 | op_encode_hdr_maxsz + 8 + \ |
| 163 | encode_getattr_maxsz) | ||
| 161 | #define NFS4_dec_write_sz (compound_decode_hdr_maxsz + \ | 164 | #define NFS4_dec_write_sz (compound_decode_hdr_maxsz + \ |
| 162 | decode_putfh_maxsz + \ | 165 | decode_putfh_maxsz + \ |
| 163 | op_decode_hdr_maxsz + 4) | 166 | op_decode_hdr_maxsz + 4 + \ |
| 167 | decode_getattr_maxsz) | ||
| 164 | #define NFS4_enc_commit_sz (compound_encode_hdr_maxsz + \ | 168 | #define NFS4_enc_commit_sz (compound_encode_hdr_maxsz + \ |
| 165 | encode_putfh_maxsz + \ | 169 | encode_putfh_maxsz + \ |
| 166 | op_encode_hdr_maxsz + 3) | 170 | op_encode_hdr_maxsz + 3 + \ |
| 171 | encode_getattr_maxsz) | ||
| 167 | #define NFS4_dec_commit_sz (compound_decode_hdr_maxsz + \ | 172 | #define NFS4_dec_commit_sz (compound_decode_hdr_maxsz + \ |
| 168 | decode_putfh_maxsz + \ | 173 | decode_putfh_maxsz + \ |
| 169 | op_decode_hdr_maxsz + 2) | 174 | op_decode_hdr_maxsz + 2 + \ |
| 175 | decode_getattr_maxsz) | ||
| 170 | #define NFS4_enc_open_sz (compound_encode_hdr_maxsz + \ | 176 | #define NFS4_enc_open_sz (compound_encode_hdr_maxsz + \ |
| 171 | encode_putfh_maxsz + \ | 177 | encode_putfh_maxsz + \ |
| 172 | op_encode_hdr_maxsz + \ | 178 | op_encode_hdr_maxsz + \ |
| @@ -196,17 +202,21 @@ static int nfs_stat_to_errno(int); | |||
| 196 | #define NFS4_enc_open_downgrade_sz \ | 202 | #define NFS4_enc_open_downgrade_sz \ |
| 197 | (compound_encode_hdr_maxsz + \ | 203 | (compound_encode_hdr_maxsz + \ |
| 198 | encode_putfh_maxsz + \ | 204 | encode_putfh_maxsz + \ |
| 199 | op_encode_hdr_maxsz + 7) | 205 | op_encode_hdr_maxsz + 7 + \ |
| 206 | encode_getattr_maxsz) | ||
| 200 | #define NFS4_dec_open_downgrade_sz \ | 207 | #define NFS4_dec_open_downgrade_sz \ |
| 201 | (compound_decode_hdr_maxsz + \ | 208 | (compound_decode_hdr_maxsz + \ |
| 202 | decode_putfh_maxsz + \ | 209 | decode_putfh_maxsz + \ |
| 203 | op_decode_hdr_maxsz + 4) | 210 | op_decode_hdr_maxsz + 4 + \ |
| 211 | decode_getattr_maxsz) | ||
| 204 | #define NFS4_enc_close_sz (compound_encode_hdr_maxsz + \ | 212 | #define NFS4_enc_close_sz (compound_encode_hdr_maxsz + \ |
| 205 | encode_putfh_maxsz + \ | 213 | encode_putfh_maxsz + \ |
| 206 | op_encode_hdr_maxsz + 5) | 214 | op_encode_hdr_maxsz + 5 + \ |
| 215 | encode_getattr_maxsz) | ||
| 207 | #define NFS4_dec_close_sz (compound_decode_hdr_maxsz + \ | 216 | #define NFS4_dec_close_sz (compound_decode_hdr_maxsz + \ |
| 208 | decode_putfh_maxsz + \ | 217 | decode_putfh_maxsz + \ |
| 209 | op_decode_hdr_maxsz + 4) | 218 | op_decode_hdr_maxsz + 4 + \ |
| 219 | decode_getattr_maxsz) | ||
| 210 | #define NFS4_enc_setattr_sz (compound_encode_hdr_maxsz + \ | 220 | #define NFS4_enc_setattr_sz (compound_encode_hdr_maxsz + \ |
| 211 | encode_putfh_maxsz + \ | 221 | encode_putfh_maxsz + \ |
| 212 | op_encode_hdr_maxsz + 4 + \ | 222 | op_encode_hdr_maxsz + 4 + \ |
| @@ -300,30 +310,44 @@ static int nfs_stat_to_errno(int); | |||
| 300 | decode_getfh_maxsz) | 310 | decode_getfh_maxsz) |
| 301 | #define NFS4_enc_remove_sz (compound_encode_hdr_maxsz + \ | 311 | #define NFS4_enc_remove_sz (compound_encode_hdr_maxsz + \ |
| 302 | encode_putfh_maxsz + \ | 312 | encode_putfh_maxsz + \ |
| 303 | encode_remove_maxsz) | 313 | encode_remove_maxsz + \ |
| 314 | encode_getattr_maxsz) | ||
| 304 | #define NFS4_dec_remove_sz (compound_decode_hdr_maxsz + \ | 315 | #define NFS4_dec_remove_sz (compound_decode_hdr_maxsz + \ |
| 305 | decode_putfh_maxsz + \ | 316 | decode_putfh_maxsz + \ |
| 306 | op_decode_hdr_maxsz + 5) | 317 | op_decode_hdr_maxsz + 5 + \ |
| 318 | decode_getattr_maxsz) | ||
| 307 | #define NFS4_enc_rename_sz (compound_encode_hdr_maxsz + \ | 319 | #define NFS4_enc_rename_sz (compound_encode_hdr_maxsz + \ |
| 308 | encode_putfh_maxsz + \ | 320 | encode_putfh_maxsz + \ |
| 309 | encode_savefh_maxsz + \ | 321 | encode_savefh_maxsz + \ |
| 310 | encode_putfh_maxsz + \ | 322 | encode_putfh_maxsz + \ |
| 311 | encode_rename_maxsz) | 323 | encode_rename_maxsz + \ |
| 324 | encode_getattr_maxsz + \ | ||
| 325 | encode_restorefh_maxsz + \ | ||
| 326 | encode_getattr_maxsz) | ||
| 312 | #define NFS4_dec_rename_sz (compound_decode_hdr_maxsz + \ | 327 | #define NFS4_dec_rename_sz (compound_decode_hdr_maxsz + \ |
| 313 | decode_putfh_maxsz + \ | 328 | decode_putfh_maxsz + \ |
| 314 | decode_savefh_maxsz + \ | 329 | decode_savefh_maxsz + \ |
| 315 | decode_putfh_maxsz + \ | 330 | decode_putfh_maxsz + \ |
| 316 | decode_rename_maxsz) | 331 | decode_rename_maxsz + \ |
| 332 | decode_getattr_maxsz + \ | ||
| 333 | decode_restorefh_maxsz + \ | ||
| 334 | decode_getattr_maxsz) | ||
| 317 | #define NFS4_enc_link_sz (compound_encode_hdr_maxsz + \ | 335 | #define NFS4_enc_link_sz (compound_encode_hdr_maxsz + \ |
| 318 | encode_putfh_maxsz + \ | 336 | encode_putfh_maxsz + \ |
| 319 | encode_savefh_maxsz + \ | 337 | encode_savefh_maxsz + \ |
| 320 | encode_putfh_maxsz + \ | 338 | encode_putfh_maxsz + \ |
| 321 | encode_link_maxsz) | 339 | encode_link_maxsz + \ |
| 340 | decode_getattr_maxsz + \ | ||
| 341 | encode_restorefh_maxsz + \ | ||
| 342 | decode_getattr_maxsz) | ||
| 322 | #define NFS4_dec_link_sz (compound_decode_hdr_maxsz + \ | 343 | #define NFS4_dec_link_sz (compound_decode_hdr_maxsz + \ |
| 323 | decode_putfh_maxsz + \ | 344 | decode_putfh_maxsz + \ |
| 324 | decode_savefh_maxsz + \ | 345 | decode_savefh_maxsz + \ |
| 325 | decode_putfh_maxsz + \ | 346 | decode_putfh_maxsz + \ |
| 326 | decode_link_maxsz) | 347 | decode_link_maxsz + \ |
| 348 | decode_getattr_maxsz + \ | ||
| 349 | decode_restorefh_maxsz + \ | ||
| 350 | decode_getattr_maxsz) | ||
| 327 | #define NFS4_enc_symlink_sz (compound_encode_hdr_maxsz + \ | 351 | #define NFS4_enc_symlink_sz (compound_encode_hdr_maxsz + \ |
| 328 | encode_putfh_maxsz + \ | 352 | encode_putfh_maxsz + \ |
| 329 | encode_symlink_maxsz + \ | 353 | encode_symlink_maxsz + \ |
| @@ -336,14 +360,20 @@ static int nfs_stat_to_errno(int); | |||
| 336 | decode_getfh_maxsz) | 360 | decode_getfh_maxsz) |
| 337 | #define NFS4_enc_create_sz (compound_encode_hdr_maxsz + \ | 361 | #define NFS4_enc_create_sz (compound_encode_hdr_maxsz + \ |
| 338 | encode_putfh_maxsz + \ | 362 | encode_putfh_maxsz + \ |
| 363 | encode_savefh_maxsz + \ | ||
| 339 | encode_create_maxsz + \ | 364 | encode_create_maxsz + \ |
| 365 | encode_getfh_maxsz + \ | ||
| 340 | encode_getattr_maxsz + \ | 366 | encode_getattr_maxsz + \ |
| 341 | encode_getfh_maxsz) | 367 | encode_restorefh_maxsz + \ |
| 368 | encode_getattr_maxsz) | ||
| 342 | #define NFS4_dec_create_sz (compound_decode_hdr_maxsz + \ | 369 | #define NFS4_dec_create_sz (compound_decode_hdr_maxsz + \ |
| 343 | decode_putfh_maxsz + \ | 370 | decode_putfh_maxsz + \ |
| 371 | decode_savefh_maxsz + \ | ||
| 344 | decode_create_maxsz + \ | 372 | decode_create_maxsz + \ |
| 373 | decode_getfh_maxsz + \ | ||
| 345 | decode_getattr_maxsz + \ | 374 | decode_getattr_maxsz + \ |
| 346 | decode_getfh_maxsz) | 375 | decode_restorefh_maxsz + \ |
| 376 | decode_getattr_maxsz) | ||
| 347 | #define NFS4_enc_pathconf_sz (compound_encode_hdr_maxsz + \ | 377 | #define NFS4_enc_pathconf_sz (compound_encode_hdr_maxsz + \ |
| 348 | encode_putfh_maxsz + \ | 378 | encode_putfh_maxsz + \ |
| 349 | encode_getattr_maxsz) | 379 | encode_getattr_maxsz) |
| @@ -602,10 +632,10 @@ static int encode_close(struct xdr_stream *xdr, const struct nfs_closeargs *arg) | |||
| 602 | { | 632 | { |
| 603 | uint32_t *p; | 633 | uint32_t *p; |
| 604 | 634 | ||
| 605 | RESERVE_SPACE(8+sizeof(arg->stateid.data)); | 635 | RESERVE_SPACE(8+sizeof(arg->stateid->data)); |
| 606 | WRITE32(OP_CLOSE); | 636 | WRITE32(OP_CLOSE); |
| 607 | WRITE32(arg->seqid); | 637 | WRITE32(arg->seqid->sequence->counter); |
| 608 | WRITEMEM(arg->stateid.data, sizeof(arg->stateid.data)); | 638 | WRITEMEM(arg->stateid->data, sizeof(arg->stateid->data)); |
| 609 | 639 | ||
| 610 | return 0; | 640 | return 0; |
| 611 | } | 641 | } |
| @@ -729,22 +759,18 @@ static int encode_lock(struct xdr_stream *xdr, const struct nfs_lockargs *arg) | |||
| 729 | WRITE64(arg->length); | 759 | WRITE64(arg->length); |
| 730 | WRITE32(opargs->new_lock_owner); | 760 | WRITE32(opargs->new_lock_owner); |
| 731 | if (opargs->new_lock_owner){ | 761 | if (opargs->new_lock_owner){ |
| 732 | struct nfs_open_to_lock *ol = opargs->u.open_lock; | ||
| 733 | |||
| 734 | RESERVE_SPACE(40); | 762 | RESERVE_SPACE(40); |
| 735 | WRITE32(ol->open_seqid); | 763 | WRITE32(opargs->open_seqid->sequence->counter); |
| 736 | WRITEMEM(&ol->open_stateid, sizeof(ol->open_stateid)); | 764 | WRITEMEM(opargs->open_stateid->data, sizeof(opargs->open_stateid->data)); |
| 737 | WRITE32(ol->lock_seqid); | 765 | WRITE32(opargs->lock_seqid->sequence->counter); |
| 738 | WRITE64(ol->lock_owner.clientid); | 766 | WRITE64(opargs->lock_owner.clientid); |
| 739 | WRITE32(4); | 767 | WRITE32(4); |
| 740 | WRITE32(ol->lock_owner.id); | 768 | WRITE32(opargs->lock_owner.id); |
| 741 | } | 769 | } |
| 742 | else { | 770 | else { |
| 743 | struct nfs_exist_lock *el = opargs->u.exist_lock; | ||
| 744 | |||
| 745 | RESERVE_SPACE(20); | 771 | RESERVE_SPACE(20); |
| 746 | WRITEMEM(&el->stateid, sizeof(el->stateid)); | 772 | WRITEMEM(opargs->lock_stateid->data, sizeof(opargs->lock_stateid->data)); |
| 747 | WRITE32(el->seqid); | 773 | WRITE32(opargs->lock_seqid->sequence->counter); |
| 748 | } | 774 | } |
| 749 | 775 | ||
| 750 | return 0; | 776 | return 0; |
| @@ -775,8 +801,8 @@ static int encode_locku(struct xdr_stream *xdr, const struct nfs_lockargs *arg) | |||
| 775 | RESERVE_SPACE(44); | 801 | RESERVE_SPACE(44); |
| 776 | WRITE32(OP_LOCKU); | 802 | WRITE32(OP_LOCKU); |
| 777 | WRITE32(arg->type); | 803 | WRITE32(arg->type); |
| 778 | WRITE32(opargs->seqid); | 804 | WRITE32(opargs->seqid->sequence->counter); |
| 779 | WRITEMEM(&opargs->stateid, sizeof(opargs->stateid)); | 805 | WRITEMEM(opargs->stateid->data, sizeof(opargs->stateid->data)); |
| 780 | WRITE64(arg->offset); | 806 | WRITE64(arg->offset); |
| 781 | WRITE64(arg->length); | 807 | WRITE64(arg->length); |
| 782 | 808 | ||
| @@ -826,7 +852,7 @@ static inline void encode_openhdr(struct xdr_stream *xdr, const struct nfs_opena | |||
| 826 | */ | 852 | */ |
| 827 | RESERVE_SPACE(8); | 853 | RESERVE_SPACE(8); |
| 828 | WRITE32(OP_OPEN); | 854 | WRITE32(OP_OPEN); |
| 829 | WRITE32(arg->seqid); | 855 | WRITE32(arg->seqid->sequence->counter); |
| 830 | encode_share_access(xdr, arg->open_flags); | 856 | encode_share_access(xdr, arg->open_flags); |
| 831 | RESERVE_SPACE(16); | 857 | RESERVE_SPACE(16); |
| 832 | WRITE64(arg->clientid); | 858 | WRITE64(arg->clientid); |
| @@ -941,7 +967,7 @@ static int encode_open_confirm(struct xdr_stream *xdr, const struct nfs_open_con | |||
| 941 | RESERVE_SPACE(8+sizeof(arg->stateid.data)); | 967 | RESERVE_SPACE(8+sizeof(arg->stateid.data)); |
| 942 | WRITE32(OP_OPEN_CONFIRM); | 968 | WRITE32(OP_OPEN_CONFIRM); |
| 943 | WRITEMEM(arg->stateid.data, sizeof(arg->stateid.data)); | 969 | WRITEMEM(arg->stateid.data, sizeof(arg->stateid.data)); |
| 944 | WRITE32(arg->seqid); | 970 | WRITE32(arg->seqid->sequence->counter); |
| 945 | 971 | ||
| 946 | return 0; | 972 | return 0; |
| 947 | } | 973 | } |
| @@ -950,10 +976,10 @@ static int encode_open_downgrade(struct xdr_stream *xdr, const struct nfs_closea | |||
| 950 | { | 976 | { |
| 951 | uint32_t *p; | 977 | uint32_t *p; |
| 952 | 978 | ||
| 953 | RESERVE_SPACE(8+sizeof(arg->stateid.data)); | 979 | RESERVE_SPACE(8+sizeof(arg->stateid->data)); |
| 954 | WRITE32(OP_OPEN_DOWNGRADE); | 980 | WRITE32(OP_OPEN_DOWNGRADE); |
| 955 | WRITEMEM(arg->stateid.data, sizeof(arg->stateid.data)); | 981 | WRITEMEM(arg->stateid->data, sizeof(arg->stateid->data)); |
| 956 | WRITE32(arg->seqid); | 982 | WRITE32(arg->seqid->sequence->counter); |
| 957 | encode_share_access(xdr, arg->open_flags); | 983 | encode_share_access(xdr, arg->open_flags); |
| 958 | return 0; | 984 | return 0; |
| 959 | } | 985 | } |
| @@ -1117,6 +1143,17 @@ static int encode_renew(struct xdr_stream *xdr, const struct nfs4_client *client | |||
| 1117 | } | 1143 | } |
| 1118 | 1144 | ||
| 1119 | static int | 1145 | static int |
| 1146 | encode_restorefh(struct xdr_stream *xdr) | ||
| 1147 | { | ||
| 1148 | uint32_t *p; | ||
| 1149 | |||
| 1150 | RESERVE_SPACE(4); | ||
| 1151 | WRITE32(OP_RESTOREFH); | ||
| 1152 | |||
| 1153 | return 0; | ||
| 1154 | } | ||
| 1155 | |||
| 1156 | static int | ||
| 1120 | encode_setacl(struct xdr_stream *xdr, struct nfs_setaclargs *arg) | 1157 | encode_setacl(struct xdr_stream *xdr, struct nfs_setaclargs *arg) |
| 1121 | { | 1158 | { |
| 1122 | uint32_t *p; | 1159 | uint32_t *p; |
| @@ -1296,14 +1333,18 @@ static int nfs4_xdr_enc_remove(struct rpc_rqst *req, uint32_t *p, const struct n | |||
| 1296 | { | 1333 | { |
| 1297 | struct xdr_stream xdr; | 1334 | struct xdr_stream xdr; |
| 1298 | struct compound_hdr hdr = { | 1335 | struct compound_hdr hdr = { |
| 1299 | .nops = 2, | 1336 | .nops = 3, |
| 1300 | }; | 1337 | }; |
| 1301 | int status; | 1338 | int status; |
| 1302 | 1339 | ||
| 1303 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | 1340 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); |
| 1304 | encode_compound_hdr(&xdr, &hdr); | 1341 | encode_compound_hdr(&xdr, &hdr); |
| 1305 | if ((status = encode_putfh(&xdr, args->fh)) == 0) | 1342 | if ((status = encode_putfh(&xdr, args->fh)) != 0) |
| 1306 | status = encode_remove(&xdr, args->name); | 1343 | goto out; |
| 1344 | if ((status = encode_remove(&xdr, args->name)) != 0) | ||
| 1345 | goto out; | ||
| 1346 | status = encode_getfattr(&xdr, args->bitmask); | ||
| 1347 | out: | ||
| 1307 | return status; | 1348 | return status; |
| 1308 | } | 1349 | } |
| 1309 | 1350 | ||
| @@ -1314,7 +1355,7 @@ static int nfs4_xdr_enc_rename(struct rpc_rqst *req, uint32_t *p, const struct n | |||
| 1314 | { | 1355 | { |
| 1315 | struct xdr_stream xdr; | 1356 | struct xdr_stream xdr; |
| 1316 | struct compound_hdr hdr = { | 1357 | struct compound_hdr hdr = { |
| 1317 | .nops = 4, | 1358 | .nops = 7, |
| 1318 | }; | 1359 | }; |
| 1319 | int status; | 1360 | int status; |
| 1320 | 1361 | ||
| @@ -1326,7 +1367,13 @@ static int nfs4_xdr_enc_rename(struct rpc_rqst *req, uint32_t *p, const struct n | |||
| 1326 | goto out; | 1367 | goto out; |
| 1327 | if ((status = encode_putfh(&xdr, args->new_dir)) != 0) | 1368 | if ((status = encode_putfh(&xdr, args->new_dir)) != 0) |
| 1328 | goto out; | 1369 | goto out; |
| 1329 | status = encode_rename(&xdr, args->old_name, args->new_name); | 1370 | if ((status = encode_rename(&xdr, args->old_name, args->new_name)) != 0) |
| 1371 | goto out; | ||
| 1372 | if ((status = encode_getfattr(&xdr, args->bitmask)) != 0) | ||
| 1373 | goto out; | ||
| 1374 | if ((status = encode_restorefh(&xdr)) != 0) | ||
| 1375 | goto out; | ||
| 1376 | status = encode_getfattr(&xdr, args->bitmask); | ||
| 1330 | out: | 1377 | out: |
| 1331 | return status; | 1378 | return status; |
| 1332 | } | 1379 | } |
| @@ -1338,7 +1385,7 @@ static int nfs4_xdr_enc_link(struct rpc_rqst *req, uint32_t *p, const struct nfs | |||
| 1338 | { | 1385 | { |
| 1339 | struct xdr_stream xdr; | 1386 | struct xdr_stream xdr; |
| 1340 | struct compound_hdr hdr = { | 1387 | struct compound_hdr hdr = { |
| 1341 | .nops = 4, | 1388 | .nops = 7, |
| 1342 | }; | 1389 | }; |
| 1343 | int status; | 1390 | int status; |
| 1344 | 1391 | ||
| @@ -1350,7 +1397,13 @@ static int nfs4_xdr_enc_link(struct rpc_rqst *req, uint32_t *p, const struct nfs | |||
| 1350 | goto out; | 1397 | goto out; |
| 1351 | if ((status = encode_putfh(&xdr, args->dir_fh)) != 0) | 1398 | if ((status = encode_putfh(&xdr, args->dir_fh)) != 0) |
| 1352 | goto out; | 1399 | goto out; |
| 1353 | status = encode_link(&xdr, args->name); | 1400 | if ((status = encode_link(&xdr, args->name)) != 0) |
| 1401 | goto out; | ||
| 1402 | if ((status = encode_getfattr(&xdr, args->bitmask)) != 0) | ||
| 1403 | goto out; | ||
| 1404 | if ((status = encode_restorefh(&xdr)) != 0) | ||
| 1405 | goto out; | ||
| 1406 | status = encode_getfattr(&xdr, args->bitmask); | ||
| 1354 | out: | 1407 | out: |
| 1355 | return status; | 1408 | return status; |
| 1356 | } | 1409 | } |
| @@ -1362,7 +1415,7 @@ static int nfs4_xdr_enc_create(struct rpc_rqst *req, uint32_t *p, const struct n | |||
| 1362 | { | 1415 | { |
| 1363 | struct xdr_stream xdr; | 1416 | struct xdr_stream xdr; |
| 1364 | struct compound_hdr hdr = { | 1417 | struct compound_hdr hdr = { |
| 1365 | .nops = 4, | 1418 | .nops = 7, |
| 1366 | }; | 1419 | }; |
| 1367 | int status; | 1420 | int status; |
| 1368 | 1421 | ||
| @@ -1370,10 +1423,16 @@ static int nfs4_xdr_enc_create(struct rpc_rqst *req, uint32_t *p, const struct n | |||
| 1370 | encode_compound_hdr(&xdr, &hdr); | 1423 | encode_compound_hdr(&xdr, &hdr); |
| 1371 | if ((status = encode_putfh(&xdr, args->dir_fh)) != 0) | 1424 | if ((status = encode_putfh(&xdr, args->dir_fh)) != 0) |
| 1372 | goto out; | 1425 | goto out; |
| 1426 | if ((status = encode_savefh(&xdr)) != 0) | ||
| 1427 | goto out; | ||
| 1373 | if ((status = encode_create(&xdr, args)) != 0) | 1428 | if ((status = encode_create(&xdr, args)) != 0) |
| 1374 | goto out; | 1429 | goto out; |
| 1375 | if ((status = encode_getfh(&xdr)) != 0) | 1430 | if ((status = encode_getfh(&xdr)) != 0) |
| 1376 | goto out; | 1431 | goto out; |
| 1432 | if ((status = encode_getfattr(&xdr, args->bitmask)) != 0) | ||
| 1433 | goto out; | ||
| 1434 | if ((status = encode_restorefh(&xdr)) != 0) | ||
| 1435 | goto out; | ||
| 1377 | status = encode_getfattr(&xdr, args->bitmask); | 1436 | status = encode_getfattr(&xdr, args->bitmask); |
| 1378 | out: | 1437 | out: |
| 1379 | return status; | 1438 | return status; |
| @@ -1412,7 +1471,7 @@ static int nfs4_xdr_enc_close(struct rpc_rqst *req, uint32_t *p, struct nfs_clos | |||
| 1412 | { | 1471 | { |
| 1413 | struct xdr_stream xdr; | 1472 | struct xdr_stream xdr; |
| 1414 | struct compound_hdr hdr = { | 1473 | struct compound_hdr hdr = { |
| 1415 | .nops = 2, | 1474 | .nops = 3, |
| 1416 | }; | 1475 | }; |
| 1417 | int status; | 1476 | int status; |
| 1418 | 1477 | ||
| @@ -1422,6 +1481,9 @@ static int nfs4_xdr_enc_close(struct rpc_rqst *req, uint32_t *p, struct nfs_clos | |||
| 1422 | if(status) | 1481 | if(status) |
| 1423 | goto out; | 1482 | goto out; |
| 1424 | status = encode_close(&xdr, args); | 1483 | status = encode_close(&xdr, args); |
| 1484 | if (status != 0) | ||
| 1485 | goto out; | ||
| 1486 | status = encode_getfattr(&xdr, args->bitmask); | ||
| 1425 | out: | 1487 | out: |
| 1426 | return status; | 1488 | return status; |
| 1427 | } | 1489 | } |
| @@ -1433,15 +1495,21 @@ static int nfs4_xdr_enc_open(struct rpc_rqst *req, uint32_t *p, struct nfs_opena | |||
| 1433 | { | 1495 | { |
| 1434 | struct xdr_stream xdr; | 1496 | struct xdr_stream xdr; |
| 1435 | struct compound_hdr hdr = { | 1497 | struct compound_hdr hdr = { |
| 1436 | .nops = 4, | 1498 | .nops = 7, |
| 1437 | }; | 1499 | }; |
| 1438 | int status; | 1500 | int status; |
| 1439 | 1501 | ||
| 1502 | status = nfs_wait_on_sequence(args->seqid, req->rq_task); | ||
| 1503 | if (status != 0) | ||
| 1504 | goto out; | ||
| 1440 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | 1505 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); |
| 1441 | encode_compound_hdr(&xdr, &hdr); | 1506 | encode_compound_hdr(&xdr, &hdr); |
| 1442 | status = encode_putfh(&xdr, args->fh); | 1507 | status = encode_putfh(&xdr, args->fh); |
| 1443 | if (status) | 1508 | if (status) |
| 1444 | goto out; | 1509 | goto out; |
| 1510 | status = encode_savefh(&xdr); | ||
| 1511 | if (status) | ||
| 1512 | goto out; | ||
| 1445 | status = encode_open(&xdr, args); | 1513 | status = encode_open(&xdr, args); |
| 1446 | if (status) | 1514 | if (status) |
| 1447 | goto out; | 1515 | goto out; |
| @@ -1449,6 +1517,12 @@ static int nfs4_xdr_enc_open(struct rpc_rqst *req, uint32_t *p, struct nfs_opena | |||
| 1449 | if (status) | 1517 | if (status) |
| 1450 | goto out; | 1518 | goto out; |
| 1451 | status = encode_getfattr(&xdr, args->bitmask); | 1519 | status = encode_getfattr(&xdr, args->bitmask); |
| 1520 | if (status) | ||
| 1521 | goto out; | ||
| 1522 | status = encode_restorefh(&xdr); | ||
| 1523 | if (status) | ||
| 1524 | goto out; | ||
| 1525 | status = encode_getfattr(&xdr, args->bitmask); | ||
| 1452 | out: | 1526 | out: |
| 1453 | return status; | 1527 | return status; |
| 1454 | } | 1528 | } |
| @@ -1464,6 +1538,9 @@ static int nfs4_xdr_enc_open_confirm(struct rpc_rqst *req, uint32_t *p, struct n | |||
| 1464 | }; | 1538 | }; |
| 1465 | int status; | 1539 | int status; |
| 1466 | 1540 | ||
| 1541 | status = nfs_wait_on_sequence(args->seqid, req->rq_task); | ||
| 1542 | if (status != 0) | ||
| 1543 | goto out; | ||
| 1467 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | 1544 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); |
| 1468 | encode_compound_hdr(&xdr, &hdr); | 1545 | encode_compound_hdr(&xdr, &hdr); |
| 1469 | status = encode_putfh(&xdr, args->fh); | 1546 | status = encode_putfh(&xdr, args->fh); |
| @@ -1485,6 +1562,9 @@ static int nfs4_xdr_enc_open_noattr(struct rpc_rqst *req, uint32_t *p, struct nf | |||
| 1485 | }; | 1562 | }; |
| 1486 | int status; | 1563 | int status; |
| 1487 | 1564 | ||
| 1565 | status = nfs_wait_on_sequence(args->seqid, req->rq_task); | ||
| 1566 | if (status != 0) | ||
| 1567 | goto out; | ||
| 1488 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | 1568 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); |
| 1489 | encode_compound_hdr(&xdr, &hdr); | 1569 | encode_compound_hdr(&xdr, &hdr); |
| 1490 | status = encode_putfh(&xdr, args->fh); | 1570 | status = encode_putfh(&xdr, args->fh); |
| @@ -1502,7 +1582,7 @@ static int nfs4_xdr_enc_open_downgrade(struct rpc_rqst *req, uint32_t *p, struct | |||
| 1502 | { | 1582 | { |
| 1503 | struct xdr_stream xdr; | 1583 | struct xdr_stream xdr; |
| 1504 | struct compound_hdr hdr = { | 1584 | struct compound_hdr hdr = { |
| 1505 | .nops = 2, | 1585 | .nops = 3, |
| 1506 | }; | 1586 | }; |
| 1507 | int status; | 1587 | int status; |
| 1508 | 1588 | ||
| @@ -1512,6 +1592,9 @@ static int nfs4_xdr_enc_open_downgrade(struct rpc_rqst *req, uint32_t *p, struct | |||
| 1512 | if (status) | 1592 | if (status) |
| 1513 | goto out; | 1593 | goto out; |
| 1514 | status = encode_open_downgrade(&xdr, args); | 1594 | status = encode_open_downgrade(&xdr, args); |
| 1595 | if (status != 0) | ||
| 1596 | goto out; | ||
| 1597 | status = encode_getfattr(&xdr, args->bitmask); | ||
| 1515 | out: | 1598 | out: |
| 1516 | return status; | 1599 | return status; |
| 1517 | } | 1600 | } |
| @@ -1525,8 +1608,15 @@ static int nfs4_xdr_enc_lock(struct rpc_rqst *req, uint32_t *p, struct nfs_locka | |||
| 1525 | struct compound_hdr hdr = { | 1608 | struct compound_hdr hdr = { |
| 1526 | .nops = 2, | 1609 | .nops = 2, |
| 1527 | }; | 1610 | }; |
| 1611 | struct nfs_lock_opargs *opargs = args->u.lock; | ||
| 1528 | int status; | 1612 | int status; |
| 1529 | 1613 | ||
| 1614 | status = nfs_wait_on_sequence(opargs->lock_seqid, req->rq_task); | ||
| 1615 | if (status != 0) | ||
| 1616 | goto out; | ||
| 1617 | /* Do we need to do an open_to_lock_owner? */ | ||
| 1618 | if (opargs->lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED) | ||
| 1619 | opargs->new_lock_owner = 0; | ||
| 1530 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | 1620 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); |
| 1531 | encode_compound_hdr(&xdr, &hdr); | 1621 | encode_compound_hdr(&xdr, &hdr); |
| 1532 | status = encode_putfh(&xdr, args->fh); | 1622 | status = encode_putfh(&xdr, args->fh); |
| @@ -1713,7 +1803,7 @@ static int nfs4_xdr_enc_write(struct rpc_rqst *req, uint32_t *p, struct nfs_writ | |||
| 1713 | { | 1803 | { |
| 1714 | struct xdr_stream xdr; | 1804 | struct xdr_stream xdr; |
| 1715 | struct compound_hdr hdr = { | 1805 | struct compound_hdr hdr = { |
| 1716 | .nops = 2, | 1806 | .nops = 3, |
| 1717 | }; | 1807 | }; |
| 1718 | int status; | 1808 | int status; |
| 1719 | 1809 | ||
| @@ -1723,6 +1813,9 @@ static int nfs4_xdr_enc_write(struct rpc_rqst *req, uint32_t *p, struct nfs_writ | |||
| 1723 | if (status) | 1813 | if (status) |
| 1724 | goto out; | 1814 | goto out; |
| 1725 | status = encode_write(&xdr, args); | 1815 | status = encode_write(&xdr, args); |
| 1816 | if (status) | ||
| 1817 | goto out; | ||
| 1818 | status = encode_getfattr(&xdr, args->bitmask); | ||
| 1726 | out: | 1819 | out: |
| 1727 | return status; | 1820 | return status; |
| 1728 | } | 1821 | } |
| @@ -1734,7 +1827,7 @@ static int nfs4_xdr_enc_commit(struct rpc_rqst *req, uint32_t *p, struct nfs_wri | |||
| 1734 | { | 1827 | { |
| 1735 | struct xdr_stream xdr; | 1828 | struct xdr_stream xdr; |
| 1736 | struct compound_hdr hdr = { | 1829 | struct compound_hdr hdr = { |
| 1737 | .nops = 2, | 1830 | .nops = 3, |
| 1738 | }; | 1831 | }; |
| 1739 | int status; | 1832 | int status; |
| 1740 | 1833 | ||
| @@ -1744,6 +1837,9 @@ static int nfs4_xdr_enc_commit(struct rpc_rqst *req, uint32_t *p, struct nfs_wri | |||
| 1744 | if (status) | 1837 | if (status) |
| 1745 | goto out; | 1838 | goto out; |
| 1746 | status = encode_commit(&xdr, args); | 1839 | status = encode_commit(&xdr, args); |
| 1840 | if (status) | ||
| 1841 | goto out; | ||
| 1842 | status = encode_getfattr(&xdr, args->bitmask); | ||
| 1747 | out: | 1843 | out: |
| 1748 | return status; | 1844 | return status; |
| 1749 | } | 1845 | } |
| @@ -2670,8 +2766,7 @@ static int decode_server_caps(struct xdr_stream *xdr, struct nfs4_server_caps_re | |||
| 2670 | goto xdr_error; | 2766 | goto xdr_error; |
| 2671 | status = verify_attr_len(xdr, savep, attrlen); | 2767 | status = verify_attr_len(xdr, savep, attrlen); |
| 2672 | xdr_error: | 2768 | xdr_error: |
| 2673 | if (status != 0) | 2769 | dprintk("%s: xdr returned %d!\n", __FUNCTION__, -status); |
| 2674 | printk(KERN_NOTICE "%s: xdr error %d!\n", __FUNCTION__, -status); | ||
| 2675 | return status; | 2770 | return status; |
| 2676 | } | 2771 | } |
| 2677 | 2772 | ||
| @@ -2704,8 +2799,7 @@ static int decode_statfs(struct xdr_stream *xdr, struct nfs_fsstat *fsstat) | |||
| 2704 | 2799 | ||
| 2705 | status = verify_attr_len(xdr, savep, attrlen); | 2800 | status = verify_attr_len(xdr, savep, attrlen); |
| 2706 | xdr_error: | 2801 | xdr_error: |
| 2707 | if (status != 0) | 2802 | dprintk("%s: xdr returned %d!\n", __FUNCTION__, -status); |
| 2708 | printk(KERN_NOTICE "%s: xdr error %d!\n", __FUNCTION__, -status); | ||
| 2709 | return status; | 2803 | return status; |
| 2710 | } | 2804 | } |
| 2711 | 2805 | ||
| @@ -2730,8 +2824,7 @@ static int decode_pathconf(struct xdr_stream *xdr, struct nfs_pathconf *pathconf | |||
| 2730 | 2824 | ||
| 2731 | status = verify_attr_len(xdr, savep, attrlen); | 2825 | status = verify_attr_len(xdr, savep, attrlen); |
| 2732 | xdr_error: | 2826 | xdr_error: |
| 2733 | if (status != 0) | 2827 | dprintk("%s: xdr returned %d!\n", __FUNCTION__, -status); |
| 2734 | printk(KERN_NOTICE "%s: xdr error %d!\n", __FUNCTION__, -status); | ||
| 2735 | return status; | 2828 | return status; |
| 2736 | } | 2829 | } |
| 2737 | 2830 | ||
| @@ -2787,13 +2880,10 @@ static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, cons | |||
| 2787 | goto xdr_error; | 2880 | goto xdr_error; |
| 2788 | if ((status = decode_attr_time_modify(xdr, bitmap, &fattr->mtime)) != 0) | 2881 | if ((status = decode_attr_time_modify(xdr, bitmap, &fattr->mtime)) != 0) |
| 2789 | goto xdr_error; | 2882 | goto xdr_error; |
| 2790 | if ((status = verify_attr_len(xdr, savep, attrlen)) == 0) { | 2883 | if ((status = verify_attr_len(xdr, savep, attrlen)) == 0) |
| 2791 | fattr->valid = NFS_ATTR_FATTR | NFS_ATTR_FATTR_V3 | NFS_ATTR_FATTR_V4; | 2884 | fattr->valid = NFS_ATTR_FATTR | NFS_ATTR_FATTR_V3 | NFS_ATTR_FATTR_V4; |
| 2792 | fattr->timestamp = jiffies; | ||
| 2793 | } | ||
| 2794 | xdr_error: | 2885 | xdr_error: |
| 2795 | if (status != 0) | 2886 | dprintk("%s: xdr returned %d\n", __FUNCTION__, -status); |
| 2796 | printk(KERN_NOTICE "%s: xdr error %d!\n", __FUNCTION__, -status); | ||
| 2797 | return status; | 2887 | return status; |
| 2798 | } | 2888 | } |
| 2799 | 2889 | ||
| @@ -2826,8 +2916,7 @@ static int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo) | |||
| 2826 | 2916 | ||
| 2827 | status = verify_attr_len(xdr, savep, attrlen); | 2917 | status = verify_attr_len(xdr, savep, attrlen); |
| 2828 | xdr_error: | 2918 | xdr_error: |
| 2829 | if (status != 0) | 2919 | dprintk("%s: xdr returned %d!\n", __FUNCTION__, -status); |
| 2830 | printk(KERN_NOTICE "%s: xdr error %d!\n", __FUNCTION__, -status); | ||
| 2831 | return status; | 2920 | return status; |
| 2832 | } | 2921 | } |
| 2833 | 2922 | ||
| @@ -2890,8 +2979,8 @@ static int decode_lock(struct xdr_stream *xdr, struct nfs_lockres *res) | |||
| 2890 | 2979 | ||
| 2891 | status = decode_op_hdr(xdr, OP_LOCK); | 2980 | status = decode_op_hdr(xdr, OP_LOCK); |
| 2892 | if (status == 0) { | 2981 | if (status == 0) { |
| 2893 | READ_BUF(sizeof(nfs4_stateid)); | 2982 | READ_BUF(sizeof(res->u.stateid.data)); |
| 2894 | COPYMEM(&res->u.stateid, sizeof(res->u.stateid)); | 2983 | COPYMEM(res->u.stateid.data, sizeof(res->u.stateid.data)); |
| 2895 | } else if (status == -NFS4ERR_DENIED) | 2984 | } else if (status == -NFS4ERR_DENIED) |
| 2896 | return decode_lock_denied(xdr, &res->u.denied); | 2985 | return decode_lock_denied(xdr, &res->u.denied); |
| 2897 | return status; | 2986 | return status; |
| @@ -2913,8 +3002,8 @@ static int decode_locku(struct xdr_stream *xdr, struct nfs_lockres *res) | |||
| 2913 | 3002 | ||
| 2914 | status = decode_op_hdr(xdr, OP_LOCKU); | 3003 | status = decode_op_hdr(xdr, OP_LOCKU); |
| 2915 | if (status == 0) { | 3004 | if (status == 0) { |
| 2916 | READ_BUF(sizeof(nfs4_stateid)); | 3005 | READ_BUF(sizeof(res->u.stateid.data)); |
| 2917 | COPYMEM(&res->u.stateid, sizeof(res->u.stateid)); | 3006 | COPYMEM(res->u.stateid.data, sizeof(res->u.stateid.data)); |
| 2918 | } | 3007 | } |
| 2919 | return status; | 3008 | return status; |
| 2920 | } | 3009 | } |
| @@ -2994,7 +3083,7 @@ static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res) | |||
| 2994 | p += bmlen; | 3083 | p += bmlen; |
| 2995 | return decode_delegation(xdr, res); | 3084 | return decode_delegation(xdr, res); |
| 2996 | xdr_error: | 3085 | xdr_error: |
| 2997 | printk(KERN_NOTICE "%s: xdr error!\n", __FUNCTION__); | 3086 | dprintk("%s: Bitmap too large! Length = %u\n", __FUNCTION__, bmlen); |
| 2998 | return -EIO; | 3087 | return -EIO; |
| 2999 | } | 3088 | } |
| 3000 | 3089 | ||
| @@ -3208,6 +3297,12 @@ static int decode_renew(struct xdr_stream *xdr) | |||
| 3208 | return decode_op_hdr(xdr, OP_RENEW); | 3297 | return decode_op_hdr(xdr, OP_RENEW); |
| 3209 | } | 3298 | } |
| 3210 | 3299 | ||
| 3300 | static int | ||
| 3301 | decode_restorefh(struct xdr_stream *xdr) | ||
| 3302 | { | ||
| 3303 | return decode_op_hdr(xdr, OP_RESTOREFH); | ||
| 3304 | } | ||
| 3305 | |||
| 3211 | static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, | 3306 | static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, |
| 3212 | size_t *acl_len) | 3307 | size_t *acl_len) |
| 3213 | { | 3308 | { |
| @@ -3243,7 +3338,8 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, | |||
| 3243 | if (attrlen <= *acl_len) | 3338 | if (attrlen <= *acl_len) |
| 3244 | xdr_read_pages(xdr, attrlen); | 3339 | xdr_read_pages(xdr, attrlen); |
| 3245 | *acl_len = attrlen; | 3340 | *acl_len = attrlen; |
| 3246 | } | 3341 | } else |
| 3342 | status = -EOPNOTSUPP; | ||
| 3247 | 3343 | ||
| 3248 | out: | 3344 | out: |
| 3249 | return status; | 3345 | return status; |
| @@ -3352,6 +3448,9 @@ static int nfs4_xdr_dec_open_downgrade(struct rpc_rqst *rqstp, uint32_t *p, stru | |||
| 3352 | if (status) | 3448 | if (status) |
| 3353 | goto out; | 3449 | goto out; |
| 3354 | status = decode_open_downgrade(&xdr, res); | 3450 | status = decode_open_downgrade(&xdr, res); |
| 3451 | if (status != 0) | ||
| 3452 | goto out; | ||
| 3453 | decode_getfattr(&xdr, res->fattr, res->server); | ||
| 3355 | out: | 3454 | out: |
| 3356 | return status; | 3455 | return status; |
| 3357 | } | 3456 | } |
| @@ -3424,7 +3523,7 @@ out: | |||
| 3424 | /* | 3523 | /* |
| 3425 | * Decode REMOVE response | 3524 | * Decode REMOVE response |
| 3426 | */ | 3525 | */ |
| 3427 | static int nfs4_xdr_dec_remove(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_change_info *cinfo) | 3526 | static int nfs4_xdr_dec_remove(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_remove_res *res) |
| 3428 | { | 3527 | { |
| 3429 | struct xdr_stream xdr; | 3528 | struct xdr_stream xdr; |
| 3430 | struct compound_hdr hdr; | 3529 | struct compound_hdr hdr; |
| @@ -3433,8 +3532,11 @@ static int nfs4_xdr_dec_remove(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_ | |||
| 3433 | xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p); | 3532 | xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p); |
| 3434 | if ((status = decode_compound_hdr(&xdr, &hdr)) != 0) | 3533 | if ((status = decode_compound_hdr(&xdr, &hdr)) != 0) |
| 3435 | goto out; | 3534 | goto out; |
| 3436 | if ((status = decode_putfh(&xdr)) == 0) | 3535 | if ((status = decode_putfh(&xdr)) != 0) |
| 3437 | status = decode_remove(&xdr, cinfo); | 3536 | goto out; |
| 3537 | if ((status = decode_remove(&xdr, &res->cinfo)) != 0) | ||
| 3538 | goto out; | ||
| 3539 | decode_getfattr(&xdr, res->dir_attr, res->server); | ||
| 3438 | out: | 3540 | out: |
| 3439 | return status; | 3541 | return status; |
| 3440 | } | 3542 | } |
| @@ -3457,7 +3559,14 @@ static int nfs4_xdr_dec_rename(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_ | |||
| 3457 | goto out; | 3559 | goto out; |
| 3458 | if ((status = decode_putfh(&xdr)) != 0) | 3560 | if ((status = decode_putfh(&xdr)) != 0) |
| 3459 | goto out; | 3561 | goto out; |
| 3460 | status = decode_rename(&xdr, &res->old_cinfo, &res->new_cinfo); | 3562 | if ((status = decode_rename(&xdr, &res->old_cinfo, &res->new_cinfo)) != 0) |
| 3563 | goto out; | ||
| 3564 | /* Current FH is target directory */ | ||
| 3565 | if (decode_getfattr(&xdr, res->new_fattr, res->server) != 0) | ||
| 3566 | goto out; | ||
| 3567 | if ((status = decode_restorefh(&xdr)) != 0) | ||
| 3568 | goto out; | ||
| 3569 | decode_getfattr(&xdr, res->old_fattr, res->server); | ||
| 3461 | out: | 3570 | out: |
| 3462 | return status; | 3571 | return status; |
| 3463 | } | 3572 | } |
| @@ -3465,7 +3574,7 @@ out: | |||
| 3465 | /* | 3574 | /* |
| 3466 | * Decode LINK response | 3575 | * Decode LINK response |
| 3467 | */ | 3576 | */ |
| 3468 | static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_change_info *cinfo) | 3577 | static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_link_res *res) |
| 3469 | { | 3578 | { |
| 3470 | struct xdr_stream xdr; | 3579 | struct xdr_stream xdr; |
| 3471 | struct compound_hdr hdr; | 3580 | struct compound_hdr hdr; |
| @@ -3480,7 +3589,17 @@ static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_ch | |||
| 3480 | goto out; | 3589 | goto out; |
| 3481 | if ((status = decode_putfh(&xdr)) != 0) | 3590 | if ((status = decode_putfh(&xdr)) != 0) |
| 3482 | goto out; | 3591 | goto out; |
| 3483 | status = decode_link(&xdr, cinfo); | 3592 | if ((status = decode_link(&xdr, &res->cinfo)) != 0) |
| 3593 | goto out; | ||
| 3594 | /* | ||
| 3595 | * Note order: OP_LINK leaves the directory as the current | ||
| 3596 | * filehandle. | ||
| 3597 | */ | ||
| 3598 | if (decode_getfattr(&xdr, res->dir_attr, res->server) != 0) | ||
| 3599 | goto out; | ||
| 3600 | if ((status = decode_restorefh(&xdr)) != 0) | ||
| 3601 | goto out; | ||
| 3602 | decode_getfattr(&xdr, res->fattr, res->server); | ||
| 3484 | out: | 3603 | out: |
| 3485 | return status; | 3604 | return status; |
| 3486 | } | 3605 | } |
| @@ -3499,13 +3618,17 @@ static int nfs4_xdr_dec_create(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_ | |||
| 3499 | goto out; | 3618 | goto out; |
| 3500 | if ((status = decode_putfh(&xdr)) != 0) | 3619 | if ((status = decode_putfh(&xdr)) != 0) |
| 3501 | goto out; | 3620 | goto out; |
| 3621 | if ((status = decode_savefh(&xdr)) != 0) | ||
| 3622 | goto out; | ||
| 3502 | if ((status = decode_create(&xdr,&res->dir_cinfo)) != 0) | 3623 | if ((status = decode_create(&xdr,&res->dir_cinfo)) != 0) |
| 3503 | goto out; | 3624 | goto out; |
| 3504 | if ((status = decode_getfh(&xdr, res->fh)) != 0) | 3625 | if ((status = decode_getfh(&xdr, res->fh)) != 0) |
| 3505 | goto out; | 3626 | goto out; |
| 3506 | status = decode_getfattr(&xdr, res->fattr, res->server); | 3627 | if (decode_getfattr(&xdr, res->fattr, res->server) != 0) |
| 3507 | if (status == NFS4ERR_DELAY) | 3628 | goto out; |
| 3508 | status = 0; | 3629 | if ((status = decode_restorefh(&xdr)) != 0) |
| 3630 | goto out; | ||
| 3631 | decode_getfattr(&xdr, res->dir_fattr, res->server); | ||
| 3509 | out: | 3632 | out: |
| 3510 | return status; | 3633 | return status; |
| 3511 | } | 3634 | } |
| @@ -3623,6 +3746,15 @@ static int nfs4_xdr_dec_close(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_cl | |||
| 3623 | if (status) | 3746 | if (status) |
| 3624 | goto out; | 3747 | goto out; |
| 3625 | status = decode_close(&xdr, res); | 3748 | status = decode_close(&xdr, res); |
| 3749 | if (status != 0) | ||
| 3750 | goto out; | ||
| 3751 | /* | ||
| 3752 | * Note: Server may do delete on close for this file | ||
| 3753 | * in which case the getattr call will fail with | ||
| 3754 | * an ESTALE error. Shouldn't be a problem, | ||
| 3755 | * though, since fattr->valid will remain unset. | ||
| 3756 | */ | ||
| 3757 | decode_getfattr(&xdr, res->fattr, res->server); | ||
| 3626 | out: | 3758 | out: |
| 3627 | return status; | 3759 | return status; |
| 3628 | } | 3760 | } |
| @@ -3643,15 +3775,20 @@ static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_ope | |||
| 3643 | status = decode_putfh(&xdr); | 3775 | status = decode_putfh(&xdr); |
| 3644 | if (status) | 3776 | if (status) |
| 3645 | goto out; | 3777 | goto out; |
| 3778 | status = decode_savefh(&xdr); | ||
| 3779 | if (status) | ||
| 3780 | goto out; | ||
| 3646 | status = decode_open(&xdr, res); | 3781 | status = decode_open(&xdr, res); |
| 3647 | if (status) | 3782 | if (status) |
| 3648 | goto out; | 3783 | goto out; |
| 3649 | status = decode_getfh(&xdr, &res->fh); | 3784 | status = decode_getfh(&xdr, &res->fh); |
| 3650 | if (status) | 3785 | if (status) |
| 3651 | goto out; | 3786 | goto out; |
| 3652 | status = decode_getfattr(&xdr, res->f_attr, res->server); | 3787 | if (decode_getfattr(&xdr, res->f_attr, res->server) != 0) |
| 3653 | if (status == NFS4ERR_DELAY) | 3788 | goto out; |
| 3654 | status = 0; | 3789 | if ((status = decode_restorefh(&xdr)) != 0) |
| 3790 | goto out; | ||
| 3791 | decode_getfattr(&xdr, res->dir_attr, res->server); | ||
| 3655 | out: | 3792 | out: |
| 3656 | return status; | 3793 | return status; |
| 3657 | } | 3794 | } |
| @@ -3869,6 +4006,9 @@ static int nfs4_xdr_dec_write(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_wr | |||
| 3869 | if (status) | 4006 | if (status) |
| 3870 | goto out; | 4007 | goto out; |
| 3871 | status = decode_write(&xdr, res); | 4008 | status = decode_write(&xdr, res); |
| 4009 | if (status) | ||
| 4010 | goto out; | ||
| 4011 | decode_getfattr(&xdr, res->fattr, res->server); | ||
| 3872 | if (!status) | 4012 | if (!status) |
| 3873 | status = res->count; | 4013 | status = res->count; |
| 3874 | out: | 4014 | out: |
| @@ -3892,6 +4032,9 @@ static int nfs4_xdr_dec_commit(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_w | |||
| 3892 | if (status) | 4032 | if (status) |
| 3893 | goto out; | 4033 | goto out; |
| 3894 | status = decode_commit(&xdr, res); | 4034 | status = decode_commit(&xdr, res); |
| 4035 | if (status) | ||
| 4036 | goto out; | ||
| 4037 | decode_getfattr(&xdr, res->fattr, res->server); | ||
| 3895 | out: | 4038 | out: |
| 3896 | return status; | 4039 | return status; |
| 3897 | } | 4040 | } |
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index be23c3fb9260..a48a003242c0 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c | |||
| @@ -61,7 +61,7 @@ nfs_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, | |||
| 61 | int status; | 61 | int status; |
| 62 | 62 | ||
| 63 | dprintk("%s: call getattr\n", __FUNCTION__); | 63 | dprintk("%s: call getattr\n", __FUNCTION__); |
| 64 | fattr->valid = 0; | 64 | nfs_fattr_init(fattr); |
| 65 | status = rpc_call(server->client_sys, NFSPROC_GETATTR, fhandle, fattr, 0); | 65 | status = rpc_call(server->client_sys, NFSPROC_GETATTR, fhandle, fattr, 0); |
| 66 | dprintk("%s: reply getattr: %d\n", __FUNCTION__, status); | 66 | dprintk("%s: reply getattr: %d\n", __FUNCTION__, status); |
| 67 | if (status) | 67 | if (status) |
| @@ -93,7 +93,7 @@ nfs_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, | |||
| 93 | int status; | 93 | int status; |
| 94 | 94 | ||
| 95 | dprintk("NFS call getattr\n"); | 95 | dprintk("NFS call getattr\n"); |
| 96 | fattr->valid = 0; | 96 | nfs_fattr_init(fattr); |
| 97 | status = rpc_call(server->client, NFSPROC_GETATTR, | 97 | status = rpc_call(server->client, NFSPROC_GETATTR, |
| 98 | fhandle, fattr, 0); | 98 | fhandle, fattr, 0); |
| 99 | dprintk("NFS reply getattr: %d\n", status); | 99 | dprintk("NFS reply getattr: %d\n", status); |
| @@ -112,7 +112,7 @@ nfs_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, | |||
| 112 | int status; | 112 | int status; |
| 113 | 113 | ||
| 114 | dprintk("NFS call setattr\n"); | 114 | dprintk("NFS call setattr\n"); |
| 115 | fattr->valid = 0; | 115 | nfs_fattr_init(fattr); |
| 116 | status = rpc_call(NFS_CLIENT(inode), NFSPROC_SETATTR, &arg, fattr, 0); | 116 | status = rpc_call(NFS_CLIENT(inode), NFSPROC_SETATTR, &arg, fattr, 0); |
| 117 | if (status == 0) | 117 | if (status == 0) |
| 118 | nfs_setattr_update_inode(inode, sattr); | 118 | nfs_setattr_update_inode(inode, sattr); |
| @@ -136,7 +136,7 @@ nfs_proc_lookup(struct inode *dir, struct qstr *name, | |||
| 136 | int status; | 136 | int status; |
| 137 | 137 | ||
| 138 | dprintk("NFS call lookup %s\n", name->name); | 138 | dprintk("NFS call lookup %s\n", name->name); |
| 139 | fattr->valid = 0; | 139 | nfs_fattr_init(fattr); |
| 140 | status = rpc_call(NFS_CLIENT(dir), NFSPROC_LOOKUP, &arg, &res, 0); | 140 | status = rpc_call(NFS_CLIENT(dir), NFSPROC_LOOKUP, &arg, &res, 0); |
| 141 | dprintk("NFS reply lookup: %d\n", status); | 141 | dprintk("NFS reply lookup: %d\n", status); |
| 142 | return status; | 142 | return status; |
| @@ -174,7 +174,7 @@ static int nfs_proc_read(struct nfs_read_data *rdata) | |||
| 174 | 174 | ||
| 175 | dprintk("NFS call read %d @ %Ld\n", rdata->args.count, | 175 | dprintk("NFS call read %d @ %Ld\n", rdata->args.count, |
| 176 | (long long) rdata->args.offset); | 176 | (long long) rdata->args.offset); |
| 177 | fattr->valid = 0; | 177 | nfs_fattr_init(fattr); |
| 178 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags); | 178 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags); |
| 179 | if (status >= 0) { | 179 | if (status >= 0) { |
| 180 | nfs_refresh_inode(inode, fattr); | 180 | nfs_refresh_inode(inode, fattr); |
| @@ -203,10 +203,10 @@ static int nfs_proc_write(struct nfs_write_data *wdata) | |||
| 203 | 203 | ||
| 204 | dprintk("NFS call write %d @ %Ld\n", wdata->args.count, | 204 | dprintk("NFS call write %d @ %Ld\n", wdata->args.count, |
| 205 | (long long) wdata->args.offset); | 205 | (long long) wdata->args.offset); |
| 206 | fattr->valid = 0; | 206 | nfs_fattr_init(fattr); |
| 207 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags); | 207 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, flags); |
| 208 | if (status >= 0) { | 208 | if (status >= 0) { |
| 209 | nfs_refresh_inode(inode, fattr); | 209 | nfs_post_op_update_inode(inode, fattr); |
| 210 | wdata->res.count = wdata->args.count; | 210 | wdata->res.count = wdata->args.count; |
| 211 | wdata->verf.committed = NFS_FILE_SYNC; | 211 | wdata->verf.committed = NFS_FILE_SYNC; |
| 212 | } | 212 | } |
| @@ -216,7 +216,7 @@ static int nfs_proc_write(struct nfs_write_data *wdata) | |||
| 216 | 216 | ||
| 217 | static int | 217 | static int |
| 218 | nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | 218 | nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, |
| 219 | int flags) | 219 | int flags, struct nameidata *nd) |
| 220 | { | 220 | { |
| 221 | struct nfs_fh fhandle; | 221 | struct nfs_fh fhandle; |
| 222 | struct nfs_fattr fattr; | 222 | struct nfs_fattr fattr; |
| @@ -232,7 +232,7 @@ nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | |||
| 232 | }; | 232 | }; |
| 233 | int status; | 233 | int status; |
| 234 | 234 | ||
| 235 | fattr.valid = 0; | 235 | nfs_fattr_init(&fattr); |
| 236 | dprintk("NFS call create %s\n", dentry->d_name.name); | 236 | dprintk("NFS call create %s\n", dentry->d_name.name); |
| 237 | status = rpc_call(NFS_CLIENT(dir), NFSPROC_CREATE, &arg, &res, 0); | 237 | status = rpc_call(NFS_CLIENT(dir), NFSPROC_CREATE, &arg, &res, 0); |
| 238 | if (status == 0) | 238 | if (status == 0) |
| @@ -273,12 +273,13 @@ nfs_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | |||
| 273 | sattr->ia_size = new_encode_dev(rdev);/* get out your barf bag */ | 273 | sattr->ia_size = new_encode_dev(rdev);/* get out your barf bag */ |
| 274 | } | 274 | } |
| 275 | 275 | ||
| 276 | fattr.valid = 0; | 276 | nfs_fattr_init(&fattr); |
| 277 | status = rpc_call(NFS_CLIENT(dir), NFSPROC_CREATE, &arg, &res, 0); | 277 | status = rpc_call(NFS_CLIENT(dir), NFSPROC_CREATE, &arg, &res, 0); |
| 278 | nfs_mark_for_revalidate(dir); | ||
| 278 | 279 | ||
| 279 | if (status == -EINVAL && S_ISFIFO(mode)) { | 280 | if (status == -EINVAL && S_ISFIFO(mode)) { |
| 280 | sattr->ia_mode = mode; | 281 | sattr->ia_mode = mode; |
| 281 | fattr.valid = 0; | 282 | nfs_fattr_init(&fattr); |
| 282 | status = rpc_call(NFS_CLIENT(dir), NFSPROC_CREATE, &arg, &res, 0); | 283 | status = rpc_call(NFS_CLIENT(dir), NFSPROC_CREATE, &arg, &res, 0); |
| 283 | } | 284 | } |
| 284 | if (status == 0) | 285 | if (status == 0) |
| @@ -305,6 +306,7 @@ nfs_proc_remove(struct inode *dir, struct qstr *name) | |||
| 305 | 306 | ||
| 306 | dprintk("NFS call remove %s\n", name->name); | 307 | dprintk("NFS call remove %s\n", name->name); |
| 307 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 308 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
| 309 | nfs_mark_for_revalidate(dir); | ||
| 308 | 310 | ||
| 309 | dprintk("NFS reply remove: %d\n", status); | 311 | dprintk("NFS reply remove: %d\n", status); |
| 310 | return status; | 312 | return status; |
| @@ -331,8 +333,10 @@ nfs_proc_unlink_done(struct dentry *dir, struct rpc_task *task) | |||
| 331 | { | 333 | { |
| 332 | struct rpc_message *msg = &task->tk_msg; | 334 | struct rpc_message *msg = &task->tk_msg; |
| 333 | 335 | ||
| 334 | if (msg->rpc_argp) | 336 | if (msg->rpc_argp) { |
| 337 | nfs_mark_for_revalidate(dir->d_inode); | ||
| 335 | kfree(msg->rpc_argp); | 338 | kfree(msg->rpc_argp); |
| 339 | } | ||
| 336 | return 0; | 340 | return 0; |
| 337 | } | 341 | } |
| 338 | 342 | ||
| @@ -352,6 +356,8 @@ nfs_proc_rename(struct inode *old_dir, struct qstr *old_name, | |||
| 352 | 356 | ||
| 353 | dprintk("NFS call rename %s -> %s\n", old_name->name, new_name->name); | 357 | dprintk("NFS call rename %s -> %s\n", old_name->name, new_name->name); |
| 354 | status = rpc_call(NFS_CLIENT(old_dir), NFSPROC_RENAME, &arg, NULL, 0); | 358 | status = rpc_call(NFS_CLIENT(old_dir), NFSPROC_RENAME, &arg, NULL, 0); |
| 359 | nfs_mark_for_revalidate(old_dir); | ||
| 360 | nfs_mark_for_revalidate(new_dir); | ||
| 355 | dprintk("NFS reply rename: %d\n", status); | 361 | dprintk("NFS reply rename: %d\n", status); |
| 356 | return status; | 362 | return status; |
| 357 | } | 363 | } |
| @@ -369,6 +375,7 @@ nfs_proc_link(struct inode *inode, struct inode *dir, struct qstr *name) | |||
| 369 | 375 | ||
| 370 | dprintk("NFS call link %s\n", name->name); | 376 | dprintk("NFS call link %s\n", name->name); |
| 371 | status = rpc_call(NFS_CLIENT(inode), NFSPROC_LINK, &arg, NULL, 0); | 377 | status = rpc_call(NFS_CLIENT(inode), NFSPROC_LINK, &arg, NULL, 0); |
| 378 | nfs_mark_for_revalidate(dir); | ||
| 372 | dprintk("NFS reply link: %d\n", status); | 379 | dprintk("NFS reply link: %d\n", status); |
| 373 | return status; | 380 | return status; |
| 374 | } | 381 | } |
| @@ -391,9 +398,10 @@ nfs_proc_symlink(struct inode *dir, struct qstr *name, struct qstr *path, | |||
| 391 | if (path->len > NFS2_MAXPATHLEN) | 398 | if (path->len > NFS2_MAXPATHLEN) |
| 392 | return -ENAMETOOLONG; | 399 | return -ENAMETOOLONG; |
| 393 | dprintk("NFS call symlink %s -> %s\n", name->name, path->name); | 400 | dprintk("NFS call symlink %s -> %s\n", name->name, path->name); |
| 394 | fattr->valid = 0; | 401 | nfs_fattr_init(fattr); |
| 395 | fhandle->size = 0; | 402 | fhandle->size = 0; |
| 396 | status = rpc_call(NFS_CLIENT(dir), NFSPROC_SYMLINK, &arg, NULL, 0); | 403 | status = rpc_call(NFS_CLIENT(dir), NFSPROC_SYMLINK, &arg, NULL, 0); |
| 404 | nfs_mark_for_revalidate(dir); | ||
| 397 | dprintk("NFS reply symlink: %d\n", status); | 405 | dprintk("NFS reply symlink: %d\n", status); |
| 398 | return status; | 406 | return status; |
| 399 | } | 407 | } |
| @@ -416,8 +424,9 @@ nfs_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr) | |||
| 416 | int status; | 424 | int status; |
| 417 | 425 | ||
| 418 | dprintk("NFS call mkdir %s\n", dentry->d_name.name); | 426 | dprintk("NFS call mkdir %s\n", dentry->d_name.name); |
| 419 | fattr.valid = 0; | 427 | nfs_fattr_init(&fattr); |
| 420 | status = rpc_call(NFS_CLIENT(dir), NFSPROC_MKDIR, &arg, &res, 0); | 428 | status = rpc_call(NFS_CLIENT(dir), NFSPROC_MKDIR, &arg, &res, 0); |
| 429 | nfs_mark_for_revalidate(dir); | ||
| 421 | if (status == 0) | 430 | if (status == 0) |
| 422 | status = nfs_instantiate(dentry, &fhandle, &fattr); | 431 | status = nfs_instantiate(dentry, &fhandle, &fattr); |
| 423 | dprintk("NFS reply mkdir: %d\n", status); | 432 | dprintk("NFS reply mkdir: %d\n", status); |
| @@ -436,6 +445,7 @@ nfs_proc_rmdir(struct inode *dir, struct qstr *name) | |||
| 436 | 445 | ||
| 437 | dprintk("NFS call rmdir %s\n", name->name); | 446 | dprintk("NFS call rmdir %s\n", name->name); |
| 438 | status = rpc_call(NFS_CLIENT(dir), NFSPROC_RMDIR, &arg, NULL, 0); | 447 | status = rpc_call(NFS_CLIENT(dir), NFSPROC_RMDIR, &arg, NULL, 0); |
| 448 | nfs_mark_for_revalidate(dir); | ||
| 439 | dprintk("NFS reply rmdir: %d\n", status); | 449 | dprintk("NFS reply rmdir: %d\n", status); |
| 440 | return status; | 450 | return status; |
| 441 | } | 451 | } |
| @@ -484,7 +494,7 @@ nfs_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, | |||
| 484 | int status; | 494 | int status; |
| 485 | 495 | ||
| 486 | dprintk("NFS call statfs\n"); | 496 | dprintk("NFS call statfs\n"); |
| 487 | stat->fattr->valid = 0; | 497 | nfs_fattr_init(stat->fattr); |
| 488 | status = rpc_call(server->client, NFSPROC_STATFS, fhandle, &fsinfo, 0); | 498 | status = rpc_call(server->client, NFSPROC_STATFS, fhandle, &fsinfo, 0); |
| 489 | dprintk("NFS reply statfs: %d\n", status); | 499 | dprintk("NFS reply statfs: %d\n", status); |
| 490 | if (status) | 500 | if (status) |
| @@ -507,7 +517,7 @@ nfs_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, | |||
| 507 | int status; | 517 | int status; |
| 508 | 518 | ||
| 509 | dprintk("NFS call fsinfo\n"); | 519 | dprintk("NFS call fsinfo\n"); |
| 510 | info->fattr->valid = 0; | 520 | nfs_fattr_init(info->fattr); |
| 511 | status = rpc_call(server->client, NFSPROC_STATFS, fhandle, &fsinfo, 0); | 521 | status = rpc_call(server->client, NFSPROC_STATFS, fhandle, &fsinfo, 0); |
| 512 | dprintk("NFS reply fsinfo: %d\n", status); | 522 | dprintk("NFS reply fsinfo: %d\n", status); |
| 513 | if (status) | 523 | if (status) |
| @@ -579,7 +589,7 @@ nfs_write_done(struct rpc_task *task) | |||
| 579 | struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata; | 589 | struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata; |
| 580 | 590 | ||
| 581 | if (task->tk_status >= 0) | 591 | if (task->tk_status >= 0) |
| 582 | nfs_refresh_inode(data->inode, data->res.fattr); | 592 | nfs_post_op_update_inode(data->inode, data->res.fattr); |
| 583 | nfs_writeback_done(task); | 593 | nfs_writeback_done(task); |
| 584 | } | 594 | } |
| 585 | 595 | ||
diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 9758ebd49905..43b03b19731b 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c | |||
| @@ -215,6 +215,7 @@ static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data, | |||
| 215 | data->res.fattr = &data->fattr; | 215 | data->res.fattr = &data->fattr; |
| 216 | data->res.count = count; | 216 | data->res.count = count; |
| 217 | data->res.eof = 0; | 217 | data->res.eof = 0; |
| 218 | nfs_fattr_init(&data->fattr); | ||
| 218 | 219 | ||
| 219 | NFS_PROTO(inode)->read_setup(data); | 220 | NFS_PROTO(inode)->read_setup(data); |
| 220 | 221 | ||
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 5130eda231d7..819a65f5071f 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
| @@ -870,6 +870,7 @@ static void nfs_write_rpcsetup(struct nfs_page *req, | |||
| 870 | data->res.fattr = &data->fattr; | 870 | data->res.fattr = &data->fattr; |
| 871 | data->res.count = count; | 871 | data->res.count = count; |
| 872 | data->res.verf = &data->verf; | 872 | data->res.verf = &data->verf; |
| 873 | nfs_fattr_init(&data->fattr); | ||
| 873 | 874 | ||
| 874 | NFS_PROTO(inode)->write_setup(data, how); | 875 | NFS_PROTO(inode)->write_setup(data, how); |
| 875 | 876 | ||
| @@ -1237,6 +1238,7 @@ static void nfs_commit_rpcsetup(struct list_head *head, | |||
| 1237 | data->res.count = 0; | 1238 | data->res.count = 0; |
| 1238 | data->res.fattr = &data->fattr; | 1239 | data->res.fattr = &data->fattr; |
| 1239 | data->res.verf = &data->verf; | 1240 | data->res.verf = &data->verf; |
| 1241 | nfs_fattr_init(&data->fattr); | ||
| 1240 | 1242 | ||
| 1241 | NFS_PROTO(inode)->commit_setup(data, how); | 1243 | NFS_PROTO(inode)->commit_setup(data, how); |
| 1242 | 1244 | ||
