diff options
-rw-r--r-- | fs/nfs/nfs4proc.c | 28 | ||||
-rw-r--r-- | fs/nfs/nfs4xdr.c | 69 | ||||
-rw-r--r-- | include/linux/nfs_xdr.h | 2 |
3 files changed, 84 insertions, 15 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 3274f2d354f3..f363fd6c7f4d 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -443,7 +443,11 @@ static int _nfs4_proc_open(struct inode *dir, struct nfs4_state_owner *sp, stru | |||
443 | nfs_increment_open_seqid(status, o_arg->seqid); | 443 | nfs_increment_open_seqid(status, o_arg->seqid); |
444 | if (status != 0) | 444 | if (status != 0) |
445 | goto out; | 445 | goto out; |
446 | 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); | ||
447 | if(o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) { | 451 | if(o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) { |
448 | status = _nfs4_proc_open_confirm(server->client, &o_res->fh, | 452 | status = _nfs4_proc_open_confirm(server->client, &o_res->fh, |
449 | sp, &o_res->stateid, o_arg->seqid); | 453 | sp, &o_res->stateid, o_arg->seqid); |
@@ -497,7 +501,7 @@ static int _nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *st | |||
497 | struct inode *inode = state->inode; | 501 | struct inode *inode = state->inode; |
498 | struct nfs_server *server = NFS_SERVER(dir); | 502 | struct nfs_server *server = NFS_SERVER(dir); |
499 | struct nfs_delegation *delegation = NFS_I(inode)->delegation; | 503 | struct nfs_delegation *delegation = NFS_I(inode)->delegation; |
500 | struct nfs_fattr f_attr; | 504 | struct nfs_fattr f_attr, dir_attr; |
501 | struct nfs_openargs o_arg = { | 505 | struct nfs_openargs o_arg = { |
502 | .fh = NFS_FH(dir), | 506 | .fh = NFS_FH(dir), |
503 | .open_flags = state->state, | 507 | .open_flags = state->state, |
@@ -507,6 +511,7 @@ static int _nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *st | |||
507 | }; | 511 | }; |
508 | struct nfs_openres o_res = { | 512 | struct nfs_openres o_res = { |
509 | .f_attr = &f_attr, | 513 | .f_attr = &f_attr, |
514 | .dir_attr = &dir_attr, | ||
510 | .server = server, | 515 | .server = server, |
511 | }; | 516 | }; |
512 | int status = 0; | 517 | int status = 0; |
@@ -524,6 +529,7 @@ static int _nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *st | |||
524 | if (o_arg.seqid == NULL) | 529 | if (o_arg.seqid == NULL) |
525 | goto out; | 530 | goto out; |
526 | nfs_fattr_init(&f_attr); | 531 | nfs_fattr_init(&f_attr); |
532 | nfs_fattr_init(&dir_attr); | ||
527 | status = _nfs4_proc_open(dir, sp, &o_arg, &o_res); | 533 | status = _nfs4_proc_open(dir, sp, &o_arg, &o_res); |
528 | if (status != 0) | 534 | if (status != 0) |
529 | goto out_nodeleg; | 535 | goto out_nodeleg; |
@@ -694,7 +700,7 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, st | |||
694 | struct nfs4_client *clp = server->nfs4_state; | 700 | struct nfs4_client *clp = server->nfs4_state; |
695 | struct inode *inode = NULL; | 701 | struct inode *inode = NULL; |
696 | int status; | 702 | int status; |
697 | struct nfs_fattr f_attr; | 703 | struct nfs_fattr f_attr, dir_attr; |
698 | struct nfs_openargs o_arg = { | 704 | struct nfs_openargs o_arg = { |
699 | .fh = NFS_FH(dir), | 705 | .fh = NFS_FH(dir), |
700 | .open_flags = flags, | 706 | .open_flags = flags, |
@@ -705,6 +711,7 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, st | |||
705 | }; | 711 | }; |
706 | struct nfs_openres o_res = { | 712 | struct nfs_openres o_res = { |
707 | .f_attr = &f_attr, | 713 | .f_attr = &f_attr, |
714 | .dir_attr = &dir_attr, | ||
708 | .server = server, | 715 | .server = server, |
709 | }; | 716 | }; |
710 | 717 | ||
@@ -727,6 +734,7 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, st | |||
727 | if (o_arg.seqid == NULL) | 734 | if (o_arg.seqid == NULL) |
728 | return -ENOMEM; | 735 | return -ENOMEM; |
729 | nfs_fattr_init(&f_attr); | 736 | nfs_fattr_init(&f_attr); |
737 | nfs_fattr_init(&dir_attr); | ||
730 | status = _nfs4_proc_open(dir, sp, &o_arg, &o_res); | 738 | status = _nfs4_proc_open(dir, sp, &o_arg, &o_res); |
731 | if (status != 0) | 739 | if (status != 0) |
732 | goto out_err; | 740 | goto out_err; |
@@ -1746,6 +1754,7 @@ static int _nfs4_proc_symlink(struct inode *dir, struct qstr *name, | |||
1746 | struct nfs_fattr *fattr) | 1754 | struct nfs_fattr *fattr) |
1747 | { | 1755 | { |
1748 | struct nfs_server *server = NFS_SERVER(dir); | 1756 | struct nfs_server *server = NFS_SERVER(dir); |
1757 | struct nfs_fattr dir_fattr; | ||
1749 | struct nfs4_create_arg arg = { | 1758 | struct nfs4_create_arg arg = { |
1750 | .dir_fh = NFS_FH(dir), | 1759 | .dir_fh = NFS_FH(dir), |
1751 | .server = server, | 1760 | .server = server, |
@@ -1758,6 +1767,7 @@ static int _nfs4_proc_symlink(struct inode *dir, struct qstr *name, | |||
1758 | .server = server, | 1767 | .server = server, |
1759 | .fh = fhandle, | 1768 | .fh = fhandle, |
1760 | .fattr = fattr, | 1769 | .fattr = fattr, |
1770 | .dir_fattr = &dir_fattr, | ||
1761 | }; | 1771 | }; |
1762 | struct rpc_message msg = { | 1772 | struct rpc_message msg = { |
1763 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SYMLINK], | 1773 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SYMLINK], |
@@ -1770,10 +1780,12 @@ static int _nfs4_proc_symlink(struct inode *dir, struct qstr *name, | |||
1770 | return -ENAMETOOLONG; | 1780 | return -ENAMETOOLONG; |
1771 | arg.u.symlink = path; | 1781 | arg.u.symlink = path; |
1772 | nfs_fattr_init(fattr); | 1782 | nfs_fattr_init(fattr); |
1783 | nfs_fattr_init(&dir_fattr); | ||
1773 | 1784 | ||
1774 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 1785 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
1775 | if (!status) | 1786 | if (!status) |
1776 | update_changeattr(dir, &res.dir_cinfo); | 1787 | update_changeattr(dir, &res.dir_cinfo); |
1788 | nfs_post_op_update_inode(dir, res.dir_fattr); | ||
1777 | return status; | 1789 | return status; |
1778 | } | 1790 | } |
1779 | 1791 | ||
@@ -1797,7 +1809,7 @@ static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry, | |||
1797 | { | 1809 | { |
1798 | struct nfs_server *server = NFS_SERVER(dir); | 1810 | struct nfs_server *server = NFS_SERVER(dir); |
1799 | struct nfs_fh fhandle; | 1811 | struct nfs_fh fhandle; |
1800 | struct nfs_fattr fattr; | 1812 | struct nfs_fattr fattr, dir_fattr; |
1801 | struct nfs4_create_arg arg = { | 1813 | struct nfs4_create_arg arg = { |
1802 | .dir_fh = NFS_FH(dir), | 1814 | .dir_fh = NFS_FH(dir), |
1803 | .server = server, | 1815 | .server = server, |
@@ -1810,6 +1822,7 @@ static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry, | |||
1810 | .server = server, | 1822 | .server = server, |
1811 | .fh = &fhandle, | 1823 | .fh = &fhandle, |
1812 | .fattr = &fattr, | 1824 | .fattr = &fattr, |
1825 | .dir_fattr = &dir_fattr, | ||
1813 | }; | 1826 | }; |
1814 | struct rpc_message msg = { | 1827 | struct rpc_message msg = { |
1815 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE], | 1828 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE], |
@@ -1819,10 +1832,12 @@ static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry, | |||
1819 | int status; | 1832 | int status; |
1820 | 1833 | ||
1821 | nfs_fattr_init(&fattr); | 1834 | nfs_fattr_init(&fattr); |
1835 | nfs_fattr_init(&dir_fattr); | ||
1822 | 1836 | ||
1823 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 1837 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
1824 | if (!status) { | 1838 | if (!status) { |
1825 | update_changeattr(dir, &res.dir_cinfo); | 1839 | update_changeattr(dir, &res.dir_cinfo); |
1840 | nfs_post_op_update_inode(dir, res.dir_fattr); | ||
1826 | status = nfs_instantiate(dentry, &fhandle, &fattr); | 1841 | status = nfs_instantiate(dentry, &fhandle, &fattr); |
1827 | } | 1842 | } |
1828 | return status; | 1843 | return status; |
@@ -1895,7 +1910,7 @@ static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, | |||
1895 | { | 1910 | { |
1896 | struct nfs_server *server = NFS_SERVER(dir); | 1911 | struct nfs_server *server = NFS_SERVER(dir); |
1897 | struct nfs_fh fh; | 1912 | struct nfs_fh fh; |
1898 | struct nfs_fattr fattr; | 1913 | struct nfs_fattr fattr, dir_fattr; |
1899 | struct nfs4_create_arg arg = { | 1914 | struct nfs4_create_arg arg = { |
1900 | .dir_fh = NFS_FH(dir), | 1915 | .dir_fh = NFS_FH(dir), |
1901 | .server = server, | 1916 | .server = server, |
@@ -1907,6 +1922,7 @@ static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, | |||
1907 | .server = server, | 1922 | .server = server, |
1908 | .fh = &fh, | 1923 | .fh = &fh, |
1909 | .fattr = &fattr, | 1924 | .fattr = &fattr, |
1925 | .dir_fattr = &dir_fattr, | ||
1910 | }; | 1926 | }; |
1911 | struct rpc_message msg = { | 1927 | struct rpc_message msg = { |
1912 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE], | 1928 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE], |
@@ -1917,6 +1933,7 @@ static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, | |||
1917 | int mode = sattr->ia_mode; | 1933 | int mode = sattr->ia_mode; |
1918 | 1934 | ||
1919 | nfs_fattr_init(&fattr); | 1935 | nfs_fattr_init(&fattr); |
1936 | nfs_fattr_init(&dir_fattr); | ||
1920 | 1937 | ||
1921 | BUG_ON(!(sattr->ia_valid & ATTR_MODE)); | 1938 | BUG_ON(!(sattr->ia_valid & ATTR_MODE)); |
1922 | BUG_ON(!S_ISFIFO(mode) && !S_ISBLK(mode) && !S_ISCHR(mode) && !S_ISSOCK(mode)); | 1939 | BUG_ON(!S_ISFIFO(mode) && !S_ISBLK(mode) && !S_ISCHR(mode) && !S_ISSOCK(mode)); |
@@ -1938,6 +1955,7 @@ static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, | |||
1938 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 1955 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
1939 | if (status == 0) { | 1956 | if (status == 0) { |
1940 | update_changeattr(dir, &res.dir_cinfo); | 1957 | update_changeattr(dir, &res.dir_cinfo); |
1958 | nfs_post_op_update_inode(dir, res.dir_fattr); | ||
1941 | status = nfs_instantiate(dentry, &fh, &fattr); | 1959 | status = nfs_instantiate(dentry, &fh, &fattr); |
1942 | } | 1960 | } |
1943 | return status; | 1961 | return status; |
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 8b21de8a06fa..7f91d613d31a 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) |
@@ -336,14 +338,20 @@ static int nfs_stat_to_errno(int); | |||
336 | decode_getfh_maxsz) | 338 | decode_getfh_maxsz) |
337 | #define NFS4_enc_create_sz (compound_encode_hdr_maxsz + \ | 339 | #define NFS4_enc_create_sz (compound_encode_hdr_maxsz + \ |
338 | encode_putfh_maxsz + \ | 340 | encode_putfh_maxsz + \ |
341 | encode_savefh_maxsz + \ | ||
339 | encode_create_maxsz + \ | 342 | encode_create_maxsz + \ |
343 | encode_getfh_maxsz + \ | ||
340 | encode_getattr_maxsz + \ | 344 | encode_getattr_maxsz + \ |
341 | encode_getfh_maxsz) | 345 | encode_restorefh_maxsz + \ |
346 | encode_getattr_maxsz) | ||
342 | #define NFS4_dec_create_sz (compound_decode_hdr_maxsz + \ | 347 | #define NFS4_dec_create_sz (compound_decode_hdr_maxsz + \ |
343 | decode_putfh_maxsz + \ | 348 | decode_putfh_maxsz + \ |
349 | decode_savefh_maxsz + \ | ||
344 | decode_create_maxsz + \ | 350 | decode_create_maxsz + \ |
351 | decode_getfh_maxsz + \ | ||
345 | decode_getattr_maxsz + \ | 352 | decode_getattr_maxsz + \ |
346 | decode_getfh_maxsz) | 353 | decode_restorefh_maxsz + \ |
354 | decode_getattr_maxsz) | ||
347 | #define NFS4_enc_pathconf_sz (compound_encode_hdr_maxsz + \ | 355 | #define NFS4_enc_pathconf_sz (compound_encode_hdr_maxsz + \ |
348 | encode_putfh_maxsz + \ | 356 | encode_putfh_maxsz + \ |
349 | encode_getattr_maxsz) | 357 | encode_getattr_maxsz) |
@@ -1113,6 +1121,17 @@ static int encode_renew(struct xdr_stream *xdr, const struct nfs4_client *client | |||
1113 | } | 1121 | } |
1114 | 1122 | ||
1115 | static int | 1123 | static int |
1124 | encode_restorefh(struct xdr_stream *xdr) | ||
1125 | { | ||
1126 | uint32_t *p; | ||
1127 | |||
1128 | RESERVE_SPACE(4); | ||
1129 | WRITE32(OP_RESTOREFH); | ||
1130 | |||
1131 | return 0; | ||
1132 | } | ||
1133 | |||
1134 | static int | ||
1116 | encode_setacl(struct xdr_stream *xdr, struct nfs_setaclargs *arg) | 1135 | encode_setacl(struct xdr_stream *xdr, struct nfs_setaclargs *arg) |
1117 | { | 1136 | { |
1118 | uint32_t *p; | 1137 | uint32_t *p; |
@@ -1358,7 +1377,7 @@ static int nfs4_xdr_enc_create(struct rpc_rqst *req, uint32_t *p, const struct n | |||
1358 | { | 1377 | { |
1359 | struct xdr_stream xdr; | 1378 | struct xdr_stream xdr; |
1360 | struct compound_hdr hdr = { | 1379 | struct compound_hdr hdr = { |
1361 | .nops = 4, | 1380 | .nops = 7, |
1362 | }; | 1381 | }; |
1363 | int status; | 1382 | int status; |
1364 | 1383 | ||
@@ -1366,10 +1385,16 @@ static int nfs4_xdr_enc_create(struct rpc_rqst *req, uint32_t *p, const struct n | |||
1366 | encode_compound_hdr(&xdr, &hdr); | 1385 | encode_compound_hdr(&xdr, &hdr); |
1367 | if ((status = encode_putfh(&xdr, args->dir_fh)) != 0) | 1386 | if ((status = encode_putfh(&xdr, args->dir_fh)) != 0) |
1368 | goto out; | 1387 | goto out; |
1388 | if ((status = encode_savefh(&xdr)) != 0) | ||
1389 | goto out; | ||
1369 | if ((status = encode_create(&xdr, args)) != 0) | 1390 | if ((status = encode_create(&xdr, args)) != 0) |
1370 | goto out; | 1391 | goto out; |
1371 | if ((status = encode_getfh(&xdr)) != 0) | 1392 | if ((status = encode_getfh(&xdr)) != 0) |
1372 | goto out; | 1393 | goto out; |
1394 | if ((status = encode_getfattr(&xdr, args->bitmask)) != 0) | ||
1395 | goto out; | ||
1396 | if ((status = encode_restorefh(&xdr)) != 0) | ||
1397 | goto out; | ||
1373 | status = encode_getfattr(&xdr, args->bitmask); | 1398 | status = encode_getfattr(&xdr, args->bitmask); |
1374 | out: | 1399 | out: |
1375 | return status; | 1400 | return status; |
@@ -1429,7 +1454,7 @@ static int nfs4_xdr_enc_open(struct rpc_rqst *req, uint32_t *p, struct nfs_opena | |||
1429 | { | 1454 | { |
1430 | struct xdr_stream xdr; | 1455 | struct xdr_stream xdr; |
1431 | struct compound_hdr hdr = { | 1456 | struct compound_hdr hdr = { |
1432 | .nops = 4, | 1457 | .nops = 7, |
1433 | }; | 1458 | }; |
1434 | int status; | 1459 | int status; |
1435 | 1460 | ||
@@ -1441,6 +1466,9 @@ static int nfs4_xdr_enc_open(struct rpc_rqst *req, uint32_t *p, struct nfs_opena | |||
1441 | status = encode_putfh(&xdr, args->fh); | 1466 | status = encode_putfh(&xdr, args->fh); |
1442 | if (status) | 1467 | if (status) |
1443 | goto out; | 1468 | goto out; |
1469 | status = encode_savefh(&xdr); | ||
1470 | if (status) | ||
1471 | goto out; | ||
1444 | status = encode_open(&xdr, args); | 1472 | status = encode_open(&xdr, args); |
1445 | if (status) | 1473 | if (status) |
1446 | goto out; | 1474 | goto out; |
@@ -1448,6 +1476,12 @@ static int nfs4_xdr_enc_open(struct rpc_rqst *req, uint32_t *p, struct nfs_opena | |||
1448 | if (status) | 1476 | if (status) |
1449 | goto out; | 1477 | goto out; |
1450 | status = encode_getfattr(&xdr, args->bitmask); | 1478 | status = encode_getfattr(&xdr, args->bitmask); |
1479 | if (status) | ||
1480 | goto out; | ||
1481 | status = encode_restorefh(&xdr); | ||
1482 | if (status) | ||
1483 | goto out; | ||
1484 | status = encode_getfattr(&xdr, args->bitmask); | ||
1451 | out: | 1485 | out: |
1452 | return status; | 1486 | return status; |
1453 | } | 1487 | } |
@@ -3218,6 +3252,12 @@ static int decode_renew(struct xdr_stream *xdr) | |||
3218 | return decode_op_hdr(xdr, OP_RENEW); | 3252 | return decode_op_hdr(xdr, OP_RENEW); |
3219 | } | 3253 | } |
3220 | 3254 | ||
3255 | static int | ||
3256 | decode_restorefh(struct xdr_stream *xdr) | ||
3257 | { | ||
3258 | return decode_op_hdr(xdr, OP_RESTOREFH); | ||
3259 | } | ||
3260 | |||
3221 | static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, | 3261 | static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req, |
3222 | size_t *acl_len) | 3262 | size_t *acl_len) |
3223 | { | 3263 | { |
@@ -3510,13 +3550,17 @@ static int nfs4_xdr_dec_create(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_ | |||
3510 | goto out; | 3550 | goto out; |
3511 | if ((status = decode_putfh(&xdr)) != 0) | 3551 | if ((status = decode_putfh(&xdr)) != 0) |
3512 | goto out; | 3552 | goto out; |
3553 | if ((status = decode_savefh(&xdr)) != 0) | ||
3554 | goto out; | ||
3513 | if ((status = decode_create(&xdr,&res->dir_cinfo)) != 0) | 3555 | if ((status = decode_create(&xdr,&res->dir_cinfo)) != 0) |
3514 | goto out; | 3556 | goto out; |
3515 | if ((status = decode_getfh(&xdr, res->fh)) != 0) | 3557 | if ((status = decode_getfh(&xdr, res->fh)) != 0) |
3516 | goto out; | 3558 | goto out; |
3517 | status = decode_getfattr(&xdr, res->fattr, res->server); | 3559 | if (decode_getfattr(&xdr, res->fattr, res->server) != 0) |
3518 | if (status == NFS4ERR_DELAY) | 3560 | goto out; |
3519 | status = 0; | 3561 | if ((status = decode_restorefh(&xdr)) != 0) |
3562 | goto out; | ||
3563 | decode_getfattr(&xdr, res->dir_fattr, res->server); | ||
3520 | out: | 3564 | out: |
3521 | return status; | 3565 | return status; |
3522 | } | 3566 | } |
@@ -3654,15 +3698,20 @@ static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_ope | |||
3654 | status = decode_putfh(&xdr); | 3698 | status = decode_putfh(&xdr); |
3655 | if (status) | 3699 | if (status) |
3656 | goto out; | 3700 | goto out; |
3701 | status = decode_savefh(&xdr); | ||
3702 | if (status) | ||
3703 | goto out; | ||
3657 | status = decode_open(&xdr, res); | 3704 | status = decode_open(&xdr, res); |
3658 | if (status) | 3705 | if (status) |
3659 | goto out; | 3706 | goto out; |
3660 | status = decode_getfh(&xdr, &res->fh); | 3707 | status = decode_getfh(&xdr, &res->fh); |
3661 | if (status) | 3708 | if (status) |
3662 | goto out; | 3709 | goto out; |
3663 | status = decode_getfattr(&xdr, res->f_attr, res->server); | 3710 | if (decode_getfattr(&xdr, res->f_attr, res->server) != 0) |
3664 | if (status == NFS4ERR_DELAY) | 3711 | goto out; |
3665 | status = 0; | 3712 | if ((status = decode_restorefh(&xdr)) != 0) |
3713 | goto out; | ||
3714 | decode_getfattr(&xdr, res->dir_attr, res->server); | ||
3666 | out: | 3715 | out: |
3667 | return status; | 3716 | return status; |
3668 | } | 3717 | } |
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index aeaee7e7c51d..6485b8b41b83 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h | |||
@@ -124,6 +124,7 @@ struct nfs_openres { | |||
124 | struct nfs4_change_info cinfo; | 124 | struct nfs4_change_info cinfo; |
125 | __u32 rflags; | 125 | __u32 rflags; |
126 | struct nfs_fattr * f_attr; | 126 | struct nfs_fattr * f_attr; |
127 | struct nfs_fattr * dir_attr; | ||
127 | const struct nfs_server *server; | 128 | const struct nfs_server *server; |
128 | int delegation_type; | 129 | int delegation_type; |
129 | nfs4_stateid delegation; | 130 | nfs4_stateid delegation; |
@@ -540,6 +541,7 @@ struct nfs4_create_res { | |||
540 | struct nfs_fh * fh; | 541 | struct nfs_fh * fh; |
541 | struct nfs_fattr * fattr; | 542 | struct nfs_fattr * fattr; |
542 | struct nfs4_change_info dir_cinfo; | 543 | struct nfs4_change_info dir_cinfo; |
544 | struct nfs_fattr * dir_fattr; | ||
543 | }; | 545 | }; |
544 | 546 | ||
545 | struct nfs4_fsinfo_arg { | 547 | struct nfs4_fsinfo_arg { |