aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/nfs4proc.c22
-rw-r--r--fs/nfs/nfs4xdr.c34
-rw-r--r--include/linux/nfs_xdr.h9
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
1725static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *name) 1725static 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);
1373out: 1385out:
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 */
3532static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_change_info *cinfo) 3544static 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);
3548out: 3570out:
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
572struct 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
571struct nfs4_lookup_arg { 580struct 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;