diff options
-rw-r--r-- | fs/nfs/nfs4proc.c | 22 | ||||
-rw-r--r-- | fs/nfs/nfs4xdr.c | 34 | ||||
-rw-r--r-- | include/linux/nfs_xdr.h | 9 |
3 files changed, 54 insertions, 11 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 7be3d2d15d6f..04995e39e867 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -1724,22 +1724,34 @@ static int nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name, | |||
1724 | 1724 | ||
1725 | static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *name) | 1725 | static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *name) |
1726 | { | 1726 | { |
1727 | struct nfs_server *server = NFS_SERVER(inode); | ||
1727 | struct nfs4_link_arg arg = { | 1728 | struct nfs4_link_arg arg = { |
1728 | .fh = NFS_FH(inode), | 1729 | .fh = NFS_FH(inode), |
1729 | .dir_fh = NFS_FH(dir), | 1730 | .dir_fh = NFS_FH(dir), |
1730 | .name = name, | 1731 | .name = name, |
1732 | .bitmask = server->attr_bitmask, | ||
1733 | }; | ||
1734 | struct nfs_fattr fattr, dir_attr; | ||
1735 | struct nfs4_link_res res = { | ||
1736 | .server = server, | ||
1737 | .fattr = &fattr, | ||
1738 | .dir_attr = &dir_attr, | ||
1731 | }; | 1739 | }; |
1732 | struct nfs4_change_info cinfo = { }; | ||
1733 | struct rpc_message msg = { | 1740 | struct rpc_message msg = { |
1734 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LINK], | 1741 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LINK], |
1735 | .rpc_argp = &arg, | 1742 | .rpc_argp = &arg, |
1736 | .rpc_resp = &cinfo, | 1743 | .rpc_resp = &res, |
1737 | }; | 1744 | }; |
1738 | int status; | 1745 | int status; |
1739 | 1746 | ||
1740 | status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); | 1747 | nfs_fattr_init(res.fattr); |
1741 | if (!status) | 1748 | nfs_fattr_init(res.dir_attr); |
1742 | update_changeattr(dir, &cinfo); | 1749 | status = rpc_call_sync(server->client, &msg, 0); |
1750 | if (!status) { | ||
1751 | update_changeattr(dir, &res.cinfo); | ||
1752 | nfs_post_op_update_inode(dir, res.dir_attr); | ||
1753 | nfs_refresh_inode(inode, res.fattr); | ||
1754 | } | ||
1743 | 1755 | ||
1744 | return status; | 1756 | return status; |
1745 | } | 1757 | } |
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index cd9e26cfa868..f624b693ce21 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -324,12 +324,18 @@ static int nfs_stat_to_errno(int); | |||
324 | encode_putfh_maxsz + \ | 324 | encode_putfh_maxsz + \ |
325 | encode_savefh_maxsz + \ | 325 | encode_savefh_maxsz + \ |
326 | encode_putfh_maxsz + \ | 326 | encode_putfh_maxsz + \ |
327 | encode_link_maxsz) | 327 | encode_link_maxsz + \ |
328 | decode_getattr_maxsz + \ | ||
329 | encode_restorefh_maxsz + \ | ||
330 | decode_getattr_maxsz) | ||
328 | #define NFS4_dec_link_sz (compound_decode_hdr_maxsz + \ | 331 | #define NFS4_dec_link_sz (compound_decode_hdr_maxsz + \ |
329 | decode_putfh_maxsz + \ | 332 | decode_putfh_maxsz + \ |
330 | decode_savefh_maxsz + \ | 333 | decode_savefh_maxsz + \ |
331 | decode_putfh_maxsz + \ | 334 | decode_putfh_maxsz + \ |
332 | decode_link_maxsz) | 335 | decode_link_maxsz + \ |
336 | decode_getattr_maxsz + \ | ||
337 | decode_restorefh_maxsz + \ | ||
338 | decode_getattr_maxsz) | ||
333 | #define NFS4_enc_symlink_sz (compound_encode_hdr_maxsz + \ | 339 | #define NFS4_enc_symlink_sz (compound_encode_hdr_maxsz + \ |
334 | encode_putfh_maxsz + \ | 340 | encode_putfh_maxsz + \ |
335 | encode_symlink_maxsz + \ | 341 | encode_symlink_maxsz + \ |
@@ -1357,7 +1363,7 @@ static int nfs4_xdr_enc_link(struct rpc_rqst *req, uint32_t *p, const struct nfs | |||
1357 | { | 1363 | { |
1358 | struct xdr_stream xdr; | 1364 | struct xdr_stream xdr; |
1359 | struct compound_hdr hdr = { | 1365 | struct compound_hdr hdr = { |
1360 | .nops = 4, | 1366 | .nops = 7, |
1361 | }; | 1367 | }; |
1362 | int status; | 1368 | int status; |
1363 | 1369 | ||
@@ -1369,7 +1375,13 @@ static int nfs4_xdr_enc_link(struct rpc_rqst *req, uint32_t *p, const struct nfs | |||
1369 | goto out; | 1375 | goto out; |
1370 | if ((status = encode_putfh(&xdr, args->dir_fh)) != 0) | 1376 | if ((status = encode_putfh(&xdr, args->dir_fh)) != 0) |
1371 | goto out; | 1377 | goto out; |
1372 | status = encode_link(&xdr, args->name); | 1378 | if ((status = encode_link(&xdr, args->name)) != 0) |
1379 | goto out; | ||
1380 | if ((status = encode_getfattr(&xdr, args->bitmask)) != 0) | ||
1381 | goto out; | ||
1382 | if ((status = encode_restorefh(&xdr)) != 0) | ||
1383 | goto out; | ||
1384 | status = encode_getfattr(&xdr, args->bitmask); | ||
1373 | out: | 1385 | out: |
1374 | return status; | 1386 | return status; |
1375 | } | 1387 | } |
@@ -3529,7 +3541,7 @@ out: | |||
3529 | /* | 3541 | /* |
3530 | * Decode LINK response | 3542 | * Decode LINK response |
3531 | */ | 3543 | */ |
3532 | static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_change_info *cinfo) | 3544 | static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_link_res *res) |
3533 | { | 3545 | { |
3534 | struct xdr_stream xdr; | 3546 | struct xdr_stream xdr; |
3535 | struct compound_hdr hdr; | 3547 | struct compound_hdr hdr; |
@@ -3544,7 +3556,17 @@ static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_ch | |||
3544 | goto out; | 3556 | goto out; |
3545 | if ((status = decode_putfh(&xdr)) != 0) | 3557 | if ((status = decode_putfh(&xdr)) != 0) |
3546 | goto out; | 3558 | goto out; |
3547 | status = decode_link(&xdr, cinfo); | 3559 | if ((status = decode_link(&xdr, &res->cinfo)) != 0) |
3560 | goto out; | ||
3561 | /* | ||
3562 | * Note order: OP_LINK leaves the directory as the current | ||
3563 | * filehandle. | ||
3564 | */ | ||
3565 | if (decode_getfattr(&xdr, res->dir_attr, res->server) != 0) | ||
3566 | goto out; | ||
3567 | if ((status = decode_restorefh(&xdr)) != 0) | ||
3568 | goto out; | ||
3569 | decode_getfattr(&xdr, res->fattr, res->server); | ||
3548 | out: | 3570 | out: |
3549 | return status; | 3571 | return status; |
3550 | } | 3572 | } |
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index 4f03dc21cf4a..89238b799cfd 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h | |||
@@ -566,8 +566,17 @@ struct nfs4_link_arg { | |||
566 | const struct nfs_fh * fh; | 566 | const struct nfs_fh * fh; |
567 | const struct nfs_fh * dir_fh; | 567 | const struct nfs_fh * dir_fh; |
568 | const struct qstr * name; | 568 | const struct qstr * name; |
569 | const u32 * bitmask; | ||
570 | }; | ||
571 | |||
572 | struct nfs4_link_res { | ||
573 | const struct nfs_server * server; | ||
574 | struct nfs_fattr * fattr; | ||
575 | struct nfs4_change_info cinfo; | ||
576 | struct nfs_fattr * dir_attr; | ||
569 | }; | 577 | }; |
570 | 578 | ||
579 | |||
571 | struct nfs4_lookup_arg { | 580 | struct nfs4_lookup_arg { |
572 | const struct nfs_fh * dir_fh; | 581 | const struct nfs_fh * dir_fh; |
573 | const struct qstr * name; | 582 | const struct qstr * name; |