summaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4xdr.c
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@primarydata.com>2015-01-30 14:21:14 -0500
committerTrond Myklebust <trond.myklebust@primarydata.com>2015-02-04 10:35:32 -0500
commit6ae373394c4257bad562817aa60464ff7fe8f9c4 (patch)
tree7f21050411045b77eb60c1080d230c3ea93a10f1 /fs/nfs/nfs4xdr.c
parent0e3b137fbf0f4ab901de58fcac7edb12922daa08 (diff)
NFSv4.1: Ask for no delegation on OPEN if using O_DIRECT
If we're using NFSv4.1, then we have the ability to let the server know whether or not we believe that returning a delegation as part of our OPEN request would be useful. The feature needs to be used with care, since the client sending the request doesn't necessarily know how other clients are using that file, and how they may be affected by the delegation. For this reason, our initial use of the feature will be to let the server know when the client believes that handing out a delegation would not be useful. The first application for this function is when opening the file using O_DIRECT. Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'fs/nfs/nfs4xdr.c')
-rw-r--r--fs/nfs/nfs4xdr.c79
1 files changed, 53 insertions, 26 deletions
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index a2329d69502b..e23a0a664e12 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -1351,24 +1351,12 @@ static void encode_lookup(struct xdr_stream *xdr, const struct qstr *name, struc
1351 encode_string(xdr, name->len, name->name); 1351 encode_string(xdr, name->len, name->name);
1352} 1352}
1353 1353
1354static void encode_share_access(struct xdr_stream *xdr, fmode_t fmode) 1354static void encode_share_access(struct xdr_stream *xdr, u32 share_access)
1355{ 1355{
1356 __be32 *p; 1356 __be32 *p;
1357 1357
1358 p = reserve_space(xdr, 8); 1358 p = reserve_space(xdr, 8);
1359 switch (fmode & (FMODE_READ|FMODE_WRITE)) { 1359 *p++ = cpu_to_be32(share_access);
1360 case FMODE_READ:
1361 *p++ = cpu_to_be32(NFS4_SHARE_ACCESS_READ);
1362 break;
1363 case FMODE_WRITE:
1364 *p++ = cpu_to_be32(NFS4_SHARE_ACCESS_WRITE);
1365 break;
1366 case FMODE_READ|FMODE_WRITE:
1367 *p++ = cpu_to_be32(NFS4_SHARE_ACCESS_BOTH);
1368 break;
1369 default:
1370 *p++ = cpu_to_be32(0);
1371 }
1372 *p = cpu_to_be32(0); /* for linux, share_deny = 0 always */ 1360 *p = cpu_to_be32(0); /* for linux, share_deny = 0 always */
1373} 1361}
1374 1362
@@ -1380,7 +1368,7 @@ static inline void encode_openhdr(struct xdr_stream *xdr, const struct nfs_opena
1380 * owner 4 = 32 1368 * owner 4 = 32
1381 */ 1369 */
1382 encode_nfs4_seqid(xdr, arg->seqid); 1370 encode_nfs4_seqid(xdr, arg->seqid);
1383 encode_share_access(xdr, arg->fmode); 1371 encode_share_access(xdr, arg->share_access);
1384 p = reserve_space(xdr, 36); 1372 p = reserve_space(xdr, 36);
1385 p = xdr_encode_hyper(p, arg->clientid); 1373 p = xdr_encode_hyper(p, arg->clientid);
1386 *p++ = cpu_to_be32(24); 1374 *p++ = cpu_to_be32(24);
@@ -1535,7 +1523,7 @@ static void encode_open_downgrade(struct xdr_stream *xdr, const struct nfs_close
1535 encode_op_hdr(xdr, OP_OPEN_DOWNGRADE, decode_open_downgrade_maxsz, hdr); 1523 encode_op_hdr(xdr, OP_OPEN_DOWNGRADE, decode_open_downgrade_maxsz, hdr);
1536 encode_nfs4_stateid(xdr, &arg->stateid); 1524 encode_nfs4_stateid(xdr, &arg->stateid);
1537 encode_nfs4_seqid(xdr, arg->seqid); 1525 encode_nfs4_seqid(xdr, arg->seqid);
1538 encode_share_access(xdr, arg->fmode); 1526 encode_share_access(xdr, arg->share_access);
1539} 1527}
1540 1528
1541static void 1529static void
@@ -4935,20 +4923,13 @@ out_overflow:
4935 return -EIO; 4923 return -EIO;
4936} 4924}
4937 4925
4938static int decode_delegation(struct xdr_stream *xdr, struct nfs_openres *res) 4926static int decode_rw_delegation(struct xdr_stream *xdr,
4927 uint32_t delegation_type,
4928 struct nfs_openres *res)
4939{ 4929{
4940 __be32 *p; 4930 __be32 *p;
4941 uint32_t delegation_type;
4942 int status; 4931 int status;
4943 4932
4944 p = xdr_inline_decode(xdr, 4);
4945 if (unlikely(!p))
4946 goto out_overflow;
4947 delegation_type = be32_to_cpup(p);
4948 if (delegation_type == NFS4_OPEN_DELEGATE_NONE) {
4949 res->delegation_type = 0;
4950 return 0;
4951 }
4952 status = decode_stateid(xdr, &res->delegation); 4933 status = decode_stateid(xdr, &res->delegation);
4953 if (unlikely(status)) 4934 if (unlikely(status))
4954 return status; 4935 return status;
@@ -4972,6 +4953,52 @@ out_overflow:
4972 return -EIO; 4953 return -EIO;
4973} 4954}
4974 4955
4956static int decode_no_delegation(struct xdr_stream *xdr, struct nfs_openres *res)
4957{
4958 __be32 *p;
4959 uint32_t why_no_delegation;
4960
4961 p = xdr_inline_decode(xdr, 4);
4962 if (unlikely(!p))
4963 goto out_overflow;
4964 why_no_delegation = be32_to_cpup(p);
4965 switch (why_no_delegation) {
4966 case WND4_CONTENTION:
4967 case WND4_RESOURCE:
4968 xdr_inline_decode(xdr, 4);
4969 /* Ignore for now */
4970 }
4971 return 0;
4972out_overflow:
4973 print_overflow_msg(__func__, xdr);
4974 return -EIO;
4975}
4976
4977static int decode_delegation(struct xdr_stream *xdr, struct nfs_openres *res)
4978{
4979 __be32 *p;
4980 uint32_t delegation_type;
4981
4982 p = xdr_inline_decode(xdr, 4);
4983 if (unlikely(!p))
4984 goto out_overflow;
4985 delegation_type = be32_to_cpup(p);
4986 res->delegation_type = 0;
4987 switch (delegation_type) {
4988 case NFS4_OPEN_DELEGATE_NONE:
4989 return 0;
4990 case NFS4_OPEN_DELEGATE_READ:
4991 case NFS4_OPEN_DELEGATE_WRITE:
4992 return decode_rw_delegation(xdr, delegation_type, res);
4993 case NFS4_OPEN_DELEGATE_NONE_EXT:
4994 return decode_no_delegation(xdr, res);
4995 }
4996 return -EIO;
4997out_overflow:
4998 print_overflow_msg(__func__, xdr);
4999 return -EIO;
5000}
5001
4975static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res) 5002static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res)
4976{ 5003{
4977 __be32 *p; 5004 __be32 *p;