* [RFC 03/85] nfs: remove incorrect usage of nfs4 compound response hdr.status
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
@ 2008-11-10 20:05 ` Benny Halevy
2008-11-17 13:24 ` [pnfs] " Benny Halevy
2008-11-10 20:18 ` [RFC 04/85] FIXME: NFS: Increment operation number in each encode_* routine Benny Halevy
` (84 subsequent siblings)
85 siblings, 1 reply; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:05 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
3 call sites look at hdr.status before returning success.
hdr.status must be zero in this case so there's no point in this.
Currently, hdr.status is correctly processed at decode_op_hdr time
if the op status cannot be decoded.
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/nfs4xdr.c | 6 ------
1 files changed, 0 insertions(+), 6 deletions(-)
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index ac2386b..69b5a56 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -4423,8 +4423,6 @@ static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, __be32 *p, struct nfs_fsinf
status = decode_putfh(&xdr);
if (!status)
status = decode_fsinfo(&xdr, fsinfo);
- if (!status)
- status = nfs4_stat_to_errno(hdr.status);
return status;
}
@@ -4513,8 +4511,6 @@ static int nfs4_xdr_dec_setclientid(struct rpc_rqst *req, __be32 *p,
status = decode_compound_hdr(&xdr, &hdr);
if (!status)
status = decode_setclientid(&xdr, clp);
- if (!status)
- status = nfs4_stat_to_errno(hdr.status);
return status;
}
@@ -4535,8 +4531,6 @@ static int nfs4_xdr_dec_setclientid_confirm(struct rpc_rqst *req, __be32 *p, str
status = decode_putrootfh(&xdr);
if (!status)
status = decode_fsinfo(&xdr, fsinfo);
- if (!status)
- status = nfs4_stat_to_errno(hdr.status);
return status;
}
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* Re: [pnfs] [RFC 03/85] nfs: remove incorrect usage of nfs4 compound response hdr.status
2008-11-10 20:05 ` [RFC 03/85] nfs: remove incorrect usage of nfs4 compound response hdr.status Benny Halevy
@ 2008-11-17 13:24 ` Benny Halevy
0 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-17 13:24 UTC (permalink / raw)
To: pnfs; +Cc: trond.myklebust, linux-nfs
On Nov. 10, 2008, 22:05 +0200, Benny Halevy <bhalevy@panasas.com> wrote:
> 3 call sites look at hdr.status before returning success.
> hdr.status must be zero in this case so there's no point in this.
>
> Currently, hdr.status is correctly processed at decode_op_hdr time
> if the op status cannot be decoded.
review 11-14: send to Trond
>
> Signed-off-by: Benny Halevy <bhalevy@panasas.com>
> ---
> fs/nfs/nfs4xdr.c | 6 ------
> 1 files changed, 0 insertions(+), 6 deletions(-)
>
> diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
> index ac2386b..69b5a56 100644
> --- a/fs/nfs/nfs4xdr.c
> +++ b/fs/nfs/nfs4xdr.c
> @@ -4423,8 +4423,6 @@ static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, __be32 *p, struct nfs_fsinf
> status = decode_putfh(&xdr);
> if (!status)
> status = decode_fsinfo(&xdr, fsinfo);
> - if (!status)
> - status = nfs4_stat_to_errno(hdr.status);
> return status;
> }
>
> @@ -4513,8 +4511,6 @@ static int nfs4_xdr_dec_setclientid(struct rpc_rqst *req, __be32 *p,
> status = decode_compound_hdr(&xdr, &hdr);
> if (!status)
> status = decode_setclientid(&xdr, clp);
> - if (!status)
> - status = nfs4_stat_to_errno(hdr.status);
> return status;
> }
>
> @@ -4535,8 +4531,6 @@ static int nfs4_xdr_dec_setclientid_confirm(struct rpc_rqst *req, __be32 *p, str
> status = decode_putrootfh(&xdr);
> if (!status)
> status = decode_fsinfo(&xdr, fsinfo);
> - if (!status)
> - status = nfs4_stat_to_errno(hdr.status);
> return status;
> }
>
^ permalink raw reply [flat|nested] 115+ messages in thread
* [RFC 04/85] FIXME: NFS: Increment operation number in each encode_* routine
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
2008-11-10 20:05 ` [RFC 03/85] nfs: remove incorrect usage of nfs4 compound response hdr.status Benny Halevy
@ 2008-11-10 20:18 ` Benny Halevy
2008-11-17 13:26 ` [pnfs] " Benny Halevy
2008-11-10 20:18 ` [RFC 05/85] nfs41: Add Kconfig symbols for NFSv4.1 Benny Halevy
` (83 subsequent siblings)
85 siblings, 1 reply; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:18 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
From: Andy Adamson <andros@netapp.com>
FIXME: bhalevy: is this a good opportunity for a cleanup-only patch to fix whitespacing?
Pass in the compound_hdr and bump the number of operations in each encode_*
subroutine so as to allow us to more easily construct new compound statements.
Fix tabs, do not fix 'do not use assignment in if condition' warnings.
Signed-off-by: Andy Adamson<andros@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/nfs4xdr.c | 630 ++++++++++++++++++++++++++++++++++--------------------
1 files changed, 401 insertions(+), 229 deletions(-)
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 69b5a56..c1ff9c9 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -578,9 +578,10 @@ static void encode_string(struct xdr_stream *xdr, unsigned int len, const char *
xdr_encode_opaque(p, str, len);
}
-static int encode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr)
+static __u32 *
+encode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr)
{
- __be32 *p;
+ __be32 *p, *nops;
dprintk("encode_compound: tag=%.*s\n", (int)hdr->taglen, hdr->tag);
BUG_ON(hdr->taglen > NFS4_MAXTAGLEN);
@@ -588,8 +589,14 @@ static int encode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr)
WRITE32(hdr->taglen);
WRITEMEM(hdr->tag, hdr->taglen);
WRITE32(NFS4_MINOR_VERSION);
+ nops = p;
WRITE32(hdr->nops);
- return 0;
+ return nops;
+}
+
+static inline void encode_nops(__be32 *nops, struct compound_hdr *hdr)
+{
+ *nops = htonl(hdr->nops);
}
static void encode_nfs4_verifier(struct xdr_stream *xdr, const nfs4_verifier *verf)
@@ -728,18 +735,22 @@ static int encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const s
return status;
}
-static int encode_access(struct xdr_stream *xdr, u32 access)
+static int
+encode_access(struct xdr_stream *xdr, u32 access, struct compound_hdr *hdr)
{
__be32 *p;
RESERVE_SPACE(8);
WRITE32(OP_ACCESS);
WRITE32(access);
-
+ hdr->nops++;
+
return 0;
}
-static int encode_close(struct xdr_stream *xdr, const struct nfs_closeargs *arg)
+static int
+encode_close(struct xdr_stream *xdr, const struct nfs_closeargs *arg,
+ struct compound_hdr *hdr)
{
__be32 *p;
@@ -747,23 +758,29 @@ static int encode_close(struct xdr_stream *xdr, const struct nfs_closeargs *arg)
WRITE32(OP_CLOSE);
WRITE32(arg->seqid->sequence->counter);
WRITEMEM(arg->stateid->data, NFS4_STATEID_SIZE);
+ hdr->nops++;
return 0;
}
-static int encode_commit(struct xdr_stream *xdr, const struct nfs_writeargs *args)
+static int
+encode_commit(struct xdr_stream *xdr, const struct nfs_writeargs *args,
+ struct compound_hdr *hdr)
{
__be32 *p;
- RESERVE_SPACE(16);
- WRITE32(OP_COMMIT);
- WRITE64(args->offset);
- WRITE32(args->count);
+ RESERVE_SPACE(16);
+ WRITE32(OP_COMMIT);
+ WRITE64(args->offset);
+ WRITE32(args->count);
+ hdr->nops++;
- return 0;
+ return 0;
}
-static int encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg *create)
+static int
+encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg *create,
+ struct compound_hdr *hdr)
{
__be32 *p;
@@ -791,11 +808,14 @@ static int encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg *c
RESERVE_SPACE(4 + create->name->len);
WRITE32(create->name->len);
WRITEMEM(create->name->name, create->name->len);
+ hdr->nops++;
return encode_attrs(xdr, create->attrs, create->server);
}
-static int encode_getattr_one(struct xdr_stream *xdr, uint32_t bitmap)
+static int
+encode_getattr_one(struct xdr_stream *xdr, uint32_t bitmap,
+ struct compound_hdr *hdr)
{
__be32 *p;
@@ -803,10 +823,13 @@ static int encode_getattr_one(struct xdr_stream *xdr, uint32_t bitmap)
WRITE32(OP_GETATTR);
WRITE32(1);
WRITE32(bitmap);
+ hdr->nops++;
return 0;
}
-static int encode_getattr_two(struct xdr_stream *xdr, uint32_t bm0, uint32_t bm1)
+static int
+encode_getattr_two(struct xdr_stream *xdr, uint32_t bm0, uint32_t bm1,
+ struct compound_hdr *hdr)
{
__be32 *p;
@@ -815,40 +838,51 @@ static int encode_getattr_two(struct xdr_stream *xdr, uint32_t bm0, uint32_t bm1
WRITE32(2);
WRITE32(bm0);
WRITE32(bm1);
+ hdr->nops++;
return 0;
}
-static int encode_getfattr(struct xdr_stream *xdr, const u32* bitmask)
+static int
+encode_getfattr(struct xdr_stream *xdr, const u32 *bitmask,
+ struct compound_hdr *hdr)
{
return encode_getattr_two(xdr,
bitmask[0] & nfs4_fattr_bitmap[0],
- bitmask[1] & nfs4_fattr_bitmap[1]);
+ bitmask[1] & nfs4_fattr_bitmap[1], hdr);
}
-static int encode_fsinfo(struct xdr_stream *xdr, const u32* bitmask)
+static int
+encode_fsinfo(struct xdr_stream *xdr, const u32 *bitmask,
+ struct compound_hdr *hdr)
{
return encode_getattr_two(xdr, bitmask[0] & nfs4_fsinfo_bitmap[0],
- bitmask[1] & nfs4_fsinfo_bitmap[1]);
+ bitmask[1] & nfs4_fsinfo_bitmap[1], hdr);
}
-static int encode_fs_locations(struct xdr_stream *xdr, const u32* bitmask)
+static int
+encode_fs_locations(struct xdr_stream *xdr, const u32 *bitmask,
+ struct compound_hdr *hdr)
{
return encode_getattr_two(xdr,
bitmask[0] & nfs4_fs_locations_bitmap[0],
- bitmask[1] & nfs4_fs_locations_bitmap[1]);
+ bitmask[1] & nfs4_fs_locations_bitmap[1],
+ hdr);
}
-static int encode_getfh(struct xdr_stream *xdr)
+static int encode_getfh(struct xdr_stream *xdr, struct compound_hdr *hdr)
{
__be32 *p;
RESERVE_SPACE(4);
WRITE32(OP_GETFH);
+ hdr->nops++;
return 0;
}
-static int encode_link(struct xdr_stream *xdr, const struct qstr *name)
+static int
+encode_link(struct xdr_stream *xdr, const struct qstr *name,
+ struct compound_hdr *hdr)
{
__be32 *p;
@@ -856,6 +890,7 @@ static int encode_link(struct xdr_stream *xdr, const struct qstr *name)
WRITE32(OP_LINK);
WRITE32(name->len);
WRITEMEM(name->name, name->len);
+ hdr->nops++;
return 0;
}
@@ -878,7 +913,9 @@ static inline uint64_t nfs4_lock_length(struct file_lock *fl)
* opcode,type,reclaim,offset,length,new_lock_owner = 32
* open_seqid,open_stateid,lock_seqid,lock_owner.clientid, lock_owner.id = 40
*/
-static int encode_lock(struct xdr_stream *xdr, const struct nfs_lock_args *args)
+static int
+encode_lock(struct xdr_stream *xdr, const struct nfs_lock_args *args,
+ struct compound_hdr *hdr)
{
__be32 *p;
@@ -904,11 +941,14 @@ static int encode_lock(struct xdr_stream *xdr, const struct nfs_lock_args *args)
WRITEMEM(args->lock_stateid->data, NFS4_STATEID_SIZE);
WRITE32(args->lock_seqid->sequence->counter);
}
+ hdr->nops++;
return 0;
}
-static int encode_lockt(struct xdr_stream *xdr, const struct nfs_lockt_args *args)
+static int
+encode_lockt(struct xdr_stream *xdr, const struct nfs_lockt_args *args,
+ struct compound_hdr *hdr)
{
__be32 *p;
@@ -921,11 +961,14 @@ static int encode_lockt(struct xdr_stream *xdr, const struct nfs_lockt_args *arg
WRITE32(16);
WRITEMEM("lock id:", 8);
WRITE64(args->lock_owner.id);
+ hdr->nops++;
return 0;
}
-static int encode_locku(struct xdr_stream *xdr, const struct nfs_locku_args *args)
+static int
+encode_locku(struct xdr_stream *xdr, const struct nfs_locku_args *args,
+ struct compound_hdr *hdr)
{
__be32 *p;
@@ -936,11 +979,14 @@ static int encode_locku(struct xdr_stream *xdr, const struct nfs_locku_args *arg
WRITEMEM(args->stateid->data, NFS4_STATEID_SIZE);
WRITE64(args->fl->fl_start);
WRITE64(nfs4_lock_length(args->fl));
+ hdr->nops++;
return 0;
}
-static int encode_lookup(struct xdr_stream *xdr, const struct qstr *name)
+static int
+encode_lookup(struct xdr_stream *xdr, const struct qstr *name,
+ struct compound_hdr *hdr)
{
int len = name->len;
__be32 *p;
@@ -949,6 +995,7 @@ static int encode_lookup(struct xdr_stream *xdr, const struct qstr *name)
WRITE32(OP_LOOKUP);
WRITE32(len);
WRITEMEM(name->name, len);
+ hdr->nops++;
return 0;
}
@@ -1072,7 +1119,9 @@ static inline void encode_claim_delegate_cur(struct xdr_stream *xdr, const struc
encode_string(xdr, name->len, name->name);
}
-static int encode_open(struct xdr_stream *xdr, const struct nfs_openargs *arg)
+static int
+encode_open(struct xdr_stream *xdr, const struct nfs_openargs *arg,
+ struct compound_hdr *hdr)
{
encode_openhdr(xdr, arg);
encode_opentype(xdr, arg);
@@ -1089,10 +1138,14 @@ static int encode_open(struct xdr_stream *xdr, const struct nfs_openargs *arg)
default:
BUG();
}
+ hdr->nops++;
return 0;
}
-static int encode_open_confirm(struct xdr_stream *xdr, const struct nfs_open_confirmargs *arg)
+static int
+encode_open_confirm(struct xdr_stream *xdr,
+ const struct nfs_open_confirmargs *arg,
+ struct compound_hdr *hdr)
{
__be32 *p;
@@ -1100,11 +1153,14 @@ static int encode_open_confirm(struct xdr_stream *xdr, const struct nfs_open_con
WRITE32(OP_OPEN_CONFIRM);
WRITEMEM(arg->stateid->data, NFS4_STATEID_SIZE);
WRITE32(arg->seqid->sequence->counter);
+ hdr->nops++;
return 0;
}
-static int encode_open_downgrade(struct xdr_stream *xdr, const struct nfs_closeargs *arg)
+static int
+encode_open_downgrade(struct xdr_stream *xdr, const struct nfs_closeargs *arg,
+ struct compound_hdr *hdr)
{
__be32 *p;
@@ -1113,11 +1169,13 @@ static int encode_open_downgrade(struct xdr_stream *xdr, const struct nfs_closea
WRITEMEM(arg->stateid->data, NFS4_STATEID_SIZE);
WRITE32(arg->seqid->sequence->counter);
encode_share_access(xdr, arg->open_flags);
+ hdr->nops++;
return 0;
}
static int
-encode_putfh(struct xdr_stream *xdr, const struct nfs_fh *fh)
+encode_putfh(struct xdr_stream *xdr, const struct nfs_fh *fh,
+ struct compound_hdr *hdr)
{
int len = fh->size;
__be32 *p;
@@ -1126,21 +1184,24 @@ encode_putfh(struct xdr_stream *xdr, const struct nfs_fh *fh)
WRITE32(OP_PUTFH);
WRITE32(len);
WRITEMEM(fh->data, len);
+ hdr->nops++;
return 0;
}
-static int encode_putrootfh(struct xdr_stream *xdr)
+static int encode_putrootfh(struct xdr_stream *xdr, struct compound_hdr *hdr)
{
__be32 *p;
RESERVE_SPACE(4);
WRITE32(OP_PUTROOTFH);
+ hdr->nops++;
return 0;
}
-static void encode_stateid(struct xdr_stream *xdr, const struct nfs_open_context *ctx)
+static void
+encode_stateid(struct xdr_stream *xdr, const struct nfs_open_context *ctx)
{
nfs4_stateid stateid;
__be32 *p;
@@ -1153,7 +1214,9 @@ static void encode_stateid(struct xdr_stream *xdr, const struct nfs_open_context
WRITEMEM(zero_stateid.data, NFS4_STATEID_SIZE);
}
-static int encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args)
+static int
+encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args,
+ struct compound_hdr *hdr)
{
__be32 *p;
@@ -1165,11 +1228,14 @@ static int encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args)
RESERVE_SPACE(12);
WRITE64(args->offset);
WRITE32(args->count);
+ hdr->nops++;
return 0;
}
-static int encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req)
+static int
+encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir,
+ struct rpc_rqst *req, struct compound_hdr *hdr)
{
uint32_t attrs[2] = {
FATTR4_WORD0_RDATTR_ERROR|FATTR4_WORD0_FILEID,
@@ -1191,6 +1257,7 @@ static int encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg
attrs[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID;
WRITE32(attrs[0] & readdir->bitmask[0]);
WRITE32(attrs[1] & readdir->bitmask[1]);
+ hdr->nops++;
dprintk("%s: cookie = %Lu, verifier = %08x:%08x, bitmap = %08x:%08x\n",
__func__,
(unsigned long long)readdir->cookie,
@@ -1202,17 +1269,22 @@ static int encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg
return 0;
}
-static int encode_readlink(struct xdr_stream *xdr, const struct nfs4_readlink *readlink, struct rpc_rqst *req)
+static int
+encode_readlink(struct xdr_stream *xdr, const struct nfs4_readlink *readlink,
+ struct rpc_rqst *req, struct compound_hdr *hdr)
{
__be32 *p;
RESERVE_SPACE(4);
WRITE32(OP_READLINK);
+ hdr->nops++;
return 0;
}
-static int encode_remove(struct xdr_stream *xdr, const struct qstr *name)
+static int
+encode_remove(struct xdr_stream *xdr, const struct qstr *name,
+ struct compound_hdr *hdr)
{
__be32 *p;
@@ -1220,11 +1292,14 @@ static int encode_remove(struct xdr_stream *xdr, const struct qstr *name)
WRITE32(OP_REMOVE);
WRITE32(name->len);
WRITEMEM(name->name, name->len);
+ hdr->nops++;
return 0;
}
-static int encode_rename(struct xdr_stream *xdr, const struct qstr *oldname, const struct qstr *newname)
+static int
+encode_rename(struct xdr_stream *xdr, const struct qstr *oldname,
+ const struct qstr *newname, struct compound_hdr *hdr)
{
__be32 *p;
@@ -1236,34 +1311,40 @@ static int encode_rename(struct xdr_stream *xdr, const struct qstr *oldname, con
RESERVE_SPACE(4 + newname->len);
WRITE32(newname->len);
WRITEMEM(newname->name, newname->len);
+ hdr->nops++;
return 0;
}
-static int encode_renew(struct xdr_stream *xdr, const struct nfs_client *client_stateid)
+static int
+encode_renew(struct xdr_stream *xdr, const struct nfs_client *client_stateid,
+ struct compound_hdr *hdr)
{
__be32 *p;
RESERVE_SPACE(12);
WRITE32(OP_RENEW);
WRITE64(client_stateid->cl_clientid);
+ hdr->nops++;
return 0;
}
static int
-encode_restorefh(struct xdr_stream *xdr)
+encode_restorefh(struct xdr_stream *xdr, struct compound_hdr *hdr)
{
__be32 *p;
RESERVE_SPACE(4);
WRITE32(OP_RESTOREFH);
+ hdr->nops++;
return 0;
}
static int
-encode_setacl(struct xdr_stream *xdr, struct nfs_setaclargs *arg)
+encode_setacl(struct xdr_stream *xdr, struct nfs_setaclargs *arg,
+ struct compound_hdr *hdr)
{
__be32 *p;
@@ -1278,21 +1359,25 @@ encode_setacl(struct xdr_stream *xdr, struct nfs_setaclargs *arg)
RESERVE_SPACE(4);
WRITE32(arg->acl_len);
xdr_write_pages(xdr, arg->acl_pages, arg->acl_pgbase, arg->acl_len);
+ hdr->nops++;
return 0;
}
static int
-encode_savefh(struct xdr_stream *xdr)
+encode_savefh(struct xdr_stream *xdr, struct compound_hdr *hdr)
{
__be32 *p;
RESERVE_SPACE(4);
WRITE32(OP_SAVEFH);
+ hdr->nops++;
return 0;
}
-static int encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs *arg, const struct nfs_server *server)
+static int
+encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs *arg,
+ const struct nfs_server *server, struct compound_hdr *hdr)
{
int status;
__be32 *p;
@@ -1300,6 +1385,7 @@ static int encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs *
RESERVE_SPACE(4+NFS4_STATEID_SIZE);
WRITE32(OP_SETATTR);
WRITEMEM(arg->stateid.data, NFS4_STATEID_SIZE);
+ hdr->nops++;
if ((status = encode_attrs(xdr, arg->iap, server)))
return status;
@@ -1307,7 +1393,10 @@ static int encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs *
return 0;
}
-static int encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclientid *setclientid)
+static int
+encode_setclientid(struct xdr_stream *xdr,
+ const struct nfs4_setclientid *setclientid,
+ struct compound_hdr *hdr)
{
__be32 *p;
@@ -1322,11 +1411,15 @@ static int encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclien
encode_string(xdr, setclientid->sc_uaddr_len, setclientid->sc_uaddr);
RESERVE_SPACE(4);
WRITE32(setclientid->sc_cb_ident);
+ hdr->nops++;
return 0;
}
-static int encode_setclientid_confirm(struct xdr_stream *xdr, const struct nfs_client *client_state)
+static int
+encode_setclientid_confirm(struct xdr_stream *xdr,
+ const struct nfs_client *client_state,
+ struct compound_hdr *hdr)
{
__be32 *p;
@@ -1334,11 +1427,14 @@ static int encode_setclientid_confirm(struct xdr_stream *xdr, const struct nfs_c
WRITE32(OP_SETCLIENTID_CONFIRM);
WRITE64(client_state->cl_clientid);
WRITEMEM(client_state->cl_confirm.data, NFS4_VERIFIER_SIZE);
+ hdr->nops++;
return 0;
}
-static int encode_write(struct xdr_stream *xdr, const struct nfs_writeargs *args)
+static int
+encode_write(struct xdr_stream *xdr, const struct nfs_writeargs *args,
+ struct compound_hdr *hdr)
{
__be32 *p;
@@ -1353,11 +1449,14 @@ static int encode_write(struct xdr_stream *xdr, const struct nfs_writeargs *args
WRITE32(args->count);
xdr_write_pages(xdr, args->pages, args->pgbase, args->count);
+ hdr->nops++;
return 0;
}
-static int encode_delegreturn(struct xdr_stream *xdr, const nfs4_stateid *stateid)
+static int
+encode_delegreturn(struct xdr_stream *xdr, const nfs4_stateid *stateid,
+ struct compound_hdr *hdr)
{
__be32 *p;
@@ -1365,6 +1464,7 @@ static int encode_delegreturn(struct xdr_stream *xdr, const nfs4_stateid *statei
WRITE32(OP_DELEGRETURN);
WRITEMEM(stateid->data, NFS4_STATEID_SIZE);
+ hdr->nops++;
return 0;
}
@@ -1379,20 +1479,22 @@ static int nfs4_xdr_enc_access(struct rpc_rqst *req, __be32 *p, const struct nfs
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 3,
+ .nops = 0,
};
int status;
+ __be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
- status = encode_putfh(&xdr, args->fh);
+ nops = encode_compound_hdr(&xdr, &hdr);
+ status = encode_putfh(&xdr, args->fh, &hdr);
if (status != 0)
goto out;
- status = encode_access(&xdr, args->access);
+ status = encode_access(&xdr, args->access, &hdr);
if (status != 0)
goto out;
- status = encode_getfattr(&xdr, args->bitmask);
+ status = encode_getfattr(&xdr, args->bitmask, &hdr);
out:
+ encode_nops(nops, &hdr);
return status;
}
@@ -1403,20 +1505,22 @@ static int nfs4_xdr_enc_lookup(struct rpc_rqst *req, __be32 *p, const struct nfs
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 4,
+ .nops = 0,
};
int status;
+ __be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
- if ((status = encode_putfh(&xdr, args->dir_fh)) != 0)
+ nops = encode_compound_hdr(&xdr, &hdr);
+ if ((status = encode_putfh(&xdr, args->dir_fh, &hdr)) != 0)
goto out;
- if ((status = encode_lookup(&xdr, args->name)) != 0)
+ if ((status = encode_lookup(&xdr, args->name, &hdr)) != 0)
goto out;
- if ((status = encode_getfh(&xdr)) != 0)
+ if ((status = encode_getfh(&xdr, &hdr)) != 0)
goto out;
- status = encode_getfattr(&xdr, args->bitmask);
+ status = encode_getfattr(&xdr, args->bitmask, &hdr);
out:
+ encode_nops(nops, &hdr);
return status;
}
@@ -1427,17 +1531,19 @@ static int nfs4_xdr_enc_lookup_root(struct rpc_rqst *req, __be32 *p, const struc
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 3,
+ .nops = 0,
};
int status;
+ __be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
- if ((status = encode_putrootfh(&xdr)) != 0)
+ nops = encode_compound_hdr(&xdr, &hdr);
+ if ((status = encode_putrootfh(&xdr, &hdr)) != 0)
goto out;
- if ((status = encode_getfh(&xdr)) == 0)
- status = encode_getfattr(&xdr, args->bitmask);
+ if ((status = encode_getfh(&xdr, &hdr)) == 0)
+ status = encode_getfattr(&xdr, args->bitmask, &hdr);
out:
+ encode_nops(nops, &hdr);
return status;
}
@@ -1448,18 +1554,20 @@ static int nfs4_xdr_enc_remove(struct rpc_rqst *req, __be32 *p, const struct nfs
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 3,
+ .nops = 0,
};
int status;
+ __be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
- if ((status = encode_putfh(&xdr, args->fh)) != 0)
+ nops = encode_compound_hdr(&xdr, &hdr);
+ if ((status = encode_putfh(&xdr, args->fh, &hdr)) != 0)
goto out;
- if ((status = encode_remove(&xdr, &args->name)) != 0)
+ if ((status = encode_remove(&xdr, &args->name, &hdr)) != 0)
goto out;
- status = encode_getfattr(&xdr, args->bitmask);
+ status = encode_getfattr(&xdr, args->bitmask, &hdr);
out:
+ encode_nops(nops, &hdr);
return status;
}
@@ -1470,26 +1578,29 @@ static int nfs4_xdr_enc_rename(struct rpc_rqst *req, __be32 *p, const struct nfs
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 7,
+ .nops = 0,
};
int status;
+ __be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
- if ((status = encode_putfh(&xdr, args->old_dir)) != 0)
+ nops = encode_compound_hdr(&xdr, &hdr);
+ if ((status = encode_putfh(&xdr, args->old_dir, &hdr)) != 0)
goto out;
- if ((status = encode_savefh(&xdr)) != 0)
+ if ((status = encode_savefh(&xdr, &hdr)) != 0)
goto out;
- if ((status = encode_putfh(&xdr, args->new_dir)) != 0)
+ if ((status = encode_putfh(&xdr, args->new_dir, &hdr)) != 0)
goto out;
- if ((status = encode_rename(&xdr, args->old_name, args->new_name)) != 0)
+ if ((status = encode_rename(&xdr, args->old_name, args->new_name,
+ &hdr)) != 0)
goto out;
- if ((status = encode_getfattr(&xdr, args->bitmask)) != 0)
+ if ((status = encode_getfattr(&xdr, args->bitmask, &hdr)) != 0)
goto out;
- if ((status = encode_restorefh(&xdr)) != 0)
+ if ((status = encode_restorefh(&xdr, &hdr)) != 0)
goto out;
- status = encode_getfattr(&xdr, args->bitmask);
+ status = encode_getfattr(&xdr, args->bitmask, &hdr);
out:
+ encode_nops(nops, &hdr);
return status;
}
@@ -1500,26 +1611,28 @@ static int nfs4_xdr_enc_link(struct rpc_rqst *req, __be32 *p, const struct nfs4_
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 7,
+ .nops = 0,
};
int status;
+ __be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
- if ((status = encode_putfh(&xdr, args->fh)) != 0)
+ nops = encode_compound_hdr(&xdr, &hdr);
+ if ((status = encode_putfh(&xdr, args->fh, &hdr)) != 0)
goto out;
- if ((status = encode_savefh(&xdr)) != 0)
+ if ((status = encode_savefh(&xdr, &hdr)) != 0)
goto out;
- if ((status = encode_putfh(&xdr, args->dir_fh)) != 0)
+ if ((status = encode_putfh(&xdr, args->dir_fh, &hdr)) != 0)
goto out;
- if ((status = encode_link(&xdr, args->name)) != 0)
+ if ((status = encode_link(&xdr, args->name, &hdr)) != 0)
goto out;
- if ((status = encode_getfattr(&xdr, args->bitmask)) != 0)
+ if ((status = encode_getfattr(&xdr, args->bitmask, &hdr)) != 0)
goto out;
- if ((status = encode_restorefh(&xdr)) != 0)
+ if ((status = encode_restorefh(&xdr, &hdr)) != 0)
goto out;
- status = encode_getfattr(&xdr, args->bitmask);
+ status = encode_getfattr(&xdr, args->bitmask, &hdr);
out:
+ encode_nops(nops, &hdr);
return status;
}
@@ -1530,26 +1643,28 @@ static int nfs4_xdr_enc_create(struct rpc_rqst *req, __be32 *p, const struct nfs
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 7,
+ .nops = 0,
};
int status;
+ __be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
- if ((status = encode_putfh(&xdr, args->dir_fh)) != 0)
+ nops = encode_compound_hdr(&xdr, &hdr);
+ if ((status = encode_putfh(&xdr, args->dir_fh, &hdr)) != 0)
goto out;
- if ((status = encode_savefh(&xdr)) != 0)
+ if ((status = encode_savefh(&xdr, &hdr)) != 0)
goto out;
- if ((status = encode_create(&xdr, args)) != 0)
+ if ((status = encode_create(&xdr, args, &hdr)) != 0)
goto out;
- if ((status = encode_getfh(&xdr)) != 0)
+ if ((status = encode_getfh(&xdr, &hdr)) != 0)
goto out;
- if ((status = encode_getfattr(&xdr, args->bitmask)) != 0)
+ if ((status = encode_getfattr(&xdr, args->bitmask, &hdr)) != 0)
goto out;
- if ((status = encode_restorefh(&xdr)) != 0)
+ if ((status = encode_restorefh(&xdr, &hdr)) != 0)
goto out;
- status = encode_getfattr(&xdr, args->bitmask);
+ status = encode_getfattr(&xdr, args->bitmask, &hdr);
out:
+ encode_nops(nops, &hdr);
return status;
}
@@ -1568,14 +1683,16 @@ static int nfs4_xdr_enc_getattr(struct rpc_rqst *req, __be32 *p, const struct nf
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 2,
+ .nops = 0,
};
int status;
+ __be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
- if ((status = encode_putfh(&xdr, args->fh)) == 0)
- status = encode_getfattr(&xdr, args->bitmask);
+ nops = encode_compound_hdr(&xdr, &hdr);
+ if ((status = encode_putfh(&xdr, args->fh, &hdr)) == 0)
+ status = encode_getfattr(&xdr, args->bitmask, &hdr);
+ encode_nops(nops, &hdr);
return status;
}
@@ -1586,20 +1703,22 @@ static int nfs4_xdr_enc_close(struct rpc_rqst *req, __be32 *p, struct nfs_closea
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 3,
+ .nops = 0,
};
int status;
+ __be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
- status = encode_putfh(&xdr, args->fh);
+ nops = encode_compound_hdr(&xdr, &hdr);
+ status = encode_putfh(&xdr, args->fh, &hdr);
if(status)
goto out;
- status = encode_close(&xdr, args);
+ status = encode_close(&xdr, args, &hdr);
if (status != 0)
goto out;
- status = encode_getfattr(&xdr, args->bitmask);
+ status = encode_getfattr(&xdr, args->bitmask, &hdr);
out:
+ encode_nops(nops, &hdr);
return status;
}
@@ -1610,32 +1729,34 @@ static int nfs4_xdr_enc_open(struct rpc_rqst *req, __be32 *p, struct nfs_openarg
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 7,
+ .nops = 0,
};
int status;
+ __be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
- status = encode_putfh(&xdr, args->fh);
+ nops = encode_compound_hdr(&xdr, &hdr);
+ status = encode_putfh(&xdr, args->fh, &hdr);
if (status)
goto out;
- status = encode_savefh(&xdr);
+ status = encode_savefh(&xdr, &hdr);
if (status)
goto out;
- status = encode_open(&xdr, args);
+ status = encode_open(&xdr, args, &hdr);
if (status)
goto out;
- status = encode_getfh(&xdr);
+ status = encode_getfh(&xdr, &hdr);
if (status)
goto out;
- status = encode_getfattr(&xdr, args->bitmask);
+ status = encode_getfattr(&xdr, args->bitmask, &hdr);
if (status)
goto out;
- status = encode_restorefh(&xdr);
+ status = encode_restorefh(&xdr, &hdr);
if (status)
goto out;
- status = encode_getfattr(&xdr, args->bitmask);
+ status = encode_getfattr(&xdr, args->bitmask, &hdr);
out:
+ encode_nops(nops, &hdr);
return status;
}
@@ -1646,17 +1767,19 @@ static int nfs4_xdr_enc_open_confirm(struct rpc_rqst *req, __be32 *p, struct nfs
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 2,
+ .nops = 0,
};
int status;
+ __be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
- status = encode_putfh(&xdr, args->fh);
+ nops = encode_compound_hdr(&xdr, &hdr);
+ status = encode_putfh(&xdr, args->fh, &hdr);
if(status)
goto out;
- status = encode_open_confirm(&xdr, args);
+ status = encode_open_confirm(&xdr, args, &hdr);
out:
+ encode_nops(nops, &hdr);
return status;
}
@@ -1667,20 +1790,22 @@ static int nfs4_xdr_enc_open_noattr(struct rpc_rqst *req, __be32 *p, struct nfs_
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 3,
+ .nops = 0,
};
int status;
+ __be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
- status = encode_putfh(&xdr, args->fh);
+ nops = encode_compound_hdr(&xdr, &hdr);
+ status = encode_putfh(&xdr, args->fh, &hdr);
if (status)
goto out;
- status = encode_open(&xdr, args);
+ status = encode_open(&xdr, args, &hdr);
if (status)
goto out;
- status = encode_getfattr(&xdr, args->bitmask);
+ status = encode_getfattr(&xdr, args->bitmask, &hdr);
out:
+ encode_nops(nops, &hdr);
return status;
}
@@ -1691,20 +1816,22 @@ static int nfs4_xdr_enc_open_downgrade(struct rpc_rqst *req, __be32 *p, struct n
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 3,
+ .nops = 0,
};
int status;
+ __be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
- status = encode_putfh(&xdr, args->fh);
+ nops = encode_compound_hdr(&xdr, &hdr);
+ status = encode_putfh(&xdr, args->fh, &hdr);
if (status)
goto out;
- status = encode_open_downgrade(&xdr, args);
+ status = encode_open_downgrade(&xdr, args, &hdr);
if (status != 0)
goto out;
- status = encode_getfattr(&xdr, args->bitmask);
+ status = encode_getfattr(&xdr, args->bitmask, &hdr);
out:
+ encode_nops(nops, &hdr);
return status;
}
@@ -1715,17 +1842,19 @@ static int nfs4_xdr_enc_lock(struct rpc_rqst *req, __be32 *p, struct nfs_lock_ar
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 2,
+ .nops = 0,
};
int status;
+ __be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
- status = encode_putfh(&xdr, args->fh);
+ nops = encode_compound_hdr(&xdr, &hdr);
+ status = encode_putfh(&xdr, args->fh, &hdr);
if(status)
goto out;
- status = encode_lock(&xdr, args);
+ status = encode_lock(&xdr, args, &hdr);
out:
+ encode_nops(nops, &hdr);
return status;
}
@@ -1736,17 +1865,19 @@ static int nfs4_xdr_enc_lockt(struct rpc_rqst *req, __be32 *p, struct nfs_lockt_
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 2,
+ .nops = 0,
};
int status;
+ __be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
- status = encode_putfh(&xdr, args->fh);
+ nops = encode_compound_hdr(&xdr, &hdr);
+ status = encode_putfh(&xdr, args->fh, &hdr);
if(status)
goto out;
- status = encode_lockt(&xdr, args);
+ status = encode_lockt(&xdr, args, &hdr);
out:
+ encode_nops(nops, &hdr);
return status;
}
@@ -1757,17 +1888,19 @@ static int nfs4_xdr_enc_locku(struct rpc_rqst *req, __be32 *p, struct nfs_locku_
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 2,
+ .nops = 0,
};
int status;
+ __be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
- status = encode_putfh(&xdr, args->fh);
+ nops = encode_compound_hdr(&xdr, &hdr);
+ status = encode_putfh(&xdr, args->fh, &hdr);
if(status)
goto out;
- status = encode_locku(&xdr, args);
+ status = encode_locku(&xdr, args, &hdr);
out:
+ encode_nops(nops, &hdr);
return status;
}
@@ -1778,18 +1911,19 @@ static int nfs4_xdr_enc_readlink(struct rpc_rqst *req, __be32 *p, const struct n
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 2,
+ .nops = 0,
};
struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
unsigned int replen;
int status;
+ __be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
- status = encode_putfh(&xdr, args->fh);
+ nops = encode_compound_hdr(&xdr, &hdr);
+ status = encode_putfh(&xdr, args->fh, &hdr);
if(status)
goto out;
- status = encode_readlink(&xdr, args, req);
+ status = encode_readlink(&xdr, args, req, &hdr);
/* set up reply kvec
* toplevel_status + taglen + rescount + OP_PUTFH + status
@@ -1800,6 +1934,7 @@ static int nfs4_xdr_enc_readlink(struct rpc_rqst *req, __be32 *p, const struct n
args->pgbase, args->pglen);
out:
+ encode_nops(nops, &hdr);
return status;
}
@@ -1810,18 +1945,19 @@ static int nfs4_xdr_enc_readdir(struct rpc_rqst *req, __be32 *p, const struct nf
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 2,
+ .nops = 0,
};
struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
int replen;
int status;
+ __be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
- status = encode_putfh(&xdr, args->fh);
+ nops = encode_compound_hdr(&xdr, &hdr);
+ status = encode_putfh(&xdr, args->fh, &hdr);
if(status)
goto out;
- status = encode_readdir(&xdr, args, req);
+ status = encode_readdir(&xdr, args, req, &hdr);
/* set up reply kvec
* toplevel_status + taglen + rescount + OP_PUTFH + status
@@ -1835,6 +1971,7 @@ static int nfs4_xdr_enc_readdir(struct rpc_rqst *req, __be32 *p, const struct nf
args->pgbase, args->count);
out:
+ encode_nops(nops, &hdr);
return status;
}
@@ -1846,16 +1983,17 @@ static int nfs4_xdr_enc_read(struct rpc_rqst *req, __be32 *p, struct nfs_readarg
struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 2,
+ .nops = 0,
};
int replen, status;
+ __be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
- status = encode_putfh(&xdr, args->fh);
+ nops = encode_compound_hdr(&xdr, &hdr);
+ status = encode_putfh(&xdr, args->fh, &hdr);
if (status)
goto out;
- status = encode_read(&xdr, args);
+ status = encode_read(&xdr, args, &hdr);
if (status)
goto out;
@@ -1868,6 +2006,7 @@ static int nfs4_xdr_enc_read(struct rpc_rqst *req, __be32 *p, struct nfs_readarg
args->pages, args->pgbase, args->count);
req->rq_rcv_buf.flags |= XDRBUF_READ;
out:
+ encode_nops(nops, &hdr);
return status;
}
@@ -1877,23 +2016,25 @@ out:
static int nfs4_xdr_enc_setattr(struct rpc_rqst *req, __be32 *p, struct nfs_setattrargs *args)
{
- struct xdr_stream xdr;
- struct compound_hdr hdr = {
- .nops = 3,
- };
- int status;
+ struct xdr_stream xdr;
+ struct compound_hdr hdr = {
+ .nops = 0,
+ };
+ int status;
+ __be32 *nops;
- xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
- status = encode_putfh(&xdr, args->fh);
- if(status)
- goto out;
- status = encode_setattr(&xdr, args, args->server);
- if(status)
- goto out;
- status = encode_getfattr(&xdr, args->bitmask);
+ xdr_init_encode(&xdr, &req->rq_snd_buf, p);
+ nops = encode_compound_hdr(&xdr, &hdr);
+ status = encode_putfh(&xdr, args->fh, &hdr);
+ if (status)
+ goto out;
+ status = encode_setattr(&xdr, args, args->server, &hdr);
+ if (status)
+ goto out;
+ status = encode_getfattr(&xdr, args->bitmask, &hdr);
out:
- return status;
+ encode_nops(nops, &hdr);
+ return status;
}
/*
@@ -1906,21 +2047,23 @@ nfs4_xdr_enc_getacl(struct rpc_rqst *req, __be32 *p,
struct xdr_stream xdr;
struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
struct compound_hdr hdr = {
- .nops = 2,
+ .nops = 0,
};
int replen, status;
+ __be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
- status = encode_putfh(&xdr, args->fh);
+ nops = encode_compound_hdr(&xdr, &hdr);
+ status = encode_putfh(&xdr, args->fh, &hdr);
if (status)
goto out;
- status = encode_getattr_two(&xdr, FATTR4_WORD0_ACL, 0);
+ status = encode_getattr_two(&xdr, FATTR4_WORD0_ACL, 0, &hdr);
/* set up reply buffer: */
replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS4_dec_getacl_sz) << 2;
xdr_inline_pages(&req->rq_rcv_buf, replen,
args->acl_pages, args->acl_pgbase, args->acl_len);
out:
+ encode_nops(nops, &hdr);
return status;
}
@@ -1931,21 +2074,23 @@ static int nfs4_xdr_enc_write(struct rpc_rqst *req, __be32 *p, struct nfs_writea
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 3,
+ .nops = 0,
};
int status;
+ __be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
- status = encode_putfh(&xdr, args->fh);
+ nops = encode_compound_hdr(&xdr, &hdr);
+ status = encode_putfh(&xdr, args->fh, &hdr);
if (status)
goto out;
- status = encode_write(&xdr, args);
+ status = encode_write(&xdr, args, &hdr);
if (status)
goto out;
req->rq_snd_buf.flags |= XDRBUF_WRITE;
- status = encode_getfattr(&xdr, args->bitmask);
+ status = encode_getfattr(&xdr, args->bitmask, &hdr);
out:
+ encode_nops(nops, &hdr);
return status;
}
@@ -1956,20 +2101,22 @@ static int nfs4_xdr_enc_commit(struct rpc_rqst *req, __be32 *p, struct nfs_write
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 3,
+ .nops = 0,
};
int status;
+ __be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
- status = encode_putfh(&xdr, args->fh);
+ nops = encode_compound_hdr(&xdr, &hdr);
+ status = encode_putfh(&xdr, args->fh, &hdr);
if (status)
goto out;
- status = encode_commit(&xdr, args);
+ status = encode_commit(&xdr, args, &hdr);
if (status)
goto out;
- status = encode_getfattr(&xdr, args->bitmask);
+ status = encode_getfattr(&xdr, args->bitmask, &hdr);
out:
+ encode_nops(nops, &hdr);
return status;
}
@@ -1980,15 +2127,17 @@ static int nfs4_xdr_enc_fsinfo(struct rpc_rqst *req, __be32 *p, struct nfs4_fsin
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 2,
+ .nops = 0,
};
int status;
+ __be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
- status = encode_putfh(&xdr, args->fh);
+ nops = encode_compound_hdr(&xdr, &hdr);
+ status = encode_putfh(&xdr, args->fh, &hdr);
if (!status)
- status = encode_fsinfo(&xdr, args->bitmask);
+ status = encode_fsinfo(&xdr, args->bitmask, &hdr);
+ encode_nops(nops, &hdr);
return status;
}
@@ -1999,16 +2148,19 @@ static int nfs4_xdr_enc_pathconf(struct rpc_rqst *req, __be32 *p, const struct n
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 2,
+ .nops = 0,
};
int status;
+ __be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
- status = encode_putfh(&xdr, args->fh);
+ nops = encode_compound_hdr(&xdr, &hdr);
+ status = encode_putfh(&xdr, args->fh, &hdr);
if (!status)
status = encode_getattr_one(&xdr,
- args->bitmask[0] & nfs4_pathconf_bitmap[0]);
+ args->bitmask[0] & nfs4_pathconf_bitmap[0],
+ &hdr);
+ encode_nops(nops, &hdr);
return status;
}
@@ -2019,17 +2171,19 @@ static int nfs4_xdr_enc_statfs(struct rpc_rqst *req, __be32 *p, const struct nfs
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 2,
+ .nops = 0,
};
int status;
+ __be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
- status = encode_putfh(&xdr, args->fh);
+ nops = encode_compound_hdr(&xdr, &hdr);
+ status = encode_putfh(&xdr, args->fh, &hdr);
if (status == 0)
status = encode_getattr_two(&xdr,
args->bitmask[0] & nfs4_statfs_bitmap[0],
- args->bitmask[1] & nfs4_statfs_bitmap[1]);
+ args->bitmask[1] & nfs4_statfs_bitmap[1], &hdr);
+ encode_nops(nops, &hdr);
return status;
}
@@ -2040,18 +2194,20 @@ static int nfs4_xdr_enc_server_caps(struct rpc_rqst *req, __be32 *p, const struc
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 2,
+ .nops = 0,
};
int status;
+ __be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
- status = encode_putfh(&xdr, fhandle);
+ nops = encode_compound_hdr(&xdr, &hdr);
+ status = encode_putfh(&xdr, fhandle, &hdr);
if (status == 0)
status = encode_getattr_one(&xdr, FATTR4_WORD0_SUPPORTED_ATTRS|
FATTR4_WORD0_LINK_SUPPORT|
FATTR4_WORD0_SYMLINK_SUPPORT|
- FATTR4_WORD0_ACLSUPPORT);
+ FATTR4_WORD0_ACLSUPPORT, &hdr);
+ encode_nops(nops, &hdr);
return status;
}
@@ -2062,12 +2218,16 @@ static int nfs4_xdr_enc_renew(struct rpc_rqst *req, __be32 *p, struct nfs_client
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 1,
+ .nops = 0,
};
+ int status;
+ __be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
- return encode_renew(&xdr, clp);
+ nops = encode_compound_hdr(&xdr, &hdr);
+ status = encode_renew(&xdr, clp, &hdr);
+ encode_nops(nops, &hdr);
+ return status;
}
/*
@@ -2077,12 +2237,16 @@ static int nfs4_xdr_enc_setclientid(struct rpc_rqst *req, __be32 *p, struct nfs4
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 1,
+ .nops = 0,
};
+ int status;
+ __be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
- return encode_setclientid(&xdr, sc);
+ nops = encode_compound_hdr(&xdr, &hdr);
+ status = encode_setclientid(&xdr, sc, &hdr);
+ encode_nops(nops, &hdr);
+ return status;
}
/*
@@ -2092,18 +2256,20 @@ static int nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, __be32 *p, str
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 3,
+ .nops = 0,
};
const u32 lease_bitmap[2] = { FATTR4_WORD0_LEASE_TIME, 0 };
int status;
+ __be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
- status = encode_setclientid_confirm(&xdr, clp);
+ nops = encode_compound_hdr(&xdr, &hdr);
+ status = encode_setclientid_confirm(&xdr, clp, &hdr);
if (!status)
- status = encode_putrootfh(&xdr);
+ status = encode_putrootfh(&xdr, &hdr);
if (!status)
- status = encode_fsinfo(&xdr, lease_bitmap);
+ status = encode_fsinfo(&xdr, lease_bitmap, &hdr);
+ encode_nops(nops, &hdr);
return status;
}
@@ -2114,20 +2280,22 @@ static int nfs4_xdr_enc_delegreturn(struct rpc_rqst *req, __be32 *p, const struc
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 3,
+ .nops = 0,
};
int status;
+ __be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
- status = encode_putfh(&xdr, args->fhandle);
+ nops = encode_compound_hdr(&xdr, &hdr);
+ status = encode_putfh(&xdr, args->fhandle, &hdr);
if (status != 0)
goto out;
- status = encode_delegreturn(&xdr, args->stateid);
+ status = encode_delegreturn(&xdr, args->stateid, &hdr);
if (status != 0)
goto out;
- status = encode_getfattr(&xdr, args->bitmask);
+ status = encode_getfattr(&xdr, args->bitmask, &hdr);
out:
+ encode_nops(nops, &hdr);
return status;
}
@@ -2138,19 +2306,20 @@ static int nfs4_xdr_enc_fs_locations(struct rpc_rqst *req, __be32 *p, struct nfs
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 3,
+ .nops = 0,
};
struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
int replen;
int status;
+ __be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
- if ((status = encode_putfh(&xdr, args->dir_fh)) != 0)
+ nops = encode_compound_hdr(&xdr, &hdr);
+ if ((status = encode_putfh(&xdr, args->dir_fh, &hdr)) != 0)
goto out;
- if ((status = encode_lookup(&xdr, args->name)) != 0)
+ if ((status = encode_lookup(&xdr, args->name, &hdr)) != 0)
goto out;
- if ((status = encode_fs_locations(&xdr, args->bitmask)) != 0)
+ if ((status = encode_fs_locations(&xdr, args->bitmask, &hdr)) != 0)
goto out;
/* set up reply
* toplevel_status + OP_PUTFH + status
@@ -2160,6 +2329,7 @@ static int nfs4_xdr_enc_fs_locations(struct rpc_rqst *req, __be32 *p, struct nfs
xdr_inline_pages(&req->rq_rcv_buf, replen, &args->page,
0, PAGE_SIZE);
out:
+ encode_nops(nops, &hdr);
return status;
}
@@ -4036,20 +4206,22 @@ out:
static int
nfs4_xdr_enc_setacl(struct rpc_rqst *req, __be32 *p, struct nfs_setaclargs *args)
{
- struct xdr_stream xdr;
- struct compound_hdr hdr = {
- .nops = 2,
- };
- int status;
+ struct xdr_stream xdr;
+ struct compound_hdr hdr = {
+ .nops = 0,
+ };
+ int status;
+ __be32 *nops;
- xdr_init_encode(&xdr, &req->rq_snd_buf, p);
- encode_compound_hdr(&xdr, &hdr);
- status = encode_putfh(&xdr, args->fh);
- if (status)
- goto out;
- status = encode_setacl(&xdr, args);
+ xdr_init_encode(&xdr, &req->rq_snd_buf, p);
+ nops = encode_compound_hdr(&xdr, &hdr);
+ status = encode_putfh(&xdr, args->fh, &hdr);
+ if (status)
+ goto out;
+ status = encode_setacl(&xdr, args, &hdr);
out:
- return status;
+ encode_nops(nops, &hdr);
+ return status;
}
/*
* Decode SETACL response
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* Re: [pnfs] [RFC 04/85] FIXME: NFS: Increment operation number in each encode_* routine
2008-11-10 20:18 ` [RFC 04/85] FIXME: NFS: Increment operation number in each encode_* routine Benny Halevy
@ 2008-11-17 13:26 ` Benny Halevy
0 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-17 13:26 UTC (permalink / raw)
To: pnfs; +Cc: trond.myklebust, linux-nfs
On Nov. 10, 2008, 22:18 +0200, Benny Halevy <bhalevy@panasas.com> wrote:
> From: Andy Adamson <andros@netapp.com>
>
> FIXME: bhalevy: is this a good opportunity for a cleanup-only patch to fix whitespacing?
>
> Pass in the compound_hdr and bump the number of operations in each encode_*
> subroutine so as to allow us to more easily construct new compound statements.
>
> Fix tabs, do not fix 'do not use assignment in if condition' warnings.
>
> Signed-off-by: Andy Adamson<andros@netapp.com>
> Signed-off-by: Benny Halevy <bhalevy@panasas.com>
review 11-14: andy will submit:
* whitespace clenaup
* status removal
* move nops ptr into compound_hdr
> ---
> fs/nfs/nfs4xdr.c | 630 ++++++++++++++++++++++++++++++++++--------------------
> 1 files changed, 401 insertions(+), 229 deletions(-)
>
> diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
> index 69b5a56..c1ff9c9 100644
> --- a/fs/nfs/nfs4xdr.c
> +++ b/fs/nfs/nfs4xdr.c
> @@ -578,9 +578,10 @@ static void encode_string(struct xdr_stream *xdr, unsigned int len, const char *
> xdr_encode_opaque(p, str, len);
> }
>
> -static int encode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr)
> +static __u32 *
> +encode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr)
> {
> - __be32 *p;
> + __be32 *p, *nops;
>
> dprintk("encode_compound: tag=%.*s\n", (int)hdr->taglen, hdr->tag);
> BUG_ON(hdr->taglen > NFS4_MAXTAGLEN);
> @@ -588,8 +589,14 @@ static int encode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr)
> WRITE32(hdr->taglen);
> WRITEMEM(hdr->tag, hdr->taglen);
> WRITE32(NFS4_MINOR_VERSION);
> + nops = p;
> WRITE32(hdr->nops);
> - return 0;
> + return nops;
> +}
> +
> +static inline void encode_nops(__be32 *nops, struct compound_hdr *hdr)
> +{
> + *nops = htonl(hdr->nops);
> }
>
> static void encode_nfs4_verifier(struct xdr_stream *xdr, const nfs4_verifier *verf)
> @@ -728,18 +735,22 @@ static int encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const s
> return status;
> }
>
> -static int encode_access(struct xdr_stream *xdr, u32 access)
> +static int
> +encode_access(struct xdr_stream *xdr, u32 access, struct compound_hdr *hdr)
> {
> __be32 *p;
>
> RESERVE_SPACE(8);
> WRITE32(OP_ACCESS);
> WRITE32(access);
> -
> + hdr->nops++;
> +
> return 0;
> }
>
> -static int encode_close(struct xdr_stream *xdr, const struct nfs_closeargs *arg)
> +static int
> +encode_close(struct xdr_stream *xdr, const struct nfs_closeargs *arg,
> + struct compound_hdr *hdr)
> {
> __be32 *p;
>
> @@ -747,23 +758,29 @@ static int encode_close(struct xdr_stream *xdr, const struct nfs_closeargs *arg)
> WRITE32(OP_CLOSE);
> WRITE32(arg->seqid->sequence->counter);
> WRITEMEM(arg->stateid->data, NFS4_STATEID_SIZE);
> + hdr->nops++;
>
> return 0;
> }
>
> -static int encode_commit(struct xdr_stream *xdr, const struct nfs_writeargs *args)
> +static int
> +encode_commit(struct xdr_stream *xdr, const struct nfs_writeargs *args,
> + struct compound_hdr *hdr)
> {
> __be32 *p;
>
> - RESERVE_SPACE(16);
> - WRITE32(OP_COMMIT);
> - WRITE64(args->offset);
> - WRITE32(args->count);
> + RESERVE_SPACE(16);
> + WRITE32(OP_COMMIT);
> + WRITE64(args->offset);
> + WRITE32(args->count);
> + hdr->nops++;
>
> - return 0;
> + return 0;
> }
>
> -static int encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg *create)
> +static int
> +encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg *create,
> + struct compound_hdr *hdr)
> {
> __be32 *p;
>
> @@ -791,11 +808,14 @@ static int encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg *c
> RESERVE_SPACE(4 + create->name->len);
> WRITE32(create->name->len);
> WRITEMEM(create->name->name, create->name->len);
> + hdr->nops++;
>
> return encode_attrs(xdr, create->attrs, create->server);
> }
>
> -static int encode_getattr_one(struct xdr_stream *xdr, uint32_t bitmap)
> +static int
> +encode_getattr_one(struct xdr_stream *xdr, uint32_t bitmap,
> + struct compound_hdr *hdr)
> {
> __be32 *p;
>
> @@ -803,10 +823,13 @@ static int encode_getattr_one(struct xdr_stream *xdr, uint32_t bitmap)
> WRITE32(OP_GETATTR);
> WRITE32(1);
> WRITE32(bitmap);
> + hdr->nops++;
> return 0;
> }
>
> -static int encode_getattr_two(struct xdr_stream *xdr, uint32_t bm0, uint32_t bm1)
> +static int
> +encode_getattr_two(struct xdr_stream *xdr, uint32_t bm0, uint32_t bm1,
> + struct compound_hdr *hdr)
> {
> __be32 *p;
>
> @@ -815,40 +838,51 @@ static int encode_getattr_two(struct xdr_stream *xdr, uint32_t bm0, uint32_t bm1
> WRITE32(2);
> WRITE32(bm0);
> WRITE32(bm1);
> + hdr->nops++;
> return 0;
> }
>
> -static int encode_getfattr(struct xdr_stream *xdr, const u32* bitmask)
> +static int
> +encode_getfattr(struct xdr_stream *xdr, const u32 *bitmask,
> + struct compound_hdr *hdr)
> {
> return encode_getattr_two(xdr,
> bitmask[0] & nfs4_fattr_bitmap[0],
> - bitmask[1] & nfs4_fattr_bitmap[1]);
> + bitmask[1] & nfs4_fattr_bitmap[1], hdr);
> }
>
> -static int encode_fsinfo(struct xdr_stream *xdr, const u32* bitmask)
> +static int
> +encode_fsinfo(struct xdr_stream *xdr, const u32 *bitmask,
> + struct compound_hdr *hdr)
> {
> return encode_getattr_two(xdr, bitmask[0] & nfs4_fsinfo_bitmap[0],
> - bitmask[1] & nfs4_fsinfo_bitmap[1]);
> + bitmask[1] & nfs4_fsinfo_bitmap[1], hdr);
> }
>
> -static int encode_fs_locations(struct xdr_stream *xdr, const u32* bitmask)
> +static int
> +encode_fs_locations(struct xdr_stream *xdr, const u32 *bitmask,
> + struct compound_hdr *hdr)
> {
> return encode_getattr_two(xdr,
> bitmask[0] & nfs4_fs_locations_bitmap[0],
> - bitmask[1] & nfs4_fs_locations_bitmap[1]);
> + bitmask[1] & nfs4_fs_locations_bitmap[1],
> + hdr);
> }
>
> -static int encode_getfh(struct xdr_stream *xdr)
> +static int encode_getfh(struct xdr_stream *xdr, struct compound_hdr *hdr)
> {
> __be32 *p;
>
> RESERVE_SPACE(4);
> WRITE32(OP_GETFH);
> + hdr->nops++;
>
> return 0;
> }
>
> -static int encode_link(struct xdr_stream *xdr, const struct qstr *name)
> +static int
> +encode_link(struct xdr_stream *xdr, const struct qstr *name,
> + struct compound_hdr *hdr)
> {
> __be32 *p;
>
> @@ -856,6 +890,7 @@ static int encode_link(struct xdr_stream *xdr, const struct qstr *name)
> WRITE32(OP_LINK);
> WRITE32(name->len);
> WRITEMEM(name->name, name->len);
> + hdr->nops++;
>
> return 0;
> }
> @@ -878,7 +913,9 @@ static inline uint64_t nfs4_lock_length(struct file_lock *fl)
> * opcode,type,reclaim,offset,length,new_lock_owner = 32
> * open_seqid,open_stateid,lock_seqid,lock_owner.clientid, lock_owner.id = 40
> */
> -static int encode_lock(struct xdr_stream *xdr, const struct nfs_lock_args *args)
> +static int
> +encode_lock(struct xdr_stream *xdr, const struct nfs_lock_args *args,
> + struct compound_hdr *hdr)
> {
> __be32 *p;
>
> @@ -904,11 +941,14 @@ static int encode_lock(struct xdr_stream *xdr, const struct nfs_lock_args *args)
> WRITEMEM(args->lock_stateid->data, NFS4_STATEID_SIZE);
> WRITE32(args->lock_seqid->sequence->counter);
> }
> + hdr->nops++;
>
> return 0;
> }
>
> -static int encode_lockt(struct xdr_stream *xdr, const struct nfs_lockt_args *args)
> +static int
> +encode_lockt(struct xdr_stream *xdr, const struct nfs_lockt_args *args,
> + struct compound_hdr *hdr)
> {
> __be32 *p;
>
> @@ -921,11 +961,14 @@ static int encode_lockt(struct xdr_stream *xdr, const struct nfs_lockt_args *arg
> WRITE32(16);
> WRITEMEM("lock id:", 8);
> WRITE64(args->lock_owner.id);
> + hdr->nops++;
>
> return 0;
> }
>
> -static int encode_locku(struct xdr_stream *xdr, const struct nfs_locku_args *args)
> +static int
> +encode_locku(struct xdr_stream *xdr, const struct nfs_locku_args *args,
> + struct compound_hdr *hdr)
> {
> __be32 *p;
>
> @@ -936,11 +979,14 @@ static int encode_locku(struct xdr_stream *xdr, const struct nfs_locku_args *arg
> WRITEMEM(args->stateid->data, NFS4_STATEID_SIZE);
> WRITE64(args->fl->fl_start);
> WRITE64(nfs4_lock_length(args->fl));
> + hdr->nops++;
>
> return 0;
> }
>
> -static int encode_lookup(struct xdr_stream *xdr, const struct qstr *name)
> +static int
> +encode_lookup(struct xdr_stream *xdr, const struct qstr *name,
> + struct compound_hdr *hdr)
> {
> int len = name->len;
> __be32 *p;
> @@ -949,6 +995,7 @@ static int encode_lookup(struct xdr_stream *xdr, const struct qstr *name)
> WRITE32(OP_LOOKUP);
> WRITE32(len);
> WRITEMEM(name->name, len);
> + hdr->nops++;
>
> return 0;
> }
> @@ -1072,7 +1119,9 @@ static inline void encode_claim_delegate_cur(struct xdr_stream *xdr, const struc
> encode_string(xdr, name->len, name->name);
> }
>
> -static int encode_open(struct xdr_stream *xdr, const struct nfs_openargs *arg)
> +static int
> +encode_open(struct xdr_stream *xdr, const struct nfs_openargs *arg,
> + struct compound_hdr *hdr)
> {
> encode_openhdr(xdr, arg);
> encode_opentype(xdr, arg);
> @@ -1089,10 +1138,14 @@ static int encode_open(struct xdr_stream *xdr, const struct nfs_openargs *arg)
> default:
> BUG();
> }
> + hdr->nops++;
> return 0;
> }
>
> -static int encode_open_confirm(struct xdr_stream *xdr, const struct nfs_open_confirmargs *arg)
> +static int
> +encode_open_confirm(struct xdr_stream *xdr,
> + const struct nfs_open_confirmargs *arg,
> + struct compound_hdr *hdr)
> {
> __be32 *p;
>
> @@ -1100,11 +1153,14 @@ static int encode_open_confirm(struct xdr_stream *xdr, const struct nfs_open_con
> WRITE32(OP_OPEN_CONFIRM);
> WRITEMEM(arg->stateid->data, NFS4_STATEID_SIZE);
> WRITE32(arg->seqid->sequence->counter);
> + hdr->nops++;
>
> return 0;
> }
>
> -static int encode_open_downgrade(struct xdr_stream *xdr, const struct nfs_closeargs *arg)
> +static int
> +encode_open_downgrade(struct xdr_stream *xdr, const struct nfs_closeargs *arg,
> + struct compound_hdr *hdr)
> {
> __be32 *p;
>
> @@ -1113,11 +1169,13 @@ static int encode_open_downgrade(struct xdr_stream *xdr, const struct nfs_closea
> WRITEMEM(arg->stateid->data, NFS4_STATEID_SIZE);
> WRITE32(arg->seqid->sequence->counter);
> encode_share_access(xdr, arg->open_flags);
> + hdr->nops++;
> return 0;
> }
>
> static int
> -encode_putfh(struct xdr_stream *xdr, const struct nfs_fh *fh)
> +encode_putfh(struct xdr_stream *xdr, const struct nfs_fh *fh,
> + struct compound_hdr *hdr)
> {
> int len = fh->size;
> __be32 *p;
> @@ -1126,21 +1184,24 @@ encode_putfh(struct xdr_stream *xdr, const struct nfs_fh *fh)
> WRITE32(OP_PUTFH);
> WRITE32(len);
> WRITEMEM(fh->data, len);
> + hdr->nops++;
>
> return 0;
> }
>
> -static int encode_putrootfh(struct xdr_stream *xdr)
> +static int encode_putrootfh(struct xdr_stream *xdr, struct compound_hdr *hdr)
> {
> __be32 *p;
>
> RESERVE_SPACE(4);
> WRITE32(OP_PUTROOTFH);
> + hdr->nops++;
>
> return 0;
> }
>
> -static void encode_stateid(struct xdr_stream *xdr, const struct nfs_open_context *ctx)
> +static void
> +encode_stateid(struct xdr_stream *xdr, const struct nfs_open_context *ctx)
> {
> nfs4_stateid stateid;
> __be32 *p;
> @@ -1153,7 +1214,9 @@ static void encode_stateid(struct xdr_stream *xdr, const struct nfs_open_context
> WRITEMEM(zero_stateid.data, NFS4_STATEID_SIZE);
> }
>
> -static int encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args)
> +static int
> +encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args,
> + struct compound_hdr *hdr)
> {
> __be32 *p;
>
> @@ -1165,11 +1228,14 @@ static int encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args)
> RESERVE_SPACE(12);
> WRITE64(args->offset);
> WRITE32(args->count);
> + hdr->nops++;
>
> return 0;
> }
>
> -static int encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req)
> +static int
> +encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir,
> + struct rpc_rqst *req, struct compound_hdr *hdr)
> {
> uint32_t attrs[2] = {
> FATTR4_WORD0_RDATTR_ERROR|FATTR4_WORD0_FILEID,
> @@ -1191,6 +1257,7 @@ static int encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg
> attrs[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID;
> WRITE32(attrs[0] & readdir->bitmask[0]);
> WRITE32(attrs[1] & readdir->bitmask[1]);
> + hdr->nops++;
> dprintk("%s: cookie = %Lu, verifier = %08x:%08x, bitmap = %08x:%08x\n",
> __func__,
> (unsigned long long)readdir->cookie,
> @@ -1202,17 +1269,22 @@ static int encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg
> return 0;
> }
>
> -static int encode_readlink(struct xdr_stream *xdr, const struct nfs4_readlink *readlink, struct rpc_rqst *req)
> +static int
> +encode_readlink(struct xdr_stream *xdr, const struct nfs4_readlink *readlink,
> + struct rpc_rqst *req, struct compound_hdr *hdr)
> {
> __be32 *p;
>
> RESERVE_SPACE(4);
> WRITE32(OP_READLINK);
> + hdr->nops++;
>
> return 0;
> }
>
> -static int encode_remove(struct xdr_stream *xdr, const struct qstr *name)
> +static int
> +encode_remove(struct xdr_stream *xdr, const struct qstr *name,
> + struct compound_hdr *hdr)
> {
> __be32 *p;
>
> @@ -1220,11 +1292,14 @@ static int encode_remove(struct xdr_stream *xdr, const struct qstr *name)
> WRITE32(OP_REMOVE);
> WRITE32(name->len);
> WRITEMEM(name->name, name->len);
> + hdr->nops++;
>
> return 0;
> }
>
> -static int encode_rename(struct xdr_stream *xdr, const struct qstr *oldname, const struct qstr *newname)
> +static int
> +encode_rename(struct xdr_stream *xdr, const struct qstr *oldname,
> + const struct qstr *newname, struct compound_hdr *hdr)
> {
> __be32 *p;
>
> @@ -1236,34 +1311,40 @@ static int encode_rename(struct xdr_stream *xdr, const struct qstr *oldname, con
> RESERVE_SPACE(4 + newname->len);
> WRITE32(newname->len);
> WRITEMEM(newname->name, newname->len);
> + hdr->nops++;
>
> return 0;
> }
>
> -static int encode_renew(struct xdr_stream *xdr, const struct nfs_client *client_stateid)
> +static int
> +encode_renew(struct xdr_stream *xdr, const struct nfs_client *client_stateid,
> + struct compound_hdr *hdr)
> {
> __be32 *p;
>
> RESERVE_SPACE(12);
> WRITE32(OP_RENEW);
> WRITE64(client_stateid->cl_clientid);
> + hdr->nops++;
>
> return 0;
> }
>
> static int
> -encode_restorefh(struct xdr_stream *xdr)
> +encode_restorefh(struct xdr_stream *xdr, struct compound_hdr *hdr)
> {
> __be32 *p;
>
> RESERVE_SPACE(4);
> WRITE32(OP_RESTOREFH);
> + hdr->nops++;
>
> return 0;
> }
>
> static int
> -encode_setacl(struct xdr_stream *xdr, struct nfs_setaclargs *arg)
> +encode_setacl(struct xdr_stream *xdr, struct nfs_setaclargs *arg,
> + struct compound_hdr *hdr)
> {
> __be32 *p;
>
> @@ -1278,21 +1359,25 @@ encode_setacl(struct xdr_stream *xdr, struct nfs_setaclargs *arg)
> RESERVE_SPACE(4);
> WRITE32(arg->acl_len);
> xdr_write_pages(xdr, arg->acl_pages, arg->acl_pgbase, arg->acl_len);
> + hdr->nops++;
> return 0;
> }
>
> static int
> -encode_savefh(struct xdr_stream *xdr)
> +encode_savefh(struct xdr_stream *xdr, struct compound_hdr *hdr)
> {
> __be32 *p;
>
> RESERVE_SPACE(4);
> WRITE32(OP_SAVEFH);
> + hdr->nops++;
>
> return 0;
> }
>
> -static int encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs *arg, const struct nfs_server *server)
> +static int
> +encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs *arg,
> + const struct nfs_server *server, struct compound_hdr *hdr)
> {
> int status;
> __be32 *p;
> @@ -1300,6 +1385,7 @@ static int encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs *
> RESERVE_SPACE(4+NFS4_STATEID_SIZE);
> WRITE32(OP_SETATTR);
> WRITEMEM(arg->stateid.data, NFS4_STATEID_SIZE);
> + hdr->nops++;
>
> if ((status = encode_attrs(xdr, arg->iap, server)))
> return status;
> @@ -1307,7 +1393,10 @@ static int encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs *
> return 0;
> }
>
> -static int encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclientid *setclientid)
> +static int
> +encode_setclientid(struct xdr_stream *xdr,
> + const struct nfs4_setclientid *setclientid,
> + struct compound_hdr *hdr)
> {
> __be32 *p;
>
> @@ -1322,11 +1411,15 @@ static int encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclien
> encode_string(xdr, setclientid->sc_uaddr_len, setclientid->sc_uaddr);
> RESERVE_SPACE(4);
> WRITE32(setclientid->sc_cb_ident);
> + hdr->nops++;
>
> return 0;
> }
>
> -static int encode_setclientid_confirm(struct xdr_stream *xdr, const struct nfs_client *client_state)
> +static int
> +encode_setclientid_confirm(struct xdr_stream *xdr,
> + const struct nfs_client *client_state,
> + struct compound_hdr *hdr)
> {
> __be32 *p;
>
> @@ -1334,11 +1427,14 @@ static int encode_setclientid_confirm(struct xdr_stream *xdr, const struct nfs_c
> WRITE32(OP_SETCLIENTID_CONFIRM);
> WRITE64(client_state->cl_clientid);
> WRITEMEM(client_state->cl_confirm.data, NFS4_VERIFIER_SIZE);
> + hdr->nops++;
>
> return 0;
> }
>
> -static int encode_write(struct xdr_stream *xdr, const struct nfs_writeargs *args)
> +static int
> +encode_write(struct xdr_stream *xdr, const struct nfs_writeargs *args,
> + struct compound_hdr *hdr)
> {
> __be32 *p;
>
> @@ -1353,11 +1449,14 @@ static int encode_write(struct xdr_stream *xdr, const struct nfs_writeargs *args
> WRITE32(args->count);
>
> xdr_write_pages(xdr, args->pages, args->pgbase, args->count);
> + hdr->nops++;
>
> return 0;
> }
>
> -static int encode_delegreturn(struct xdr_stream *xdr, const nfs4_stateid *stateid)
> +static int
> +encode_delegreturn(struct xdr_stream *xdr, const nfs4_stateid *stateid,
> + struct compound_hdr *hdr)
> {
> __be32 *p;
>
> @@ -1365,6 +1464,7 @@ static int encode_delegreturn(struct xdr_stream *xdr, const nfs4_stateid *statei
>
> WRITE32(OP_DELEGRETURN);
> WRITEMEM(stateid->data, NFS4_STATEID_SIZE);
> + hdr->nops++;
> return 0;
>
> }
> @@ -1379,20 +1479,22 @@ static int nfs4_xdr_enc_access(struct rpc_rqst *req, __be32 *p, const struct nfs
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 3,
> + .nops = 0,
> };
> int status;
> + __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> - encode_compound_hdr(&xdr, &hdr);
> - status = encode_putfh(&xdr, args->fh);
> + nops = encode_compound_hdr(&xdr, &hdr);
> + status = encode_putfh(&xdr, args->fh, &hdr);
> if (status != 0)
> goto out;
> - status = encode_access(&xdr, args->access);
> + status = encode_access(&xdr, args->access, &hdr);
> if (status != 0)
> goto out;
> - status = encode_getfattr(&xdr, args->bitmask);
> + status = encode_getfattr(&xdr, args->bitmask, &hdr);
> out:
> + encode_nops(nops, &hdr);
> return status;
> }
>
> @@ -1403,20 +1505,22 @@ static int nfs4_xdr_enc_lookup(struct rpc_rqst *req, __be32 *p, const struct nfs
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 4,
> + .nops = 0,
> };
> int status;
> + __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> - encode_compound_hdr(&xdr, &hdr);
> - if ((status = encode_putfh(&xdr, args->dir_fh)) != 0)
> + nops = encode_compound_hdr(&xdr, &hdr);
> + if ((status = encode_putfh(&xdr, args->dir_fh, &hdr)) != 0)
> goto out;
> - if ((status = encode_lookup(&xdr, args->name)) != 0)
> + if ((status = encode_lookup(&xdr, args->name, &hdr)) != 0)
> goto out;
> - if ((status = encode_getfh(&xdr)) != 0)
> + if ((status = encode_getfh(&xdr, &hdr)) != 0)
> goto out;
> - status = encode_getfattr(&xdr, args->bitmask);
> + status = encode_getfattr(&xdr, args->bitmask, &hdr);
> out:
> + encode_nops(nops, &hdr);
> return status;
> }
>
> @@ -1427,17 +1531,19 @@ static int nfs4_xdr_enc_lookup_root(struct rpc_rqst *req, __be32 *p, const struc
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 3,
> + .nops = 0,
> };
> int status;
> + __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> - encode_compound_hdr(&xdr, &hdr);
> - if ((status = encode_putrootfh(&xdr)) != 0)
> + nops = encode_compound_hdr(&xdr, &hdr);
> + if ((status = encode_putrootfh(&xdr, &hdr)) != 0)
> goto out;
> - if ((status = encode_getfh(&xdr)) == 0)
> - status = encode_getfattr(&xdr, args->bitmask);
> + if ((status = encode_getfh(&xdr, &hdr)) == 0)
> + status = encode_getfattr(&xdr, args->bitmask, &hdr);
> out:
> + encode_nops(nops, &hdr);
> return status;
> }
>
> @@ -1448,18 +1554,20 @@ static int nfs4_xdr_enc_remove(struct rpc_rqst *req, __be32 *p, const struct nfs
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 3,
> + .nops = 0,
> };
> int status;
> + __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> - encode_compound_hdr(&xdr, &hdr);
> - if ((status = encode_putfh(&xdr, args->fh)) != 0)
> + nops = encode_compound_hdr(&xdr, &hdr);
> + if ((status = encode_putfh(&xdr, args->fh, &hdr)) != 0)
> goto out;
> - if ((status = encode_remove(&xdr, &args->name)) != 0)
> + if ((status = encode_remove(&xdr, &args->name, &hdr)) != 0)
> goto out;
> - status = encode_getfattr(&xdr, args->bitmask);
> + status = encode_getfattr(&xdr, args->bitmask, &hdr);
> out:
> + encode_nops(nops, &hdr);
> return status;
> }
>
> @@ -1470,26 +1578,29 @@ static int nfs4_xdr_enc_rename(struct rpc_rqst *req, __be32 *p, const struct nfs
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 7,
> + .nops = 0,
> };
> int status;
> + __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> - encode_compound_hdr(&xdr, &hdr);
> - if ((status = encode_putfh(&xdr, args->old_dir)) != 0)
> + nops = encode_compound_hdr(&xdr, &hdr);
> + if ((status = encode_putfh(&xdr, args->old_dir, &hdr)) != 0)
> goto out;
> - if ((status = encode_savefh(&xdr)) != 0)
> + if ((status = encode_savefh(&xdr, &hdr)) != 0)
> goto out;
> - if ((status = encode_putfh(&xdr, args->new_dir)) != 0)
> + if ((status = encode_putfh(&xdr, args->new_dir, &hdr)) != 0)
> goto out;
> - if ((status = encode_rename(&xdr, args->old_name, args->new_name)) != 0)
> + if ((status = encode_rename(&xdr, args->old_name, args->new_name,
> + &hdr)) != 0)
> goto out;
> - if ((status = encode_getfattr(&xdr, args->bitmask)) != 0)
> + if ((status = encode_getfattr(&xdr, args->bitmask, &hdr)) != 0)
> goto out;
> - if ((status = encode_restorefh(&xdr)) != 0)
> + if ((status = encode_restorefh(&xdr, &hdr)) != 0)
> goto out;
> - status = encode_getfattr(&xdr, args->bitmask);
> + status = encode_getfattr(&xdr, args->bitmask, &hdr);
> out:
> + encode_nops(nops, &hdr);
> return status;
> }
>
> @@ -1500,26 +1611,28 @@ static int nfs4_xdr_enc_link(struct rpc_rqst *req, __be32 *p, const struct nfs4_
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 7,
> + .nops = 0,
> };
> int status;
> + __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> - encode_compound_hdr(&xdr, &hdr);
> - if ((status = encode_putfh(&xdr, args->fh)) != 0)
> + nops = encode_compound_hdr(&xdr, &hdr);
> + if ((status = encode_putfh(&xdr, args->fh, &hdr)) != 0)
> goto out;
> - if ((status = encode_savefh(&xdr)) != 0)
> + if ((status = encode_savefh(&xdr, &hdr)) != 0)
> goto out;
> - if ((status = encode_putfh(&xdr, args->dir_fh)) != 0)
> + if ((status = encode_putfh(&xdr, args->dir_fh, &hdr)) != 0)
> goto out;
> - if ((status = encode_link(&xdr, args->name)) != 0)
> + if ((status = encode_link(&xdr, args->name, &hdr)) != 0)
> goto out;
> - if ((status = encode_getfattr(&xdr, args->bitmask)) != 0)
> + if ((status = encode_getfattr(&xdr, args->bitmask, &hdr)) != 0)
> goto out;
> - if ((status = encode_restorefh(&xdr)) != 0)
> + if ((status = encode_restorefh(&xdr, &hdr)) != 0)
> goto out;
> - status = encode_getfattr(&xdr, args->bitmask);
> + status = encode_getfattr(&xdr, args->bitmask, &hdr);
> out:
> + encode_nops(nops, &hdr);
> return status;
> }
>
> @@ -1530,26 +1643,28 @@ static int nfs4_xdr_enc_create(struct rpc_rqst *req, __be32 *p, const struct nfs
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 7,
> + .nops = 0,
> };
> int status;
> + __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> - encode_compound_hdr(&xdr, &hdr);
> - if ((status = encode_putfh(&xdr, args->dir_fh)) != 0)
> + nops = encode_compound_hdr(&xdr, &hdr);
> + if ((status = encode_putfh(&xdr, args->dir_fh, &hdr)) != 0)
> goto out;
> - if ((status = encode_savefh(&xdr)) != 0)
> + if ((status = encode_savefh(&xdr, &hdr)) != 0)
> goto out;
> - if ((status = encode_create(&xdr, args)) != 0)
> + if ((status = encode_create(&xdr, args, &hdr)) != 0)
> goto out;
> - if ((status = encode_getfh(&xdr)) != 0)
> + if ((status = encode_getfh(&xdr, &hdr)) != 0)
> goto out;
> - if ((status = encode_getfattr(&xdr, args->bitmask)) != 0)
> + if ((status = encode_getfattr(&xdr, args->bitmask, &hdr)) != 0)
> goto out;
> - if ((status = encode_restorefh(&xdr)) != 0)
> + if ((status = encode_restorefh(&xdr, &hdr)) != 0)
> goto out;
> - status = encode_getfattr(&xdr, args->bitmask);
> + status = encode_getfattr(&xdr, args->bitmask, &hdr);
> out:
> + encode_nops(nops, &hdr);
> return status;
> }
>
> @@ -1568,14 +1683,16 @@ static int nfs4_xdr_enc_getattr(struct rpc_rqst *req, __be32 *p, const struct nf
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 2,
> + .nops = 0,
> };
> int status;
> + __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> - encode_compound_hdr(&xdr, &hdr);
> - if ((status = encode_putfh(&xdr, args->fh)) == 0)
> - status = encode_getfattr(&xdr, args->bitmask);
> + nops = encode_compound_hdr(&xdr, &hdr);
> + if ((status = encode_putfh(&xdr, args->fh, &hdr)) == 0)
> + status = encode_getfattr(&xdr, args->bitmask, &hdr);
> + encode_nops(nops, &hdr);
> return status;
> }
>
> @@ -1586,20 +1703,22 @@ static int nfs4_xdr_enc_close(struct rpc_rqst *req, __be32 *p, struct nfs_closea
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 3,
> + .nops = 0,
> };
> int status;
> + __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> - encode_compound_hdr(&xdr, &hdr);
> - status = encode_putfh(&xdr, args->fh);
> + nops = encode_compound_hdr(&xdr, &hdr);
> + status = encode_putfh(&xdr, args->fh, &hdr);
> if(status)
> goto out;
> - status = encode_close(&xdr, args);
> + status = encode_close(&xdr, args, &hdr);
> if (status != 0)
> goto out;
> - status = encode_getfattr(&xdr, args->bitmask);
> + status = encode_getfattr(&xdr, args->bitmask, &hdr);
> out:
> + encode_nops(nops, &hdr);
> return status;
> }
>
> @@ -1610,32 +1729,34 @@ static int nfs4_xdr_enc_open(struct rpc_rqst *req, __be32 *p, struct nfs_openarg
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 7,
> + .nops = 0,
> };
> int status;
> + __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> - encode_compound_hdr(&xdr, &hdr);
> - status = encode_putfh(&xdr, args->fh);
> + nops = encode_compound_hdr(&xdr, &hdr);
> + status = encode_putfh(&xdr, args->fh, &hdr);
> if (status)
> goto out;
> - status = encode_savefh(&xdr);
> + status = encode_savefh(&xdr, &hdr);
> if (status)
> goto out;
> - status = encode_open(&xdr, args);
> + status = encode_open(&xdr, args, &hdr);
> if (status)
> goto out;
> - status = encode_getfh(&xdr);
> + status = encode_getfh(&xdr, &hdr);
> if (status)
> goto out;
> - status = encode_getfattr(&xdr, args->bitmask);
> + status = encode_getfattr(&xdr, args->bitmask, &hdr);
> if (status)
> goto out;
> - status = encode_restorefh(&xdr);
> + status = encode_restorefh(&xdr, &hdr);
> if (status)
> goto out;
> - status = encode_getfattr(&xdr, args->bitmask);
> + status = encode_getfattr(&xdr, args->bitmask, &hdr);
> out:
> + encode_nops(nops, &hdr);
> return status;
> }
>
> @@ -1646,17 +1767,19 @@ static int nfs4_xdr_enc_open_confirm(struct rpc_rqst *req, __be32 *p, struct nfs
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 2,
> + .nops = 0,
> };
> int status;
> + __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> - encode_compound_hdr(&xdr, &hdr);
> - status = encode_putfh(&xdr, args->fh);
> + nops = encode_compound_hdr(&xdr, &hdr);
> + status = encode_putfh(&xdr, args->fh, &hdr);
> if(status)
> goto out;
> - status = encode_open_confirm(&xdr, args);
> + status = encode_open_confirm(&xdr, args, &hdr);
> out:
> + encode_nops(nops, &hdr);
> return status;
> }
>
> @@ -1667,20 +1790,22 @@ static int nfs4_xdr_enc_open_noattr(struct rpc_rqst *req, __be32 *p, struct nfs_
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 3,
> + .nops = 0,
> };
> int status;
> + __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> - encode_compound_hdr(&xdr, &hdr);
> - status = encode_putfh(&xdr, args->fh);
> + nops = encode_compound_hdr(&xdr, &hdr);
> + status = encode_putfh(&xdr, args->fh, &hdr);
> if (status)
> goto out;
> - status = encode_open(&xdr, args);
> + status = encode_open(&xdr, args, &hdr);
> if (status)
> goto out;
> - status = encode_getfattr(&xdr, args->bitmask);
> + status = encode_getfattr(&xdr, args->bitmask, &hdr);
> out:
> + encode_nops(nops, &hdr);
> return status;
> }
>
> @@ -1691,20 +1816,22 @@ static int nfs4_xdr_enc_open_downgrade(struct rpc_rqst *req, __be32 *p, struct n
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 3,
> + .nops = 0,
> };
> int status;
> + __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> - encode_compound_hdr(&xdr, &hdr);
> - status = encode_putfh(&xdr, args->fh);
> + nops = encode_compound_hdr(&xdr, &hdr);
> + status = encode_putfh(&xdr, args->fh, &hdr);
> if (status)
> goto out;
> - status = encode_open_downgrade(&xdr, args);
> + status = encode_open_downgrade(&xdr, args, &hdr);
> if (status != 0)
> goto out;
> - status = encode_getfattr(&xdr, args->bitmask);
> + status = encode_getfattr(&xdr, args->bitmask, &hdr);
> out:
> + encode_nops(nops, &hdr);
> return status;
> }
>
> @@ -1715,17 +1842,19 @@ static int nfs4_xdr_enc_lock(struct rpc_rqst *req, __be32 *p, struct nfs_lock_ar
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 2,
> + .nops = 0,
> };
> int status;
> + __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> - encode_compound_hdr(&xdr, &hdr);
> - status = encode_putfh(&xdr, args->fh);
> + nops = encode_compound_hdr(&xdr, &hdr);
> + status = encode_putfh(&xdr, args->fh, &hdr);
> if(status)
> goto out;
> - status = encode_lock(&xdr, args);
> + status = encode_lock(&xdr, args, &hdr);
> out:
> + encode_nops(nops, &hdr);
> return status;
> }
>
> @@ -1736,17 +1865,19 @@ static int nfs4_xdr_enc_lockt(struct rpc_rqst *req, __be32 *p, struct nfs_lockt_
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 2,
> + .nops = 0,
> };
> int status;
> + __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> - encode_compound_hdr(&xdr, &hdr);
> - status = encode_putfh(&xdr, args->fh);
> + nops = encode_compound_hdr(&xdr, &hdr);
> + status = encode_putfh(&xdr, args->fh, &hdr);
> if(status)
> goto out;
> - status = encode_lockt(&xdr, args);
> + status = encode_lockt(&xdr, args, &hdr);
> out:
> + encode_nops(nops, &hdr);
> return status;
> }
>
> @@ -1757,17 +1888,19 @@ static int nfs4_xdr_enc_locku(struct rpc_rqst *req, __be32 *p, struct nfs_locku_
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 2,
> + .nops = 0,
> };
> int status;
> + __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> - encode_compound_hdr(&xdr, &hdr);
> - status = encode_putfh(&xdr, args->fh);
> + nops = encode_compound_hdr(&xdr, &hdr);
> + status = encode_putfh(&xdr, args->fh, &hdr);
> if(status)
> goto out;
> - status = encode_locku(&xdr, args);
> + status = encode_locku(&xdr, args, &hdr);
> out:
> + encode_nops(nops, &hdr);
> return status;
> }
>
> @@ -1778,18 +1911,19 @@ static int nfs4_xdr_enc_readlink(struct rpc_rqst *req, __be32 *p, const struct n
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 2,
> + .nops = 0,
> };
> struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
> unsigned int replen;
> int status;
> + __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> - encode_compound_hdr(&xdr, &hdr);
> - status = encode_putfh(&xdr, args->fh);
> + nops = encode_compound_hdr(&xdr, &hdr);
> + status = encode_putfh(&xdr, args->fh, &hdr);
> if(status)
> goto out;
> - status = encode_readlink(&xdr, args, req);
> + status = encode_readlink(&xdr, args, req, &hdr);
>
> /* set up reply kvec
> * toplevel_status + taglen + rescount + OP_PUTFH + status
> @@ -1800,6 +1934,7 @@ static int nfs4_xdr_enc_readlink(struct rpc_rqst *req, __be32 *p, const struct n
> args->pgbase, args->pglen);
>
> out:
> + encode_nops(nops, &hdr);
> return status;
> }
>
> @@ -1810,18 +1945,19 @@ static int nfs4_xdr_enc_readdir(struct rpc_rqst *req, __be32 *p, const struct nf
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 2,
> + .nops = 0,
> };
> struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
> int replen;
> int status;
> + __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> - encode_compound_hdr(&xdr, &hdr);
> - status = encode_putfh(&xdr, args->fh);
> + nops = encode_compound_hdr(&xdr, &hdr);
> + status = encode_putfh(&xdr, args->fh, &hdr);
> if(status)
> goto out;
> - status = encode_readdir(&xdr, args, req);
> + status = encode_readdir(&xdr, args, req, &hdr);
>
> /* set up reply kvec
> * toplevel_status + taglen + rescount + OP_PUTFH + status
> @@ -1835,6 +1971,7 @@ static int nfs4_xdr_enc_readdir(struct rpc_rqst *req, __be32 *p, const struct nf
> args->pgbase, args->count);
>
> out:
> + encode_nops(nops, &hdr);
> return status;
> }
>
> @@ -1846,16 +1983,17 @@ static int nfs4_xdr_enc_read(struct rpc_rqst *req, __be32 *p, struct nfs_readarg
> struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 2,
> + .nops = 0,
> };
> int replen, status;
> + __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> - encode_compound_hdr(&xdr, &hdr);
> - status = encode_putfh(&xdr, args->fh);
> + nops = encode_compound_hdr(&xdr, &hdr);
> + status = encode_putfh(&xdr, args->fh, &hdr);
> if (status)
> goto out;
> - status = encode_read(&xdr, args);
> + status = encode_read(&xdr, args, &hdr);
> if (status)
> goto out;
>
> @@ -1868,6 +2006,7 @@ static int nfs4_xdr_enc_read(struct rpc_rqst *req, __be32 *p, struct nfs_readarg
> args->pages, args->pgbase, args->count);
> req->rq_rcv_buf.flags |= XDRBUF_READ;
> out:
> + encode_nops(nops, &hdr);
> return status;
> }
>
> @@ -1877,23 +2016,25 @@ out:
> static int nfs4_xdr_enc_setattr(struct rpc_rqst *req, __be32 *p, struct nfs_setattrargs *args)
>
> {
> - struct xdr_stream xdr;
> - struct compound_hdr hdr = {
> - .nops = 3,
> - };
> - int status;
> + struct xdr_stream xdr;
> + struct compound_hdr hdr = {
> + .nops = 0,
> + };
> + int status;
> + __be32 *nops;
>
> - xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> - encode_compound_hdr(&xdr, &hdr);
> - status = encode_putfh(&xdr, args->fh);
> - if(status)
> - goto out;
> - status = encode_setattr(&xdr, args, args->server);
> - if(status)
> - goto out;
> - status = encode_getfattr(&xdr, args->bitmask);
> + xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> + nops = encode_compound_hdr(&xdr, &hdr);
> + status = encode_putfh(&xdr, args->fh, &hdr);
> + if (status)
> + goto out;
> + status = encode_setattr(&xdr, args, args->server, &hdr);
> + if (status)
> + goto out;
> + status = encode_getfattr(&xdr, args->bitmask, &hdr);
> out:
> - return status;
> + encode_nops(nops, &hdr);
> + return status;
> }
>
> /*
> @@ -1906,21 +2047,23 @@ nfs4_xdr_enc_getacl(struct rpc_rqst *req, __be32 *p,
> struct xdr_stream xdr;
> struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
> struct compound_hdr hdr = {
> - .nops = 2,
> + .nops = 0,
> };
> int replen, status;
> + __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> - encode_compound_hdr(&xdr, &hdr);
> - status = encode_putfh(&xdr, args->fh);
> + nops = encode_compound_hdr(&xdr, &hdr);
> + status = encode_putfh(&xdr, args->fh, &hdr);
> if (status)
> goto out;
> - status = encode_getattr_two(&xdr, FATTR4_WORD0_ACL, 0);
> + status = encode_getattr_two(&xdr, FATTR4_WORD0_ACL, 0, &hdr);
> /* set up reply buffer: */
> replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS4_dec_getacl_sz) << 2;
> xdr_inline_pages(&req->rq_rcv_buf, replen,
> args->acl_pages, args->acl_pgbase, args->acl_len);
> out:
> + encode_nops(nops, &hdr);
> return status;
> }
>
> @@ -1931,21 +2074,23 @@ static int nfs4_xdr_enc_write(struct rpc_rqst *req, __be32 *p, struct nfs_writea
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 3,
> + .nops = 0,
> };
> int status;
> + __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> - encode_compound_hdr(&xdr, &hdr);
> - status = encode_putfh(&xdr, args->fh);
> + nops = encode_compound_hdr(&xdr, &hdr);
> + status = encode_putfh(&xdr, args->fh, &hdr);
> if (status)
> goto out;
> - status = encode_write(&xdr, args);
> + status = encode_write(&xdr, args, &hdr);
> if (status)
> goto out;
> req->rq_snd_buf.flags |= XDRBUF_WRITE;
> - status = encode_getfattr(&xdr, args->bitmask);
> + status = encode_getfattr(&xdr, args->bitmask, &hdr);
> out:
> + encode_nops(nops, &hdr);
> return status;
> }
>
> @@ -1956,20 +2101,22 @@ static int nfs4_xdr_enc_commit(struct rpc_rqst *req, __be32 *p, struct nfs_write
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 3,
> + .nops = 0,
> };
> int status;
> + __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> - encode_compound_hdr(&xdr, &hdr);
> - status = encode_putfh(&xdr, args->fh);
> + nops = encode_compound_hdr(&xdr, &hdr);
> + status = encode_putfh(&xdr, args->fh, &hdr);
> if (status)
> goto out;
> - status = encode_commit(&xdr, args);
> + status = encode_commit(&xdr, args, &hdr);
> if (status)
> goto out;
> - status = encode_getfattr(&xdr, args->bitmask);
> + status = encode_getfattr(&xdr, args->bitmask, &hdr);
> out:
> + encode_nops(nops, &hdr);
> return status;
> }
>
> @@ -1980,15 +2127,17 @@ static int nfs4_xdr_enc_fsinfo(struct rpc_rqst *req, __be32 *p, struct nfs4_fsin
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 2,
> + .nops = 0,
> };
> int status;
> + __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> - encode_compound_hdr(&xdr, &hdr);
> - status = encode_putfh(&xdr, args->fh);
> + nops = encode_compound_hdr(&xdr, &hdr);
> + status = encode_putfh(&xdr, args->fh, &hdr);
> if (!status)
> - status = encode_fsinfo(&xdr, args->bitmask);
> + status = encode_fsinfo(&xdr, args->bitmask, &hdr);
> + encode_nops(nops, &hdr);
> return status;
> }
>
> @@ -1999,16 +2148,19 @@ static int nfs4_xdr_enc_pathconf(struct rpc_rqst *req, __be32 *p, const struct n
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 2,
> + .nops = 0,
> };
> int status;
> + __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> - encode_compound_hdr(&xdr, &hdr);
> - status = encode_putfh(&xdr, args->fh);
> + nops = encode_compound_hdr(&xdr, &hdr);
> + status = encode_putfh(&xdr, args->fh, &hdr);
> if (!status)
> status = encode_getattr_one(&xdr,
> - args->bitmask[0] & nfs4_pathconf_bitmap[0]);
> + args->bitmask[0] & nfs4_pathconf_bitmap[0],
> + &hdr);
> + encode_nops(nops, &hdr);
> return status;
> }
>
> @@ -2019,17 +2171,19 @@ static int nfs4_xdr_enc_statfs(struct rpc_rqst *req, __be32 *p, const struct nfs
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 2,
> + .nops = 0,
> };
> int status;
> + __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> - encode_compound_hdr(&xdr, &hdr);
> - status = encode_putfh(&xdr, args->fh);
> + nops = encode_compound_hdr(&xdr, &hdr);
> + status = encode_putfh(&xdr, args->fh, &hdr);
> if (status == 0)
> status = encode_getattr_two(&xdr,
> args->bitmask[0] & nfs4_statfs_bitmap[0],
> - args->bitmask[1] & nfs4_statfs_bitmap[1]);
> + args->bitmask[1] & nfs4_statfs_bitmap[1], &hdr);
> + encode_nops(nops, &hdr);
> return status;
> }
>
> @@ -2040,18 +2194,20 @@ static int nfs4_xdr_enc_server_caps(struct rpc_rqst *req, __be32 *p, const struc
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 2,
> + .nops = 0,
> };
> int status;
> + __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> - encode_compound_hdr(&xdr, &hdr);
> - status = encode_putfh(&xdr, fhandle);
> + nops = encode_compound_hdr(&xdr, &hdr);
> + status = encode_putfh(&xdr, fhandle, &hdr);
> if (status == 0)
> status = encode_getattr_one(&xdr, FATTR4_WORD0_SUPPORTED_ATTRS|
> FATTR4_WORD0_LINK_SUPPORT|
> FATTR4_WORD0_SYMLINK_SUPPORT|
> - FATTR4_WORD0_ACLSUPPORT);
> + FATTR4_WORD0_ACLSUPPORT, &hdr);
> + encode_nops(nops, &hdr);
> return status;
> }
>
> @@ -2062,12 +2218,16 @@ static int nfs4_xdr_enc_renew(struct rpc_rqst *req, __be32 *p, struct nfs_client
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 1,
> + .nops = 0,
> };
> + int status;
> + __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> - encode_compound_hdr(&xdr, &hdr);
> - return encode_renew(&xdr, clp);
> + nops = encode_compound_hdr(&xdr, &hdr);
> + status = encode_renew(&xdr, clp, &hdr);
> + encode_nops(nops, &hdr);
> + return status;
> }
>
> /*
> @@ -2077,12 +2237,16 @@ static int nfs4_xdr_enc_setclientid(struct rpc_rqst *req, __be32 *p, struct nfs4
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 1,
> + .nops = 0,
> };
> + int status;
> + __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> - encode_compound_hdr(&xdr, &hdr);
> - return encode_setclientid(&xdr, sc);
> + nops = encode_compound_hdr(&xdr, &hdr);
> + status = encode_setclientid(&xdr, sc, &hdr);
> + encode_nops(nops, &hdr);
> + return status;
> }
>
> /*
> @@ -2092,18 +2256,20 @@ static int nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, __be32 *p, str
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 3,
> + .nops = 0,
> };
> const u32 lease_bitmap[2] = { FATTR4_WORD0_LEASE_TIME, 0 };
> int status;
> + __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> - encode_compound_hdr(&xdr, &hdr);
> - status = encode_setclientid_confirm(&xdr, clp);
> + nops = encode_compound_hdr(&xdr, &hdr);
> + status = encode_setclientid_confirm(&xdr, clp, &hdr);
> if (!status)
> - status = encode_putrootfh(&xdr);
> + status = encode_putrootfh(&xdr, &hdr);
> if (!status)
> - status = encode_fsinfo(&xdr, lease_bitmap);
> + status = encode_fsinfo(&xdr, lease_bitmap, &hdr);
> + encode_nops(nops, &hdr);
> return status;
> }
>
> @@ -2114,20 +2280,22 @@ static int nfs4_xdr_enc_delegreturn(struct rpc_rqst *req, __be32 *p, const struc
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 3,
> + .nops = 0,
> };
> int status;
> + __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> - encode_compound_hdr(&xdr, &hdr);
> - status = encode_putfh(&xdr, args->fhandle);
> + nops = encode_compound_hdr(&xdr, &hdr);
> + status = encode_putfh(&xdr, args->fhandle, &hdr);
> if (status != 0)
> goto out;
> - status = encode_delegreturn(&xdr, args->stateid);
> + status = encode_delegreturn(&xdr, args->stateid, &hdr);
> if (status != 0)
> goto out;
> - status = encode_getfattr(&xdr, args->bitmask);
> + status = encode_getfattr(&xdr, args->bitmask, &hdr);
> out:
> + encode_nops(nops, &hdr);
> return status;
> }
>
> @@ -2138,19 +2306,20 @@ static int nfs4_xdr_enc_fs_locations(struct rpc_rqst *req, __be32 *p, struct nfs
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 3,
> + .nops = 0,
> };
> struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
> int replen;
> int status;
> + __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> - encode_compound_hdr(&xdr, &hdr);
> - if ((status = encode_putfh(&xdr, args->dir_fh)) != 0)
> + nops = encode_compound_hdr(&xdr, &hdr);
> + if ((status = encode_putfh(&xdr, args->dir_fh, &hdr)) != 0)
> goto out;
> - if ((status = encode_lookup(&xdr, args->name)) != 0)
> + if ((status = encode_lookup(&xdr, args->name, &hdr)) != 0)
> goto out;
> - if ((status = encode_fs_locations(&xdr, args->bitmask)) != 0)
> + if ((status = encode_fs_locations(&xdr, args->bitmask, &hdr)) != 0)
> goto out;
> /* set up reply
> * toplevel_status + OP_PUTFH + status
> @@ -2160,6 +2329,7 @@ static int nfs4_xdr_enc_fs_locations(struct rpc_rqst *req, __be32 *p, struct nfs
> xdr_inline_pages(&req->rq_rcv_buf, replen, &args->page,
> 0, PAGE_SIZE);
> out:
> + encode_nops(nops, &hdr);
> return status;
> }
>
> @@ -4036,20 +4206,22 @@ out:
> static int
> nfs4_xdr_enc_setacl(struct rpc_rqst *req, __be32 *p, struct nfs_setaclargs *args)
> {
> - struct xdr_stream xdr;
> - struct compound_hdr hdr = {
> - .nops = 2,
> - };
> - int status;
> + struct xdr_stream xdr;
> + struct compound_hdr hdr = {
> + .nops = 0,
> + };
> + int status;
> + __be32 *nops;
>
> - xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> - encode_compound_hdr(&xdr, &hdr);
> - status = encode_putfh(&xdr, args->fh);
> - if (status)
> - goto out;
> - status = encode_setacl(&xdr, args);
> + xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> + nops = encode_compound_hdr(&xdr, &hdr);
> + status = encode_putfh(&xdr, args->fh, &hdr);
> + if (status)
> + goto out;
> + status = encode_setacl(&xdr, args, &hdr);
> out:
> - return status;
> + encode_nops(nops, &hdr);
> + return status;
> }
> /*
> * Decode SETACL response
> --
> 1.6.0.1
>
^ permalink raw reply [flat|nested] 115+ messages in thread
* [RFC 05/85] nfs41: Add Kconfig symbols for NFSv4.1
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
2008-11-10 20:05 ` [RFC 03/85] nfs: remove incorrect usage of nfs4 compound response hdr.status Benny Halevy
2008-11-10 20:18 ` [RFC 04/85] FIXME: NFS: Increment operation number in each encode_* routine Benny Halevy
@ 2008-11-10 20:18 ` Benny Halevy
2008-11-17 13:27 ` [pnfs] " Benny Halevy
2008-11-10 20:18 ` [RFC 06/85] nfs41: common protocol definitions Benny Halevy
` (82 subsequent siblings)
85 siblings, 1 reply; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:18 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
From: Ricardo Labiaga <ricardo.labiaga@netapp.com>
Added CONFIG_NFS_V4_1 and made it depend upon CONFIG_NFS_V4 and EXPERIMENTAL.
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/Kconfig | 9 +++++++++
1 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/fs/Kconfig b/fs/Kconfig
index 522469a..9363634 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -1216,6 +1216,15 @@ config NFS_V4
If unsure, say N.
+config NFS_V4_1
+ bool "NFS client support for NFSv4.1 (EXPERIMENTAL)"
+ depends on NFS_V4 && EXPERIMENTAL
+ help
+ This option enables support for minor version 1 of the NFSv4 protocol
+ (draft-ietf-nfsv4-minorversion1) in the kernel's NFS client.
+
+ If unsure, say N.
+
config ROOT_NFS
bool "Root file system on NFS"
depends on NFS_FS=y && IP_PNP
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* Re: [pnfs] [RFC 05/85] nfs41: Add Kconfig symbols for NFSv4.1
2008-11-10 20:18 ` [RFC 05/85] nfs41: Add Kconfig symbols for NFSv4.1 Benny Halevy
@ 2008-11-17 13:27 ` Benny Halevy
0 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-17 13:27 UTC (permalink / raw)
To: pnfs; +Cc: trond.myklebust, linux-nfs
On Nov. 10, 2008, 22:18 +0200, Benny Halevy <bhalevy@panasas.com> wrote:
> From: Ricardo Labiaga <ricardo.labiaga@netapp.com>
>
> Added CONFIG_NFS_V4_1 and made it depend upon CONFIG_NFS_V4 and EXPERIMENTAL.
>
> Signed-off-by: Benny Halevy <bhalevy@panasas.com>
> ---
> fs/Kconfig | 9 +++++++++
> 1 files changed, 9 insertions(+), 0 deletions(-)
>
> diff --git a/fs/Kconfig b/fs/Kconfig
> index 522469a..9363634 100644
> --- a/fs/Kconfig
> +++ b/fs/Kconfig
> @@ -1216,6 +1216,15 @@ config NFS_V4
>
> If unsure, say N.
>
> +config NFS_V4_1
> + bool "NFS client support for NFSv4.1 (EXPERIMENTAL)"
review 11-14: s/EXPERIMENTAL/DEVELOPER ONLY/
> + depends on NFS_V4 && EXPERIMENTAL
> + help
> + This option enables support for minor version 1 of the NFSv4 protocol
> + (draft-ietf-nfsv4-minorversion1) in the kernel's NFS client.
> +
Unless you're an NFS developer, say N.
> + If unsure, say N.
> +
> config ROOT_NFS
> bool "Root file system on NFS"
> depends on NFS_FS=y && IP_PNP
^ permalink raw reply [flat|nested] 115+ messages in thread
* [RFC 06/85] nfs41: common protocol definitions
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (2 preceding siblings ...)
2008-11-10 20:18 ` [RFC 05/85] nfs41: Add Kconfig symbols for NFSv4.1 Benny Halevy
@ 2008-11-10 20:18 ` Benny Halevy
2008-11-17 13:28 ` [pnfs] " Benny Halevy
2008-11-10 20:19 ` [RFC 07/85] nfs41: define NFS4_MAX_MINOR_VERSION based on CONFIG_NFS_V4_1 Benny Halevy
` (81 subsequent siblings)
85 siblings, 1 reply; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:18 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
nfs41: define all NFSv4.1 operation and error code constants.
Note that some of the definitions are used by both the nfs41 client
and the server code (hence enclosed in
defined(CONFIG_NFSD_V4_1) || defined(CONFIG_NFS_V4_1)).
Signed-off-by: Andy Adamson<andros@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
include/linux/nfs.h | 19 ++++++++-
include/linux/nfs4.h | 112 +++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 128 insertions(+), 3 deletions(-)
diff --git a/include/linux/nfs.h b/include/linux/nfs.h
index 54af92c..4dd83f2 100644
--- a/include/linux/nfs.h
+++ b/include/linux/nfs.h
@@ -109,7 +109,24 @@
NFSERR_FILE_OPEN = 10046, /* v4 */
NFSERR_ADMIN_REVOKED = 10047, /* v4 */
NFSERR_CB_PATH_DOWN = 10048, /* v4 */
- NFSERR_REPLAY_ME = 10049 /* v4 */
+ NFSERR_BADIOMODE = 10049, /* v4.1 */
+ NFSERR_BADLAYOUT = 10050, /* v4.1 */
+ NFSERR_BAD_SESSION_DIGEST = 10051, /* v4.1 */
+ NFSERR_BADSESSION = 10052, /* v4.1 */
+ NFSERR_BADSLOT = 10053, /* v4.1 */
+ NFSERR_COMPLETE_ALREADY = 10054, /* v4.1 */
+ NFSERR_CONN_NOT_BOUND_TO_SESSION = 10055,/* v4.1 */
+ NFSERR_DELEG_ALREADY_WANTED = 10056, /* v4.1 */
+ NFSERR_DIRDELEG_UNAVAIL = 10057, /* v4.1 */
+ NFSERR_LAYOUTTRYLATER = 10058, /* v4.1 */
+ NFSERR_LAYOUTUNAVAILABLE = 10059, /* v4.1 */
+ NFSERR_NOMATCHING_LAYOUT = 10060, /* v4.1 */
+ NFSERR_RECALLCONFLICT = 10061, /* v4.1 */
+ NFSERR_UNKNOWN_LAYOUTTYPE = 10062, /* v4.1 */
+ NFSERR_SEQ_MISORDERED = 10063, /* v4.1 */
+ NFSERR_SEQUENCE_POS = 10064, /* v4.1 */
+
+ NFSERR_REPLAY_ME = 11001, /* linux internal */
};
/* NFSv2 file types - beware, these are not the same in NFSv3 */
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
index ea03667..bdcd316 100644
--- a/include/linux/nfs4.h
+++ b/include/linux/nfs4.h
@@ -21,6 +21,7 @@
#define NFS4_FHSIZE 128
#define NFS4_MAXPATHLEN PATH_MAX
#define NFS4_MAXNAMLEN NAME_MAX
+#define NFS4_MAX_SESSIONID_LEN 16
#define NFS4_ACCESS_READ 0x0001
#define NFS4_ACCESS_LOOKUP 0x0002
@@ -38,6 +39,7 @@
#define NFS4_OPEN_RESULT_CONFIRM 0x0002
#define NFS4_OPEN_RESULT_LOCKTYPE_POSIX 0x0004
+#define NFS4_SHARE_DENY_MASK 0x000F
#define NFS4_SHARE_ACCESS_READ 0x0001
#define NFS4_SHARE_ACCESS_WRITE 0x0002
#define NFS4_SHARE_ACCESS_BOTH 0x0003
@@ -45,6 +47,20 @@
#define NFS4_SHARE_DENY_WRITE 0x0002
#define NFS4_SHARE_DENY_BOTH 0x0003
+#if defined(CONFIG_NFSD_V4_1) || defined(CONFIG_NFS_V4_1)
+#define NFS4_SHARE_WANT_MASK 0xFF00
+#define NFS4_SHARE_WANT_NO_PREFERENCE 0x0000
+#define NFS4_SHARE_WANT_READ_DELEG 0x0100
+#define NFS4_SHARE_WANT_WRITE_DELEG 0x0200
+#define NFS4_SHARE_WANT_ANY_DELEG 0x0300
+#define NFS4_SHARE_WANT_NO_DELEG 0x0400
+#define NFS4_SHARE_WANT_CANCEL 0x0500
+
+#define NFS4_SHARE_WHEN_MASK 0xF0000
+#define NFS4_SHARE_SIGNAL_DELEG_WHEN_RESRC_AVAIL 0x10000
+#define NFS4_SHARE_PUSH_DELEG_WHEN_UNCONTENDED 0x20000
+#endif /* CONFIG_NFSD_V4_1 || CONFIG_NFS_V4_1 */
+
#define NFS4_SET_TO_SERVER_TIME 0
#define NFS4_SET_TO_CLIENT_TIME 1
@@ -88,6 +104,15 @@
#define NFS4_ACE_GENERIC_EXECUTE 0x001200A0
#define NFS4_ACE_MASK_ALL 0x001F01FF
+#define EXCHGID4_FLAG_SUPP_MOVED_REFER 0x00000001
+#define EXCHGID4_FLAG_SUPP_MOVED_MIGR 0x00000002
+#define EXCHGID4_FLAG_USE_NON_PNFS 0x00010000
+#define EXCHGID4_FLAG_USE_PNFS_MDS 0x00020000
+#define EXCHGID4_FLAG_USE_PNFS_DS 0x00040000
+#define EXCHGID4_INVAL_FLAG_MASK 0x77707774
+
+#define NFS4_LENGTH_EOF (~(u64)0)
+
enum nfs4_acl_whotype {
NFS4_ACL_WHO_NAMED = 0,
NFS4_ACL_WHO_OWNER,
@@ -152,6 +177,27 @@ enum nfs_opnum4 {
OP_VERIFY = 37,
OP_WRITE = 38,
OP_RELEASE_LOCKOWNER = 39,
+#if defined(CONFIG_NFSD_V4_1) || defined(CONFIG_NFS_V4_1)
+ OP_BACKCHANNEL_CTL = 40,
+ OP_BIND_CONN_TO_SESSION = 41,
+ OP_EXCHANGE_ID = 42,
+ OP_CREATE_SESSION = 43,
+ OP_DESTROY_SESSION = 44,
+ OP_FREE_STATEID = 45,
+ OP_GET_DIR_DELEGATION = 46,
+ OP_GETDEVICEINFO = 47,
+ OP_GETDEVICELIST = 48,
+ OP_LAYOUTCOMMIT = 49,
+ OP_LAYOUTGET = 50,
+ OP_LAYOUTRETURN = 51,
+ OP_SECINFO_NO_NAME = 52,
+ OP_SEQUENCE = 53,
+ OP_SET_SSV = 54,
+ OP_TEST_STATEID = 55,
+ OP_WANT_DELEGATION = 56,
+ OP_DESTROY_CLIENTID = 57,
+ OP_RECLAIM_COMPLETE = 58,
+#endif /* defined(CONFIG_NFSD_V4_1) || defined(CONFIG_NFS_V4_1) */
OP_ILLEGAL = 10044,
};
@@ -228,7 +274,47 @@ enum nfsstat4 {
NFS4ERR_DEADLOCK = 10045,
NFS4ERR_FILE_OPEN = 10046,
NFS4ERR_ADMIN_REVOKED = 10047,
- NFS4ERR_CB_PATH_DOWN = 10048
+ NFS4ERR_CB_PATH_DOWN = 10048,
+#if defined(CONFIG_NFS_V4_1)
+ NFS4ERR_BADIOMODE = 10049,
+ NFS4ERR_BADLAYOUT = 10050,
+ NFS4ERR_BAD_SESSION_DIGEST = 10051,
+ NFS4ERR_BADSESSION = 10052,
+ NFS4ERR_BADSLOT = 10053,
+ NFS4ERR_COMPLETE_ALREADY = 10054,
+ NFS4ERR_CONN_NOT_BOUND_TO_SESSION = 10055,
+ NFS4ERR_DELEG_ALREADY_WANTED = 10056,
+ NFS4ERR_BACK_CHAN_BUSY = 10057, /* backchan reqs outstanding */
+ NFS4ERR_LAYOUTTRYLATER = 10058,
+ NFS4ERR_LAYOUTUNAVAILABLE = 10059,
+ NFS4ERR_NOMATCHING_LAYOUT = 10060,
+ NFS4ERR_RECALLCONFLICT = 10061,
+ NFS4ERR_UNKNOWN_LAYOUTTYPE = 10062,
+ NFS4ERR_SEQ_MISORDERED = 10063, /* unexpected seq.id in req */
+ NFS4ERR_SEQUENCE_POS = 10064, /* [CB_]SEQ. op not 1st op */
+ NFS4ERR_REQ_TOO_BIG = 10065, /* request too big */
+ NFS4ERR_REP_TOO_BIG = 10066, /* reply too big */
+ NFS4ERR_REP_TOO_BIG_TO_CACHE = 10067, /* rep. not all cached */
+ NFS4ERR_RETRY_UNCACHED_REP = 10068, /* retry & rep. uncached */
+ NFS4ERR_UNSAFE_COMPOUND = 10069, /* retry/recovery too hard */
+ NFS4ERR_TOO_MANY_OPS = 10070, /* too many ops in [CB_]COMP */
+ NFS4ERR_OP_NOT_IN_SESSION = 10071, /* op needs [CB_]SEQ. op */
+ NFS4ERR_HASH_ALG_UNSUPP = 10072, /* hash alg. not supp. */
+ NFS4ERR_CONN_BINDING_NOT_ENFORCED = 10073, /* SET_SSV not allowed */
+ NFS4ERR_CLIENTID_BUSY = 10074, /* clientid has state */
+ NFS4ERR_PNFS_IO_HOLE = 10075, /* IO to _SPARSE file hole */
+ NFS4ERR_SEQ_FALSE_RETRY = 10076, /* retry not origional */
+ NFS4ERR_BAD_HIGH_SLOT = 10077, /* sequence arg bad */
+ NFS4ERR_DEADSESSION = 10078, /* persistent session dead */
+ NFS4ERR_ENCR_ALG_UNSUPP = 10079, /* SSV alg mismatch */
+ NFS4ERR_PNFS_NO_LAYOUT = 10080, /* direct I/O with no layout */
+ NFS4ERR_NOT_ONLY_OP = 10081, /* bad compound */
+ NFS4ERR_WRONG_CRED = 10082, /* permissions:state change */
+ NFS4ERR_WRONG_TYPE = 10083, /* current operation mismatch */
+ NFS4ERR_DIRDELEG_UNAVAIL = 10084, /* no directory delegation */
+ NFS4ERR_REJECT_DELEG = 10085, /* on callback */
+ NFS4ERR_RETURNCONFLICT = 10086, /* outstanding layoutreturn */
+#endif /* CONFIG_NFS_V4_1 */
};
/*
@@ -348,7 +434,7 @@ enum lock_type4 {
#define NFSPROC4_NULL 0
#define NFSPROC4_COMPOUND 1
-#define NFS4_MINOR_VERSION 0
+#define NFS4_MINOR_VERSION 1
#define NFS4_DEBUG 1
/* Index of predefined Linux client operations */
@@ -389,7 +475,29 @@ enum {
NFSPROC4_CLNT_GETACL,
NFSPROC4_CLNT_SETACL,
NFSPROC4_CLNT_FS_LOCATIONS,
+#if defined(CONFIG_NFS_V4_1)
+ NFSPROC4_CLNT_EXCHANGE_ID,
+ NFSPROC4_CLNT_CREATE_SESSION,
+ NFSPROC4_CLNT_DESTROY_SESSION,
+ NFSPROC4_CLNT_SEQUENCE,
+ NFSPROC4_CLNT_GET_LEASE_TIME,
+#endif /* CONFIG_NFSD_V4_1 */
+};
+
+#if defined(CONFIG_NFSD_V4_1) || defined(CONFIG_NFS_V4_1)
+typedef unsigned char nfs41_sessionid[16];
+
+/* Create Session Flags */
+#define SESSION4_PERSIST 0x001
+#define SESSION4_BACK_CHAN 0x002
+#define SESSION4_RDMA 0x004
+
+enum state_protect_how4 {
+ SP4_NONE = 0,
+ SP4_MACH_CRED = 1,
+ SP4_SSV = 2
};
+#endif /* defined(CONFIG_NFSD_V4_1) || defined(CONFIG_NFS_V4_1) */
#endif
#endif
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* Re: [pnfs] [RFC 06/85] nfs41: common protocol definitions
2008-11-10 20:18 ` [RFC 06/85] nfs41: common protocol definitions Benny Halevy
@ 2008-11-17 13:28 ` Benny Halevy
0 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-17 13:28 UTC (permalink / raw)
To: pnfs; +Cc: trond.myklebust, linux-nfs
On Nov. 10, 2008, 22:18 +0200, Benny Halevy <bhalevy@panasas.com> wrote:
> nfs41: define all NFSv4.1 operation and error code constants.
>
> Note that some of the definitions are used by both the nfs41 client
> and the server code (hence enclosed in
> defined(CONFIG_NFSD_V4_1) || defined(CONFIG_NFS_V4_1)).
>
> Signed-off-by: Andy Adamson<andros@netapp.com>
> Signed-off-by: Benny Halevy <bhalevy@panasas.com>
> include/linux/nfs.h | 19 ++++++++-
> include/linux/nfs4.h | 112 +++++++++++++++++++++++++++++++++++++++++++++++++-
> 2 files changed, 128 insertions(+), 3 deletions(-)
>
> diff --git a/include/linux/nfs.h b/include/linux/nfs.h
> index 54af92c..4dd83f2 100644
> --- a/include/linux/nfs.h
> +++ b/include/linux/nfs.h
> @@ -109,7 +109,24 @@
> NFSERR_FILE_OPEN = 10046, /* v4 */
> NFSERR_ADMIN_REVOKED = 10047, /* v4 */
> NFSERR_CB_PATH_DOWN = 10048, /* v4 */
> - NFSERR_REPLAY_ME = 10049 /* v4 */
> + NFSERR_BADIOMODE = 10049, /* v4.1 */
> + NFSERR_BADLAYOUT = 10050, /* v4.1 */
> + NFSERR_BAD_SESSION_DIGEST = 10051, /* v4.1 */
> + NFSERR_BADSESSION = 10052, /* v4.1 */
> + NFSERR_BADSLOT = 10053, /* v4.1 */
> + NFSERR_COMPLETE_ALREADY = 10054, /* v4.1 */
> + NFSERR_CONN_NOT_BOUND_TO_SESSION = 10055,/* v4.1 */
> + NFSERR_DELEG_ALREADY_WANTED = 10056, /* v4.1 */
> + NFSERR_DIRDELEG_UNAVAIL = 10057, /* v4.1 */
> + NFSERR_LAYOUTTRYLATER = 10058, /* v4.1 */
> + NFSERR_LAYOUTUNAVAILABLE = 10059, /* v4.1 */
> + NFSERR_NOMATCHING_LAYOUT = 10060, /* v4.1 */
> + NFSERR_RECALLCONFLICT = 10061, /* v4.1 */
> + NFSERR_UNKNOWN_LAYOUTTYPE = 10062, /* v4.1 */
> + NFSERR_SEQ_MISORDERED = 10063, /* v4.1 */
> + NFSERR_SEQUENCE_POS = 10064, /* v4.1 */
> +
> + NFSERR_REPLAY_ME = 11001, /* linux internal */
review 11-14: Trond wants to get rid of the NFSERR_ consts
and use NFS4ERR (enum nfs_stat) this will also clean up linux/nfs.h
so that nfs4 defs will be in nfs4.h
> };
>
> /* NFSv2 file types - beware, these are not the same in NFSv3 */
> diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
> index ea03667..bdcd316 100644
> --- a/include/linux/nfs4.h
> +++ b/include/linux/nfs4.h
> @@ -21,6 +21,7 @@
> #define NFS4_FHSIZE 128
> #define NFS4_MAXPATHLEN PATH_MAX
> #define NFS4_MAXNAMLEN NAME_MAX
> +#define NFS4_MAX_SESSIONID_LEN 16
>
> #define NFS4_ACCESS_READ 0x0001
> #define NFS4_ACCESS_LOOKUP 0x0002
> @@ -38,6 +39,7 @@
> #define NFS4_OPEN_RESULT_CONFIRM 0x0002
> #define NFS4_OPEN_RESULT_LOCKTYPE_POSIX 0x0004
>
> +#define NFS4_SHARE_DENY_MASK 0x000F
review 11-14: NFS4_SHARE_ACCESS_MASK
> #define NFS4_SHARE_ACCESS_READ 0x0001
> #define NFS4_SHARE_ACCESS_WRITE 0x0002
> #define NFS4_SHARE_ACCESS_BOTH 0x0003
> @@ -45,6 +47,20 @@
> #define NFS4_SHARE_DENY_WRITE 0x0002
> #define NFS4_SHARE_DENY_BOTH 0x0003
>
> +#if defined(CONFIG_NFSD_V4_1) || defined(CONFIG_NFS_V4_1)
review 11-14: get rid of #ifdef in the definition
> +#define NFS4_SHARE_WANT_MASK 0xFF00
> +#define NFS4_SHARE_WANT_NO_PREFERENCE 0x0000
> +#define NFS4_SHARE_WANT_READ_DELEG 0x0100
> +#define NFS4_SHARE_WANT_WRITE_DELEG 0x0200
> +#define NFS4_SHARE_WANT_ANY_DELEG 0x0300
> +#define NFS4_SHARE_WANT_NO_DELEG 0x0400
> +#define NFS4_SHARE_WANT_CANCEL 0x0500
> +
> +#define NFS4_SHARE_WHEN_MASK 0xF0000
> +#define NFS4_SHARE_SIGNAL_DELEG_WHEN_RESRC_AVAIL 0x10000
> +#define NFS4_SHARE_PUSH_DELEG_WHEN_UNCONTENDED 0x20000
> +#endif /* CONFIG_NFSD_V4_1 || CONFIG_NFS_V4_1 */
> +
> #define NFS4_SET_TO_SERVER_TIME 0
> #define NFS4_SET_TO_CLIENT_TIME 1
>
> @@ -88,6 +104,15 @@
> #define NFS4_ACE_GENERIC_EXECUTE 0x001200A0
> #define NFS4_ACE_MASK_ALL 0x001F01FF
>
> +#define EXCHGID4_FLAG_SUPP_MOVED_REFER 0x00000001
> +#define EXCHGID4_FLAG_SUPP_MOVED_MIGR 0x00000002
> +#define EXCHGID4_FLAG_USE_NON_PNFS 0x00010000
> +#define EXCHGID4_FLAG_USE_PNFS_MDS 0x00020000
> +#define EXCHGID4_FLAG_USE_PNFS_DS 0x00040000
> +#define EXCHGID4_INVAL_FLAG_MASK 0x77707774
> +
> +#define NFS4_LENGTH_EOF (~(u64)0)
review 11-14: s/NFS4_LENGTH_EOF/NFS4_MAX_UINT64/
> +
> enum nfs4_acl_whotype {
> NFS4_ACL_WHO_NAMED = 0,
> NFS4_ACL_WHO_OWNER,
> @@ -152,6 +177,27 @@ enum nfs_opnum4 {
> OP_VERIFY = 37,
> OP_WRITE = 38,
> OP_RELEASE_LOCKOWNER = 39,
> +#if defined(CONFIG_NFSD_V4_1) || defined(CONFIG_NFS_V4_1)
review 11-14: get rid of #ifdef
> + OP_BACKCHANNEL_CTL = 40,
> + OP_BIND_CONN_TO_SESSION = 41,
> + OP_EXCHANGE_ID = 42,
> + OP_CREATE_SESSION = 43,
> + OP_DESTROY_SESSION = 44,
> + OP_FREE_STATEID = 45,
> + OP_GET_DIR_DELEGATION = 46,
> + OP_GETDEVICEINFO = 47,
> + OP_GETDEVICELIST = 48,
> + OP_LAYOUTCOMMIT = 49,
> + OP_LAYOUTGET = 50,
> + OP_LAYOUTRETURN = 51,
> + OP_SECINFO_NO_NAME = 52,
> + OP_SEQUENCE = 53,
> + OP_SET_SSV = 54,
> + OP_TEST_STATEID = 55,
> + OP_WANT_DELEGATION = 56,
> + OP_DESTROY_CLIENTID = 57,
> + OP_RECLAIM_COMPLETE = 58,
> +#endif /* defined(CONFIG_NFSD_V4_1) || defined(CONFIG_NFS_V4_1) */
> OP_ILLEGAL = 10044,
> };
>
> @@ -228,7 +274,47 @@ enum nfsstat4 {
> NFS4ERR_DEADLOCK = 10045,
> NFS4ERR_FILE_OPEN = 10046,
> NFS4ERR_ADMIN_REVOKED = 10047,
> - NFS4ERR_CB_PATH_DOWN = 10048
> + NFS4ERR_CB_PATH_DOWN = 10048,
> +#if defined(CONFIG_NFS_V4_1)
review 11-14: ditto
> + NFS4ERR_BADIOMODE = 10049,
> + NFS4ERR_BADLAYOUT = 10050,
> + NFS4ERR_BAD_SESSION_DIGEST = 10051,
> + NFS4ERR_BADSESSION = 10052,
> + NFS4ERR_BADSLOT = 10053,
> + NFS4ERR_COMPLETE_ALREADY = 10054,
> + NFS4ERR_CONN_NOT_BOUND_TO_SESSION = 10055,
> + NFS4ERR_DELEG_ALREADY_WANTED = 10056,
> + NFS4ERR_BACK_CHAN_BUSY = 10057, /* backchan reqs outstanding */
> + NFS4ERR_LAYOUTTRYLATER = 10058,
> + NFS4ERR_LAYOUTUNAVAILABLE = 10059,
> + NFS4ERR_NOMATCHING_LAYOUT = 10060,
> + NFS4ERR_RECALLCONFLICT = 10061,
> + NFS4ERR_UNKNOWN_LAYOUTTYPE = 10062,
> + NFS4ERR_SEQ_MISORDERED = 10063, /* unexpected seq.id in req */
> + NFS4ERR_SEQUENCE_POS = 10064, /* [CB_]SEQ. op not 1st op */
> + NFS4ERR_REQ_TOO_BIG = 10065, /* request too big */
> + NFS4ERR_REP_TOO_BIG = 10066, /* reply too big */
> + NFS4ERR_REP_TOO_BIG_TO_CACHE = 10067, /* rep. not all cached */
> + NFS4ERR_RETRY_UNCACHED_REP = 10068, /* retry & rep. uncached */
> + NFS4ERR_UNSAFE_COMPOUND = 10069, /* retry/recovery too hard */
> + NFS4ERR_TOO_MANY_OPS = 10070, /* too many ops in [CB_]COMP */
> + NFS4ERR_OP_NOT_IN_SESSION = 10071, /* op needs [CB_]SEQ. op */
> + NFS4ERR_HASH_ALG_UNSUPP = 10072, /* hash alg. not supp. */
> + NFS4ERR_CONN_BINDING_NOT_ENFORCED = 10073, /* SET_SSV not allowed */
> + NFS4ERR_CLIENTID_BUSY = 10074, /* clientid has state */
> + NFS4ERR_PNFS_IO_HOLE = 10075, /* IO to _SPARSE file hole */
> + NFS4ERR_SEQ_FALSE_RETRY = 10076, /* retry not origional */
> + NFS4ERR_BAD_HIGH_SLOT = 10077, /* sequence arg bad */
> + NFS4ERR_DEADSESSION = 10078, /* persistent session dead */
> + NFS4ERR_ENCR_ALG_UNSUPP = 10079, /* SSV alg mismatch */
> + NFS4ERR_PNFS_NO_LAYOUT = 10080, /* direct I/O with no layout */
> + NFS4ERR_NOT_ONLY_OP = 10081, /* bad compound */
> + NFS4ERR_WRONG_CRED = 10082, /* permissions:state change */
> + NFS4ERR_WRONG_TYPE = 10083, /* current operation mismatch */
> + NFS4ERR_DIRDELEG_UNAVAIL = 10084, /* no directory delegation */
> + NFS4ERR_REJECT_DELEG = 10085, /* on callback */
> + NFS4ERR_RETURNCONFLICT = 10086, /* outstanding layoutreturn */
> +#endif /* CONFIG_NFS_V4_1 */
> };
>
> /*
> @@ -348,7 +434,7 @@ enum lock_type4 {
>
> #define NFSPROC4_NULL 0
> #define NFSPROC4_COMPOUND 1
> -#define NFS4_MINOR_VERSION 0
> +#define NFS4_MINOR_VERSION 1
review 11-14: get rid of this, it's unused.
> #define NFS4_DEBUG 1
>
> /* Index of predefined Linux client operations */
> @@ -389,7 +475,29 @@ enum {
> NFSPROC4_CLNT_GETACL,
> NFSPROC4_CLNT_SETACL,
> NFSPROC4_CLNT_FS_LOCATIONS,
> +#if defined(CONFIG_NFS_V4_1)
review 11-14: get rid of #ifdef
> + NFSPROC4_CLNT_EXCHANGE_ID,
> + NFSPROC4_CLNT_CREATE_SESSION,
> + NFSPROC4_CLNT_DESTROY_SESSION,
> + NFSPROC4_CLNT_SEQUENCE,
> + NFSPROC4_CLNT_GET_LEASE_TIME,
> +#endif /* CONFIG_NFSD_V4_1 */
> +};
> +
> +#if defined(CONFIG_NFSD_V4_1) || defined(CONFIG_NFS_V4_1)
get rid of the #ifdef
> +typedef unsigned char nfs41_sessionid[16];
review 11-14: change to struct nfs4_sessionid { unsigned char data[16]; };
no typedef.
change server name to nfsd4_private_sessionid
> +
> +/* Create Session Flags */
> +#define SESSION4_PERSIST 0x001
> +#define SESSION4_BACK_CHAN 0x002
> +#define SESSION4_RDMA 0x004
> +
> +enum state_protect_how4 {
> + SP4_NONE = 0,
> + SP4_MACH_CRED = 1,
> + SP4_SSV = 2
> };
> +#endif /* defined(CONFIG_NFSD_V4_1) || defined(CONFIG_NFS_V4_1) */
>
> #endif
> #endif
^ permalink raw reply [flat|nested] 115+ messages in thread
* [RFC 07/85] nfs41: define NFS4_MAX_MINOR_VERSION based on CONFIG_NFS_V4_1
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (3 preceding siblings ...)
2008-11-10 20:18 ` [RFC 06/85] nfs41: common protocol definitions Benny Halevy
@ 2008-11-10 20:19 ` Benny Halevy
2008-11-10 20:19 ` [RFC 08/85] nfs41: client xdr definitions Benny Halevy
` (80 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:19 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
From: Mike Sager <sager@netapp.com>
If 4.1 isn't supported, NFS4_MAX_MINOR_VERSION will be 0.
Signed-off-by: Mike Sager <sager@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
include/linux/nfs4.h | 7 +++++++
1 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
index bdcd316..a69bbfa 100644
--- a/include/linux/nfs4.h
+++ b/include/linux/nfs4.h
@@ -435,6 +435,13 @@ enum lock_type4 {
#define NFSPROC4_NULL 0
#define NFSPROC4_COMPOUND 1
#define NFS4_MINOR_VERSION 1
+
+#if defined(CONFIG_NFS_V4_1)
+#define NFS4_MAX_MINOR_VERSION 1
+#else
+#define NFS4_MAX_MINOR_VERSION 0
+#endif /* CONFIG_NFS_V4_1 */
+
#define NFS4_DEBUG 1
/* Index of predefined Linux client operations */
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 08/85] nfs41: client xdr definitions
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (4 preceding siblings ...)
2008-11-10 20:19 ` [RFC 07/85] nfs41: define NFS4_MAX_MINOR_VERSION based on CONFIG_NFS_V4_1 Benny Halevy
@ 2008-11-10 20:19 ` Benny Halevy
2008-11-17 13:31 ` [pnfs] " Benny Halevy
2008-11-10 20:19 ` [RFC 09/85] nfs41: add mount command option minorvers Benny Halevy
` (79 subsequent siblings)
85 siblings, 1 reply; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:19 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
Define stubs for sequence args and res data structures and embed
them in all other nfs4 and nfs41 xdr types. They are needed for
sending any op in a nfs41 compound rpc.
Signed-off-by: Andy Adamson<andros@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
include/linux/nfs_xdr.h | 118 +++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 118 insertions(+), 0 deletions(-)
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index c1c31ac..a8a0953 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -113,6 +113,43 @@ struct nfs4_change_info {
};
struct nfs_seqid;
+
+/* Opaque session ID */
+struct sessionid4 {
+ char data[NFS4_MAX_SESSIONID_LEN];
+};
+
+struct nfs41_sequence_args {
+ /* stub */
+};
+
+#define SEQ4_STATUS_CB_PATH_DOWN 0x00000001
+#define SEQ4_STATUS_CB_GSS_CONTEXTS_EXPIRING 0x00000002
+#define SEQ4_STATUS_CB_GSS_CONTEXTS_EXPIRED 0x00000004
+#define SEQ4_STATUS_EXPIRED_ALL_STATE_REVOKED 0x00000008
+#define SEQ4_STATUS_EXPIRED_SOME_STATE_REVOKED 0x00000010
+#define SEQ4_STATUS_ADMIN_STATE_REVOKED 0x00000020
+#define SEQ4_STATUS_RECALLABLE_STATE_REVOKED 0x00000040
+#define SEQ4_STATUS_LEASE_MOVED 0x00000080
+#define SEQ4_STATUS_RESTART_RECLAIM_NEEDED 0x00000100
+
+struct nfs41_sequence_res {
+ /* stub */
+};
+
+#if defined(CONFIG_NFS_V4_1)
+
+struct nfs4_get_lease_time_args {
+ struct nfs41_sequence_args la_seq_args;
+};
+
+struct nfs4_get_lease_time_res {
+ struct nfs_fsinfo *lr_fsinfo;
+ struct nfs41_sequence_res lr_seq_res;
+};
+
+#endif /* CONFIG_NFS_V4_1 */
+
/*
* Arguments to the open call.
*/
@@ -132,6 +169,7 @@ struct nfs_openargs {
const struct nfs_server *server; /* Needed for ID mapping */
const u32 * bitmask;
__u32 claim;
+ struct nfs41_sequence_args seq_args;
};
struct nfs_openres {
@@ -148,6 +186,7 @@ struct nfs_openres {
__u32 do_recall;
__u64 maxsize;
__u32 attrset[NFS4_BITMAP_SIZE];
+ struct nfs41_sequence_res seq_res;
};
/*
@@ -173,6 +212,7 @@ struct nfs_closeargs {
struct nfs_seqid * seqid;
int open_flags;
const u32 * bitmask;
+ struct nfs41_sequence_args seq_args;
};
struct nfs_closeres {
@@ -180,6 +220,7 @@ struct nfs_closeres {
struct nfs_fattr * fattr;
struct nfs_seqid * seqid;
const struct nfs_server *server;
+ struct nfs41_sequence_res seq_res;
};
/*
* * Arguments to the lock,lockt, and locku call.
@@ -200,12 +241,14 @@ struct nfs_lock_args {
unsigned char block : 1;
unsigned char reclaim : 1;
unsigned char new_lock_owner : 1;
+ struct nfs41_sequence_args seq_args;
};
struct nfs_lock_res {
nfs4_stateid stateid;
struct nfs_seqid * lock_seqid;
struct nfs_seqid * open_seqid;
+ struct nfs41_sequence_res seq_res;
};
struct nfs_locku_args {
@@ -213,32 +256,38 @@ struct nfs_locku_args {
struct file_lock * fl;
struct nfs_seqid * seqid;
nfs4_stateid * stateid;
+ struct nfs41_sequence_args seq_args;
};
struct nfs_locku_res {
nfs4_stateid stateid;
struct nfs_seqid * seqid;
+ struct nfs41_sequence_res seq_res;
};
struct nfs_lockt_args {
struct nfs_fh * fh;
struct file_lock * fl;
struct nfs_lowner lock_owner;
+ struct nfs41_sequence_args seq_args;
};
struct nfs_lockt_res {
struct file_lock * denied; /* LOCK, LOCKT failed */
+ struct nfs41_sequence_res seq_res;
};
struct nfs4_delegreturnargs {
const struct nfs_fh *fhandle;
const nfs4_stateid *stateid;
const u32 * bitmask;
+ struct nfs41_sequence_args seq_args;
};
struct nfs4_delegreturnres {
struct nfs_fattr * fattr;
const struct nfs_server *server;
+ struct nfs41_sequence_res seq_res;
};
/*
@@ -251,12 +300,14 @@ struct nfs_readargs {
__u32 count;
unsigned int pgbase;
struct page ** pages;
+ struct nfs41_sequence_args seq_args;
};
struct nfs_readres {
struct nfs_fattr * fattr;
__u32 count;
int eof;
+ struct nfs41_sequence_res seq_res;
};
/*
@@ -271,6 +322,7 @@ struct nfs_writeargs {
unsigned int pgbase;
struct page ** pages;
const u32 * bitmask;
+ struct nfs41_sequence_args seq_args;
};
struct nfs_writeverf {
@@ -283,6 +335,7 @@ struct nfs_writeres {
struct nfs_writeverf * verf;
__u32 count;
const struct nfs_server *server;
+ struct nfs41_sequence_res seq_res;
};
/*
@@ -292,12 +345,14 @@ struct nfs_removeargs {
const struct nfs_fh *fh;
struct qstr name;
const u32 * bitmask;
+ struct nfs41_sequence_args seq_args;
};
struct nfs_removeres {
const struct nfs_server *server;
struct nfs4_change_info cinfo;
struct nfs_fattr dir_attr;
+ struct nfs41_sequence_res seq_res;
};
/*
@@ -350,6 +405,7 @@ struct nfs_setattrargs {
struct iattr * iap;
const struct nfs_server * server; /* Needed for name mapping */
const u32 * bitmask;
+ struct nfs41_sequence_args seq_args;
};
struct nfs_setaclargs {
@@ -357,6 +413,11 @@ struct nfs_setaclargs {
size_t acl_len;
unsigned int acl_pgbase;
struct page ** acl_pages;
+ struct nfs41_sequence_args seq_args;
+};
+
+struct nfs_setaclres {
+ struct nfs41_sequence_res seq_res;
};
struct nfs_getaclargs {
@@ -364,11 +425,18 @@ struct nfs_getaclargs {
size_t acl_len;
unsigned int acl_pgbase;
struct page ** acl_pages;
+ struct nfs41_sequence_args seq_args;
+};
+
+struct nfs_getaclres {
+ size_t *acl_len;
+ struct nfs41_sequence_res seq_res;
};
struct nfs_setattrres {
struct nfs_fattr * fattr;
const struct nfs_server * server;
+ struct nfs41_sequence_res seq_res;
};
struct nfs_linkargs {
@@ -548,6 +616,7 @@ struct nfs4_accessargs {
const struct nfs_fh * fh;
const u32 * bitmask;
u32 access;
+ struct nfs41_sequence_args seq_args;
};
struct nfs4_accessres {
@@ -555,6 +624,7 @@ struct nfs4_accessres {
struct nfs_fattr * fattr;
u32 supported;
u32 access;
+ struct nfs41_sequence_res seq_res;
};
struct nfs4_create_arg {
@@ -574,6 +644,7 @@ struct nfs4_create_arg {
const struct iattr * attrs;
const struct nfs_fh * dir_fh;
const u32 * bitmask;
+ struct nfs41_sequence_args seq_args;
};
struct nfs4_create_res {
@@ -582,21 +653,30 @@ struct nfs4_create_res {
struct nfs_fattr * fattr;
struct nfs4_change_info dir_cinfo;
struct nfs_fattr * dir_fattr;
+ struct nfs41_sequence_res seq_res;
};
struct nfs4_fsinfo_arg {
const struct nfs_fh * fh;
const u32 * bitmask;
+ struct nfs41_sequence_args seq_args;
+};
+
+struct nfs4_fsinfo_res {
+ struct nfs_fsinfo *fsinfo;
+ struct nfs41_sequence_res seq_res;
};
struct nfs4_getattr_arg {
const struct nfs_fh * fh;
const u32 * bitmask;
+ struct nfs41_sequence_args seq_args;
};
struct nfs4_getattr_res {
const struct nfs_server * server;
struct nfs_fattr * fattr;
+ struct nfs41_sequence_res seq_res;
};
struct nfs4_link_arg {
@@ -604,6 +684,7 @@ struct nfs4_link_arg {
const struct nfs_fh * dir_fh;
const struct qstr * name;
const u32 * bitmask;
+ struct nfs41_sequence_args seq_args;
};
struct nfs4_link_res {
@@ -611,6 +692,7 @@ struct nfs4_link_res {
struct nfs_fattr * fattr;
struct nfs4_change_info cinfo;
struct nfs_fattr * dir_attr;
+ struct nfs41_sequence_res seq_res;
};
@@ -618,21 +700,30 @@ struct nfs4_lookup_arg {
const struct nfs_fh * dir_fh;
const struct qstr * name;
const u32 * bitmask;
+ struct nfs41_sequence_args seq_args;
};
struct nfs4_lookup_res {
const struct nfs_server * server;
struct nfs_fattr * fattr;
struct nfs_fh * fh;
+ struct nfs41_sequence_res seq_res;
};
struct nfs4_lookup_root_arg {
const u32 * bitmask;
+ struct nfs41_sequence_args seq_args;
};
struct nfs4_pathconf_arg {
const struct nfs_fh * fh;
const u32 * bitmask;
+ struct nfs41_sequence_args seq_args;
+};
+
+struct nfs4_pathconf_res {
+ struct nfs_pathconf *pathconf;
+ struct nfs41_sequence_res seq_res;
};
struct nfs4_readdir_arg {
@@ -643,11 +734,13 @@ struct nfs4_readdir_arg {
struct page ** pages; /* zero-copy data */
unsigned int pgbase; /* zero-copy data */
const u32 * bitmask;
+ struct nfs41_sequence_args seq_args;
};
struct nfs4_readdir_res {
nfs4_verifier verifier;
unsigned int pgbase;
+ struct nfs41_sequence_res seq_res;
};
struct nfs4_readlink {
@@ -655,6 +748,11 @@ struct nfs4_readlink {
unsigned int pgbase;
unsigned int pglen; /* zero-copy data */
struct page ** pages; /* zero-copy data */
+ struct nfs41_sequence_args seq_args;
+};
+
+struct nfs4_readlink_res {
+ struct nfs41_sequence_res seq_res;
};
struct nfs4_rename_arg {
@@ -663,6 +761,7 @@ struct nfs4_rename_arg {
const struct qstr * old_name;
const struct qstr * new_name;
const u32 * bitmask;
+ struct nfs41_sequence_args seq_args;
};
struct nfs4_rename_res {
@@ -671,6 +770,7 @@ struct nfs4_rename_res {
struct nfs_fattr * old_fattr;
struct nfs4_change_info new_cinfo;
struct nfs_fattr * new_fattr;
+ struct nfs41_sequence_res seq_res;
};
#define NFS4_SETCLIENTID_NAMELEN (127)
@@ -689,6 +789,17 @@ struct nfs4_setclientid {
struct nfs4_statfs_arg {
const struct nfs_fh * fh;
const u32 * bitmask;
+ struct nfs41_sequence_args seq_args;
+};
+
+struct nfs4_statfs_res {
+ struct nfs_fsstat *fsstat;
+ struct nfs41_sequence_res seq_res;
+};
+
+struct nfs4_server_caps_arg {
+ struct nfs_fh *fhandle;
+ struct nfs41_sequence_args seq_args;
};
struct nfs4_server_caps_res {
@@ -696,6 +807,7 @@ struct nfs4_server_caps_res {
u32 acl_bitmask;
u32 has_links;
u32 has_symlinks;
+ struct nfs41_sequence_res seq_res;
};
struct nfs4_string {
@@ -730,6 +842,12 @@ struct nfs4_fs_locations_arg {
const struct qstr *name;
struct page *page;
const u32 *bitmask;
+ struct nfs41_sequence_args seq_args;
+};
+
+struct nfs4_fs_locations_res {
+ struct nfs4_fs_locations *fs_locations;
+ struct nfs41_sequence_res seq_res;
};
#endif /* CONFIG_NFS_V4 */
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* Re: [pnfs] [RFC 08/85] nfs41: client xdr definitions
2008-11-10 20:19 ` [RFC 08/85] nfs41: client xdr definitions Benny Halevy
@ 2008-11-17 13:31 ` Benny Halevy
0 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-17 13:31 UTC (permalink / raw)
To: pnfs; +Cc: trond.myklebust, linux-nfs
On Nov. 10, 2008, 22:19 +0200, Benny Halevy <bhalevy@panasas.com> wrote:
> Define stubs for sequence args and res data structures and embed
> them in all other nfs4 and nfs41 xdr types. They are needed for
> sending any op in a nfs41 compound rpc.
>
> Signed-off-by: Andy Adamson<andros@netapp.com>
> Signed-off-by: Benny Halevy <bhalevy@panasas.com>
> ---
> include/linux/nfs_xdr.h | 118 +++++++++++++++++++++++++++++++++++++++++++++++
> 1 files changed, 118 insertions(+), 0 deletions(-)
>
> diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
> index c1c31ac..a8a0953 100644
> --- a/include/linux/nfs_xdr.h
> +++ b/include/linux/nfs_xdr.h
> @@ -113,6 +113,43 @@ struct nfs4_change_info {
> };
>
> struct nfs_seqid;
> +
> +/* Opaque session ID */
> +struct sessionid4 {
> + char data[NFS4_MAX_SESSIONID_LEN];
> +};
review 11-14: this is redundant.
> +
> +struct nfs41_sequence_args {
> + /* stub */
> +};
> +
> +#define SEQ4_STATUS_CB_PATH_DOWN 0x00000001
> +#define SEQ4_STATUS_CB_GSS_CONTEXTS_EXPIRING 0x00000002
> +#define SEQ4_STATUS_CB_GSS_CONTEXTS_EXPIRED 0x00000004
> +#define SEQ4_STATUS_EXPIRED_ALL_STATE_REVOKED 0x00000008
> +#define SEQ4_STATUS_EXPIRED_SOME_STATE_REVOKED 0x00000010
> +#define SEQ4_STATUS_ADMIN_STATE_REVOKED 0x00000020
> +#define SEQ4_STATUS_RECALLABLE_STATE_REVOKED 0x00000040
> +#define SEQ4_STATUS_LEASE_MOVED 0x00000080
> +#define SEQ4_STATUS_RESTART_RECLAIM_NEEDED 0x00000100
> +
> +struct nfs41_sequence_res {
> + /* stub */
> +};
> +
> +#if defined(CONFIG_NFS_V4_1)
review 11-14: no need for #ifdef
> +
> +struct nfs4_get_lease_time_args {
> + struct nfs41_sequence_args la_seq_args;
> +};
> +
> +struct nfs4_get_lease_time_res {
> + struct nfs_fsinfo *lr_fsinfo;
> + struct nfs41_sequence_res lr_seq_res;
> +};
> +
> +#endif /* CONFIG_NFS_V4_1 */
> +
> /*
> * Arguments to the open call.
> */
> @@ -132,6 +169,7 @@ struct nfs_openargs {
> const struct nfs_server *server; /* Needed for ID mapping */
> const u32 * bitmask;
> __u32 claim;
> + struct nfs41_sequence_args seq_args;
review 11-14: discussed embedding seq_args/res vs. having a wrapper
structure a-la
struct nfs_rpc_args {
void *op_args;
struct nfs41_sequence_args seq_args;
};
struct nfs_rpc_res {
void *op_res;
struct nfs41_sequence_res seq_res;
};
Trond prefers the former (keep current).
> };
>
> struct nfs_openres {
> @@ -148,6 +186,7 @@ struct nfs_openres {
> __u32 do_recall;
> __u64 maxsize;
> __u32 attrset[NFS4_BITMAP_SIZE];
> + struct nfs41_sequence_res seq_res;
> };
>
> /*
> @@ -173,6 +212,7 @@ struct nfs_closeargs {
> struct nfs_seqid * seqid;
> int open_flags;
> const u32 * bitmask;
> + struct nfs41_sequence_args seq_args;
> };
>
> struct nfs_closeres {
> @@ -180,6 +220,7 @@ struct nfs_closeres {
> struct nfs_fattr * fattr;
> struct nfs_seqid * seqid;
> const struct nfs_server *server;
> + struct nfs41_sequence_res seq_res;
> };
> /*
> * * Arguments to the lock,lockt, and locku call.
> @@ -200,12 +241,14 @@ struct nfs_lock_args {
> unsigned char block : 1;
> unsigned char reclaim : 1;
> unsigned char new_lock_owner : 1;
> + struct nfs41_sequence_args seq_args;
> };
>
> struct nfs_lock_res {
> nfs4_stateid stateid;
> struct nfs_seqid * lock_seqid;
> struct nfs_seqid * open_seqid;
> + struct nfs41_sequence_res seq_res;
> };
>
> struct nfs_locku_args {
> @@ -213,32 +256,38 @@ struct nfs_locku_args {
> struct file_lock * fl;
> struct nfs_seqid * seqid;
> nfs4_stateid * stateid;
> + struct nfs41_sequence_args seq_args;
> };
>
> struct nfs_locku_res {
> nfs4_stateid stateid;
> struct nfs_seqid * seqid;
> + struct nfs41_sequence_res seq_res;
> };
>
> struct nfs_lockt_args {
> struct nfs_fh * fh;
> struct file_lock * fl;
> struct nfs_lowner lock_owner;
> + struct nfs41_sequence_args seq_args;
> };
>
> struct nfs_lockt_res {
> struct file_lock * denied; /* LOCK, LOCKT failed */
> + struct nfs41_sequence_res seq_res;
> };
>
> struct nfs4_delegreturnargs {
> const struct nfs_fh *fhandle;
> const nfs4_stateid *stateid;
> const u32 * bitmask;
> + struct nfs41_sequence_args seq_args;
> };
>
> struct nfs4_delegreturnres {
> struct nfs_fattr * fattr;
> const struct nfs_server *server;
> + struct nfs41_sequence_res seq_res;
> };
>
> /*
> @@ -251,12 +300,14 @@ struct nfs_readargs {
> __u32 count;
> unsigned int pgbase;
> struct page ** pages;
> + struct nfs41_sequence_args seq_args;
> };
>
> struct nfs_readres {
> struct nfs_fattr * fattr;
> __u32 count;
> int eof;
> + struct nfs41_sequence_res seq_res;
> };
>
> /*
> @@ -271,6 +322,7 @@ struct nfs_writeargs {
> unsigned int pgbase;
> struct page ** pages;
> const u32 * bitmask;
> + struct nfs41_sequence_args seq_args;
> };
>
> struct nfs_writeverf {
> @@ -283,6 +335,7 @@ struct nfs_writeres {
> struct nfs_writeverf * verf;
> __u32 count;
> const struct nfs_server *server;
> + struct nfs41_sequence_res seq_res;
> };
>
> /*
> @@ -292,12 +345,14 @@ struct nfs_removeargs {
> const struct nfs_fh *fh;
> struct qstr name;
> const u32 * bitmask;
> + struct nfs41_sequence_args seq_args;
> };
>
> struct nfs_removeres {
> const struct nfs_server *server;
> struct nfs4_change_info cinfo;
> struct nfs_fattr dir_attr;
> + struct nfs41_sequence_res seq_res;
> };
>
> /*
> @@ -350,6 +405,7 @@ struct nfs_setattrargs {
> struct iattr * iap;
> const struct nfs_server * server; /* Needed for name mapping */
> const u32 * bitmask;
> + struct nfs41_sequence_args seq_args;
> };
>
> struct nfs_setaclargs {
> @@ -357,6 +413,11 @@ struct nfs_setaclargs {
> size_t acl_len;
> unsigned int acl_pgbase;
> struct page ** acl_pages;
> + struct nfs41_sequence_args seq_args;
> +};
> +
> +struct nfs_setaclres {
> + struct nfs41_sequence_res seq_res;
> };
>
> struct nfs_getaclargs {
> @@ -364,11 +425,18 @@ struct nfs_getaclargs {
> size_t acl_len;
> unsigned int acl_pgbase;
> struct page ** acl_pages;
> + struct nfs41_sequence_args seq_args;
> +};
> +
> +struct nfs_getaclres {
> + size_t *acl_len;
> + struct nfs41_sequence_res seq_res;
> };
>
> struct nfs_setattrres {
> struct nfs_fattr * fattr;
> const struct nfs_server * server;
> + struct nfs41_sequence_res seq_res;
> };
>
> struct nfs_linkargs {
> @@ -548,6 +616,7 @@ struct nfs4_accessargs {
> const struct nfs_fh * fh;
> const u32 * bitmask;
> u32 access;
> + struct nfs41_sequence_args seq_args;
> };
>
> struct nfs4_accessres {
> @@ -555,6 +624,7 @@ struct nfs4_accessres {
> struct nfs_fattr * fattr;
> u32 supported;
> u32 access;
> + struct nfs41_sequence_res seq_res;
> };
>
> struct nfs4_create_arg {
> @@ -574,6 +644,7 @@ struct nfs4_create_arg {
> const struct iattr * attrs;
> const struct nfs_fh * dir_fh;
> const u32 * bitmask;
> + struct nfs41_sequence_args seq_args;
> };
>
> struct nfs4_create_res {
> @@ -582,21 +653,30 @@ struct nfs4_create_res {
> struct nfs_fattr * fattr;
> struct nfs4_change_info dir_cinfo;
> struct nfs_fattr * dir_fattr;
> + struct nfs41_sequence_res seq_res;
> };
>
> struct nfs4_fsinfo_arg {
> const struct nfs_fh * fh;
> const u32 * bitmask;
> + struct nfs41_sequence_args seq_args;
> +};
> +
> +struct nfs4_fsinfo_res {
> + struct nfs_fsinfo *fsinfo;
> + struct nfs41_sequence_res seq_res;
> };
>
> struct nfs4_getattr_arg {
> const struct nfs_fh * fh;
> const u32 * bitmask;
> + struct nfs41_sequence_args seq_args;
> };
>
> struct nfs4_getattr_res {
> const struct nfs_server * server;
> struct nfs_fattr * fattr;
> + struct nfs41_sequence_res seq_res;
> };
>
> struct nfs4_link_arg {
> @@ -604,6 +684,7 @@ struct nfs4_link_arg {
> const struct nfs_fh * dir_fh;
> const struct qstr * name;
> const u32 * bitmask;
> + struct nfs41_sequence_args seq_args;
> };
>
> struct nfs4_link_res {
> @@ -611,6 +692,7 @@ struct nfs4_link_res {
> struct nfs_fattr * fattr;
> struct nfs4_change_info cinfo;
> struct nfs_fattr * dir_attr;
> + struct nfs41_sequence_res seq_res;
> };
>
>
> @@ -618,21 +700,30 @@ struct nfs4_lookup_arg {
> const struct nfs_fh * dir_fh;
> const struct qstr * name;
> const u32 * bitmask;
> + struct nfs41_sequence_args seq_args;
> };
>
> struct nfs4_lookup_res {
> const struct nfs_server * server;
> struct nfs_fattr * fattr;
> struct nfs_fh * fh;
> + struct nfs41_sequence_res seq_res;
> };
>
> struct nfs4_lookup_root_arg {
> const u32 * bitmask;
> + struct nfs41_sequence_args seq_args;
> };
>
> struct nfs4_pathconf_arg {
> const struct nfs_fh * fh;
> const u32 * bitmask;
> + struct nfs41_sequence_args seq_args;
> +};
> +
> +struct nfs4_pathconf_res {
> + struct nfs_pathconf *pathconf;
> + struct nfs41_sequence_res seq_res;
> };
>
> struct nfs4_readdir_arg {
> @@ -643,11 +734,13 @@ struct nfs4_readdir_arg {
> struct page ** pages; /* zero-copy data */
> unsigned int pgbase; /* zero-copy data */
> const u32 * bitmask;
> + struct nfs41_sequence_args seq_args;
> };
>
> struct nfs4_readdir_res {
> nfs4_verifier verifier;
> unsigned int pgbase;
> + struct nfs41_sequence_res seq_res;
> };
>
> struct nfs4_readlink {
> @@ -655,6 +748,11 @@ struct nfs4_readlink {
> unsigned int pgbase;
> unsigned int pglen; /* zero-copy data */
> struct page ** pages; /* zero-copy data */
> + struct nfs41_sequence_args seq_args;
> +};
> +
> +struct nfs4_readlink_res {
> + struct nfs41_sequence_res seq_res;
> };
>
> struct nfs4_rename_arg {
> @@ -663,6 +761,7 @@ struct nfs4_rename_arg {
> const struct qstr * old_name;
> const struct qstr * new_name;
> const u32 * bitmask;
> + struct nfs41_sequence_args seq_args;
> };
>
> struct nfs4_rename_res {
> @@ -671,6 +770,7 @@ struct nfs4_rename_res {
> struct nfs_fattr * old_fattr;
> struct nfs4_change_info new_cinfo;
> struct nfs_fattr * new_fattr;
> + struct nfs41_sequence_res seq_res;
> };
>
> #define NFS4_SETCLIENTID_NAMELEN (127)
> @@ -689,6 +789,17 @@ struct nfs4_setclientid {
> struct nfs4_statfs_arg {
> const struct nfs_fh * fh;
> const u32 * bitmask;
> + struct nfs41_sequence_args seq_args;
> +};
> +
> +struct nfs4_statfs_res {
> + struct nfs_fsstat *fsstat;
> + struct nfs41_sequence_res seq_res;
> +};
> +
> +struct nfs4_server_caps_arg {
> + struct nfs_fh *fhandle;
> + struct nfs41_sequence_args seq_args;
> };
>
> struct nfs4_server_caps_res {
> @@ -696,6 +807,7 @@ struct nfs4_server_caps_res {
> u32 acl_bitmask;
> u32 has_links;
> u32 has_symlinks;
> + struct nfs41_sequence_res seq_res;
> };
>
> struct nfs4_string {
> @@ -730,6 +842,12 @@ struct nfs4_fs_locations_arg {
> const struct qstr *name;
> struct page *page;
> const u32 *bitmask;
> + struct nfs41_sequence_args seq_args;
> +};
> +
> +struct nfs4_fs_locations_res {
> + struct nfs4_fs_locations *fs_locations;
> + struct nfs41_sequence_res seq_res;
> };
>
> #endif /* CONFIG_NFS_V4 */
^ permalink raw reply [flat|nested] 115+ messages in thread
* [RFC 09/85] nfs41: add mount command option minorvers
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (5 preceding siblings ...)
2008-11-10 20:19 ` [RFC 08/85] nfs41: client xdr definitions Benny Halevy
@ 2008-11-10 20:19 ` Benny Halevy
2008-11-17 13:34 ` [pnfs] " Benny Halevy
2008-11-10 20:19 ` [RFC 10/85] nfs41: struct nfs_server minorversion Benny Halevy
` (78 subsequent siblings)
85 siblings, 1 reply; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:19 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
From: Mike Sager <sager@netapp.com>
mount -t nfs4 -o minorvers=[0|1] specifies whether to use 4.0 or 4.1.
The default is 1.
Signed-off-by: Mike Sager <sager@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/internal.h | 1 +
fs/nfs/super.c | 10 ++++++++++
2 files changed, 11 insertions(+), 0 deletions(-)
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index d212ee4..b423422 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -41,6 +41,7 @@ struct nfs_parsed_mount_data {
unsigned int auth_flavor_len;
rpc_authflavor_t auth_flavors[1];
char *client_address;
+ unsigned int minorversion;
struct {
struct sockaddr_storage address;
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index f48db67..03f143d 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -87,6 +87,7 @@ enum {
Opt_mountport,
Opt_mountvers,
Opt_nfsvers,
+ Opt_minorversion,
/* Mount options that take string arguments */
Opt_sec, Opt_proto, Opt_mountproto, Opt_mounthost,
@@ -146,6 +147,7 @@ static const match_table_t nfs_mount_option_tokens = {
{ Opt_mountvers, "mountvers=%u" },
{ Opt_nfsvers, "nfsvers=%u" },
{ Opt_nfsvers, "vers=%u" },
+ { Opt_minorversion, "minorversion=%u" },
{ Opt_sec, "sec=%s" },
{ Opt_proto, "proto=%s" },
@@ -1160,6 +1162,13 @@ static int nfs_parse_mount_options(char *raw,
nfs_parse_invalid_value("nfsvers");
}
break;
+ case Opt_minorversion:
+ if (match_int(args, &option))
+ return 0;
+ if (option < 0 || option > NFS4_MAX_MINOR_VERSION)
+ return 0;
+ mnt->minorversion = option;
+ break;
/*
* options that take text values
@@ -2208,6 +2217,7 @@ static int nfs4_validate_mount_data(void *options,
args->nfs_server.port = NFS_PORT; /* 2049 unless user set port= */
args->auth_flavors[0] = RPC_AUTH_UNIX;
args->auth_flavor_len = 0;
+ args->minorversion = NFS4_MAX_MINOR_VERSION;
switch (data->version) {
case 1:
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* Re: [pnfs] [RFC 09/85] nfs41: add mount command option minorvers
2008-11-10 20:19 ` [RFC 09/85] nfs41: add mount command option minorvers Benny Halevy
@ 2008-11-17 13:34 ` Benny Halevy
0 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-17 13:34 UTC (permalink / raw)
To: pnfs; +Cc: trond.myklebust, linux-nfs
review 11-13: s/minorvers/minorversion/ in patch description
add to commit message reasoning - mounting a broken nfsv4.0 server
that breaks when attempting a 4.1 mount
On Nov. 10, 2008, 22:19 +0200, Benny Halevy <bhalevy@panasas.com> wrote:
> From: Mike Sager <sager@netapp.com>
>
> mount -t nfs4 -o minorvers=[0|1] specifies whether to use 4.0 or 4.1.
> The default is 1.
>
> Signed-off-by: Mike Sager <sager@netapp.com>
> Signed-off-by: Benny Halevy <bhalevy@panasas.com>
> ---
> fs/nfs/internal.h | 1 +
> fs/nfs/super.c | 10 ++++++++++
> 2 files changed, 11 insertions(+), 0 deletions(-)
>
> diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
> index d212ee4..b423422 100644
> --- a/fs/nfs/internal.h
> +++ b/fs/nfs/internal.h
> @@ -41,6 +41,7 @@ struct nfs_parsed_mount_data {
> unsigned int auth_flavor_len;
> rpc_authflavor_t auth_flavors[1];
> char *client_address;
> + unsigned int minorversion;
>
> struct {
> struct sockaddr_storage address;
> diff --git a/fs/nfs/super.c b/fs/nfs/super.c
> index f48db67..03f143d 100644
> --- a/fs/nfs/super.c
> +++ b/fs/nfs/super.c
> @@ -87,6 +87,7 @@ enum {
> Opt_mountport,
> Opt_mountvers,
> Opt_nfsvers,
> + Opt_minorversion,
>
> /* Mount options that take string arguments */
> Opt_sec, Opt_proto, Opt_mountproto, Opt_mounthost,
> @@ -146,6 +147,7 @@ static const match_table_t nfs_mount_option_tokens = {
> { Opt_mountvers, "mountvers=%u" },
> { Opt_nfsvers, "nfsvers=%u" },
> { Opt_nfsvers, "vers=%u" },
> + { Opt_minorversion, "minorversion=%u" },
>
> { Opt_sec, "sec=%s" },
> { Opt_proto, "proto=%s" },
> @@ -1160,6 +1162,13 @@ static int nfs_parse_mount_options(char *raw,
> nfs_parse_invalid_value("nfsvers");
> }
> break;
> + case Opt_minorversion:
> + if (match_int(args, &option))
> + return 0;
> + if (option < 0 || option > NFS4_MAX_MINOR_VERSION)
> + return 0;
> + mnt->minorversion = option;
> + break;
>
> /*
> * options that take text values
> @@ -2208,6 +2217,7 @@ static int nfs4_validate_mount_data(void *options,
> args->nfs_server.port = NFS_PORT; /* 2049 unless user set port= */
> args->auth_flavors[0] = RPC_AUTH_UNIX;
> args->auth_flavor_len = 0;
> + args->minorversion = NFS4_MAX_MINOR_VERSION;
>
> switch (data->version) {
> case 1:
^ permalink raw reply [flat|nested] 115+ messages in thread
* [RFC 10/85] nfs41: struct nfs_server minorversion
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (6 preceding siblings ...)
2008-11-10 20:19 ` [RFC 09/85] nfs41: add mount command option minorvers Benny Halevy
@ 2008-11-10 20:19 ` Benny Halevy
2008-11-17 13:34 ` [pnfs] " Benny Halevy
2008-11-10 20:19 ` [RFC 11/85] nfs41: nfs_client.cl_minorversion Benny Halevy
` (77 subsequent siblings)
85 siblings, 1 reply; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:19 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
From: Mike Sager <sager@netapp.com>
Set nfs_server minorversion from mount option (or default).
During client initialization, use this minorversion.
Signed-off-by: Mike Sager <sager@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/client.c | 2 ++
include/linux/nfs_fs_sb.h | 1 +
2 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 7547600..fe0bac9 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -1112,6 +1112,8 @@ struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data,
if (!server)
return ERR_PTR(-ENOMEM);
+ server->minorversion = data->minorversion;
+
/* set up the general RPC client */
error = nfs4_init_server(server, data);
if (error < 0)
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index 4e477ae..bfc83cc 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -115,6 +115,7 @@ struct nfs_server {
u32 acl_bitmask; /* V4 bitmask representing the ACEs
that are supported on this
filesystem */
+ u32 minorversion;
#endif
void (*destroy)(struct nfs_server *);
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* Re: [pnfs] [RFC 10/85] nfs41: struct nfs_server minorversion
2008-11-10 20:19 ` [RFC 10/85] nfs41: struct nfs_server minorversion Benny Halevy
@ 2008-11-17 13:34 ` Benny Halevy
0 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-17 13:34 UTC (permalink / raw)
To: pnfs; +Cc: trond.myklebust, linux-nfs
On Nov. 10, 2008, 22:19 +0200, Benny Halevy <bhalevy@panasas.com> wrote:
> From: Mike Sager <sager@netapp.com>
>
> Set nfs_server minorversion from mount option (or default).
> During client initialization, use this minorversion.
>
> Signed-off-by: Mike Sager <sager@netapp.com>
> Signed-off-by: Benny Halevy <bhalevy@panasas.com>
review 11-14: see if wse can only keep one copy of the minorversion
in the nfs_client.
> ---
> fs/nfs/client.c | 2 ++
> include/linux/nfs_fs_sb.h | 1 +
> 2 files changed, 3 insertions(+), 0 deletions(-)
>
> diff --git a/fs/nfs/client.c b/fs/nfs/client.c
> index 7547600..fe0bac9 100644
> --- a/fs/nfs/client.c
> +++ b/fs/nfs/client.c
> @@ -1112,6 +1112,8 @@ struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data,
> if (!server)
> return ERR_PTR(-ENOMEM);
>
> + server->minorversion = data->minorversion;
> +
> /* set up the general RPC client */
> error = nfs4_init_server(server, data);
> if (error < 0)
> diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
> index 4e477ae..bfc83cc 100644
> --- a/include/linux/nfs_fs_sb.h
> +++ b/include/linux/nfs_fs_sb.h
> @@ -115,6 +115,7 @@ struct nfs_server {
> u32 acl_bitmask; /* V4 bitmask representing the ACEs
> that are supported on this
> filesystem */
> + u32 minorversion;
> #endif
> void (*destroy)(struct nfs_server *);
>
--
Benny Halevy
Software Architect
Tel/Fax: +972-3-647-8340
Mobile: +972-54-802-8340
bhalevy@panasas.com
Panasas, Inc.
The Leader in Parallel Storage
www.panasas.com
^ permalink raw reply [flat|nested] 115+ messages in thread
* [RFC 11/85] nfs41: nfs_client.cl_minorversion
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (7 preceding siblings ...)
2008-11-10 20:19 ` [RFC 10/85] nfs41: struct nfs_server minorversion Benny Halevy
@ 2008-11-10 20:19 ` Benny Halevy
2008-11-17 13:37 ` [pnfs] " Benny Halevy
2008-11-10 20:19 ` [RFC 12/85] nfs41: set nfs_client rpc_ops based on minorversion Benny Halevy
` (76 subsequent siblings)
85 siblings, 1 reply; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:19 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
This field is set to the nfsv4 minor version for this mount.
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/client.c | 1 +
include/linux/nfs_fs_sb.h | 3 ++-
2 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index fe0bac9..c6e9b4e 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -1030,6 +1030,7 @@ static int nfs4_set_client(struct nfs_server *server,
error = PTR_ERR(clp);
goto error;
}
+ clp->cl_minorversion = server->minorversion;
error = nfs4_init_client(clp, timeparms, ip_addr, authflavour);
if (error < 0)
goto error_put;
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index bfc83cc..8379dd5 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -69,7 +69,8 @@ struct nfs_client {
*/
char cl_ipaddr[48];
unsigned char cl_id_uniquifier;
-#endif
+ u32 cl_minorversion;
+#endif /* CONFIG_NFS_V4 */
};
/*
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* Re: [pnfs] [RFC 11/85] nfs41: nfs_client.cl_minorversion
2008-11-10 20:19 ` [RFC 11/85] nfs41: nfs_client.cl_minorversion Benny Halevy
@ 2008-11-17 13:37 ` Benny Halevy
0 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-17 13:37 UTC (permalink / raw)
To: pnfs; +Cc: trond.myklebust, linux-nfs
On Nov. 10, 2008, 22:19 +0200, Benny Halevy <bhalevy@panasas.com> wrote:
> This field is set to the nfsv4 minor version for this mount.
>
> Signed-off-by: Benny Halevy <bhalevy@panasas.com>
review 11-14: directly set cl_minorversion to data->minorversion in
callers of nfs4_set_client.
we want to differentiate between autodetect minorersion (-1) and
one that's explictly set by the mount option. and remember that
for referrals. keep that as a flag in nfs_client.cl_res_state
On autodetect reclaimer should try with the highest minorversion
and possibly fallback if needed, otherwise try only given
minorversion. On clone (referral) follow the same algorithm
using the master copy's minorversion configuration.
> ---
> fs/nfs/client.c | 1 +
> include/linux/nfs_fs_sb.h | 3 ++-
> 2 files changed, 3 insertions(+), 1 deletions(-)
>
> diff --git a/fs/nfs/client.c b/fs/nfs/client.c
> index fe0bac9..c6e9b4e 100644
> --- a/fs/nfs/client.c
> +++ b/fs/nfs/client.c
> @@ -1030,6 +1030,7 @@ static int nfs4_set_client(struct nfs_server *server,
> error = PTR_ERR(clp);
> goto error;
> }
> + clp->cl_minorversion = server->minorversion;
> error = nfs4_init_client(clp, timeparms, ip_addr, authflavour);
> if (error < 0)
> goto error_put;
> diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
> index bfc83cc..8379dd5 100644
> --- a/include/linux/nfs_fs_sb.h
> +++ b/include/linux/nfs_fs_sb.h
> @@ -69,7 +69,8 @@ struct nfs_client {
> */
> char cl_ipaddr[48];
> unsigned char cl_id_uniquifier;
> -#endif
> + u32 cl_minorversion;
> +#endif /* CONFIG_NFS_V4 */
> };
>
> /*
^ permalink raw reply [flat|nested] 115+ messages in thread
* [RFC 12/85] nfs41: set nfs_client rpc_ops based on minorversion
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (8 preceding siblings ...)
2008-11-10 20:19 ` [RFC 11/85] nfs41: nfs_client.cl_minorversion Benny Halevy
@ 2008-11-10 20:19 ` Benny Halevy
2008-11-10 20:20 ` [RFC 13/85] nfs41: use ptr to rpc procedures via struct nfs_client Benny Halevy
` (75 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:19 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/client.c | 6 ++--
fs/nfs/nfs4proc.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++-
include/linux/nfs_xdr.h | 3 ++
3 files changed, 54 insertions(+), 4 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index c6e9b4e..7bc150b 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -359,7 +359,8 @@ static struct nfs_client *nfs_get_client(const struct nfs_client_initdata *cl_in
int error;
dprintk("--> nfs_get_client(%s,v%u)\n",
- cl_init->hostname ?: "", cl_init->rpc_ops->version);
+ cl_init->hostname ?: "",
+ cl_init->rpc_ops ? cl_init->rpc_ops->version : 0);
/* see if the client already exists */
do {
@@ -976,7 +977,7 @@ static int nfs4_init_client(struct nfs_client *clp,
}
/* Check NFS protocol revision and initialize RPC op vector */
- clp->rpc_ops = &nfs_v4_clientops;
+ clp->rpc_ops = nfsv4_minorversion_clientops[clp->cl_minorversion];
error = nfs_create_rpc_client(clp, timeparms, authflavour,
RPC_CLNT_CREATE_DISCRTRY);
@@ -1016,7 +1017,6 @@ static int nfs4_set_client(struct nfs_server *server,
.hostname = hostname,
.addr = addr,
.addrlen = addrlen,
- .rpc_ops = &nfs_v4_clientops,
.proto = proto,
};
struct nfs_client *clp;
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 83e700a..0256c97 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -3682,7 +3682,7 @@ static const struct inode_operations nfs4_file_inode_operations = {
.listxattr = nfs4_listxattr,
};
-const struct nfs_rpc_ops nfs_v4_clientops = {
+const struct nfs_rpc_ops nfs_v40_clientops = {
.version = 4, /* protocol version */
.dentry_ops = &nfs4_dentry_operations,
.dir_inode_ops = &nfs4_dir_inode_operations,
@@ -3720,6 +3720,53 @@ const struct nfs_rpc_ops nfs_v4_clientops = {
.clear_acl_cache = nfs4_zap_acl_attr,
};
+#if defined(CONFIG_NFS_V4_1)
+const struct nfs_rpc_ops nfs_v41_clientops = {
+ .version = 4, /* protocol version */
+ .dentry_ops = &nfs4_dentry_operations,
+ .dir_inode_ops = &nfs4_dir_inode_operations,
+ .file_inode_ops = &nfs4_file_inode_operations,
+ .getroot = nfs4_proc_get_root,
+ .getattr = nfs4_proc_getattr,
+ .setattr = nfs4_proc_setattr,
+ .lookupfh = nfs4_proc_lookupfh,
+ .lookup = nfs4_proc_lookup,
+ .access = nfs4_proc_access,
+ .readlink = nfs4_proc_readlink,
+ .create = nfs4_proc_create,
+ .remove = nfs4_proc_remove,
+ .unlink_setup = nfs4_proc_unlink_setup,
+ .unlink_done = nfs4_proc_unlink_done,
+ .rename = nfs4_proc_rename,
+ .link = nfs4_proc_link,
+ .symlink = nfs4_proc_symlink,
+ .mkdir = nfs4_proc_mkdir,
+ .rmdir = nfs4_proc_remove,
+ .readdir = nfs4_proc_readdir,
+ .mknod = nfs4_proc_mknod,
+ .statfs = nfs4_proc_statfs,
+ .fsinfo = nfs4_proc_fsinfo,
+ .pathconf = nfs4_proc_pathconf,
+ .set_capabilities = nfs4_server_capabilities,
+ .decode_dirent = nfs4_decode_dirent,
+ .read_setup = nfs4_proc_read_setup,
+ .read_done = nfs4_read_done,
+ .write_setup = nfs4_proc_write_setup,
+ .write_done = nfs4_write_done,
+ .commit_setup = nfs4_proc_commit_setup,
+ .commit_done = nfs4_commit_done,
+ .lock = nfs4_proc_lock,
+ .clear_acl_cache = nfs4_zap_acl_attr,
+};
+#endif /* CONFIG_NFS_V4_1 */
+
+const struct nfs_rpc_ops *nfsv4_minorversion_clientops[] = {
+ &nfs_v40_clientops,
+#if defined(CONFIG_NFS_V4_1)
+ &nfs_v41_clientops,
+#endif
+};
+
/*
* Local variables:
* c-basic-offset: 8
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index a8a0953..1d6f09a 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -966,6 +966,9 @@ struct nfs_rpc_ops {
extern const struct nfs_rpc_ops nfs_v2_clientops;
extern const struct nfs_rpc_ops nfs_v3_clientops;
extern const struct nfs_rpc_ops nfs_v4_clientops;
+extern const struct nfs_rpc_ops nfs_v40_clientops;
+extern const struct nfs_rpc_ops nfs_v41_clientops;
+extern const struct nfs_rpc_ops *nfsv4_minorversion_clientops[];
extern struct rpc_version nfs_version2;
extern struct rpc_version nfs_version3;
extern struct rpc_version nfs_version4;
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 13/85] nfs41: use ptr to rpc procedures via struct nfs_client
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (9 preceding siblings ...)
2008-11-10 20:19 ` [RFC 12/85] nfs41: set nfs_client rpc_ops based on minorversion Benny Halevy
@ 2008-11-10 20:20 ` Benny Halevy
2008-11-17 13:40 ` [pnfs] " Benny Halevy
2008-11-10 20:20 ` [RFC 14/85] nfs41: sunrpc: support minorversion for rpc_clnt version table Benny Halevy
` (74 subsequent siblings)
85 siblings, 1 reply; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:20 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
To support heterogenuous mount minor version, use the ptr to the effective
rpc procedures table via nfs_client->cl_rpcclient->cl_procinfo rather than
a global one.
nfs4_proc() is a static inline helper to get the rpc procedure
given a struct nfs_client * and the procedure index.
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/internal.h | 5 ---
fs/nfs/nfs4_fs.h | 1 -
fs/nfs/nfs4proc.c | 88 ++++++++++++++++++++++++++-------------------
fs/nfs/nfs4xdr.c | 22 +++++++++--
include/linux/nfs_fs_sb.h | 9 +++++
include/linux/nfs_xdr.h | 3 ++
6 files changed, 81 insertions(+), 47 deletions(-)
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index b423422..8386e99 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -134,11 +134,6 @@ extern __be32 *nfs3_decode_dirent(__be32 *, struct nfs_entry *, int);
extern __be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus);
#endif
-/* nfs4proc.c */
-#ifdef CONFIG_NFS_V4
-extern struct rpc_procinfo nfs4_procedures[];
-#endif
-
/* dir.c */
extern int nfs_access_cache_shrinker(int nr_to_scan, gfp_t gfp_mask);
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index ea79064..5fb7382 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -226,7 +226,6 @@ extern const nfs4_stateid zero_stateid;
/* nfs4xdr.c */
extern __be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus);
-extern struct rpc_procinfo nfs4_procedures[];
struct nfs4_mount_data;
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 0256c97..ef3370f 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -762,7 +762,8 @@ static int _nfs4_proc_open_confirm(struct nfs4_opendata *data)
struct nfs_server *server = NFS_SERVER(data->dir->d_inode);
struct rpc_task *task;
struct rpc_message msg = {
- .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_CONFIRM],
+ .rpc_proc = nfs4_proc(server->nfs_client,
+ NFSPROC4_CLNT_OPEN_CONFIRM),
.rpc_argp = &data->c_arg,
.rpc_resp = &data->c_res,
.rpc_cred = data->owner->so_cred,
@@ -823,7 +824,8 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
data->o_arg.id = sp->so_owner_id.id;
data->o_arg.clientid = sp->so_client->cl_clientid;
if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS) {
- task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR];
+ task->tk_msg.rpc_proc = nfs4_proc(sp->so_client,
+ NFSPROC4_CLNT_OPEN_NOATTR);
nfs_copy_fh(&data->o_res.fh, data->o_arg.fh);
}
data->timestamp = jiffies;
@@ -899,7 +901,7 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
struct nfs_openres *o_res = &data->o_res;
struct rpc_task *task;
struct rpc_message msg = {
- .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN],
+ .rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_OPEN),
.rpc_argp = o_arg,
.rpc_resp = o_res,
.rpc_cred = data->owner->so_cred,
@@ -1153,7 +1155,8 @@ static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
.server = server,
};
struct rpc_message msg = {
- .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETATTR],
+ .rpc_proc = nfs4_proc(server->nfs_client,
+ NFSPROC4_CLNT_SETATTR),
.rpc_argp = &arg,
.rpc_resp = &res,
.rpc_cred = cred,
@@ -1271,10 +1274,12 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
}
nfs_fattr_init(calldata->res.fattr);
if (test_bit(NFS_O_RDONLY_STATE, &state->flags) != 0) {
- task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE];
+ task->tk_msg.rpc_proc = nfs4_proc(state->owner->so_client,
+ NFSPROC4_CLNT_OPEN_DOWNGRADE);
calldata->arg.open_flags = FMODE_READ;
} else if (test_bit(NFS_O_WRONLY_STATE, &state->flags) != 0) {
- task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE];
+ task->tk_msg.rpc_proc = nfs4_proc(state->owner->so_client,
+ NFSPROC4_CLNT_OPEN_DOWNGRADE);
calldata->arg.open_flags = FMODE_WRITE;
}
calldata->timestamp = jiffies;
@@ -1305,7 +1310,7 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait)
struct nfs4_state_owner *sp = state->owner;
struct rpc_task *task;
struct rpc_message msg = {
- .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CLOSE],
+ .rpc_proc = nfs4_proc(sp->so_client, NFSPROC4_CLNT_CLOSE),
.rpc_cred = state->owner->so_cred,
};
struct rpc_task_setup task_setup_data = {
@@ -1472,7 +1477,7 @@ static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f
{
struct nfs4_server_caps_res res = {};
struct rpc_message msg = {
- .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SERVER_CAPS],
+ .rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_SERVER_CAPS),
.rpc_argp = fhandle,
.rpc_resp = &res,
};
@@ -1516,7 +1521,7 @@ static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
.fh = fhandle,
};
struct rpc_message msg = {
- .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOOKUP_ROOT],
+ .rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_LOOKUP_ROOT),
.rpc_argp = &args,
.rpc_resp = &res,
};
@@ -1605,7 +1610,7 @@ static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
.server = server,
};
struct rpc_message msg = {
- .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETATTR],
+ .rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_GETATTR),
.rpc_argp = &args,
.rpc_resp = &res,
};
@@ -1687,7 +1692,7 @@ static int _nfs4_proc_lookupfh(struct nfs_server *server, const struct nfs_fh *d
.fh = fhandle,
};
struct rpc_message msg = {
- .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOOKUP],
+ .rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_LOOKUP),
.rpc_argp = &args,
.rpc_resp = &res,
};
@@ -1756,7 +1761,7 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry
.fattr = &fattr,
};
struct rpc_message msg = {
- .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_ACCESS],
+ .rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_ACCESS),
.rpc_argp = &args,
.rpc_resp = &res,
.rpc_cred = entry->cred,
@@ -1834,6 +1839,7 @@ static int nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry)
static int _nfs4_proc_readlink(struct inode *inode, struct page *page,
unsigned int pgbase, unsigned int pglen)
{
+ struct nfs_server *server = NFS_SERVER(inode);
struct nfs4_readlink args = {
.fh = NFS_FH(inode),
.pgbase = pgbase,
@@ -1841,7 +1847,7 @@ static int _nfs4_proc_readlink(struct inode *inode, struct page *page,
.pages = &page,
};
struct rpc_message msg = {
- .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READLINK],
+ .rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_READLINK),
.rpc_argp = &args,
.rpc_resp = NULL,
};
@@ -1932,7 +1938,7 @@ static int _nfs4_proc_remove(struct inode *dir, struct qstr *name)
.server = server,
};
struct rpc_message msg = {
- .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE],
+ .rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_REMOVE),
.rpc_argp = &args,
.rpc_resp = &res,
};
@@ -1967,7 +1973,7 @@ static void nfs4_proc_unlink_setup(struct rpc_message *msg, struct inode *dir)
args->bitmask = server->attr_bitmask;
res->server = server;
- msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE];
+ msg->rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_REMOVE);
}
static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir)
@@ -1999,7 +2005,7 @@ static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name,
.new_fattr = &new_fattr,
};
struct rpc_message msg = {
- .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENAME],
+ .rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_RENAME),
.rpc_argp = &arg,
.rpc_resp = &res,
};
@@ -2048,7 +2054,7 @@ static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *
.dir_attr = &dir_attr,
};
struct rpc_message msg = {
- .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LINK],
+ .rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_LINK),
.rpc_argp = &arg,
.rpc_resp = &res,
};
@@ -2096,7 +2102,8 @@ static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir,
if (data != NULL) {
struct nfs_server *server = NFS_SERVER(dir);
- data->msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE];
+ data->msg.rpc_proc = nfs4_proc(server->nfs_client,
+ NFSPROC4_CLNT_CREATE);
data->msg.rpc_argp = &data->arg;
data->msg.rpc_resp = &data->res;
data->arg.dir_fh = NFS_FH(dir);
@@ -2145,7 +2152,8 @@ static int _nfs4_proc_symlink(struct inode *dir, struct dentry *dentry,
if (data == NULL)
goto out;
- data->msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SYMLINK];
+ data->msg.rpc_proc = nfs4_proc(NFS_SERVER(dir)->nfs_client,
+ NFSPROC4_CLNT_SYMLINK);
data->arg.u.symlink.pages = &page;
data->arg.u.symlink.len = len;
@@ -2204,6 +2212,7 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
u64 cookie, struct page *page, unsigned int count, int plus)
{
struct inode *dir = dentry->d_inode;
+ struct nfs_server *server = NFS_SERVER(dir);
struct nfs4_readdir_arg args = {
.fh = NFS_FH(dir),
.pages = &page,
@@ -2213,7 +2222,7 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
};
struct nfs4_readdir_res res;
struct rpc_message msg = {
- .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READDIR],
+ .rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_READDIR),
.rpc_argp = &args,
.rpc_resp = &res,
.rpc_cred = cred,
@@ -2305,7 +2314,7 @@ static int _nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
.bitmask = server->attr_bitmask,
};
struct rpc_message msg = {
- .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_STATFS],
+ .rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_STATFS),
.rpc_argp = &args,
.rpc_resp = fsstat,
};
@@ -2334,7 +2343,7 @@ static int _nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle,
.bitmask = server->attr_bitmask,
};
struct rpc_message msg = {
- .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FSINFO],
+ .rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_FSINFO),
.rpc_argp = &args,
.rpc_resp = fsinfo,
};
@@ -2369,7 +2378,7 @@ static int _nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle
.bitmask = server->attr_bitmask,
};
struct rpc_message msg = {
- .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_PATHCONF],
+ .rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_PATHCONF),
.rpc_argp = &args,
.rpc_resp = pathconf,
};
@@ -2415,8 +2424,10 @@ static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data)
static void nfs4_proc_read_setup(struct nfs_read_data *data, struct rpc_message *msg)
{
+ struct nfs_server *server = NFS_SERVER(data->inode);
+
data->timestamp = jiffies;
- msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ];
+ msg->rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_READ);
}
static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data)
@@ -2442,7 +2453,7 @@ static void nfs4_proc_write_setup(struct nfs_write_data *data, struct rpc_messag
data->res.server = server;
data->timestamp = jiffies;
- msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE];
+ msg->rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_WRITE);
}
static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data)
@@ -2463,7 +2474,7 @@ static void nfs4_proc_commit_setup(struct nfs_write_data *data, struct rpc_messa
data->args.bitmask = server->attr_bitmask;
data->res.server = server;
- msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT];
+ msg->rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_COMMIT);
}
/*
@@ -2497,7 +2508,7 @@ static const struct rpc_call_ops nfs4_renew_ops = {
int nfs4_proc_async_renew(struct nfs_client *clp, struct rpc_cred *cred)
{
struct rpc_message msg = {
- .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENEW],
+ .rpc_proc = nfs4_proc(clp, NFSPROC4_CLNT_RENEW),
.rpc_argp = clp,
.rpc_cred = cred,
};
@@ -2509,7 +2520,7 @@ int nfs4_proc_async_renew(struct nfs_client *clp, struct rpc_cred *cred)
int nfs4_proc_renew(struct nfs_client *clp, struct rpc_cred *cred)
{
struct rpc_message msg = {
- .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENEW],
+ .rpc_proc = nfs4_proc(clp, NFSPROC4_CLNT_RENEW),
.rpc_argp = clp,
.rpc_cred = cred,
};
@@ -2629,8 +2640,9 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu
};
size_t resp_len = buflen;
void *resp_buf;
+ struct nfs_server *server = NFS_SERVER(inode);
struct rpc_message msg = {
- .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETACL],
+ .rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_GETACL),
.rpc_argp = &args,
.rpc_resp = &resp_len,
};
@@ -2713,7 +2725,7 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl
.acl_len = buflen,
};
struct rpc_message msg = {
- .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETACL],
+ .rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_SETACL),
.rpc_argp = &arg,
.rpc_resp = NULL,
};
@@ -2853,7 +2865,7 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, unsigned short po
.sc_prog = program,
};
struct rpc_message msg = {
- .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETCLIENTID],
+ .rpc_proc = nfs4_proc(clp, NFSPROC4_CLNT_SETCLIENTID),
.rpc_argp = &setclientid,
.rpc_resp = clp,
.rpc_cred = cred,
@@ -2902,7 +2914,7 @@ static int _nfs4_proc_setclientid_confirm(struct nfs_client *clp, struct rpc_cre
{
struct nfs_fsinfo fsinfo;
struct rpc_message msg = {
- .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETCLIENTID_CONFIRM],
+ .rpc_proc = nfs4_proc(clp, NFSPROC4_CLNT_SETCLIENTID_CONFIRM),
.rpc_argp = clp,
.rpc_resp = &fsinfo,
.rpc_cred = cred,
@@ -2974,7 +2986,7 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co
struct nfs_server *server = NFS_SERVER(inode);
struct rpc_task *task;
struct rpc_message msg = {
- .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_DELEGRETURN],
+ .rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_DELEGRETURN),
.rpc_cred = cred,
};
struct rpc_task_setup task_setup_data = {
@@ -3066,7 +3078,7 @@ static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock
.denied = request,
};
struct rpc_message msg = {
- .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCKT],
+ .rpc_proc = nfs4_proc(clp, NFSPROC4_CLNT_LOCKT),
.rpc_argp = &arg,
.rpc_resp = &res,
.rpc_cred = state->owner->so_cred,
@@ -3218,7 +3230,8 @@ static struct rpc_task *nfs4_do_unlck(struct file_lock *fl,
{
struct nfs4_unlockdata *data;
struct rpc_message msg = {
- .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCKU],
+ .rpc_proc = nfs4_proc(NFS_SERVER(lsp->ls_state->inode)->nfs_client,
+ NFSPROC4_CLNT_LOCKU),
.rpc_cred = ctx->cred,
};
struct rpc_task_setup task_setup_data = {
@@ -3405,7 +3418,8 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f
struct nfs4_lockdata *data;
struct rpc_task *task;
struct rpc_message msg = {
- .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCK],
+ .rpc_proc = nfs4_proc(NFS_SERVER(state->inode)->nfs_client,
+ NFSPROC4_CLNT_LOCK),
.rpc_cred = state->owner->so_cred,
};
struct rpc_task_setup task_setup_data = {
@@ -3648,7 +3662,7 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
.bitmask = bitmask,
};
struct rpc_message msg = {
- .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FS_LOCATIONS],
+ .rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_FS_LOCATIONS),
.rpc_argp = &args,
.rpc_resp = fs_locations,
};
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index c1ff9c9..30addf4 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -4922,11 +4922,25 @@ struct rpc_procinfo nfs4_procedures[] = {
PROC(FS_LOCATIONS, enc_fs_locations, dec_fs_locations),
};
-struct rpc_version nfs_version4 = {
- .number = 4,
- .nrprocs = ARRAY_SIZE(nfs4_procedures),
- .procs = nfs4_procedures
+#if defined(CONFIG_NFS_V4_1)
+struct rpc_procinfo nfs41_procedures[] = {
};
+#endif /* CONFIG_NFS_V4_1 */
+
+struct rpc_version nfs_version4 = {
+ .number = 4,
+ .nrprocs = ARRAY_SIZE(nfs4_procedures),
+ .procs = nfs4_procedures
+};
+
+#ifdef CONFIG_NFS_V4_1
+struct rpc_version nfs_version41 = {
+ .number = 4,
+ .nrprocs = ARRAY_SIZE(nfs41_procedures),
+ .procs = nfs41_procedures
+};
+
+#endif /* CONFIG_NFS_V4_1 */
/*
* Local variables:
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index 8379dd5..c5cb574 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -73,6 +73,15 @@ struct nfs_client {
#endif /* CONFIG_NFS_V4 */
};
+#ifdef CONFIG_NFS_V4
+static inline struct rpc_procinfo *
+nfs4_proc(struct nfs_client *clp, int idx)
+{
+ struct rpc_procinfo *procs = clp->cl_rpcclient->cl_procinfo;
+ return &procs[idx];
+}
+#endif /* CONFIG_NFS_V4 */
+
/*
* NFS client parameters stored in the superblock.
*/
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 1d6f09a..743b5ac 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -969,6 +969,9 @@ extern const struct nfs_rpc_ops nfs_v4_clientops;
extern const struct nfs_rpc_ops nfs_v40_clientops;
extern const struct nfs_rpc_ops nfs_v41_clientops;
extern const struct nfs_rpc_ops *nfsv4_minorversion_clientops[];
+extern struct rpc_version *nfs4_minorversions[];
+extern struct rpc_procinfo *nfs4_minorversion_procedures[];
+
extern struct rpc_version nfs_version2;
extern struct rpc_version nfs_version3;
extern struct rpc_version nfs_version4;
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* Re: [pnfs] [RFC 13/85] nfs41: use ptr to rpc procedures via struct nfs_client
2008-11-10 20:20 ` [RFC 13/85] nfs41: use ptr to rpc procedures via struct nfs_client Benny Halevy
@ 2008-11-17 13:40 ` Benny Halevy
0 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-17 13:40 UTC (permalink / raw)
To: pnfs; +Cc: trond.myklebust, linux-nfs
On Nov. 10, 2008, 22:20 +0200, Benny Halevy <bhalevy@panasas.com> wrote:
> To support heterogenuous mount minor version, use the ptr to the effective
> rpc procedures table via nfs_client->cl_rpcclient->cl_procinfo rather than
> a global one.
>
> nfs4_proc() is a static inline helper to get the rpc procedure
> given a struct nfs_client * and the procedure index.
>
> Signed-off-by: Benny Halevy <bhalevy@panasas.com>
review 11-14: this patch should be dropped since there's no nfs41_prcedures
and no need for nfs_version41 (when we take the minorversion field out of
struct rpc_version)
> ---
> fs/nfs/internal.h | 5 ---
> fs/nfs/nfs4_fs.h | 1 -
> fs/nfs/nfs4proc.c | 88 ++++++++++++++++++++++++++-------------------
> fs/nfs/nfs4xdr.c | 22 +++++++++--
> include/linux/nfs_fs_sb.h | 9 +++++
> include/linux/nfs_xdr.h | 3 ++
> 6 files changed, 81 insertions(+), 47 deletions(-)
>
> diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
> index b423422..8386e99 100644
> --- a/fs/nfs/internal.h
> +++ b/fs/nfs/internal.h
> @@ -134,11 +134,6 @@ extern __be32 *nfs3_decode_dirent(__be32 *, struct nfs_entry *, int);
> extern __be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus);
> #endif
>
> -/* nfs4proc.c */
> -#ifdef CONFIG_NFS_V4
> -extern struct rpc_procinfo nfs4_procedures[];
> -#endif
> -
> /* dir.c */
> extern int nfs_access_cache_shrinker(int nr_to_scan, gfp_t gfp_mask);
>
> diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
> index ea79064..5fb7382 100644
> --- a/fs/nfs/nfs4_fs.h
> +++ b/fs/nfs/nfs4_fs.h
> @@ -226,7 +226,6 @@ extern const nfs4_stateid zero_stateid;
>
> /* nfs4xdr.c */
> extern __be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus);
> -extern struct rpc_procinfo nfs4_procedures[];
>
> struct nfs4_mount_data;
>
> diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
> index 0256c97..ef3370f 100644
> --- a/fs/nfs/nfs4proc.c
> +++ b/fs/nfs/nfs4proc.c
> @@ -762,7 +762,8 @@ static int _nfs4_proc_open_confirm(struct nfs4_opendata *data)
> struct nfs_server *server = NFS_SERVER(data->dir->d_inode);
> struct rpc_task *task;
> struct rpc_message msg = {
> - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_CONFIRM],
> + .rpc_proc = nfs4_proc(server->nfs_client,
> + NFSPROC4_CLNT_OPEN_CONFIRM),
> .rpc_argp = &data->c_arg,
> .rpc_resp = &data->c_res,
> .rpc_cred = data->owner->so_cred,
> @@ -823,7 +824,8 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
> data->o_arg.id = sp->so_owner_id.id;
> data->o_arg.clientid = sp->so_client->cl_clientid;
> if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS) {
> - task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR];
> + task->tk_msg.rpc_proc = nfs4_proc(sp->so_client,
> + NFSPROC4_CLNT_OPEN_NOATTR);
> nfs_copy_fh(&data->o_res.fh, data->o_arg.fh);
> }
> data->timestamp = jiffies;
> @@ -899,7 +901,7 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
> struct nfs_openres *o_res = &data->o_res;
> struct rpc_task *task;
> struct rpc_message msg = {
> - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN],
> + .rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_OPEN),
> .rpc_argp = o_arg,
> .rpc_resp = o_res,
> .rpc_cred = data->owner->so_cred,
> @@ -1153,7 +1155,8 @@ static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
> .server = server,
> };
> struct rpc_message msg = {
> - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETATTR],
> + .rpc_proc = nfs4_proc(server->nfs_client,
> + NFSPROC4_CLNT_SETATTR),
> .rpc_argp = &arg,
> .rpc_resp = &res,
> .rpc_cred = cred,
> @@ -1271,10 +1274,12 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
> }
> nfs_fattr_init(calldata->res.fattr);
> if (test_bit(NFS_O_RDONLY_STATE, &state->flags) != 0) {
> - task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE];
> + task->tk_msg.rpc_proc = nfs4_proc(state->owner->so_client,
> + NFSPROC4_CLNT_OPEN_DOWNGRADE);
> calldata->arg.open_flags = FMODE_READ;
> } else if (test_bit(NFS_O_WRONLY_STATE, &state->flags) != 0) {
> - task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE];
> + task->tk_msg.rpc_proc = nfs4_proc(state->owner->so_client,
> + NFSPROC4_CLNT_OPEN_DOWNGRADE);
> calldata->arg.open_flags = FMODE_WRITE;
> }
> calldata->timestamp = jiffies;
> @@ -1305,7 +1310,7 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait)
> struct nfs4_state_owner *sp = state->owner;
> struct rpc_task *task;
> struct rpc_message msg = {
> - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CLOSE],
> + .rpc_proc = nfs4_proc(sp->so_client, NFSPROC4_CLNT_CLOSE),
> .rpc_cred = state->owner->so_cred,
> };
> struct rpc_task_setup task_setup_data = {
> @@ -1472,7 +1477,7 @@ static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f
> {
> struct nfs4_server_caps_res res = {};
> struct rpc_message msg = {
> - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SERVER_CAPS],
> + .rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_SERVER_CAPS),
> .rpc_argp = fhandle,
> .rpc_resp = &res,
> };
> @@ -1516,7 +1521,7 @@ static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
> .fh = fhandle,
> };
> struct rpc_message msg = {
> - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOOKUP_ROOT],
> + .rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_LOOKUP_ROOT),
> .rpc_argp = &args,
> .rpc_resp = &res,
> };
> @@ -1605,7 +1610,7 @@ static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
> .server = server,
> };
> struct rpc_message msg = {
> - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETATTR],
> + .rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_GETATTR),
> .rpc_argp = &args,
> .rpc_resp = &res,
> };
> @@ -1687,7 +1692,7 @@ static int _nfs4_proc_lookupfh(struct nfs_server *server, const struct nfs_fh *d
> .fh = fhandle,
> };
> struct rpc_message msg = {
> - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOOKUP],
> + .rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_LOOKUP),
> .rpc_argp = &args,
> .rpc_resp = &res,
> };
> @@ -1756,7 +1761,7 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry
> .fattr = &fattr,
> };
> struct rpc_message msg = {
> - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_ACCESS],
> + .rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_ACCESS),
> .rpc_argp = &args,
> .rpc_resp = &res,
> .rpc_cred = entry->cred,
> @@ -1834,6 +1839,7 @@ static int nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry)
> static int _nfs4_proc_readlink(struct inode *inode, struct page *page,
> unsigned int pgbase, unsigned int pglen)
> {
> + struct nfs_server *server = NFS_SERVER(inode);
> struct nfs4_readlink args = {
> .fh = NFS_FH(inode),
> .pgbase = pgbase,
> @@ -1841,7 +1847,7 @@ static int _nfs4_proc_readlink(struct inode *inode, struct page *page,
> .pages = &page,
> };
> struct rpc_message msg = {
> - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READLINK],
> + .rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_READLINK),
> .rpc_argp = &args,
> .rpc_resp = NULL,
> };
> @@ -1932,7 +1938,7 @@ static int _nfs4_proc_remove(struct inode *dir, struct qstr *name)
> .server = server,
> };
> struct rpc_message msg = {
> - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE],
> + .rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_REMOVE),
> .rpc_argp = &args,
> .rpc_resp = &res,
> };
> @@ -1967,7 +1973,7 @@ static void nfs4_proc_unlink_setup(struct rpc_message *msg, struct inode *dir)
>
> args->bitmask = server->attr_bitmask;
> res->server = server;
> - msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE];
> + msg->rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_REMOVE);
> }
>
> static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir)
> @@ -1999,7 +2005,7 @@ static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name,
> .new_fattr = &new_fattr,
> };
> struct rpc_message msg = {
> - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENAME],
> + .rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_RENAME),
> .rpc_argp = &arg,
> .rpc_resp = &res,
> };
> @@ -2048,7 +2054,7 @@ static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *
> .dir_attr = &dir_attr,
> };
> struct rpc_message msg = {
> - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LINK],
> + .rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_LINK),
> .rpc_argp = &arg,
> .rpc_resp = &res,
> };
> @@ -2096,7 +2102,8 @@ static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir,
> if (data != NULL) {
> struct nfs_server *server = NFS_SERVER(dir);
>
> - data->msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE];
> + data->msg.rpc_proc = nfs4_proc(server->nfs_client,
> + NFSPROC4_CLNT_CREATE);
> data->msg.rpc_argp = &data->arg;
> data->msg.rpc_resp = &data->res;
> data->arg.dir_fh = NFS_FH(dir);
> @@ -2145,7 +2152,8 @@ static int _nfs4_proc_symlink(struct inode *dir, struct dentry *dentry,
> if (data == NULL)
> goto out;
>
> - data->msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SYMLINK];
> + data->msg.rpc_proc = nfs4_proc(NFS_SERVER(dir)->nfs_client,
> + NFSPROC4_CLNT_SYMLINK);
> data->arg.u.symlink.pages = &page;
> data->arg.u.symlink.len = len;
>
> @@ -2204,6 +2212,7 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
> u64 cookie, struct page *page, unsigned int count, int plus)
> {
> struct inode *dir = dentry->d_inode;
> + struct nfs_server *server = NFS_SERVER(dir);
> struct nfs4_readdir_arg args = {
> .fh = NFS_FH(dir),
> .pages = &page,
> @@ -2213,7 +2222,7 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
> };
> struct nfs4_readdir_res res;
> struct rpc_message msg = {
> - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READDIR],
> + .rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_READDIR),
> .rpc_argp = &args,
> .rpc_resp = &res,
> .rpc_cred = cred,
> @@ -2305,7 +2314,7 @@ static int _nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
> .bitmask = server->attr_bitmask,
> };
> struct rpc_message msg = {
> - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_STATFS],
> + .rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_STATFS),
> .rpc_argp = &args,
> .rpc_resp = fsstat,
> };
> @@ -2334,7 +2343,7 @@ static int _nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle,
> .bitmask = server->attr_bitmask,
> };
> struct rpc_message msg = {
> - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FSINFO],
> + .rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_FSINFO),
> .rpc_argp = &args,
> .rpc_resp = fsinfo,
> };
> @@ -2369,7 +2378,7 @@ static int _nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle
> .bitmask = server->attr_bitmask,
> };
> struct rpc_message msg = {
> - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_PATHCONF],
> + .rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_PATHCONF),
> .rpc_argp = &args,
> .rpc_resp = pathconf,
> };
> @@ -2415,8 +2424,10 @@ static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data)
>
> static void nfs4_proc_read_setup(struct nfs_read_data *data, struct rpc_message *msg)
> {
> + struct nfs_server *server = NFS_SERVER(data->inode);
> +
> data->timestamp = jiffies;
> - msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ];
> + msg->rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_READ);
> }
>
> static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data)
> @@ -2442,7 +2453,7 @@ static void nfs4_proc_write_setup(struct nfs_write_data *data, struct rpc_messag
> data->res.server = server;
> data->timestamp = jiffies;
>
> - msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE];
> + msg->rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_WRITE);
> }
>
> static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data)
> @@ -2463,7 +2474,7 @@ static void nfs4_proc_commit_setup(struct nfs_write_data *data, struct rpc_messa
>
> data->args.bitmask = server->attr_bitmask;
> data->res.server = server;
> - msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT];
> + msg->rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_COMMIT);
> }
>
> /*
> @@ -2497,7 +2508,7 @@ static const struct rpc_call_ops nfs4_renew_ops = {
> int nfs4_proc_async_renew(struct nfs_client *clp, struct rpc_cred *cred)
> {
> struct rpc_message msg = {
> - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENEW],
> + .rpc_proc = nfs4_proc(clp, NFSPROC4_CLNT_RENEW),
> .rpc_argp = clp,
> .rpc_cred = cred,
> };
> @@ -2509,7 +2520,7 @@ int nfs4_proc_async_renew(struct nfs_client *clp, struct rpc_cred *cred)
> int nfs4_proc_renew(struct nfs_client *clp, struct rpc_cred *cred)
> {
> struct rpc_message msg = {
> - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENEW],
> + .rpc_proc = nfs4_proc(clp, NFSPROC4_CLNT_RENEW),
> .rpc_argp = clp,
> .rpc_cred = cred,
> };
> @@ -2629,8 +2640,9 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu
> };
> size_t resp_len = buflen;
> void *resp_buf;
> + struct nfs_server *server = NFS_SERVER(inode);
> struct rpc_message msg = {
> - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETACL],
> + .rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_GETACL),
> .rpc_argp = &args,
> .rpc_resp = &resp_len,
> };
> @@ -2713,7 +2725,7 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl
> .acl_len = buflen,
> };
> struct rpc_message msg = {
> - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETACL],
> + .rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_SETACL),
> .rpc_argp = &arg,
> .rpc_resp = NULL,
> };
> @@ -2853,7 +2865,7 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, unsigned short po
> .sc_prog = program,
> };
> struct rpc_message msg = {
> - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETCLIENTID],
> + .rpc_proc = nfs4_proc(clp, NFSPROC4_CLNT_SETCLIENTID),
> .rpc_argp = &setclientid,
> .rpc_resp = clp,
> .rpc_cred = cred,
> @@ -2902,7 +2914,7 @@ static int _nfs4_proc_setclientid_confirm(struct nfs_client *clp, struct rpc_cre
> {
> struct nfs_fsinfo fsinfo;
> struct rpc_message msg = {
> - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETCLIENTID_CONFIRM],
> + .rpc_proc = nfs4_proc(clp, NFSPROC4_CLNT_SETCLIENTID_CONFIRM),
> .rpc_argp = clp,
> .rpc_resp = &fsinfo,
> .rpc_cred = cred,
> @@ -2974,7 +2986,7 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co
> struct nfs_server *server = NFS_SERVER(inode);
> struct rpc_task *task;
> struct rpc_message msg = {
> - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_DELEGRETURN],
> + .rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_DELEGRETURN),
> .rpc_cred = cred,
> };
> struct rpc_task_setup task_setup_data = {
> @@ -3066,7 +3078,7 @@ static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock
> .denied = request,
> };
> struct rpc_message msg = {
> - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCKT],
> + .rpc_proc = nfs4_proc(clp, NFSPROC4_CLNT_LOCKT),
> .rpc_argp = &arg,
> .rpc_resp = &res,
> .rpc_cred = state->owner->so_cred,
> @@ -3218,7 +3230,8 @@ static struct rpc_task *nfs4_do_unlck(struct file_lock *fl,
> {
> struct nfs4_unlockdata *data;
> struct rpc_message msg = {
> - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCKU],
> + .rpc_proc = nfs4_proc(NFS_SERVER(lsp->ls_state->inode)->nfs_client,
> + NFSPROC4_CLNT_LOCKU),
> .rpc_cred = ctx->cred,
> };
> struct rpc_task_setup task_setup_data = {
> @@ -3405,7 +3418,8 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f
> struct nfs4_lockdata *data;
> struct rpc_task *task;
> struct rpc_message msg = {
> - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOCK],
> + .rpc_proc = nfs4_proc(NFS_SERVER(state->inode)->nfs_client,
> + NFSPROC4_CLNT_LOCK),
> .rpc_cred = state->owner->so_cred,
> };
> struct rpc_task_setup task_setup_data = {
> @@ -3648,7 +3662,7 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
> .bitmask = bitmask,
> };
> struct rpc_message msg = {
> - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FS_LOCATIONS],
> + .rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_FS_LOCATIONS),
> .rpc_argp = &args,
> .rpc_resp = fs_locations,
> };
> diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
> index c1ff9c9..30addf4 100644
> --- a/fs/nfs/nfs4xdr.c
> +++ b/fs/nfs/nfs4xdr.c
> @@ -4922,11 +4922,25 @@ struct rpc_procinfo nfs4_procedures[] = {
> PROC(FS_LOCATIONS, enc_fs_locations, dec_fs_locations),
> };
>
> -struct rpc_version nfs_version4 = {
> - .number = 4,
> - .nrprocs = ARRAY_SIZE(nfs4_procedures),
> - .procs = nfs4_procedures
> +#if defined(CONFIG_NFS_V4_1)
> +struct rpc_procinfo nfs41_procedures[] = {
> };
> +#endif /* CONFIG_NFS_V4_1 */
> +
> +struct rpc_version nfs_version4 = {
> + .number = 4,
> + .nrprocs = ARRAY_SIZE(nfs4_procedures),
> + .procs = nfs4_procedures
> +};
> +
> +#ifdef CONFIG_NFS_V4_1
> +struct rpc_version nfs_version41 = {
> + .number = 4,
> + .nrprocs = ARRAY_SIZE(nfs41_procedures),
> + .procs = nfs41_procedures
> +};
> +
> +#endif /* CONFIG_NFS_V4_1 */
>
> /*
> * Local variables:
> diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
> index 8379dd5..c5cb574 100644
> --- a/include/linux/nfs_fs_sb.h
> +++ b/include/linux/nfs_fs_sb.h
> @@ -73,6 +73,15 @@ struct nfs_client {
> #endif /* CONFIG_NFS_V4 */
> };
>
> +#ifdef CONFIG_NFS_V4
> +static inline struct rpc_procinfo *
> +nfs4_proc(struct nfs_client *clp, int idx)
> +{
> + struct rpc_procinfo *procs = clp->cl_rpcclient->cl_procinfo;
> + return &procs[idx];
> +}
> +#endif /* CONFIG_NFS_V4 */
> +
> /*
> * NFS client parameters stored in the superblock.
> */
> diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
> index 1d6f09a..743b5ac 100644
> --- a/include/linux/nfs_xdr.h
> +++ b/include/linux/nfs_xdr.h
> @@ -969,6 +969,9 @@ extern const struct nfs_rpc_ops nfs_v4_clientops;
> extern const struct nfs_rpc_ops nfs_v40_clientops;
> extern const struct nfs_rpc_ops nfs_v41_clientops;
> extern const struct nfs_rpc_ops *nfsv4_minorversion_clientops[];
> +extern struct rpc_version *nfs4_minorversions[];
> +extern struct rpc_procinfo *nfs4_minorversion_procedures[];
> +
> extern struct rpc_version nfs_version2;
> extern struct rpc_version nfs_version3;
> extern struct rpc_version nfs_version4;
^ permalink raw reply [flat|nested] 115+ messages in thread
* [RFC 14/85] nfs41: sunrpc: support minorversion for rpc_clnt version table.
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (10 preceding siblings ...)
2008-11-10 20:20 ` [RFC 13/85] nfs41: use ptr to rpc procedures via struct nfs_client Benny Halevy
@ 2008-11-10 20:20 ` Benny Halevy
2008-11-17 13:41 ` [pnfs] " Benny Halevy
2008-11-10 20:20 ` [RFC 15/85] nfs41: Proper initialization of nfs_client_initdata.rpc_ops Benny Halevy
` (73 subsequent siblings)
85 siblings, 1 reply; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:20 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
Validate minorversion only if not zero as legacy code declares
nrminorvers==0 and that should work just fine with minorversion==0 argument.
Pass minorversion down to rpc_create in nfs_create_rpc_client
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/client.c | 17 ++++++++++++++---
include/linux/nfs_xdr.h | 3 +++
include/linux/sunrpc/clnt.h | 10 +++++++++-
net/sunrpc/clnt.c | 13 ++++++++-----
4 files changed, 34 insertions(+), 9 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 7bc150b..4e8c641 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -56,7 +56,10 @@ static DECLARE_WAIT_QUEUE_HEAD(nfs_client_active_wq);
/*
* RPC cruft for NFS
*/
-static struct rpc_version *nfs_version[5] = {
+#define NFS_MAXVERSION 4
+
+static struct rpc_version *nfs_version[(NFS_MAXVERSION + 1) *
+ (NFS4_MAX_MINOR_VERSION + 1)] = {
[2] = &nfs_version2,
#ifdef CONFIG_NFS_V3
[3] = &nfs_version3,
@@ -64,12 +67,16 @@ static struct rpc_version *nfs_version[5] = {
#ifdef CONFIG_NFS_V4
[4] = &nfs_version4,
#endif
+#ifdef CONFIG_NFS_V4_1
+ [(NFS_MAXVERSION + 1) + 4] = &nfs_version41,
+#endif /* CONFIG_NFS_V4_1 */
};
struct rpc_program nfs_program = {
.name = "nfs",
.number = NFS_PROGRAM,
- .nrvers = ARRAY_SIZE(nfs_version),
+ .nrvers = NFS_MAXVERSION + 1,
+ .nrminorvers = NFS4_MAX_MINOR_VERSION + 1,
.version = nfs_version,
.stats = &nfs_rpcstat,
.pipe_dir_name = "/nfs",
@@ -482,6 +489,9 @@ static int nfs_create_rpc_client(struct nfs_client *clp,
.servername = clp->cl_hostname,
.program = &nfs_program,
.version = clp->rpc_ops->version,
+#ifdef CONFIG_NFS_V4
+ .minorversion = clp->cl_minorversion,
+#endif /* CONFIG_NFS_V4 */
.authflavor = flavor,
.flags = flags,
};
@@ -550,7 +560,7 @@ static void nfs_init_server_aclclient(struct nfs_server *server)
if (server->flags & NFS_MOUNT_NOACL)
goto out_noacl;
- server->client_acl = rpc_bind_new_program(server->client, &nfsacl_program, 3);
+ server->client_acl = rpc_bind_new_program(server->client, &nfsacl_program, 3, 0);
if (IS_ERR(server->client_acl))
goto out_noacl;
@@ -970,6 +980,7 @@ static int nfs4_init_client(struct nfs_client *clp,
{
int error;
+ dprintk("--> nfs4_init_client minorversion %u\n", clp->cl_minorversion);
if (clp->cl_cons_state == NFS_CS_READY) {
/* the client is initialised already */
dprintk("<-- nfs4_init_client() = 0 [already %p]\n", clp);
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 743b5ac..b401477 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -975,6 +975,9 @@ extern struct rpc_procinfo *nfs4_minorversion_procedures[];
extern struct rpc_version nfs_version2;
extern struct rpc_version nfs_version3;
extern struct rpc_version nfs_version4;
+#if defined(CONFIG_NFS_V4_1)
+extern struct rpc_version nfs_version41;
+#endif /* CONFIG_NFS_V4_1 */
extern struct rpc_version nfsacl_version3;
extern struct rpc_program nfsacl_program;
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index 6f0ee1b..99d4f9e 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -68,11 +68,18 @@ struct rpc_program {
char * name; /* protocol name */
u32 number; /* program number */
unsigned int nrvers; /* number of versions */
+ unsigned int nrminorvers; /* number of minor versions */
struct rpc_version ** version; /* version array */
struct rpc_stat * stats; /* statistics */
char * pipe_dir_name; /* path to rpc_pipefs dir */
};
+static inline struct rpc_version *
+get_rpc_version(struct rpc_program *prog, u32 vers, int minorvers)
+{
+ return prog->version[minorvers * prog->nrvers + vers];
+}
+
struct rpc_version {
u32 number; /* version number */
unsigned int nrprocs; /* number of procs */
@@ -106,6 +113,7 @@ struct rpc_create_args {
struct rpc_program *program;
u32 prognumber; /* overrides program->number */
u32 version;
+ unsigned char minorversion;
rpc_authflavor_t authflavor;
unsigned long flags;
};
@@ -120,7 +128,7 @@ struct rpc_create_args {
struct rpc_clnt *rpc_create(struct rpc_create_args *args);
struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *,
- struct rpc_program *, u32);
+ struct rpc_program *, u32, int minorversion);
struct rpc_clnt *rpc_clone_client(struct rpc_clnt *);
void rpc_shutdown_client(struct rpc_clnt *);
void rpc_release_client(struct rpc_clnt *);
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 4895c34..44f251d 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -148,9 +148,10 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru
if (!xprt)
goto out_no_xprt;
- if (args->version >= program->nrvers)
+ if (args->version >= program->nrvers ||
+ (args->minorversion && args->minorversion >= program->nrminorvers))
goto out_err;
- version = program->version[args->version];
+ version = get_rpc_version(program, args->version, args->minorversion);
if (version == NULL)
goto out_err;
@@ -472,14 +473,16 @@ rpc_release_client(struct rpc_clnt *clnt)
*/
struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old,
struct rpc_program *program,
- u32 vers)
+ u32 vers, int minorversion)
{
struct rpc_clnt *clnt;
struct rpc_version *version;
int err;
- BUG_ON(vers >= program->nrvers || !program->version[vers]);
- version = program->version[vers];
+ BUG_ON(vers >= program->nrvers ||
+ (minorversion && minorversion >= program->nrminorvers) ||
+ !get_rpc_version(program, vers, minorversion));
+ version = get_rpc_version(program, vers, minorversion);
clnt = rpc_clone_client(old);
if (IS_ERR(clnt))
goto out;
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* Re: [pnfs] [RFC 14/85] nfs41: sunrpc: support minorversion for rpc_clnt version table.
2008-11-10 20:20 ` [RFC 14/85] nfs41: sunrpc: support minorversion for rpc_clnt version table Benny Halevy
@ 2008-11-17 13:41 ` Benny Halevy
0 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-17 13:41 UTC (permalink / raw)
To: pnfs; +Cc: trond.myklebust, linux-nfs
On Nov. 10, 2008, 22:20 +0200, Benny Halevy <bhalevy@panasas.com> wrote:
> Validate minorversion only if not zero as legacy code declares
> nrminorvers==0 and that should work just fine with minorversion==0 argument.
>
> Pass minorversion down to rpc_create in nfs_create_rpc_client
>
> Signed-off-by: Benny Halevy <bhalevy@panasas.com>
review 11-14: patch will be dropped.
> ---
> fs/nfs/client.c | 17 ++++++++++++++---
> include/linux/nfs_xdr.h | 3 +++
> include/linux/sunrpc/clnt.h | 10 +++++++++-
> net/sunrpc/clnt.c | 13 ++++++++-----
> 4 files changed, 34 insertions(+), 9 deletions(-)
>
> diff --git a/fs/nfs/client.c b/fs/nfs/client.c
> index 7bc150b..4e8c641 100644
> --- a/fs/nfs/client.c
> +++ b/fs/nfs/client.c
> @@ -56,7 +56,10 @@ static DECLARE_WAIT_QUEUE_HEAD(nfs_client_active_wq);
> /*
> * RPC cruft for NFS
> */
> -static struct rpc_version *nfs_version[5] = {
> +#define NFS_MAXVERSION 4
> +
> +static struct rpc_version *nfs_version[(NFS_MAXVERSION + 1) *
> + (NFS4_MAX_MINOR_VERSION + 1)] = {
> [2] = &nfs_version2,
> #ifdef CONFIG_NFS_V3
> [3] = &nfs_version3,
> @@ -64,12 +67,16 @@ static struct rpc_version *nfs_version[5] = {
> #ifdef CONFIG_NFS_V4
> [4] = &nfs_version4,
> #endif
> +#ifdef CONFIG_NFS_V4_1
> + [(NFS_MAXVERSION + 1) + 4] = &nfs_version41,
> +#endif /* CONFIG_NFS_V4_1 */
> };
>
> struct rpc_program nfs_program = {
> .name = "nfs",
> .number = NFS_PROGRAM,
> - .nrvers = ARRAY_SIZE(nfs_version),
> + .nrvers = NFS_MAXVERSION + 1,
> + .nrminorvers = NFS4_MAX_MINOR_VERSION + 1,
> .version = nfs_version,
> .stats = &nfs_rpcstat,
> .pipe_dir_name = "/nfs",
> @@ -482,6 +489,9 @@ static int nfs_create_rpc_client(struct nfs_client *clp,
> .servername = clp->cl_hostname,
> .program = &nfs_program,
> .version = clp->rpc_ops->version,
> +#ifdef CONFIG_NFS_V4
> + .minorversion = clp->cl_minorversion,
> +#endif /* CONFIG_NFS_V4 */
> .authflavor = flavor,
> .flags = flags,
> };
> @@ -550,7 +560,7 @@ static void nfs_init_server_aclclient(struct nfs_server *server)
> if (server->flags & NFS_MOUNT_NOACL)
> goto out_noacl;
>
> - server->client_acl = rpc_bind_new_program(server->client, &nfsacl_program, 3);
> + server->client_acl = rpc_bind_new_program(server->client, &nfsacl_program, 3, 0);
> if (IS_ERR(server->client_acl))
> goto out_noacl;
>
> @@ -970,6 +980,7 @@ static int nfs4_init_client(struct nfs_client *clp,
> {
> int error;
>
> + dprintk("--> nfs4_init_client minorversion %u\n", clp->cl_minorversion);
> if (clp->cl_cons_state == NFS_CS_READY) {
> /* the client is initialised already */
> dprintk("<-- nfs4_init_client() = 0 [already %p]\n", clp);
> diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
> index 743b5ac..b401477 100644
> --- a/include/linux/nfs_xdr.h
> +++ b/include/linux/nfs_xdr.h
> @@ -975,6 +975,9 @@ extern struct rpc_procinfo *nfs4_minorversion_procedures[];
> extern struct rpc_version nfs_version2;
> extern struct rpc_version nfs_version3;
> extern struct rpc_version nfs_version4;
> +#if defined(CONFIG_NFS_V4_1)
> +extern struct rpc_version nfs_version41;
> +#endif /* CONFIG_NFS_V4_1 */
>
> extern struct rpc_version nfsacl_version3;
> extern struct rpc_program nfsacl_program;
> diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
> index 6f0ee1b..99d4f9e 100644
> --- a/include/linux/sunrpc/clnt.h
> +++ b/include/linux/sunrpc/clnt.h
> @@ -68,11 +68,18 @@ struct rpc_program {
> char * name; /* protocol name */
> u32 number; /* program number */
> unsigned int nrvers; /* number of versions */
> + unsigned int nrminorvers; /* number of minor versions */
> struct rpc_version ** version; /* version array */
> struct rpc_stat * stats; /* statistics */
> char * pipe_dir_name; /* path to rpc_pipefs dir */
> };
>
> +static inline struct rpc_version *
> +get_rpc_version(struct rpc_program *prog, u32 vers, int minorvers)
> +{
> + return prog->version[minorvers * prog->nrvers + vers];
> +}
> +
> struct rpc_version {
> u32 number; /* version number */
> unsigned int nrprocs; /* number of procs */
> @@ -106,6 +113,7 @@ struct rpc_create_args {
> struct rpc_program *program;
> u32 prognumber; /* overrides program->number */
> u32 version;
> + unsigned char minorversion;
> rpc_authflavor_t authflavor;
> unsigned long flags;
> };
> @@ -120,7 +128,7 @@ struct rpc_create_args {
>
> struct rpc_clnt *rpc_create(struct rpc_create_args *args);
> struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *,
> - struct rpc_program *, u32);
> + struct rpc_program *, u32, int minorversion);
> struct rpc_clnt *rpc_clone_client(struct rpc_clnt *);
> void rpc_shutdown_client(struct rpc_clnt *);
> void rpc_release_client(struct rpc_clnt *);
> diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
> index 4895c34..44f251d 100644
> --- a/net/sunrpc/clnt.c
> +++ b/net/sunrpc/clnt.c
> @@ -148,9 +148,10 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru
> if (!xprt)
> goto out_no_xprt;
>
> - if (args->version >= program->nrvers)
> + if (args->version >= program->nrvers ||
> + (args->minorversion && args->minorversion >= program->nrminorvers))
> goto out_err;
> - version = program->version[args->version];
> + version = get_rpc_version(program, args->version, args->minorversion);
> if (version == NULL)
> goto out_err;
>
> @@ -472,14 +473,16 @@ rpc_release_client(struct rpc_clnt *clnt)
> */
> struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old,
> struct rpc_program *program,
> - u32 vers)
> + u32 vers, int minorversion)
> {
> struct rpc_clnt *clnt;
> struct rpc_version *version;
> int err;
>
> - BUG_ON(vers >= program->nrvers || !program->version[vers]);
> - version = program->version[vers];
> + BUG_ON(vers >= program->nrvers ||
> + (minorversion && minorversion >= program->nrminorvers) ||
> + !get_rpc_version(program, vers, minorversion));
> + version = get_rpc_version(program, vers, minorversion);
> clnt = rpc_clone_client(old);
> if (IS_ERR(clnt))
> goto out;
^ permalink raw reply [flat|nested] 115+ messages in thread
* [RFC 15/85] nfs41: Proper initialization of nfs_client_initdata.rpc_ops
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (11 preceding siblings ...)
2008-11-10 20:20 ` [RFC 14/85] nfs41: sunrpc: support minorversion for rpc_clnt version table Benny Halevy
@ 2008-11-10 20:20 ` Benny Halevy
2008-11-17 13:41 ` [pnfs] " Benny Halevy
2008-11-10 20:20 ` [RFC 16/85] nfs41: pass recovery status from reclaimer kthread up to nfs4_wait_clnt_recover Benny Halevy
` (72 subsequent siblings)
85 siblings, 1 reply; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:20 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
From: Ricardo Labiaga <ricardo.labiaga@netapp.com>
The rpc_ops needs to be initialized to the proper minor version clientops
so that nfs_get_client() can find an existing nfs_client structure if
a mount to the same server has already occurred.
This enables the traditional sharing of nfs_client structures, as well
as fixes the problem where mounts of the same filesystem on the same
mountpoint were not being detected correctly.
Signed-off-by: Ricardo Labiaga <ricardo.labiaga@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/client.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 4e8c641..11c845d 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -1028,6 +1028,8 @@ static int nfs4_set_client(struct nfs_server *server,
.hostname = hostname,
.addr = addr,
.addrlen = addrlen,
+ .rpc_ops =
+ nfsv4_minorversion_clientops[server->minorversion],
.proto = proto,
};
struct nfs_client *clp;
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* Re: [pnfs] [RFC 15/85] nfs41: Proper initialization of nfs_client_initdata.rpc_ops
2008-11-10 20:20 ` [RFC 15/85] nfs41: Proper initialization of nfs_client_initdata.rpc_ops Benny Halevy
@ 2008-11-17 13:41 ` Benny Halevy
0 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-17 13:41 UTC (permalink / raw)
To: pnfs; +Cc: trond.myklebust, linux-nfs
On Nov. 10, 2008, 22:20 +0200, Benny Halevy <bhalevy@panasas.com> wrote:
> From: Ricardo Labiaga <ricardo.labiaga@netapp.com>
>
> The rpc_ops needs to be initialized to the proper minor version clientops
> so that nfs_get_client() can find an existing nfs_client structure if
> a mount to the same server has already occurred.
>
> This enables the traditional sharing of nfs_client structures, as well
> as fixes the problem where mounts of the same filesystem on the same
> mountpoint were not being detected correctly.
>
> Signed-off-by: Ricardo Labiaga <ricardo.labiaga@netapp.com>
> Signed-off-by: Benny Halevy <bhalevy@panasas.com>
review 11-14: see if we can get rid of that since right now
nfs_v41_clientops == nfs_v40_clientops
> ---
> fs/nfs/client.c | 2 ++
> 1 files changed, 2 insertions(+), 0 deletions(-)
>
> diff --git a/fs/nfs/client.c b/fs/nfs/client.c
> index 4e8c641..11c845d 100644
> --- a/fs/nfs/client.c
> +++ b/fs/nfs/client.c
> @@ -1028,6 +1028,8 @@ static int nfs4_set_client(struct nfs_server *server,
> .hostname = hostname,
> .addr = addr,
> .addrlen = addrlen,
> + .rpc_ops =
> + nfsv4_minorversion_clientops[server->minorversion],
> .proto = proto,
> };
> struct nfs_client *clp;
^ permalink raw reply [flat|nested] 115+ messages in thread
* [RFC 16/85] nfs41: pass recovery status from reclaimer kthread up to nfs4_wait_clnt_recover
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (12 preceding siblings ...)
2008-11-10 20:20 ` [RFC 15/85] nfs41: Proper initialization of nfs_client_initdata.rpc_ops Benny Halevy
@ 2008-11-10 20:20 ` Benny Halevy
2008-11-17 13:42 ` [pnfs] " Benny Halevy
2008-11-10 20:20 ` [RFC 17/85] nfs41: fallback to lower minorversion if nfs4_create_server fails Benny Halevy
` (71 subsequent siblings)
85 siblings, 1 reply; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:20 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
status is cleared on recovery start and may be left as non-zero
if recovery failed so it can be picked up by an upper layer caller
(e.g. nfs4_create_server)
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/nfs4proc.c | 2 ++
fs/nfs/nfs4state.c | 5 ++++-
include/linux/nfs_fs_sb.h | 1 +
3 files changed, 7 insertions(+), 1 deletions(-)
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index ef3370f..f87d4de 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -2802,6 +2802,8 @@ static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs_client *clp)
res = wait_on_bit(&clp->cl_state, NFS4CLNT_STATE_RECOVER,
nfs4_wait_bit_killable, TASK_KILLABLE);
+ if (!res)
+ res = clp->cl_recovery_status;
rwsem_release(&clp->cl_sem.dep_map, 1, _RET_IP_);
return res;
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index c391caf..09ca7b1 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -814,8 +814,10 @@ void nfs4_schedule_state_recovery(struct nfs_client *clp)
{
if (!clp)
return;
- if (test_and_set_bit(NFS4CLNT_STATE_RECOVER, &clp->cl_state) == 0)
+ if (test_and_set_bit(NFS4CLNT_STATE_RECOVER, &clp->cl_state) == 0) {
+ clp->cl_recovery_status = 0;
nfs4_recover_state(clp);
+ }
}
static int nfs4_reclaim_locks(struct nfs4_state_recovery_ops *ops, struct nfs4_state *state)
@@ -1018,6 +1020,7 @@ out:
out_error:
printk(KERN_WARNING "Error: state recovery failed on NFSv4 server %s"
" with error %d\n", clp->cl_hostname, -status);
+ clp->cl_recovery_status = status;
set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
goto out;
}
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index c5cb574..80e0fc3 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -38,6 +38,7 @@ struct nfs_client {
u64 cl_clientid; /* constant */
nfs4_verifier cl_confirm;
unsigned long cl_state;
+ int cl_recovery_status;
struct rb_root cl_openowner_id;
struct rb_root cl_lockowner_id;
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* Re: [pnfs] [RFC 16/85] nfs41: pass recovery status from reclaimer kthread up to nfs4_wait_clnt_recover
2008-11-10 20:20 ` [RFC 16/85] nfs41: pass recovery status from reclaimer kthread up to nfs4_wait_clnt_recover Benny Halevy
@ 2008-11-17 13:42 ` Benny Halevy
0 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-17 13:42 UTC (permalink / raw)
To: pnfs; +Cc: trond.myklebust, linux-nfs
On Nov. 10, 2008, 22:20 +0200, Benny Halevy <bhalevy@panasas.com> wrote:
> status is cleared on recovery start and may be left as non-zero
> if recovery failed so it can be picked up by an upper layer caller
> (e.g. nfs4_create_server)
>
> Signed-off-by: Benny Halevy <bhalevy@panasas.com>
review 11-14: let the reclaimer fallback to lower minorversion
and drop this patch.
> ---
> fs/nfs/nfs4proc.c | 2 ++
> fs/nfs/nfs4state.c | 5 ++++-
> include/linux/nfs_fs_sb.h | 1 +
> 3 files changed, 7 insertions(+), 1 deletions(-)
>
> diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
> index ef3370f..f87d4de 100644
> --- a/fs/nfs/nfs4proc.c
> +++ b/fs/nfs/nfs4proc.c
> @@ -2802,6 +2802,8 @@ static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs_client *clp)
>
> res = wait_on_bit(&clp->cl_state, NFS4CLNT_STATE_RECOVER,
> nfs4_wait_bit_killable, TASK_KILLABLE);
> + if (!res)
> + res = clp->cl_recovery_status;
>
> rwsem_release(&clp->cl_sem.dep_map, 1, _RET_IP_);
> return res;
> diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
> index c391caf..09ca7b1 100644
> --- a/fs/nfs/nfs4state.c
> +++ b/fs/nfs/nfs4state.c
> @@ -814,8 +814,10 @@ void nfs4_schedule_state_recovery(struct nfs_client *clp)
> {
> if (!clp)
> return;
> - if (test_and_set_bit(NFS4CLNT_STATE_RECOVER, &clp->cl_state) == 0)
> + if (test_and_set_bit(NFS4CLNT_STATE_RECOVER, &clp->cl_state) == 0) {
> + clp->cl_recovery_status = 0;
> nfs4_recover_state(clp);
> + }
> }
>
> static int nfs4_reclaim_locks(struct nfs4_state_recovery_ops *ops, struct nfs4_state *state)
> @@ -1018,6 +1020,7 @@ out:
> out_error:
> printk(KERN_WARNING "Error: state recovery failed on NFSv4 server %s"
> " with error %d\n", clp->cl_hostname, -status);
> + clp->cl_recovery_status = status;
> set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
> goto out;
> }
> diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
> index c5cb574..80e0fc3 100644
> --- a/include/linux/nfs_fs_sb.h
> +++ b/include/linux/nfs_fs_sb.h
> @@ -38,6 +38,7 @@ struct nfs_client {
> u64 cl_clientid; /* constant */
> nfs4_verifier cl_confirm;
> unsigned long cl_state;
> + int cl_recovery_status;
>
> struct rb_root cl_openowner_id;
> struct rb_root cl_lockowner_id;
^ permalink raw reply [flat|nested] 115+ messages in thread
* [RFC 17/85] nfs41: fallback to lower minorversion if nfs4_create_server fails
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (13 preceding siblings ...)
2008-11-10 20:20 ` [RFC 16/85] nfs41: pass recovery status from reclaimer kthread up to nfs4_wait_clnt_recover Benny Halevy
@ 2008-11-10 20:20 ` Benny Halevy
2008-11-17 13:43 ` [pnfs] " Benny Halevy
2008-11-10 20:20 ` [RFC 18/85] nfs41: sessions client infrastructure Benny Halevy
` (70 subsequent siblings)
85 siblings, 1 reply; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:20 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
retry nfs4_create_server with lower minorversion on minorvers_mismatch error
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/client.c | 12 +++++++++++-
1 files changed, 11 insertions(+), 1 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 11c845d..0a8a082 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -1118,15 +1118,17 @@ struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data,
{
struct nfs_fattr fattr;
struct nfs_server *server;
+ int minorvers = data->minorversion;
int error;
dprintk("--> nfs4_create_server()\n");
+retry:
server = nfs_alloc_server();
if (!server)
return ERR_PTR(-ENOMEM);
- server->minorversion = data->minorversion;
+ server->minorversion = minorvers;
/* set up the general RPC client */
error = nfs4_init_server(server, data);
@@ -1168,7 +1170,15 @@ struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data,
return server;
error:
+ if (server->nfs_client && server->nfs_client->cl_recovery_status)
+ error = server->nfs_client->cl_recovery_status;
nfs_free_server(server);
+ if (minorvers > 0 && error == -NFS4ERR_MINOR_VERS_MISMATCH) {
+ minorvers--;
+ dprintk("%s: error %d retrying with minorvers=%d\n",
+ __func__, error, minorvers);
+ goto retry;
+ }
dprintk("<-- nfs4_create_server() = error %d\n", error);
return ERR_PTR(error);
}
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* Re: [pnfs] [RFC 17/85] nfs41: fallback to lower minorversion if nfs4_create_server fails
2008-11-10 20:20 ` [RFC 17/85] nfs41: fallback to lower minorversion if nfs4_create_server fails Benny Halevy
@ 2008-11-17 13:43 ` Benny Halevy
0 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-17 13:43 UTC (permalink / raw)
To: pnfs; +Cc: trond.myklebust, linux-nfs
On Nov. 10, 2008, 22:20 +0200, Benny Halevy <bhalevy@panasas.com> wrote:
> retry nfs4_create_server with lower minorversion on minorvers_mismatch error
>
> Signed-off-by: Benny Halevy <bhalevy@panasas.com>
review 11-14: move logic to reclaimer();
> ---
> fs/nfs/client.c | 12 +++++++++++-
> 1 files changed, 11 insertions(+), 1 deletions(-)
>
> diff --git a/fs/nfs/client.c b/fs/nfs/client.c
> index 11c845d..0a8a082 100644
> --- a/fs/nfs/client.c
> +++ b/fs/nfs/client.c
> @@ -1118,15 +1118,17 @@ struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data,
> {
> struct nfs_fattr fattr;
> struct nfs_server *server;
> + int minorvers = data->minorversion;
> int error;
>
> dprintk("--> nfs4_create_server()\n");
>
> +retry:
> server = nfs_alloc_server();
> if (!server)
> return ERR_PTR(-ENOMEM);
>
> - server->minorversion = data->minorversion;
> + server->minorversion = minorvers;
>
> /* set up the general RPC client */
> error = nfs4_init_server(server, data);
> @@ -1168,7 +1170,15 @@ struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data,
> return server;
>
> error:
> + if (server->nfs_client && server->nfs_client->cl_recovery_status)
> + error = server->nfs_client->cl_recovery_status;
> nfs_free_server(server);
> + if (minorvers > 0 && error == -NFS4ERR_MINOR_VERS_MISMATCH) {
> + minorvers--;
> + dprintk("%s: error %d retrying with minorvers=%d\n",
> + __func__, error, minorvers);
> + goto retry;
> + }
> dprintk("<-- nfs4_create_server() = error %d\n", error);
> return ERR_PTR(error);
> }
^ permalink raw reply [flat|nested] 115+ messages in thread
* [RFC 18/85] nfs41: sessions client infrastructure
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (14 preceding siblings ...)
2008-11-10 20:20 ` [RFC 17/85] nfs41: fallback to lower minorversion if nfs4_create_server fails Benny Halevy
@ 2008-11-10 20:20 ` Benny Halevy
2008-11-17 13:44 ` [pnfs] " Benny Halevy
2008-11-10 20:21 ` [RFC 19/85] nfs41: share client sessions across mounts Benny Halevy
` (69 subsequent siblings)
85 siblings, 1 reply; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:20 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
From: Andy Adamson <andros@netapp.com>
NFSv4.1 Sessions basic data types, initialization, and destruction.
The session is always associated with a struct nfs_client that holds
the exchange_id results. Add an nfs_client struct backpointer to the session
and refactor the session recovery routines to only require a struct
nfs4_sessions parameter.
Signed-off-by: Rahul Iyer <iyer@netapp.com>
Signed-off-by: Andy Adamson<andros@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/client.c | 40 +++++++++++++++++++++++++++++++++++++
fs/nfs/internal.h | 1 +
fs/nfs/nfs4_fs.h | 4 +++
fs/nfs/nfs4proc.c | 35 ++++++++++++++++++++++++++++++++
include/linux/nfs4_session.h | 45 ++++++++++++++++++++++++++++++++++++++++++
include/linux/nfs_fs_sb.h | 5 ++++
6 files changed, 130 insertions(+), 0 deletions(-)
create mode 100644 include/linux/nfs4_session.h
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 0a8a082..80091dc 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -37,6 +37,9 @@
#include <linux/in6.h>
#include <net/ipv6.h>
#include <linux/nfs_xdr.h>
+#if defined(CONFIG_NFS_V4_1)
+#include <linux/nfs4_session.h>
+#endif /* CONFIG_NFS_V4_1 */
#include <asm/system.h>
@@ -884,6 +887,11 @@ void nfs_free_server(struct nfs_server *server)
list_del(&server->master_link);
spin_unlock(&nfs_client_lock);
+#ifdef CONFIG_NFS_V4_1
+ if (server->nfs_client->cl_session != NULL)
+ nfs4_put_session(&server->nfs_client->cl_session);
+#endif /* CONFIG_NFS_V4_1 */
+
if (server->destroy != NULL)
server->destroy(server);
@@ -1110,6 +1118,34 @@ error:
}
/*
+ * Allocate and initialize a session if required
+ */
+int nfs4_init_session(struct nfs_client *clp, struct rpc_clnt *clnt)
+{
+ int error = 0;
+
+#if defined(CONFIG_NFS_V4_1)
+ if (clp->cl_minorversion) {
+ struct nfs4_session *session = NULL;
+ /*
+ * Create the session and mark it expired.
+ * When a SEQUENCE operation encounters the expired session
+ * it will do session recovery to initialize it.
+ */
+ session = nfs4_alloc_session();
+ if (!session)
+ error = -ENOMEM;
+ else {
+ session->clnt = clnt;
+ session->clp = clp;
+ }
+ clp->cl_session = session;
+ }
+#endif /* CONFIG_NFS_V4_1 */
+ return error;
+}
+
+/*
* Create a version 4 volume record
* - keyed on server and FSID
*/
@@ -1139,6 +1175,10 @@ retry:
BUG_ON(!server->nfs_client->rpc_ops);
BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
+ error = nfs4_init_session(server->nfs_client, server->client);
+ if (error)
+ goto error;
+
/* Probe the root fh to retrieve its FSID */
error = nfs4_path_walk(server, mntfh, data->nfs_server.export_path);
if (error < 0)
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 8386e99..9b2228f 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -82,6 +82,7 @@ extern void nfs_free_server(struct nfs_server *server);
extern struct nfs_server *nfs_clone_server(struct nfs_server *,
struct nfs_fh *,
struct nfs_fattr *);
+extern int nfs4_init_session(struct nfs_client *clp, struct rpc_clnt *clnt);
#ifdef CONFIG_PROC_FS
extern int __init nfs_fs_proc_init(void);
extern void nfs_fs_proc_exit(void);
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 5fb7382..4b13945 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -188,6 +188,10 @@ extern int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops;
extern struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops;
+#if defined(CONFIG_NFS_V4_1)
+extern void nfs4_put_session(struct nfs4_session **session);
+extern struct nfs4_session *nfs4_alloc_session(void);
+#endif /* CONFIG_NFS_V4_1 */
extern const u32 nfs4_fattr_bitmap[2];
extern const u32 nfs4_statfs_bitmap[2];
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index f87d4de..8e373e9 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -53,6 +53,9 @@
#include "delegation.h"
#include "internal.h"
#include "iostat.h"
+#if defined(CONFIG_NFS_V4_1)
+#include <linux/nfs4_session.h>
+#endif /* CONFIG_NFS_V4_1 */
#define NFSDBG_FACILITY NFSDBG_PROC
@@ -3679,6 +3682,38 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
return status;
}
+#ifdef CONFIG_NFS_V4_1
+struct nfs4_session *nfs4_alloc_session(void)
+{
+ struct nfs4_session *session;
+
+ session = kzalloc(sizeof(struct nfs4_session), GFP_ATOMIC);
+ if (!session)
+ return NULL;
+
+ atomic_set(&session->ref_count, 1);
+
+ return session;
+}
+
+static void nfs4_free_session(struct nfs4_session *session)
+{
+ dprintk("%s: freeing session %p\n", __func__, session);
+ kfree(session);
+}
+
+void nfs4_put_session(struct nfs4_session **session)
+{
+ dprintk("--> nfs4_put_session()\n");
+ if (atomic_dec_and_test(&((*session)->ref_count))) {
+ nfs4_free_session(*session);
+ *session = NULL;
+ }
+ dprintk("<-- nfs4_put_session()\n");
+}
+
+#endif /* CONFIG_NFS_V4_1 */
+
struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops = {
.recover_open = nfs4_open_reclaim,
.recover_lock = nfs4_lock_reclaim,
diff --git a/include/linux/nfs4_session.h b/include/linux/nfs4_session.h
new file mode 100644
index 0000000..36c0f94
--- /dev/null
+++ b/include/linux/nfs4_session.h
@@ -0,0 +1,45 @@
+#ifndef _NFS4_SESSIONS_H
+#define _NFS4_SESSIONS_H
+
+#if defined(CONFIG_NFS_V4_1)
+
+#include <linux/nfs4.h>
+#include <linux/smp_lock.h>
+#include <linux/sunrpc/sched.h>
+
+struct nfs4_channel_attrs {
+ u32 headerpadsz;
+ u32 max_rqst_sz;
+ u32 max_resp_sz;
+ u32 max_resp_sz_cached;
+ u32 max_ops;
+ u32 max_reqs;
+ u32 rdma_attrs;
+};
+
+struct nfs4_channel {
+ struct nfs4_channel_attrs chan_attrs;
+ struct rpc_clnt *rpc_client;
+};
+
+/*
+ * Session related parameters
+ */
+struct nfs4_session {
+ nfs41_sessionid sess_id;
+ u32 flags;
+ unsigned long session_state;
+ u32 hash_alg;
+ u32 ssv_len;
+
+ /* The fore and back channel */
+ struct nfs4_channel fore_channel;
+ struct nfs4_channel back_channel;
+
+ atomic_t ref_count;
+ struct rpc_clnt *clnt;
+ struct nfs_client *clp;
+};
+
+#endif /* CONFIG_NFS_V4_1 */
+#endif
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index 80e0fc3..15c0aa5 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -7,6 +7,7 @@
#include <asm/atomic.h>
+struct nfs4_session;
struct nfs_iostats;
struct nlm_host;
@@ -72,6 +73,10 @@ struct nfs_client {
unsigned char cl_id_uniquifier;
u32 cl_minorversion;
#endif /* CONFIG_NFS_V4 */
+
+#ifdef CONFIG_NFS_V4_1
+ struct nfs4_session *cl_session; /* sharred session */
+#endif /* CONFIG_NFS_V4_1 */
};
#ifdef CONFIG_NFS_V4
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* Re: [pnfs] [RFC 18/85] nfs41: sessions client infrastructure
2008-11-10 20:20 ` [RFC 18/85] nfs41: sessions client infrastructure Benny Halevy
@ 2008-11-17 13:44 ` Benny Halevy
0 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-17 13:44 UTC (permalink / raw)
To: pnfs; +Cc: trond.myklebust, linux-nfs
On Nov. 10, 2008, 22:20 +0200, Benny Halevy <bhalevy@panasas.com> wrote:
> From: Andy Adamson <andros@netapp.com>
>
> NFSv4.1 Sessions basic data types, initialization, and destruction.
>
> The session is always associated with a struct nfs_client that holds
> the exchange_id results. Add an nfs_client struct backpointer to the session
> and refactor the session recovery routines to only require a struct
> nfs4_sessions parameter.
>
> Signed-off-by: Rahul Iyer <iyer@netapp.com>
> Signed-off-by: Andy Adamson<andros@netapp.com>
> Signed-off-by: Benny Halevy <bhalevy@panasas.com>
> ---
> fs/nfs/client.c | 40 +++++++++++++++++++++++++++++++++++++
> fs/nfs/internal.h | 1 +
> fs/nfs/nfs4_fs.h | 4 +++
> fs/nfs/nfs4proc.c | 35 ++++++++++++++++++++++++++++++++
> include/linux/nfs4_session.h | 45 ++++++++++++++++++++++++++++++++++++++++++
> include/linux/nfs_fs_sb.h | 5 ++++
> 6 files changed, 130 insertions(+), 0 deletions(-)
> create mode 100644 include/linux/nfs4_session.h
>
> diff --git a/fs/nfs/client.c b/fs/nfs/client.c
> index 0a8a082..80091dc 100644
> --- a/fs/nfs/client.c
> +++ b/fs/nfs/client.c
> @@ -37,6 +37,9 @@
> #include <linux/in6.h>
> #include <net/ipv6.h>
> #include <linux/nfs_xdr.h>
> +#if defined(CONFIG_NFS_V4_1)
> +#include <linux/nfs4_session.h>
> +#endif /* CONFIG_NFS_V4_1 */
>
> #include <asm/system.h>
>
> @@ -884,6 +887,11 @@ void nfs_free_server(struct nfs_server *server)
> list_del(&server->master_link);
> spin_unlock(&nfs_client_lock);
>
> +#ifdef CONFIG_NFS_V4_1
> + if (server->nfs_client->cl_session != NULL)
> + nfs4_put_session(&server->nfs_client->cl_session);
> +#endif /* CONFIG_NFS_V4_1 */
> +
> if (server->destroy != NULL)
> server->destroy(server);
>
> @@ -1110,6 +1118,34 @@ error:
> }
>
> /*
> + * Allocate and initialize a session if required
> + */
> +int nfs4_init_session(struct nfs_client *clp, struct rpc_clnt *clnt)
> +{
> + int error = 0;
> +
> +#if defined(CONFIG_NFS_V4_1)
> + if (clp->cl_minorversion) {
> + struct nfs4_session *session = NULL;
> + /*
> + * Create the session and mark it expired.
> + * When a SEQUENCE operation encounters the expired session
> + * it will do session recovery to initialize it.
> + */
> + session = nfs4_alloc_session();
> + if (!session)
> + error = -ENOMEM;
> + else {
> + session->clnt = clnt;
> + session->clp = clp;
> + }
> + clp->cl_session = session;
> + }
> +#endif /* CONFIG_NFS_V4_1 */
> + return error;
> +}
> +
> +/*
> * Create a version 4 volume record
> * - keyed on server and FSID
> */
> @@ -1139,6 +1175,10 @@ retry:
> BUG_ON(!server->nfs_client->rpc_ops);
> BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
>
> + error = nfs4_init_session(server->nfs_client, server->client);
> + if (error)
> + goto error;
> +
> /* Probe the root fh to retrieve its FSID */
> error = nfs4_path_walk(server, mntfh, data->nfs_server.export_path);
> if (error < 0)
> diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
> index 8386e99..9b2228f 100644
> --- a/fs/nfs/internal.h
> +++ b/fs/nfs/internal.h
> @@ -82,6 +82,7 @@ extern void nfs_free_server(struct nfs_server *server);
> extern struct nfs_server *nfs_clone_server(struct nfs_server *,
> struct nfs_fh *,
> struct nfs_fattr *);
> +extern int nfs4_init_session(struct nfs_client *clp, struct rpc_clnt *clnt);
> #ifdef CONFIG_PROC_FS
> extern int __init nfs_fs_proc_init(void);
> extern void nfs_fs_proc_exit(void);
> diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
> index 5fb7382..4b13945 100644
> --- a/fs/nfs/nfs4_fs.h
> +++ b/fs/nfs/nfs4_fs.h
> @@ -188,6 +188,10 @@ extern int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
>
> extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops;
> extern struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops;
> +#if defined(CONFIG_NFS_V4_1)
> +extern void nfs4_put_session(struct nfs4_session **session);
> +extern struct nfs4_session *nfs4_alloc_session(void);
> +#endif /* CONFIG_NFS_V4_1 */
>
> extern const u32 nfs4_fattr_bitmap[2];
> extern const u32 nfs4_statfs_bitmap[2];
> diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
> index f87d4de..8e373e9 100644
> --- a/fs/nfs/nfs4proc.c
> +++ b/fs/nfs/nfs4proc.c
> @@ -53,6 +53,9 @@
> #include "delegation.h"
> #include "internal.h"
> #include "iostat.h"
> +#if defined(CONFIG_NFS_V4_1)
> +#include <linux/nfs4_session.h>
> +#endif /* CONFIG_NFS_V4_1 */
>
> #define NFSDBG_FACILITY NFSDBG_PROC
>
> @@ -3679,6 +3682,38 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
> return status;
> }
>
> +#ifdef CONFIG_NFS_V4_1
> +struct nfs4_session *nfs4_alloc_session(void)
> +{
> + struct nfs4_session *session;
> +
> + session = kzalloc(sizeof(struct nfs4_session), GFP_ATOMIC);
> + if (!session)
> + return NULL;
> +
> + atomic_set(&session->ref_count, 1);
> +
> + return session;
> +}
> +
> +static void nfs4_free_session(struct nfs4_session *session)
> +{
> + dprintk("%s: freeing session %p\n", __func__, session);
> + kfree(session);
> +}
> +
> +void nfs4_put_session(struct nfs4_session **session)
review 11-14: pass a struct nfs4_session* (not **)
do not set *session to NULL
> +{
> + dprintk("--> nfs4_put_session()\n");
> + if (atomic_dec_and_test(&((*session)->ref_count))) {
> + nfs4_free_session(*session);
> + *session = NULL;
> + }
> + dprintk("<-- nfs4_put_session()\n");
> +}
> +
> +#endif /* CONFIG_NFS_V4_1 */
> +
> struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops = {
> .recover_open = nfs4_open_reclaim,
> .recover_lock = nfs4_lock_reclaim,
> diff --git a/include/linux/nfs4_session.h b/include/linux/nfs4_session.h
> new file mode 100644
> index 0000000..36c0f94
> --- /dev/null
> +++ b/include/linux/nfs4_session.h
review 11-14: move to fs/nfs/nfs4_fs.h
> @@ -0,0 +1,45 @@
> +#ifndef _NFS4_SESSIONS_H
> +#define _NFS4_SESSIONS_H
> +
> +#if defined(CONFIG_NFS_V4_1)
> +
> +#include <linux/nfs4.h>
> +#include <linux/smp_lock.h>
> +#include <linux/sunrpc/sched.h>
> +
> +struct nfs4_channel_attrs {
> + u32 headerpadsz;
> + u32 max_rqst_sz;
> + u32 max_resp_sz;
> + u32 max_resp_sz_cached;
> + u32 max_ops;
> + u32 max_reqs;
> + u32 rdma_attrs;
review 11-14: weed out unused fields
> +};
> +
> +struct nfs4_channel {
> + struct nfs4_channel_attrs chan_attrs;
> + struct rpc_clnt *rpc_client;
review 11-14: unused, no need for this struct
> +};
> +
> +/*
> + * Session related parameters
> + */
> +struct nfs4_session {
> + nfs41_sessionid sess_id;
> + u32 flags;
review 11-14: remove until used
> + unsigned long session_state;
> + u32 hash_alg;
> + u32 ssv_len;
review 11-14: take these out for now.
> +
> + /* The fore and back channel */
> + struct nfs4_channel fore_channel;
review 11-14: s/nfs4_channel/nfs4_channel_attrs/
> + struct nfs4_channel back_channel;
> +
> + atomic_t ref_count;
> + struct rpc_clnt *clnt;
review 11-14: use clp->cl_rpcclient instead
> + struct nfs_client *clp;
> +};
> +
> +#endif /* CONFIG_NFS_V4_1 */
> +#endif
> diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
> index 80e0fc3..15c0aa5 100644
> --- a/include/linux/nfs_fs_sb.h
> +++ b/include/linux/nfs_fs_sb.h
> @@ -7,6 +7,7 @@
>
> #include <asm/atomic.h>
>
> +struct nfs4_session;
> struct nfs_iostats;
> struct nlm_host;
>
> @@ -72,6 +73,10 @@ struct nfs_client {
> unsigned char cl_id_uniquifier;
> u32 cl_minorversion;
> #endif /* CONFIG_NFS_V4 */
> +
> +#ifdef CONFIG_NFS_V4_1
> + struct nfs4_session *cl_session; /* sharred session */
> +#endif /* CONFIG_NFS_V4_1 */
> };
>
> #ifdef CONFIG_NFS_V4
^ permalink raw reply [flat|nested] 115+ messages in thread
* [RFC 19/85] nfs41: share client sessions across mounts
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (15 preceding siblings ...)
2008-11-10 20:20 ` [RFC 18/85] nfs41: sessions client infrastructure Benny Halevy
@ 2008-11-10 20:21 ` Benny Halevy
2008-11-17 13:45 ` [pnfs] " Benny Halevy
2008-11-10 20:21 ` [RFC 20/85] nfs41: slot table init and destroy Benny Halevy
` (68 subsequent siblings)
85 siblings, 1 reply; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:21 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
From: Andy Adamson <andros@netapp.com>
Do not create a new session for each new mount (FSID).
Call nfs4_get_session to bump the reference count for each cloned nfs4 server
which now share the struct nfs_client session.
nfs41: check minorversion on nfs41_get_session
Signed-off-by: Andy Adamson<andros@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/client.c | 4 ++++
fs/nfs/nfs4_fs.h | 1 +
fs/nfs/nfs4proc.c | 5 +++++
3 files changed, 10 insertions(+), 0 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 80091dc..62bdf31 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -1336,6 +1336,10 @@ struct nfs_server *nfs_clone_server(struct nfs_server *source,
if (!IS_ERR(source->client_acl))
nfs_init_server_aclclient(server);
+#ifdef CONFIG_NFS_V4_1
+ nfs4_get_session(server->nfs_client);
+#endif /* CONFIG_NFS_V4_1 */
+
/* probe the filesystem info for this server filesystem */
error = nfs_probe_fsinfo(server, fh, &fattr_fsinfo);
if (error < 0)
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 4b13945..a28427f 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -190,6 +190,7 @@ extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops;
extern struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops;
#if defined(CONFIG_NFS_V4_1)
extern void nfs4_put_session(struct nfs4_session **session);
+extern void nfs4_get_session(struct nfs_client *clp);
extern struct nfs4_session *nfs4_alloc_session(void);
#endif /* CONFIG_NFS_V4_1 */
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 8e373e9..d0b6ca1 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -3712,6 +3712,11 @@ void nfs4_put_session(struct nfs4_session **session)
dprintk("<-- nfs4_put_session()\n");
}
+void nfs4_get_session(struct nfs_client *clp)
+{
+ if (clp->cl_minorversion == 1)
+ atomic_inc(&clp->cl_session->ref_count);
+}
#endif /* CONFIG_NFS_V4_1 */
struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops = {
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* Re: [pnfs] [RFC 19/85] nfs41: share client sessions across mounts
2008-11-10 20:21 ` [RFC 19/85] nfs41: share client sessions across mounts Benny Halevy
@ 2008-11-17 13:45 ` Benny Halevy
0 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-17 13:45 UTC (permalink / raw)
To: pnfs; +Cc: trond.myklebust, linux-nfs
On Nov. 10, 2008, 22:21 +0200, Benny Halevy <bhalevy@panasas.com> wrote:
> From: Andy Adamson <andros@netapp.com>
>
> Do not create a new session for each new mount (FSID).
>
> Call nfs4_get_session to bump the reference count for each cloned nfs4 server
> which now share the struct nfs_client session.
>
> nfs41: check minorversion on nfs41_get_session
>
> Signed-off-by: Andy Adamson<andros@netapp.com>
> Signed-off-by: Benny Halevy <bhalevy@panasas.com>
> ---
> fs/nfs/client.c | 4 ++++
> fs/nfs/nfs4_fs.h | 1 +
> fs/nfs/nfs4proc.c | 5 +++++
> 3 files changed, 10 insertions(+), 0 deletions(-)
>
> diff --git a/fs/nfs/client.c b/fs/nfs/client.c
> index 80091dc..62bdf31 100644
> --- a/fs/nfs/client.c
> +++ b/fs/nfs/client.c
> @@ -1336,6 +1336,10 @@ struct nfs_server *nfs_clone_server(struct nfs_server *source,
> if (!IS_ERR(source->client_acl))
> nfs_init_server_aclclient(server);
>
> +#ifdef CONFIG_NFS_V4_1
review 11-14: check for clp->cl_session != NULL
> + nfs4_get_session(server->nfs_client);
> +#endif /* CONFIG_NFS_V4_1 */
> +
> /* probe the filesystem info for this server filesystem */
> error = nfs_probe_fsinfo(server, fh, &fattr_fsinfo);
> if (error < 0)
> diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
> index 4b13945..a28427f 100644
> --- a/fs/nfs/nfs4_fs.h
> +++ b/fs/nfs/nfs4_fs.h
> @@ -190,6 +190,7 @@ extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops;
> extern struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops;
> #if defined(CONFIG_NFS_V4_1)
> extern void nfs4_put_session(struct nfs4_session **session);
> +extern void nfs4_get_session(struct nfs_client *clp);
> extern struct nfs4_session *nfs4_alloc_session(void);
> #endif /* CONFIG_NFS_V4_1 */
>
> diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
> index 8e373e9..d0b6ca1 100644
> --- a/fs/nfs/nfs4proc.c
> +++ b/fs/nfs/nfs4proc.c
> @@ -3712,6 +3712,11 @@ void nfs4_put_session(struct nfs4_session **session)
> dprintk("<-- nfs4_put_session()\n");
> }
>
> +void nfs4_get_session(struct nfs_client *clp)
review 11-14: just pass a session*
> +{
> + if (clp->cl_minorversion == 1)
> + atomic_inc(&clp->cl_session->ref_count);
> +}
> #endif /* CONFIG_NFS_V4_1 */
>
> struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops = {
^ permalink raw reply [flat|nested] 115+ messages in thread
* [RFC 20/85] nfs41: slot table init and destroy
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (16 preceding siblings ...)
2008-11-10 20:21 ` [RFC 19/85] nfs41: share client sessions across mounts Benny Halevy
@ 2008-11-10 20:21 ` Benny Halevy
2008-11-17 13:46 ` [pnfs] " Benny Halevy
2008-11-10 20:21 ` [RFC 21/85] nfs41: find slot Benny Halevy
` (67 subsequent siblings)
85 siblings, 1 reply; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:21 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
Code to initialize and destroy the slot table.
Uses bitmap-based allocation.
Signed-off-by: Andy Adamson<andros@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/nfs4proc.c | 88 ++++++++++++++++++++++++++++++++++++++++++
include/linux/nfs4_session.h | 17 ++++++++
2 files changed, 105 insertions(+), 0 deletions(-)
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index d0b6ca1..08e7129 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -3683,6 +3683,92 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
}
#ifdef CONFIG_NFS_V4_1
+/*
+ * Initialize slot table
+ *
+ * Note: the "used" bitmap points to _used_slots id max_slots <= BITS_PER_LONG.
+ * Otherwise, we dynamically allocate enough ulongs to hold max_slots bits.
+ */
+static int nfs4_init_slot_table(struct nfs4_channel *channel)
+{
+ struct nfs4_slot_table *tbl = &channel->slot_table;
+ int i, max_slots = channel->chan_attrs.max_reqs;
+ struct nfs4_slot *slot;
+ unsigned long *used;
+ int ret = -ENOMEM;
+
+ dprintk("--> %s: max_reqs=%u\n", __func__,
+ channel->chan_attrs.max_reqs);
+ slot = kzalloc(max_slots * sizeof(struct nfs4_slot), GFP_ATOMIC);
+ if (!slot)
+ goto out;
+ for (i = 0; i < max_slots; ++i)
+ slot[i].seq_nr = 1;
+
+ if (max_slots <= BITS_PER_LONG)
+ used = &tbl->_used_slots; /* use word in tbl */
+ else {
+ /* allocate enough unsigned longs for max_slots bits */
+ used = kzalloc(sizeof(unsigned long) *
+ DIV_ROUND_UP(max_slots, BITS_PER_LONG),
+ GFP_ATOMIC);
+ if (!used)
+ goto out_free;
+ }
+ ret = 0;
+
+ spin_lock(&tbl->slot_tbl_lock);
+ if (tbl->slots != NULL) {
+ spin_unlock(&tbl->slot_tbl_lock);
+ dprintk("%s: slot table already initialized. tbl=%p slots=%p\n",
+ __func__, tbl, tbl->slots);
+ WARN_ON(1);
+ goto out_free;
+ }
+ tbl->max_slots = max_slots;
+ tbl->slots = slot;
+ tbl->used_slots = used;
+ tbl->lowest_free_slotid = 0; /* first slot is free */
+ tbl->highest_used_slotid = -1; /* no slot is currently used */
+ spin_unlock(&tbl->slot_tbl_lock);
+ dprintk("%s: tbl=%p slots=%p max_slots=%d\n", __func__,
+ tbl, tbl->slots, tbl->max_slots);
+out:
+ dprintk("<-- %s: return %d\n", __func__, ret);
+ return ret;
+out_free:
+ kfree(slot);
+ if (used != &tbl->_used_slots)
+ kfree(used);
+ goto out;
+}
+
+/* Destroy the slot table */
+static void nfs4_destroy_slot_table(struct nfs4_channel *channel)
+{
+ if (channel->slot_table.slots == NULL)
+ return;
+ kfree(channel->slot_table.slots);
+ channel->slot_table.slots = NULL;
+ /* Was the "used" bitmap dynamically allocated? */
+ if (channel->slot_table.used_slots != &channel->slot_table._used_slots)
+ kfree(channel->slot_table.used_slots);
+
+ return;
+}
+
+static int nfs4_init_channel(struct nfs4_channel *channel)
+{
+ struct nfs4_slot_table *tbl;
+
+ tbl = &channel->slot_table;
+
+ spin_lock_init(&tbl->slot_tbl_lock);
+ rpc_init_wait_queue(&tbl->slot_tbl_waitq, "Slot table");
+
+ return 0;
+}
+
struct nfs4_session *nfs4_alloc_session(void)
{
struct nfs4_session *session;
@@ -3693,6 +3779,7 @@ struct nfs4_session *nfs4_alloc_session(void)
atomic_set(&session->ref_count, 1);
+ nfs4_init_channel(&session->fore_channel);
return session;
}
@@ -3706,6 +3793,7 @@ void nfs4_put_session(struct nfs4_session **session)
{
dprintk("--> nfs4_put_session()\n");
if (atomic_dec_and_test(&((*session)->ref_count))) {
+ nfs4_destroy_slot_table(&((*session)->fore_channel));
nfs4_free_session(*session);
*session = NULL;
}
diff --git a/include/linux/nfs4_session.h b/include/linux/nfs4_session.h
index 36c0f94..d534269 100644
--- a/include/linux/nfs4_session.h
+++ b/include/linux/nfs4_session.h
@@ -17,9 +17,26 @@ struct nfs4_channel_attrs {
u32 rdma_attrs;
};
+struct nfs4_slot {
+ u32 seq_nr;
+};
+
+struct nfs4_slot_table {
+ struct nfs4_slot *slots; /* seqid per slot */
+ unsigned long *used_slots; /* used/unused bitmap */
+ unsigned long _used_slots; /* used when max_slots fits */
+ spinlock_t slot_tbl_lock;
+ struct rpc_wait_queue slot_tbl_waitq; /* allocators may wait here */
+ int max_slots; /* # slots in table */
+ int lowest_free_slotid; /* lower bound hint */
+ int highest_used_slotid; /* sent to server on each SEQ.
+ * op for dynamic resizing */
+};
+
struct nfs4_channel {
struct nfs4_channel_attrs chan_attrs;
struct rpc_clnt *rpc_client;
+ struct nfs4_slot_table slot_table;
};
/*
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* Re: [pnfs] [RFC 20/85] nfs41: slot table init and destroy
2008-11-10 20:21 ` [RFC 20/85] nfs41: slot table init and destroy Benny Halevy
@ 2008-11-17 13:46 ` Benny Halevy
0 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-17 13:46 UTC (permalink / raw)
To: pnfs; +Cc: trond.myklebust, linux-nfs
On Nov. 10, 2008, 22:21 +0200, Benny Halevy <bhalevy@panasas.com> wrote:
> Code to initialize and destroy the slot table.
> Uses bitmap-based allocation.
>
> Signed-off-by: Andy Adamson<andros@netapp.com>
> Signed-off-by: Benny Halevy <bhalevy@panasas.com>
> ---
> fs/nfs/nfs4proc.c | 88 ++++++++++++++++++++++++++++++++++++++++++
> include/linux/nfs4_session.h | 17 ++++++++
> 2 files changed, 105 insertions(+), 0 deletions(-)
>
> diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
> index d0b6ca1..08e7129 100644
> --- a/fs/nfs/nfs4proc.c
> +++ b/fs/nfs/nfs4proc.c
> @@ -3683,6 +3683,92 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
> }
>
> #ifdef CONFIG_NFS_V4_1
> +/*
> + * Initialize slot table
> + *
> + * Note: the "used" bitmap points to _used_slots id max_slots <= BITS_PER_LONG.
> + * Otherwise, we dynamically allocate enough ulongs to hold max_slots bits.
> + */
> +static int nfs4_init_slot_table(struct nfs4_channel *channel)
> +{
> + struct nfs4_slot_table *tbl = &channel->slot_table;
> + int i, max_slots = channel->chan_attrs.max_reqs;
> + struct nfs4_slot *slot;
> + unsigned long *used;
> + int ret = -ENOMEM;
> +
> + dprintk("--> %s: max_reqs=%u\n", __func__,
> + channel->chan_attrs.max_reqs);
> + slot = kzalloc(max_slots * sizeof(struct nfs4_slot), GFP_ATOMIC);
> + if (!slot)
> + goto out;
> + for (i = 0; i < max_slots; ++i)
> + slot[i].seq_nr = 1;
> +
> + if (max_slots <= BITS_PER_LONG)
> + used = &tbl->_used_slots; /* use word in tbl */
> + else {
> + /* allocate enough unsigned longs for max_slots bits */
> + used = kzalloc(sizeof(unsigned long) *
> + DIV_ROUND_UP(max_slots, BITS_PER_LONG),
> + GFP_ATOMIC);
> + if (!used)
> + goto out_free;
> + }
> + ret = 0;
> +
> + spin_lock(&tbl->slot_tbl_lock);
> + if (tbl->slots != NULL) {
> + spin_unlock(&tbl->slot_tbl_lock);
> + dprintk("%s: slot table already initialized. tbl=%p slots=%p\n",
> + __func__, tbl, tbl->slots);
> + WARN_ON(1);
> + goto out_free;
> + }
> + tbl->max_slots = max_slots;
> + tbl->slots = slot;
> + tbl->used_slots = used;
> + tbl->lowest_free_slotid = 0; /* first slot is free */
> + tbl->highest_used_slotid = -1; /* no slot is currently used */
> + spin_unlock(&tbl->slot_tbl_lock);
> + dprintk("%s: tbl=%p slots=%p max_slots=%d\n", __func__,
> + tbl, tbl->slots, tbl->max_slots);
> +out:
> + dprintk("<-- %s: return %d\n", __func__, ret);
> + return ret;
> +out_free:
> + kfree(slot);
> + if (used != &tbl->_used_slots)
> + kfree(used);
> + goto out;
> +}
> +
> +/* Destroy the slot table */
> +static void nfs4_destroy_slot_table(struct nfs4_channel *channel)
> +{
> + if (channel->slot_table.slots == NULL)
> + return;
> + kfree(channel->slot_table.slots);
> + channel->slot_table.slots = NULL;
> + /* Was the "used" bitmap dynamically allocated? */
> + if (channel->slot_table.used_slots != &channel->slot_table._used_slots)
> + kfree(channel->slot_table.used_slots);
> +
> + return;
> +}
> +
> +static int nfs4_init_channel(struct nfs4_channel *channel)
> +{
> + struct nfs4_slot_table *tbl;
> +
> + tbl = &channel->slot_table;
> +
> + spin_lock_init(&tbl->slot_tbl_lock);
> + rpc_init_wait_queue(&tbl->slot_tbl_waitq, "Slot table");
> +
> + return 0;
> +}
> +
> struct nfs4_session *nfs4_alloc_session(void)
> {
> struct nfs4_session *session;
> @@ -3693,6 +3779,7 @@ struct nfs4_session *nfs4_alloc_session(void)
>
> atomic_set(&session->ref_count, 1);
>
> + nfs4_init_channel(&session->fore_channel);
> return session;
> }
>
> @@ -3706,6 +3793,7 @@ void nfs4_put_session(struct nfs4_session **session)
> {
> dprintk("--> nfs4_put_session()\n");
> if (atomic_dec_and_test(&((*session)->ref_count))) {
> + nfs4_destroy_slot_table(&((*session)->fore_channel));
> nfs4_free_session(*session);
> *session = NULL;
> }
> diff --git a/include/linux/nfs4_session.h b/include/linux/nfs4_session.h
> index 36c0f94..d534269 100644
> --- a/include/linux/nfs4_session.h
> +++ b/include/linux/nfs4_session.h
> @@ -17,9 +17,26 @@ struct nfs4_channel_attrs {
> u32 rdma_attrs;
> };
>
> +struct nfs4_slot {
> + u32 seq_nr;
> +};
> +
> +struct nfs4_slot_table {
> + struct nfs4_slot *slots; /* seqid per slot */
> + unsigned long *used_slots; /* used/unused bitmap */
> + unsigned long _used_slots; /* used when max_slots fits */
review 11-14: just limit to 128 bits, no dynamic allocation
> + spinlock_t slot_tbl_lock;
> + struct rpc_wait_queue slot_tbl_waitq; /* allocators may wait here */
> + int max_slots; /* # slots in table */
> + int lowest_free_slotid; /* lower bound hint */
> + int highest_used_slotid; /* sent to server on each SEQ.
> + * op for dynamic resizing */
> +};
> +
> struct nfs4_channel {
> struct nfs4_channel_attrs chan_attrs;
> struct rpc_clnt *rpc_client;
> + struct nfs4_slot_table slot_table;
> };
>
> /*
^ permalink raw reply [flat|nested] 115+ messages in thread
* [RFC 21/85] nfs41: find slot
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (17 preceding siblings ...)
2008-11-10 20:21 ` [RFC 20/85] nfs41: slot table init and destroy Benny Halevy
@ 2008-11-10 20:21 ` Benny Halevy
2008-11-17 13:46 ` [pnfs] " Benny Halevy
2008-11-10 20:21 ` [RFC 22/85] nfs41: free slot Benny Halevy
` (66 subsequent siblings)
85 siblings, 1 reply; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:21 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
Find a free slot using bitmap-based allocation.
Use the optimized ffz function to find a zero bit
in the bitmap that indicates a free slot, starting
the search from the 'lowest_free_slotid' position.
If found, mark the slot as used in the bitmap, get
the slot's slotid and seqid, and update max_slotid
to be used by the SEQUENCE operation.
Also, update lowest_free_slotid for next search.
If no free slot was found the caller has to wait
for a free slot (outside the scope of this function)
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/nfs4proc.c | 88 ++++++++++++++++++++++++++++++++++++++++++
include/linux/nfs4_session.h | 5 ++
2 files changed, 93 insertions(+), 0 deletions(-)
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 08e7129..4ded3a5 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -207,6 +207,94 @@ static void renew_lease(const struct nfs_server *server, unsigned long timestamp
spin_unlock(&clp->cl_lock);
}
+#if defined(CONFIG_NFS_V4_1)
+
+/*
+ * idx2bmp - return pointer to bitmap word holding index "idx".
+ *
+ * inputs:
+ * @base points to bitmap.
+ * @idx slot index.
+ *
+ * output:
+ * @bit optional, *bit set to bit index of "idx" in the returned
+ * bitmap word.
+ */
+static inline unsigned long *idx2bmp(unsigned long *base, int idx, int *bit)
+{
+ base += idx / BITS_PER_LONG;
+ if (bit)
+ *bit = idx & (BITS_PER_LONG - 1);
+ return base;
+}
+
+/*
+ * bmp2idx - return absolute index of bmp:bit in bitmap.
+ *
+ * inputs:
+ * @base points to bitmap.
+ * @bmp points to bitmap word.
+ * @bit bit index in bitmap word.
+ */
+static inline int bmp2idx(unsigned long *base, unsigned long *bmp,
+ int bit)
+{
+ return ((bmp - base) * BITS_PER_LONG) + bit;
+}
+
+/*
+ * nfs4_find_slot - efficiently look for a free slot
+ *
+ * nfs4_find_slot uses the ffz cpu-optimized function to look for an unset
+ * bit in each word in the bitmap.
+ * Scan starts at lowest_free_slotid, which is a hint for the free slot,
+ * as all lower-numbered slots are known to be used.
+ * If found, we mark the slot as used, update the highest_used_slotid,
+ * and respectively set up the sequence operation args.
+ * The lowest_free_slotid is always set to the successive slotid.
+ * A pointer to the slot's seqid is returned if found, or NULL otherwise.
+ */
+static struct nfs4_slot *
+nfs4_find_slot(struct nfs4_slot_table *tbl, struct rpc_task *task)
+{
+ int bit, slotid;
+ struct nfs4_slot *slot = NULL;
+ unsigned long *used, u;
+
+ spin_lock(&tbl->slot_tbl_lock);
+ slotid = tbl->lowest_free_slotid;
+ while (slotid < tbl->max_slots) {
+ used = idx2bmp(tbl->used_slots, slotid, NULL);
+ u = *used;
+ if (u == ~0UL) {
+ /* all slots marked used in this word */
+ slotid += BITS_PER_LONG;
+ continue;
+ }
+ /* find first slot marked free in word */
+ bit = ffz(u);
+ slotid = bmp2idx(tbl->used_slots, used, bit);
+ /* mark slot used. note that we don't do that if
+ * slotid >= tbl->max_slots so not to confuse
+ * highest_used_slotid algorithm */
+ if (slotid < tbl->max_slots) {
+ *used |= (1 << bit);
+ if (slotid > tbl->highest_used_slotid)
+ tbl->highest_used_slotid = slotid;
+ slot = tbl->slots + slotid;
+ slotid++; /* for updating lowest_free_slot */
+ }
+ break;
+ }
+ tbl->lowest_free_slotid = slotid;
+ spin_unlock(&tbl->slot_tbl_lock);
+ dprintk("<-- %s slot %p slotid %d\n", __func__,
+ slot, slot ? slot_idx(tbl, slot) : -1);
+ return slot;
+}
+
+#endif /* CONFIG_NFS_V4_1 */
+
static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo)
{
struct nfs_inode *nfsi = NFS_I(dir);
diff --git a/include/linux/nfs4_session.h b/include/linux/nfs4_session.h
index d534269..2960ba9 100644
--- a/include/linux/nfs4_session.h
+++ b/include/linux/nfs4_session.h
@@ -33,6 +33,11 @@ struct nfs4_slot_table {
* op for dynamic resizing */
};
+static inline int slot_idx(struct nfs4_slot_table *tbl, struct nfs4_slot *sp)
+{
+ return sp - tbl->slots;
+}
+
struct nfs4_channel {
struct nfs4_channel_attrs chan_attrs;
struct rpc_clnt *rpc_client;
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* Re: [pnfs] [RFC 21/85] nfs41: find slot
2008-11-10 20:21 ` [RFC 21/85] nfs41: find slot Benny Halevy
@ 2008-11-17 13:46 ` Benny Halevy
0 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-17 13:46 UTC (permalink / raw)
To: pnfs; +Cc: trond.myklebust, linux-nfs
On Nov. 10, 2008, 22:21 +0200, Benny Halevy <bhalevy@panasas.com> wrote:
> Find a free slot using bitmap-based allocation.
> Use the optimized ffz function to find a zero bit
> in the bitmap that indicates a free slot, starting
> the search from the 'lowest_free_slotid' position.
>
> If found, mark the slot as used in the bitmap, get
> the slot's slotid and seqid, and update max_slotid
> to be used by the SEQUENCE operation.
>
> Also, update lowest_free_slotid for next search.
>
> If no free slot was found the caller has to wait
> for a free slot (outside the scope of this function)
>
> Signed-off-by: Benny Halevy <bhalevy@panasas.com>
> ---
> fs/nfs/nfs4proc.c | 88 ++++++++++++++++++++++++++++++++++++++++++
> include/linux/nfs4_session.h | 5 ++
> 2 files changed, 93 insertions(+), 0 deletions(-)
>
> diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
> index 08e7129..4ded3a5 100644
> --- a/fs/nfs/nfs4proc.c
> +++ b/fs/nfs/nfs4proc.c
> @@ -207,6 +207,94 @@ static void renew_lease(const struct nfs_server *server, unsigned long timestamp
> spin_unlock(&clp->cl_lock);
> }
>
> +#if defined(CONFIG_NFS_V4_1)
> +
> +/*
> + * idx2bmp - return pointer to bitmap word holding index "idx".
> + *
> + * inputs:
> + * @base points to bitmap.
> + * @idx slot index.
> + *
> + * output:
> + * @bit optional, *bit set to bit index of "idx" in the returned
> + * bitmap word.
> + */
> +static inline unsigned long *idx2bmp(unsigned long *base, int idx, int *bit)
> +{
> + base += idx / BITS_PER_LONG;
> + if (bit)
> + *bit = idx & (BITS_PER_LONG - 1);
> + return base;
> +}
> +
> +/*
> + * bmp2idx - return absolute index of bmp:bit in bitmap.
> + *
> + * inputs:
> + * @base points to bitmap.
> + * @bmp points to bitmap word.
> + * @bit bit index in bitmap word.
> + */
> +static inline int bmp2idx(unsigned long *base, unsigned long *bmp,
> + int bit)
> +{
> + return ((bmp - base) * BITS_PER_LONG) + bit;
> +}
> +
> +/*
> + * nfs4_find_slot - efficiently look for a free slot
> + *
> + * nfs4_find_slot uses the ffz cpu-optimized function to look for an unset
> + * bit in each word in the bitmap.
> + * Scan starts at lowest_free_slotid, which is a hint for the free slot,
> + * as all lower-numbered slots are known to be used.
> + * If found, we mark the slot as used, update the highest_used_slotid,
> + * and respectively set up the sequence operation args.
> + * The lowest_free_slotid is always set to the successive slotid.
> + * A pointer to the slot's seqid is returned if found, or NULL otherwise.
> + */
> +static struct nfs4_slot *
> +nfs4_find_slot(struct nfs4_slot_table *tbl, struct rpc_task *task)
> +{
> + int bit, slotid;
> + struct nfs4_slot *slot = NULL;
> + unsigned long *used, u;
> +
> + spin_lock(&tbl->slot_tbl_lock);
> + slotid = tbl->lowest_free_slotid;
> + while (slotid < tbl->max_slots) {
> + used = idx2bmp(tbl->used_slots, slotid, NULL);
> + u = *used;
> + if (u == ~0UL) {
> + /* all slots marked used in this word */
> + slotid += BITS_PER_LONG;
> + continue;
> + }
> + /* find first slot marked free in word */
> + bit = ffz(u);
review 11-14: look into using a bitmap_find_free_region function
> + slotid = bmp2idx(tbl->used_slots, used, bit);
> + /* mark slot used. note that we don't do that if
> + * slotid >= tbl->max_slots so not to confuse
> + * highest_used_slotid algorithm */
> + if (slotid < tbl->max_slots) {
> + *used |= (1 << bit);
> + if (slotid > tbl->highest_used_slotid)
> + tbl->highest_used_slotid = slotid;
> + slot = tbl->slots + slotid;
> + slotid++; /* for updating lowest_free_slot */
> + }
> + break;
> + }
> + tbl->lowest_free_slotid = slotid;
> + spin_unlock(&tbl->slot_tbl_lock);
> + dprintk("<-- %s slot %p slotid %d\n", __func__,
> + slot, slot ? slot_idx(tbl, slot) : -1);
> + return slot;
> +}
> +
> +#endif /* CONFIG_NFS_V4_1 */
> +
> static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo)
> {
> struct nfs_inode *nfsi = NFS_I(dir);
> diff --git a/include/linux/nfs4_session.h b/include/linux/nfs4_session.h
> index d534269..2960ba9 100644
> --- a/include/linux/nfs4_session.h
> +++ b/include/linux/nfs4_session.h
> @@ -33,6 +33,11 @@ struct nfs4_slot_table {
> * op for dynamic resizing */
> };
>
> +static inline int slot_idx(struct nfs4_slot_table *tbl, struct nfs4_slot *sp)
> +{
> + return sp - tbl->slots;
> +}
> +
> struct nfs4_channel {
> struct nfs4_channel_attrs chan_attrs;
> struct rpc_clnt *rpc_client;
^ permalink raw reply [flat|nested] 115+ messages in thread
* [RFC 22/85] nfs41: free slot
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (18 preceding siblings ...)
2008-11-10 20:21 ` [RFC 21/85] nfs41: find slot Benny Halevy
@ 2008-11-10 20:21 ` Benny Halevy
2008-11-17 13:47 ` [pnfs] " Benny Halevy
2008-11-10 20:21 ` [RFC 23/85] nfs41: minorversion support for xdr Benny Halevy
` (65 subsequent siblings)
85 siblings, 1 reply; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:21 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
Free a slot in the slot table.
Mark the slot as free in the bitmap-based allocation table
by clearing a bit corresponding to the slotid.
Update lowest_free_slotid if freed slotid is lower than that.
Update highest_used_slotid. In the case the freed slotid
equals the highest_used_slotid, scan downwards for the next
highest used slotid using the optimized fls* functions.
Finally, wake up thread waiting on slot_tbl_waitq for a free slot
to become available.
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/nfs4proc.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 54 insertions(+), 0 deletions(-)
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 4ded3a5..d26f61d 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -243,6 +243,60 @@ static inline int bmp2idx(unsigned long *base, unsigned long *bmp,
}
/*
+ * nfs4_find_slot - free a slot and efficiently update slot table.
+ *
+ * freeing a slot is trivially done by clearing its respective bit
+ * in the bitmap.
+ * The lowest_free_slotid is updated if the freed slotid is lower than that.
+ * If the freed slotid equals highest_used_slotid we want to update it
+ * so that the server would be able to size down the slot table if needed,
+ * otherwise we know that the highest_used_slotid is still in use.
+ * When updating highest_used_slotid there may be "holes" in the bitmap
+ * so we need to scan down from highest_used_slotid to 0 looking for the now
+ * highest slotid in use.
+ * We use the fls cpu-optimized function to look for the last set bit in each
+ * word in the bitmap.
+ * If none found, highest_used_slotid is set to -1.
+ */
+static void
+nfs41_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *slot)
+{
+ int slotid = slot_idx(tbl, slot);
+ unsigned long *used, u;
+ int bit;
+
+ spin_lock(&tbl->slot_tbl_lock);
+ /* clear used bit in bitmap */
+ used = idx2bmp(tbl->used_slots, slotid, &bit);
+ *used &= ~(1 << bit);
+
+ if (slotid < tbl->lowest_free_slotid)
+ tbl->lowest_free_slotid = slotid;
+
+ /* update highest_used_slotid when it is freed */
+ if (slotid == tbl->highest_used_slotid) {
+ tbl->highest_used_slotid = -1;
+ slotid--;
+ /* scan down for the highest used slotid */
+ while (slotid >= 0) {
+ used = idx2bmp(tbl->used_slots, slotid, NULL);
+ u = *used;
+ if (!u) {
+ /* all slots marked free in this word */
+ slotid -= BITS_PER_LONG;
+ continue;
+ }
+ bit = __fls(u);
+ tbl->highest_used_slotid = bmp2idx(tbl->used_slots,
+ used, bit);
+ break;
+ }
+ }
+ spin_unlock(&tbl->slot_tbl_lock);
+ rpc_wake_up_next(&tbl->slot_tbl_waitq);
+}
+
+/*
* nfs4_find_slot - efficiently look for a free slot
*
* nfs4_find_slot uses the ffz cpu-optimized function to look for an unset
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* Re: [pnfs] [RFC 22/85] nfs41: free slot
2008-11-10 20:21 ` [RFC 22/85] nfs41: free slot Benny Halevy
@ 2008-11-17 13:47 ` Benny Halevy
0 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-17 13:47 UTC (permalink / raw)
To: pnfs; +Cc: trond.myklebust, linux-nfs
On Nov. 10, 2008, 22:21 +0200, Benny Halevy <bhalevy@panasas.com> wrote:
> Free a slot in the slot table.
>
> Mark the slot as free in the bitmap-based allocation table
> by clearing a bit corresponding to the slotid.
>
> Update lowest_free_slotid if freed slotid is lower than that.
> Update highest_used_slotid. In the case the freed slotid
> equals the highest_used_slotid, scan downwards for the next
> highest used slotid using the optimized fls* functions.
>
> Finally, wake up thread waiting on slot_tbl_waitq for a free slot
> to become available.
>
> Signed-off-by: Benny Halevy <bhalevy@panasas.com>
> ---
> fs/nfs/nfs4proc.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 files changed, 54 insertions(+), 0 deletions(-)
>
> diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
> index 4ded3a5..d26f61d 100644
> --- a/fs/nfs/nfs4proc.c
> +++ b/fs/nfs/nfs4proc.c
> @@ -243,6 +243,60 @@ static inline int bmp2idx(unsigned long *base, unsigned long *bmp,
> }
>
> /*
> + * nfs4_find_slot - free a slot and efficiently update slot table.
> + *
> + * freeing a slot is trivially done by clearing its respective bit
> + * in the bitmap.
> + * The lowest_free_slotid is updated if the freed slotid is lower than that.
> + * If the freed slotid equals highest_used_slotid we want to update it
> + * so that the server would be able to size down the slot table if needed,
> + * otherwise we know that the highest_used_slotid is still in use.
> + * When updating highest_used_slotid there may be "holes" in the bitmap
> + * so we need to scan down from highest_used_slotid to 0 looking for the now
> + * highest slotid in use.
> + * We use the fls cpu-optimized function to look for the last set bit in each
> + * word in the bitmap.
> + * If none found, highest_used_slotid is set to -1.
> + */
> +static void
> +nfs41_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *slot)
> +{
> + int slotid = slot_idx(tbl, slot);
> + unsigned long *used, u;
> + int bit;
> +
> + spin_lock(&tbl->slot_tbl_lock);
> + /* clear used bit in bitmap */
> + used = idx2bmp(tbl->used_slots, slotid, &bit);
> + *used &= ~(1 << bit);
> +
> + if (slotid < tbl->lowest_free_slotid)
> + tbl->lowest_free_slotid = slotid;
> +
> + /* update highest_used_slotid when it is freed */
> + if (slotid == tbl->highest_used_slotid) {
> + tbl->highest_used_slotid = -1;
> + slotid--;
> + /* scan down for the highest used slotid */
> + while (slotid >= 0) {
> + used = idx2bmp(tbl->used_slots, slotid, NULL);
review 11-14: look into using a bitmap_ function, add one if needed
> + u = *used;
> + if (!u) {
> + /* all slots marked free in this word */
> + slotid -= BITS_PER_LONG;
> + continue;
> + }
> + bit = __fls(u);
> + tbl->highest_used_slotid = bmp2idx(tbl->used_slots,
> + used, bit);
> + break;
> + }
> + }
> + spin_unlock(&tbl->slot_tbl_lock);
> + rpc_wake_up_next(&tbl->slot_tbl_waitq);
> +}
> +
> +/*
> * nfs4_find_slot - efficiently look for a free slot
> *
> * nfs4_find_slot uses the ffz cpu-optimized function to look for an unset
^ permalink raw reply [flat|nested] 115+ messages in thread
* [RFC 23/85] nfs41: minorversion support for xdr
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (19 preceding siblings ...)
2008-11-10 20:21 ` [RFC 22/85] nfs41: free slot Benny Halevy
@ 2008-11-10 20:21 ` Benny Halevy
2008-11-17 13:48 ` [pnfs] " Benny Halevy
2008-11-10 20:22 ` [RFC 24/85] nfs41: stubs for nfs41 procedures Benny Halevy
` (64 subsequent siblings)
85 siblings, 1 reply; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:21 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
From: Andy Adamson <andros@netapp.com>
Add the minorversion to struct rpc_version and struct rpc_clnt, and struct
compound_hdr. Switch on the minorversion to perfom NFSv4.0 vrs NFSv4.1
encoding,
Add the nfsv41 encode and decode sizes. Add encode_sequence to all
nfs4_enc_* routines and decode_sequence to all nfs4_dec_* routines as required
by v41.
Signed-off-by: Andy Adamson<andros@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/nfs4xdr.c | 641 +++++++++++++++++++++++++++++++------------
include/linux/sunrpc/clnt.h | 2 +
net/sunrpc/clnt.c | 2 +
3 files changed, 471 insertions(+), 174 deletions(-)
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 30addf4..d3da7a5 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -240,43 +240,63 @@ static int nfs4_stat_to_errno(int);
(encode_getattr_maxsz)
#define decode_fs_locations_maxsz \
(0)
+
+#if defined(CONFIG_NFS_V4_1)
+#define encode_sequence_maxsz 0 /* stub */
+#define decode_sequence_maxsz 0 /* stub */
+#else /* CONFIG_NFS_V4_1 */
+#define encode_sequence_maxsz 0
+#define decode_sequence_maxsz 0
+#endif /* CONFIG_NFS_V4_1 */
+
#define NFS4_enc_compound_sz (1024) /* XXX: large enough? */
#define NFS4_dec_compound_sz (1024) /* XXX: large enough? */
#define NFS4_enc_read_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_read_maxsz)
#define NFS4_dec_read_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_read_maxsz)
#define NFS4_enc_readlink_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_readlink_maxsz)
#define NFS4_dec_readlink_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_readlink_maxsz)
#define NFS4_enc_readdir_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_readdir_maxsz)
#define NFS4_dec_readdir_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_readdir_maxsz)
#define NFS4_enc_write_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_write_maxsz + \
encode_getattr_maxsz)
#define NFS4_dec_write_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_write_maxsz + \
decode_getattr_maxsz)
#define NFS4_enc_commit_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_commit_maxsz + \
encode_getattr_maxsz)
#define NFS4_dec_commit_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_commit_maxsz + \
decode_getattr_maxsz)
-#define NFS4_enc_open_sz (compound_encode_hdr_maxsz + \
+#define NFS4_enc_open_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_savefh_maxsz + \
encode_open_maxsz + \
@@ -284,7 +304,8 @@ static int nfs4_stat_to_errno(int);
encode_getattr_maxsz + \
encode_restorefh_maxsz + \
encode_getattr_maxsz)
-#define NFS4_dec_open_sz (compound_decode_hdr_maxsz + \
+#define NFS4_dec_open_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_savefh_maxsz + \
decode_open_maxsz + \
@@ -301,43 +322,53 @@ static int nfs4_stat_to_errno(int);
decode_putfh_maxsz + \
decode_open_confirm_maxsz)
#define NFS4_enc_open_noattr_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_open_maxsz + \
encode_getattr_maxsz)
#define NFS4_dec_open_noattr_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_open_maxsz + \
decode_getattr_maxsz)
#define NFS4_enc_open_downgrade_sz \
(compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_open_downgrade_maxsz + \
encode_getattr_maxsz)
#define NFS4_dec_open_downgrade_sz \
(compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_open_downgrade_maxsz + \
decode_getattr_maxsz)
#define NFS4_enc_close_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_close_maxsz + \
encode_getattr_maxsz)
#define NFS4_dec_close_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_close_maxsz + \
decode_getattr_maxsz)
#define NFS4_enc_setattr_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_setattr_maxsz + \
encode_getattr_maxsz)
#define NFS4_dec_setattr_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_setattr_maxsz + \
decode_getattr_maxsz)
#define NFS4_enc_fsinfo_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_fsinfo_maxsz)
#define NFS4_dec_fsinfo_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_fsinfo_maxsz)
#define NFS4_enc_renew_sz (compound_encode_hdr_maxsz + \
@@ -359,64 +390,81 @@ static int nfs4_stat_to_errno(int);
decode_putrootfh_maxsz + \
decode_fsinfo_maxsz)
#define NFS4_enc_lock_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_lock_maxsz)
#define NFS4_dec_lock_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_lock_maxsz)
#define NFS4_enc_lockt_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_lockt_maxsz)
#define NFS4_dec_lockt_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_lockt_maxsz)
#define NFS4_enc_locku_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_locku_maxsz)
#define NFS4_dec_locku_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_locku_maxsz)
#define NFS4_enc_access_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_access_maxsz + \
encode_getattr_maxsz)
#define NFS4_dec_access_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_access_maxsz + \
decode_getattr_maxsz)
#define NFS4_enc_getattr_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_getattr_maxsz)
#define NFS4_dec_getattr_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_getattr_maxsz)
#define NFS4_enc_lookup_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_lookup_maxsz + \
encode_getattr_maxsz + \
encode_getfh_maxsz)
#define NFS4_dec_lookup_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_lookup_maxsz + \
decode_getattr_maxsz + \
decode_getfh_maxsz)
#define NFS4_enc_lookup_root_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putrootfh_maxsz + \
encode_getattr_maxsz + \
encode_getfh_maxsz)
#define NFS4_dec_lookup_root_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putrootfh_maxsz + \
decode_getattr_maxsz + \
decode_getfh_maxsz)
#define NFS4_enc_remove_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_remove_maxsz + \
encode_getattr_maxsz)
#define NFS4_dec_remove_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
op_decode_hdr_maxsz + 5 + \
decode_getattr_maxsz)
#define NFS4_enc_rename_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_savefh_maxsz + \
encode_putfh_maxsz + \
@@ -425,6 +473,7 @@ static int nfs4_stat_to_errno(int);
encode_restorefh_maxsz + \
encode_getattr_maxsz)
#define NFS4_dec_rename_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_savefh_maxsz + \
decode_putfh_maxsz + \
@@ -433,6 +482,7 @@ static int nfs4_stat_to_errno(int);
decode_restorefh_maxsz + \
decode_getattr_maxsz)
#define NFS4_enc_link_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_savefh_maxsz + \
encode_putfh_maxsz + \
@@ -441,6 +491,7 @@ static int nfs4_stat_to_errno(int);
encode_restorefh_maxsz + \
decode_getattr_maxsz)
#define NFS4_dec_link_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_savefh_maxsz + \
decode_putfh_maxsz + \
@@ -449,16 +500,19 @@ static int nfs4_stat_to_errno(int);
decode_restorefh_maxsz + \
decode_getattr_maxsz)
#define NFS4_enc_symlink_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_symlink_maxsz + \
encode_getattr_maxsz + \
encode_getfh_maxsz)
#define NFS4_dec_symlink_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_symlink_maxsz + \
decode_getattr_maxsz + \
decode_getfh_maxsz)
#define NFS4_enc_create_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_savefh_maxsz + \
encode_create_maxsz + \
@@ -467,6 +521,7 @@ static int nfs4_stat_to_errno(int);
encode_restorefh_maxsz + \
encode_getattr_maxsz)
#define NFS4_dec_create_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_savefh_maxsz + \
decode_create_maxsz + \
@@ -475,49 +530,63 @@ static int nfs4_stat_to_errno(int);
decode_restorefh_maxsz + \
decode_getattr_maxsz)
#define NFS4_enc_pathconf_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_getattr_maxsz)
#define NFS4_dec_pathconf_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_getattr_maxsz)
#define NFS4_enc_statfs_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_statfs_maxsz)
#define NFS4_dec_statfs_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_statfs_maxsz)
#define NFS4_enc_server_caps_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_getattr_maxsz)
#define NFS4_dec_server_caps_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_getattr_maxsz)
#define NFS4_enc_delegreturn_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_delegreturn_maxsz + \
encode_getattr_maxsz)
#define NFS4_dec_delegreturn_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_delegreturn_maxsz + \
decode_getattr_maxsz)
#define NFS4_enc_getacl_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_getacl_maxsz)
#define NFS4_dec_getacl_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_getacl_maxsz)
#define NFS4_enc_setacl_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_setacl_maxsz)
#define NFS4_dec_setacl_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_setacl_maxsz)
#define NFS4_enc_fs_locations_sz \
(compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
encode_putfh_maxsz + \
encode_lookup_maxsz + \
encode_fs_locations_maxsz)
#define NFS4_dec_fs_locations_sz \
(compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_lookup_maxsz + \
decode_fs_locations_maxsz)
@@ -543,6 +612,7 @@ struct compound_hdr {
uint32_t nops;
uint32_t taglen;
char * tag;
+ u32 minorversion;
};
/*
@@ -578,7 +648,7 @@ static void encode_string(struct xdr_stream *xdr, unsigned int len, const char *
xdr_encode_opaque(p, str, len);
}
-static __u32 *
+static __be32*
encode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr)
{
__be32 *p, *nops;
@@ -588,7 +658,7 @@ encode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr)
RESERVE_SPACE(12+(XDR_QUADLEN(hdr->taglen)<<2));
WRITE32(hdr->taglen);
WRITEMEM(hdr->tag, hdr->taglen);
- WRITE32(NFS4_MINOR_VERSION);
+ WRITE32(hdr->minorversion);
nops = p;
WRITE32(hdr->nops);
return nops;
@@ -1377,7 +1447,8 @@ encode_savefh(struct xdr_stream *xdr, struct compound_hdr *hdr)
static int
encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs *arg,
- const struct nfs_server *server, struct compound_hdr *hdr)
+ const struct nfs_server *server,
+ struct compound_hdr *hdr)
{
int status;
__be32 *p;
@@ -1468,6 +1539,30 @@ encode_delegreturn(struct xdr_stream *xdr, const nfs4_stateid *stateid,
return 0;
}
+
+#if defined(CONFIG_NFS_V4_1)
+/* NFSv4.1 operations */
+static int encode_sequence(struct xdr_stream *xdr,
+ const struct nfs41_sequence_args *args,
+ struct compound_hdr *hdr)
+{
+ if (hdr->minorversion == 0)
+ return 0;
+
+ /* stub */
+ hdr->nops++;
+
+ return 0;
+}
+#else /* CONFIG_NFS_V4_1 */
+static inline int encode_sequence(struct xdr_stream *xdr,
+ const struct nfs41_sequence_args *args,
+ struct compound_hdr *hdr)
+{
+ return 0;
+}
+#endif /* CONFIG_NFS_V4_1 */
+
/*
* END OF "GENERIC" ENCODE ROUTINES.
*/
@@ -1475,17 +1570,19 @@ encode_delegreturn(struct xdr_stream *xdr, const nfs4_stateid *stateid,
/*
* Encode an ACCESS request
*/
-static int nfs4_xdr_enc_access(struct rpc_rqst *req, __be32 *p, const struct nfs4_accessargs *args)
+static int nfs4_xdr_enc_access(struct rpc_rqst *req, __be32 *p,
+ const struct nfs4_accessargs *args)
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = req->rq_task->tk_client->cl_mvers,
};
int status;
__be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
nops = encode_compound_hdr(&xdr, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
status = encode_putfh(&xdr, args->fh, &hdr);
if (status != 0)
goto out;
@@ -1501,17 +1598,19 @@ out:
/*
* Encode LOOKUP request
*/
-static int nfs4_xdr_enc_lookup(struct rpc_rqst *req, __be32 *p, const struct nfs4_lookup_arg *args)
+static int nfs4_xdr_enc_lookup(struct rpc_rqst *req, __be32 *p,
+ const struct nfs4_lookup_arg *args)
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = req->rq_task->tk_client->cl_mvers,
};
int status;
__be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
nops = encode_compound_hdr(&xdr, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
if ((status = encode_putfh(&xdr, args->dir_fh, &hdr)) != 0)
goto out;
if ((status = encode_lookup(&xdr, args->name, &hdr)) != 0)
@@ -1527,17 +1626,19 @@ out:
/*
* Encode LOOKUP_ROOT request
*/
-static int nfs4_xdr_enc_lookup_root(struct rpc_rqst *req, __be32 *p, const struct nfs4_lookup_root_arg *args)
+static int nfs4_xdr_enc_lookup_root(struct rpc_rqst *req, __be32 *p,
+ const struct nfs4_lookup_root_arg *args)
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = req->rq_task->tk_client->cl_mvers,
};
int status;
__be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
nops = encode_compound_hdr(&xdr, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
if ((status = encode_putrootfh(&xdr, &hdr)) != 0)
goto out;
if ((status = encode_getfh(&xdr, &hdr)) == 0)
@@ -1550,17 +1651,19 @@ out:
/*
* Encode REMOVE request
*/
-static int nfs4_xdr_enc_remove(struct rpc_rqst *req, __be32 *p, const struct nfs_removeargs *args)
+static int nfs4_xdr_enc_remove(struct rpc_rqst *req, __be32 *p,
+ const struct nfs_removeargs *args)
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = req->rq_task->tk_client->cl_mvers,
};
int status;
__be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
nops = encode_compound_hdr(&xdr, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
if ((status = encode_putfh(&xdr, args->fh, &hdr)) != 0)
goto out;
if ((status = encode_remove(&xdr, &args->name, &hdr)) != 0)
@@ -1574,17 +1677,19 @@ out:
/*
* Encode RENAME request
*/
-static int nfs4_xdr_enc_rename(struct rpc_rqst *req, __be32 *p, const struct nfs4_rename_arg *args)
+static int nfs4_xdr_enc_rename(struct rpc_rqst *req, __be32 *p,
+ const struct nfs4_rename_arg *args)
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = req->rq_task->tk_client->cl_mvers,
};
int status;
__be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
nops = encode_compound_hdr(&xdr, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
if ((status = encode_putfh(&xdr, args->old_dir, &hdr)) != 0)
goto out;
if ((status = encode_savefh(&xdr, &hdr)) != 0)
@@ -1607,17 +1712,19 @@ out:
/*
* Encode LINK request
*/
-static int nfs4_xdr_enc_link(struct rpc_rqst *req, __be32 *p, const struct nfs4_link_arg *args)
+static int nfs4_xdr_enc_link(struct rpc_rqst *req, __be32 *p,
+ const struct nfs4_link_arg *args)
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = req->rq_task->tk_client->cl_mvers,
};
int status;
__be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
nops = encode_compound_hdr(&xdr, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
if ((status = encode_putfh(&xdr, args->fh, &hdr)) != 0)
goto out;
if ((status = encode_savefh(&xdr, &hdr)) != 0)
@@ -1639,17 +1746,19 @@ out:
/*
* Encode CREATE request
*/
-static int nfs4_xdr_enc_create(struct rpc_rqst *req, __be32 *p, const struct nfs4_create_arg *args)
+static int nfs4_xdr_enc_create(struct rpc_rqst *req, __be32 *p,
+ const struct nfs4_create_arg *args)
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = req->rq_task->tk_client->cl_mvers,
};
int status;
__be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
nops = encode_compound_hdr(&xdr, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
if ((status = encode_putfh(&xdr, args->dir_fh, &hdr)) != 0)
goto out;
if ((status = encode_savefh(&xdr, &hdr)) != 0)
@@ -1679,17 +1788,19 @@ static int nfs4_xdr_enc_symlink(struct rpc_rqst *req, __be32 *p, const struct nf
/*
* Encode GETATTR request
*/
-static int nfs4_xdr_enc_getattr(struct rpc_rqst *req, __be32 *p, const struct nfs4_getattr_arg *args)
+static int nfs4_xdr_enc_getattr(struct rpc_rqst *req, __be32 *p,
+ const struct nfs4_getattr_arg *args)
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = req->rq_task->tk_client->cl_mvers,
};
int status;
__be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
nops = encode_compound_hdr(&xdr, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
if ((status = encode_putfh(&xdr, args->fh, &hdr)) == 0)
status = encode_getfattr(&xdr, args->bitmask, &hdr);
encode_nops(nops, &hdr);
@@ -1699,17 +1810,19 @@ static int nfs4_xdr_enc_getattr(struct rpc_rqst *req, __be32 *p, const struct nf
/*
* Encode a CLOSE request
*/
-static int nfs4_xdr_enc_close(struct rpc_rqst *req, __be32 *p, struct nfs_closeargs *args)
+static int nfs4_xdr_enc_close(struct rpc_rqst *req, __be32 *p,
+ struct nfs_closeargs *args)
{
- struct xdr_stream xdr;
- struct compound_hdr hdr = {
- .nops = 0,
- };
+ struct xdr_stream xdr;
+ struct compound_hdr hdr = {
+ .minorversion = req->rq_task->tk_client->cl_mvers,
+ };
int status;
__be32 *nops;
- xdr_init_encode(&xdr, &req->rq_snd_buf, p);
+ xdr_init_encode(&xdr, &req->rq_snd_buf, p);
nops = encode_compound_hdr(&xdr, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
status = encode_putfh(&xdr, args->fh, &hdr);
if(status)
goto out;
@@ -1725,17 +1838,19 @@ out:
/*
* Encode an OPEN request
*/
-static int nfs4_xdr_enc_open(struct rpc_rqst *req, __be32 *p, struct nfs_openargs *args)
+static int nfs4_xdr_enc_open(struct rpc_rqst *req, __be32 *p,
+ struct nfs_openargs *args)
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = req->rq_task->tk_client->cl_mvers,
};
int status;
__be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
nops = encode_compound_hdr(&xdr, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
status = encode_putfh(&xdr, args->fh, &hdr);
if (status)
goto out;
@@ -1767,7 +1882,7 @@ static int nfs4_xdr_enc_open_confirm(struct rpc_rqst *req, __be32 *p, struct nfs
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = req->rq_task->tk_client->cl_mvers,
};
int status;
__be32 *nops;
@@ -1786,17 +1901,19 @@ out:
/*
* Encode an OPEN request with no attributes.
*/
-static int nfs4_xdr_enc_open_noattr(struct rpc_rqst *req, __be32 *p, struct nfs_openargs *args)
+static int nfs4_xdr_enc_open_noattr(struct rpc_rqst *req, __be32 *p,
+ struct nfs_openargs *args)
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = req->rq_task->tk_client->cl_mvers,
};
int status;
__be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
nops = encode_compound_hdr(&xdr, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
status = encode_putfh(&xdr, args->fh, &hdr);
if (status)
goto out;
@@ -1812,17 +1929,19 @@ out:
/*
* Encode an OPEN_DOWNGRADE request
*/
-static int nfs4_xdr_enc_open_downgrade(struct rpc_rqst *req, __be32 *p, struct nfs_closeargs *args)
+static int nfs4_xdr_enc_open_downgrade(struct rpc_rqst *req, __be32 *p,
+ struct nfs_closeargs *args)
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = req->rq_task->tk_client->cl_mvers,
};
int status;
__be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
nops = encode_compound_hdr(&xdr, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
status = encode_putfh(&xdr, args->fh, &hdr);
if (status)
goto out;
@@ -1838,17 +1957,19 @@ out:
/*
* Encode a LOCK request
*/
-static int nfs4_xdr_enc_lock(struct rpc_rqst *req, __be32 *p, struct nfs_lock_args *args)
+static int nfs4_xdr_enc_lock(struct rpc_rqst *req, __be32 *p,
+ struct nfs_lock_args *args)
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = req->rq_task->tk_client->cl_mvers,
};
int status;
__be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
nops = encode_compound_hdr(&xdr, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
status = encode_putfh(&xdr, args->fh, &hdr);
if(status)
goto out;
@@ -1861,17 +1982,19 @@ out:
/*
* Encode a LOCKT request
*/
-static int nfs4_xdr_enc_lockt(struct rpc_rqst *req, __be32 *p, struct nfs_lockt_args *args)
+static int nfs4_xdr_enc_lockt(struct rpc_rqst *req, __be32 *p,
+ struct nfs_lockt_args *args)
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = req->rq_task->tk_client->cl_mvers,
};
int status;
__be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
nops = encode_compound_hdr(&xdr, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
status = encode_putfh(&xdr, args->fh, &hdr);
if(status)
goto out;
@@ -1884,17 +2007,19 @@ out:
/*
* Encode a LOCKU request
*/
-static int nfs4_xdr_enc_locku(struct rpc_rqst *req, __be32 *p, struct nfs_locku_args *args)
+static int nfs4_xdr_enc_locku(struct rpc_rqst *req, __be32 *p,
+ struct nfs_locku_args *args)
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = req->rq_task->tk_client->cl_mvers,
};
int status;
__be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
nops = encode_compound_hdr(&xdr, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
status = encode_putfh(&xdr, args->fh, &hdr);
if(status)
goto out;
@@ -1907,11 +2032,12 @@ out:
/*
* Encode a READLINK request
*/
-static int nfs4_xdr_enc_readlink(struct rpc_rqst *req, __be32 *p, const struct nfs4_readlink *args)
+static int nfs4_xdr_enc_readlink(struct rpc_rqst *req, __be32 *p,
+ const struct nfs4_readlink *args)
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = req->rq_task->tk_client->cl_mvers,
};
struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
unsigned int replen;
@@ -1920,6 +2046,7 @@ static int nfs4_xdr_enc_readlink(struct rpc_rqst *req, __be32 *p, const struct n
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
nops = encode_compound_hdr(&xdr, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
status = encode_putfh(&xdr, args->fh, &hdr);
if(status)
goto out;
@@ -1941,11 +2068,12 @@ out:
/*
* Encode a READDIR request
*/
-static int nfs4_xdr_enc_readdir(struct rpc_rqst *req, __be32 *p, const struct nfs4_readdir_arg *args)
+static int nfs4_xdr_enc_readdir(struct rpc_rqst *req, __be32 *p,
+ const struct nfs4_readdir_arg *args)
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = req->rq_task->tk_client->cl_mvers,
};
struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
int replen;
@@ -1954,6 +2082,7 @@ static int nfs4_xdr_enc_readdir(struct rpc_rqst *req, __be32 *p, const struct nf
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
nops = encode_compound_hdr(&xdr, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
status = encode_putfh(&xdr, args->fh, &hdr);
if(status)
goto out;
@@ -1978,18 +2107,20 @@ out:
/*
* Encode a READ request
*/
-static int nfs4_xdr_enc_read(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args)
+static int nfs4_xdr_enc_read(struct rpc_rqst *req, __be32 *p,
+ struct nfs_readargs *args)
{
struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = req->rq_task->tk_client->cl_mvers,
};
int replen, status;
__be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
nops = encode_compound_hdr(&xdr, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
status = encode_putfh(&xdr, args->fh, &hdr);
if (status)
goto out;
@@ -2013,18 +2144,20 @@ out:
/*
* Encode an SETATTR request
*/
-static int nfs4_xdr_enc_setattr(struct rpc_rqst *req, __be32 *p, struct nfs_setattrargs *args)
+static int nfs4_xdr_enc_setattr(struct rpc_rqst *req, __be32 *p,
+ struct nfs_setattrargs *args)
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = req->rq_task->tk_client->cl_mvers,
};
int status;
__be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
nops = encode_compound_hdr(&xdr, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
status = encode_putfh(&xdr, args->fh, &hdr);
if (status)
goto out;
@@ -2042,18 +2175,19 @@ out:
*/
static int
nfs4_xdr_enc_getacl(struct rpc_rqst *req, __be32 *p,
- struct nfs_getaclargs *args)
+ struct nfs_getaclargs *args)
{
struct xdr_stream xdr;
struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = req->rq_task->tk_client->cl_mvers,
};
int replen, status;
__be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
nops = encode_compound_hdr(&xdr, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
status = encode_putfh(&xdr, args->fh, &hdr);
if (status)
goto out;
@@ -2070,24 +2204,25 @@ out:
/*
* Encode a WRITE request
*/
-static int nfs4_xdr_enc_write(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args)
+static int nfs4_xdr_enc_write(struct rpc_rqst *req, __be32 *p,
+ struct nfs_writeargs *args)
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = req->rq_task->tk_client->cl_mvers,
};
int status;
__be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
nops = encode_compound_hdr(&xdr, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
status = encode_putfh(&xdr, args->fh, &hdr);
if (status)
goto out;
status = encode_write(&xdr, args, &hdr);
if (status)
goto out;
- req->rq_snd_buf.flags |= XDRBUF_WRITE;
status = encode_getfattr(&xdr, args->bitmask, &hdr);
out:
encode_nops(nops, &hdr);
@@ -2097,17 +2232,19 @@ out:
/*
* a COMMIT request
*/
-static int nfs4_xdr_enc_commit(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args)
+static int nfs4_xdr_enc_commit(struct rpc_rqst *req, __be32 *p,
+ struct nfs_writeargs *args)
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = req->rq_task->tk_client->cl_mvers,
};
int status;
__be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
nops = encode_compound_hdr(&xdr, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
status = encode_putfh(&xdr, args->fh, &hdr);
if (status)
goto out;
@@ -2123,17 +2260,19 @@ out:
/*
* FSINFO request
*/
-static int nfs4_xdr_enc_fsinfo(struct rpc_rqst *req, __be32 *p, struct nfs4_fsinfo_arg *args)
+static int nfs4_xdr_enc_fsinfo(struct rpc_rqst *req, __be32 *p,
+ struct nfs4_fsinfo_arg *args)
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = req->rq_task->tk_client->cl_mvers,
};
int status;
__be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
nops = encode_compound_hdr(&xdr, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
status = encode_putfh(&xdr, args->fh, &hdr);
if (!status)
status = encode_fsinfo(&xdr, args->bitmask, &hdr);
@@ -2144,17 +2283,19 @@ static int nfs4_xdr_enc_fsinfo(struct rpc_rqst *req, __be32 *p, struct nfs4_fsin
/*
* a PATHCONF request
*/
-static int nfs4_xdr_enc_pathconf(struct rpc_rqst *req, __be32 *p, const struct nfs4_pathconf_arg *args)
+static int nfs4_xdr_enc_pathconf(struct rpc_rqst *req, __be32 *p,
+ const struct nfs4_pathconf_arg *args)
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = req->rq_task->tk_client->cl_mvers,
};
int status;
__be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
nops = encode_compound_hdr(&xdr, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
status = encode_putfh(&xdr, args->fh, &hdr);
if (!status)
status = encode_getattr_one(&xdr,
@@ -2167,22 +2308,25 @@ static int nfs4_xdr_enc_pathconf(struct rpc_rqst *req, __be32 *p, const struct n
/*
* a STATFS request
*/
-static int nfs4_xdr_enc_statfs(struct rpc_rqst *req, __be32 *p, const struct nfs4_statfs_arg *args)
+static int nfs4_xdr_enc_statfs(struct rpc_rqst *req, __be32 *p,
+ const struct nfs4_statfs_arg *args)
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = req->rq_task->tk_client->cl_mvers,
};
int status;
__be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
nops = encode_compound_hdr(&xdr, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
status = encode_putfh(&xdr, args->fh, &hdr);
if (status == 0)
status = encode_getattr_two(&xdr,
args->bitmask[0] & nfs4_statfs_bitmap[0],
- args->bitmask[1] & nfs4_statfs_bitmap[1], &hdr);
+ args->bitmask[1] & nfs4_statfs_bitmap[1],
+ &hdr);
encode_nops(nops, &hdr);
return status;
}
@@ -2190,18 +2334,20 @@ static int nfs4_xdr_enc_statfs(struct rpc_rqst *req, __be32 *p, const struct nfs
/*
* GETATTR_BITMAP request
*/
-static int nfs4_xdr_enc_server_caps(struct rpc_rqst *req, __be32 *p, const struct nfs_fh *fhandle)
+static int nfs4_xdr_enc_server_caps(struct rpc_rqst *req, __be32 *p,
+ struct nfs4_server_caps_arg *args)
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = req->rq_task->tk_client->cl_mvers,
};
int status;
__be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
nops = encode_compound_hdr(&xdr, &hdr);
- status = encode_putfh(&xdr, fhandle, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
+ status = encode_putfh(&xdr, args->fhandle, &hdr);
if (status == 0)
status = encode_getattr_one(&xdr, FATTR4_WORD0_SUPPORTED_ATTRS|
FATTR4_WORD0_LINK_SUPPORT|
@@ -2218,7 +2364,7 @@ static int nfs4_xdr_enc_renew(struct rpc_rqst *req, __be32 *p, struct nfs_client
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = req->rq_task->tk_client->cl_mvers,
};
int status;
__be32 *nops;
@@ -2226,6 +2372,7 @@ static int nfs4_xdr_enc_renew(struct rpc_rqst *req, __be32 *p, struct nfs_client
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
nops = encode_compound_hdr(&xdr, &hdr);
status = encode_renew(&xdr, clp, &hdr);
+
encode_nops(nops, &hdr);
return status;
}
@@ -2237,7 +2384,7 @@ static int nfs4_xdr_enc_setclientid(struct rpc_rqst *req, __be32 *p, struct nfs4
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = req->rq_task->tk_client->cl_mvers,
};
int status;
__be32 *nops;
@@ -2245,6 +2392,7 @@ static int nfs4_xdr_enc_setclientid(struct rpc_rqst *req, __be32 *p, struct nfs4
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
nops = encode_compound_hdr(&xdr, &hdr);
status = encode_setclientid(&xdr, sc, &hdr);
+
encode_nops(nops, &hdr);
return status;
}
@@ -2256,7 +2404,7 @@ static int nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, __be32 *p, str
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = req->rq_task->tk_client->cl_mvers,
};
const u32 lease_bitmap[2] = { FATTR4_WORD0_LEASE_TIME, 0 };
int status;
@@ -2276,17 +2424,19 @@ static int nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, __be32 *p, str
/*
* DELEGRETURN request
*/
-static int nfs4_xdr_enc_delegreturn(struct rpc_rqst *req, __be32 *p, const struct nfs4_delegreturnargs *args)
+static int nfs4_xdr_enc_delegreturn(struct rpc_rqst *req, __be32 *p,
+ const struct nfs4_delegreturnargs *args)
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = req->rq_task->tk_client->cl_mvers,
};
int status;
__be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
nops = encode_compound_hdr(&xdr, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
status = encode_putfh(&xdr, args->fhandle, &hdr);
if (status != 0)
goto out;
@@ -2302,11 +2452,12 @@ out:
/*
* Encode FS_LOCATIONS request
*/
-static int nfs4_xdr_enc_fs_locations(struct rpc_rqst *req, __be32 *p, struct nfs4_fs_locations_arg *args)
+static int nfs4_xdr_enc_fs_locations(struct rpc_rqst *req, __be32 *p,
+ struct nfs4_fs_locations_arg *args)
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = req->rq_task->tk_client->cl_mvers,
};
struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
int replen;
@@ -2315,6 +2466,7 @@ static int nfs4_xdr_enc_fs_locations(struct rpc_rqst *req, __be32 *p, struct nfs
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
nops = encode_compound_hdr(&xdr, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
if ((status = encode_putfh(&xdr, args->dir_fh, &hdr)) != 0)
goto out;
if ((status = encode_lookup(&xdr, args->name, &hdr)) != 0)
@@ -2325,7 +2477,7 @@ static int nfs4_xdr_enc_fs_locations(struct rpc_rqst *req, __be32 *p, struct nfs
* toplevel_status + OP_PUTFH + status
* + OP_LOOKUP + status + OP_GETATTR + status = 7
*/
- replen = (RPC_REPHDRSIZE + auth->au_rslack + 7) << 2;
+ replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS4_enc_fsinfo_sz) << 2;
xdr_inline_pages(&req->rq_rcv_buf, replen, &args->page,
0, PAGE_SIZE);
out:
@@ -3963,19 +4115,48 @@ static int decode_delegreturn(struct xdr_stream *xdr)
return decode_op_hdr(xdr, OP_DELEGRETURN);
}
+#if defined(CONFIG_NFS_V4_1)
+static int decode_sequence(struct xdr_stream *xdr,
+ struct nfs41_sequence_res *res,
+ struct rpc_rqst *rqstp)
+{
+ if (rqstp->rq_task->tk_client->cl_mvers == 0)
+ return 0;
+
+ /* stub */
+
+ return 0;
+}
+#else /* CONFIG_NFS_V4_1 */
+static inline int decode_sequence(struct xdr_stream *xdr,
+ struct nfs41_sequence_res *res,
+ struct rpc_rqst *rqstp)
+{
+ return 0;
+}
+#endif /* CONFIG_NFS_V4_1 */
+
+/*
+ * END OF "GENERIC" DECODE ROUTINES.
+ */
+
/*
* Decode OPEN_DOWNGRADE response
*/
-static int nfs4_xdr_dec_open_downgrade(struct rpc_rqst *rqstp, __be32 *p, struct nfs_closeres *res)
+static int nfs4_xdr_dec_open_downgrade(struct rpc_rqst *rqstp, __be32 *p,
+ struct nfs_closeres *res)
{
- struct xdr_stream xdr;
- struct compound_hdr hdr;
- int status;
+ struct xdr_stream xdr;
+ struct compound_hdr hdr;
+ int status;
- xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
- status = decode_compound_hdr(&xdr, &hdr);
- if (status)
- goto out;
+ xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
+ status = decode_compound_hdr(&xdr, &hdr);
+ if (status)
+ goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
+ goto out;
status = decode_putfh(&xdr);
if (status)
goto out;
@@ -3988,20 +4169,21 @@ out:
}
/*
- * END OF "GENERIC" DECODE ROUTINES.
- */
-
-/*
* Decode ACCESS response
*/
-static int nfs4_xdr_dec_access(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_accessres *res)
+static int nfs4_xdr_dec_access(struct rpc_rqst *rqstp, __be32 *p,
+ struct nfs4_accessres *res)
{
struct xdr_stream xdr;
struct compound_hdr hdr;
int status;
xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
- if ((status = decode_compound_hdr(&xdr, &hdr)) != 0)
+ status = decode_compound_hdr(&xdr, &hdr);
+ if (status)
+ goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
goto out;
status = decode_putfh(&xdr);
if (status != 0)
@@ -4017,14 +4199,19 @@ out:
/*
* Decode LOOKUP response
*/
-static int nfs4_xdr_dec_lookup(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_lookup_res *res)
+static int nfs4_xdr_dec_lookup(struct rpc_rqst *rqstp, __be32 *p,
+ struct nfs4_lookup_res *res)
{
struct xdr_stream xdr;
struct compound_hdr hdr;
int status;
xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
- if ((status = decode_compound_hdr(&xdr, &hdr)) != 0)
+ status = decode_compound_hdr(&xdr, &hdr);
+ if (status)
+ goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
goto out;
if ((status = decode_putfh(&xdr)) != 0)
goto out;
@@ -4040,14 +4227,19 @@ out:
/*
* Decode LOOKUP_ROOT response
*/
-static int nfs4_xdr_dec_lookup_root(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_lookup_res *res)
+static int nfs4_xdr_dec_lookup_root(struct rpc_rqst *rqstp, __be32 *p,
+ struct nfs4_lookup_res *res)
{
struct xdr_stream xdr;
struct compound_hdr hdr;
int status;
xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
- if ((status = decode_compound_hdr(&xdr, &hdr)) != 0)
+ status = decode_compound_hdr(&xdr, &hdr);
+ if (status)
+ goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
goto out;
if ((status = decode_putrootfh(&xdr)) != 0)
goto out;
@@ -4060,14 +4252,19 @@ out:
/*
* Decode REMOVE response
*/
-static int nfs4_xdr_dec_remove(struct rpc_rqst *rqstp, __be32 *p, struct nfs_removeres *res)
+static int nfs4_xdr_dec_remove(struct rpc_rqst *rqstp, __be32 *p,
+ struct nfs_removeres *res)
{
struct xdr_stream xdr;
struct compound_hdr hdr;
int status;
xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
- if ((status = decode_compound_hdr(&xdr, &hdr)) != 0)
+ status = decode_compound_hdr(&xdr, &hdr);
+ if (status)
+ goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
goto out;
if ((status = decode_putfh(&xdr)) != 0)
goto out;
@@ -4081,14 +4278,19 @@ out:
/*
* Decode RENAME response
*/
-static int nfs4_xdr_dec_rename(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_rename_res *res)
+static int nfs4_xdr_dec_rename(struct rpc_rqst *rqstp, __be32 *p,
+ struct nfs4_rename_res *res)
{
struct xdr_stream xdr;
struct compound_hdr hdr;
int status;
-
+
xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
- if ((status = decode_compound_hdr(&xdr, &hdr)) != 0)
+ status = decode_compound_hdr(&xdr, &hdr);
+ if (status)
+ goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
goto out;
if ((status = decode_putfh(&xdr)) != 0)
goto out;
@@ -4111,14 +4313,19 @@ out:
/*
* Decode LINK response
*/
-static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_link_res *res)
+static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, __be32 *p,
+ struct nfs4_link_res *res)
{
struct xdr_stream xdr;
struct compound_hdr hdr;
int status;
xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
- if ((status = decode_compound_hdr(&xdr, &hdr)) != 0)
+ status = decode_compound_hdr(&xdr, &hdr);
+ if (status)
+ goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
goto out;
if ((status = decode_putfh(&xdr)) != 0)
goto out;
@@ -4144,14 +4351,19 @@ out:
/*
* Decode CREATE response
*/
-static int nfs4_xdr_dec_create(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_create_res *res)
+static int nfs4_xdr_dec_create(struct rpc_rqst *rqstp, __be32 *p,
+ struct nfs4_create_res *res)
{
struct xdr_stream xdr;
struct compound_hdr hdr;
int status;
-
+
xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
- if ((status = decode_compound_hdr(&xdr, &hdr)) != 0)
+ status = decode_compound_hdr(&xdr, &hdr);
+ if (status)
+ goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
goto out;
if ((status = decode_putfh(&xdr)) != 0)
goto out;
@@ -4181,7 +4393,8 @@ static int nfs4_xdr_dec_symlink(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_c
/*
* Decode GETATTR response
*/
-static int nfs4_xdr_dec_getattr(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_getattr_res *res)
+static int nfs4_xdr_dec_getattr(struct rpc_rqst *rqstp, __be32 *p,
+ struct nfs4_getattr_res *res)
{
struct xdr_stream xdr;
struct compound_hdr hdr;
@@ -4191,56 +4404,65 @@ static int nfs4_xdr_dec_getattr(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_g
status = decode_compound_hdr(&xdr, &hdr);
if (status)
goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
+ goto out;
status = decode_putfh(&xdr);
if (status)
goto out;
status = decode_getfattr(&xdr, res->fattr, res->server);
out:
return status;
-
}
/*
* Encode an SETACL request
*/
static int
-nfs4_xdr_enc_setacl(struct rpc_rqst *req, __be32 *p, struct nfs_setaclargs *args)
+nfs4_xdr_enc_setacl(struct rpc_rqst *req, __be32 *p,
+ struct nfs_setaclargs *args)
{
struct xdr_stream xdr;
struct compound_hdr hdr = {
- .nops = 0,
+ .minorversion = req->rq_task->tk_client->cl_mvers,
};
int status;
__be32 *nops;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
nops = encode_compound_hdr(&xdr, &hdr);
+ encode_sequence(&xdr, &args->seq_args, &hdr);
status = encode_putfh(&xdr, args->fh, &hdr);
if (status)
goto out;
status = encode_setacl(&xdr, args, &hdr);
out:
- encode_nops(nops, &hdr);
return status;
}
+
/*
* Decode SETACL response
*/
static int
-nfs4_xdr_dec_setacl(struct rpc_rqst *rqstp, __be32 *p, void *res)
+nfs4_xdr_dec_setacl(struct rpc_rqst *rqstp, __be32 *p,
+ struct nfs_setaclres *res)
{
struct xdr_stream xdr;
struct compound_hdr hdr;
+ struct nfs_setattrres *sattrp = NULL;
int status;
xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
status = decode_compound_hdr(&xdr, &hdr);
if (status)
goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
+ goto out;
status = decode_putfh(&xdr);
if (status)
goto out;
- status = decode_setattr(&xdr, res);
+ status = decode_setattr(&xdr, sattrp);
out:
return status;
}
@@ -4249,7 +4471,8 @@ out:
* Decode GETACL response
*/
static int
-nfs4_xdr_dec_getacl(struct rpc_rqst *rqstp, __be32 *p, size_t *acl_len)
+nfs4_xdr_dec_getacl(struct rpc_rqst *rqstp, __be32 *p,
+ struct nfs_getaclres *res)
{
struct xdr_stream xdr;
struct compound_hdr hdr;
@@ -4259,10 +4482,13 @@ nfs4_xdr_dec_getacl(struct rpc_rqst *rqstp, __be32 *p, size_t *acl_len)
status = decode_compound_hdr(&xdr, &hdr);
if (status)
goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
+ goto out;
status = decode_putfh(&xdr);
if (status)
goto out;
- status = decode_getacl(&xdr, rqstp, acl_len);
+ status = decode_getacl(&xdr, rqstp, res->acl_len);
out:
return status;
@@ -4271,16 +4497,20 @@ out:
/*
* Decode CLOSE response
*/
-static int nfs4_xdr_dec_close(struct rpc_rqst *rqstp, __be32 *p, struct nfs_closeres *res)
+static int nfs4_xdr_dec_close(struct rpc_rqst *rqstp, __be32 *p,
+ struct nfs_closeres *res)
{
- struct xdr_stream xdr;
- struct compound_hdr hdr;
- int status;
+ struct xdr_stream xdr;
+ struct compound_hdr hdr;
+ int status;
- xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
- status = decode_compound_hdr(&xdr, &hdr);
- if (status)
- goto out;
+ xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
+ status = decode_compound_hdr(&xdr, &hdr);
+ if (status)
+ goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
+ goto out;
status = decode_putfh(&xdr);
if (status)
goto out;
@@ -4301,16 +4531,20 @@ out:
/*
* Decode OPEN response
*/
-static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, __be32 *p, struct nfs_openres *res)
+static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, __be32 *p,
+ struct nfs_openres *res)
{
- struct xdr_stream xdr;
- struct compound_hdr hdr;
- int status;
+ struct xdr_stream xdr;
+ struct compound_hdr hdr;
+ int status;
- xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
- status = decode_compound_hdr(&xdr, &hdr);
- if (status)
- goto out;
+ xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
+ status = decode_compound_hdr(&xdr, &hdr);
+ if (status)
+ goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
+ goto out;
status = decode_putfh(&xdr);
if (status)
goto out;
@@ -4355,16 +4589,20 @@ out:
/*
* Decode OPEN response
*/
-static int nfs4_xdr_dec_open_noattr(struct rpc_rqst *rqstp, __be32 *p, struct nfs_openres *res)
+static int nfs4_xdr_dec_open_noattr(struct rpc_rqst *rqstp, __be32 *p,
+ struct nfs_openres *res)
{
- struct xdr_stream xdr;
- struct compound_hdr hdr;
- int status;
+ struct xdr_stream xdr;
+ struct compound_hdr hdr;
+ int status;
- xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
- status = decode_compound_hdr(&xdr, &hdr);
- if (status)
- goto out;
+ xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
+ status = decode_compound_hdr(&xdr, &hdr);
+ if (status)
+ goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
+ goto out;
status = decode_putfh(&xdr);
if (status)
goto out;
@@ -4379,16 +4617,20 @@ out:
/*
* Decode SETATTR response
*/
-static int nfs4_xdr_dec_setattr(struct rpc_rqst *rqstp, __be32 *p, struct nfs_setattrres *res)
+static int nfs4_xdr_dec_setattr(struct rpc_rqst *rqstp, __be32 *p,
+ struct nfs_setattrres *res)
{
- struct xdr_stream xdr;
- struct compound_hdr hdr;
- int status;
+ struct xdr_stream xdr;
+ struct compound_hdr hdr;
+ int status;
- xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
- status = decode_compound_hdr(&xdr, &hdr);
- if (status)
- goto out;
+ xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
+ status = decode_compound_hdr(&xdr, &hdr);
+ if (status)
+ goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
+ goto out;
status = decode_putfh(&xdr);
if (status)
goto out;
@@ -4405,7 +4647,8 @@ out:
/*
* Decode LOCK response
*/
-static int nfs4_xdr_dec_lock(struct rpc_rqst *rqstp, __be32 *p, struct nfs_lock_res *res)
+static int nfs4_xdr_dec_lock(struct rpc_rqst *rqstp, __be32 *p,
+ struct nfs_lock_res *res)
{
struct xdr_stream xdr;
struct compound_hdr hdr;
@@ -4415,6 +4658,9 @@ static int nfs4_xdr_dec_lock(struct rpc_rqst *rqstp, __be32 *p, struct nfs_lock_
status = decode_compound_hdr(&xdr, &hdr);
if (status)
goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
+ goto out;
status = decode_putfh(&xdr);
if (status)
goto out;
@@ -4426,7 +4672,8 @@ out:
/*
* Decode LOCKT response
*/
-static int nfs4_xdr_dec_lockt(struct rpc_rqst *rqstp, __be32 *p, struct nfs_lockt_res *res)
+static int nfs4_xdr_dec_lockt(struct rpc_rqst *rqstp, __be32 *p,
+ struct nfs_lockt_res *res)
{
struct xdr_stream xdr;
struct compound_hdr hdr;
@@ -4436,6 +4683,9 @@ static int nfs4_xdr_dec_lockt(struct rpc_rqst *rqstp, __be32 *p, struct nfs_lock
status = decode_compound_hdr(&xdr, &hdr);
if (status)
goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
+ goto out;
status = decode_putfh(&xdr);
if (status)
goto out;
@@ -4447,7 +4697,8 @@ out:
/*
* Decode LOCKU response
*/
-static int nfs4_xdr_dec_locku(struct rpc_rqst *rqstp, __be32 *p, struct nfs_locku_res *res)
+static int nfs4_xdr_dec_locku(struct rpc_rqst *rqstp, __be32 *p,
+ struct nfs_locku_res *res)
{
struct xdr_stream xdr;
struct compound_hdr hdr;
@@ -4457,6 +4708,9 @@ static int nfs4_xdr_dec_locku(struct rpc_rqst *rqstp, __be32 *p, struct nfs_lock
status = decode_compound_hdr(&xdr, &hdr);
if (status)
goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
+ goto out;
status = decode_putfh(&xdr);
if (status)
goto out;
@@ -4468,7 +4722,8 @@ out:
/*
* Decode READLINK response
*/
-static int nfs4_xdr_dec_readlink(struct rpc_rqst *rqstp, __be32 *p, void *res)
+static int nfs4_xdr_dec_readlink(struct rpc_rqst *rqstp, __be32 *p,
+ struct nfs4_readlink_res *res)
{
struct xdr_stream xdr;
struct compound_hdr hdr;
@@ -4478,6 +4733,9 @@ static int nfs4_xdr_dec_readlink(struct rpc_rqst *rqstp, __be32 *p, void *res)
status = decode_compound_hdr(&xdr, &hdr);
if (status)
goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
+ goto out;
status = decode_putfh(&xdr);
if (status)
goto out;
@@ -4489,7 +4747,8 @@ out:
/*
* Decode READDIR response
*/
-static int nfs4_xdr_dec_readdir(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_readdir_res *res)
+static int nfs4_xdr_dec_readdir(struct rpc_rqst *rqstp, __be32 *p,
+ struct nfs4_readdir_res *res)
{
struct xdr_stream xdr;
struct compound_hdr hdr;
@@ -4499,6 +4758,9 @@ static int nfs4_xdr_dec_readdir(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_r
status = decode_compound_hdr(&xdr, &hdr);
if (status)
goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
+ goto out;
status = decode_putfh(&xdr);
if (status)
goto out;
@@ -4510,7 +4772,8 @@ out:
/*
* Decode Read response
*/
-static int nfs4_xdr_dec_read(struct rpc_rqst *rqstp, __be32 *p, struct nfs_readres *res)
+static int nfs4_xdr_dec_read(struct rpc_rqst *rqstp, __be32 *p,
+ struct nfs_readres *res)
{
struct xdr_stream xdr;
struct compound_hdr hdr;
@@ -4520,6 +4783,9 @@ static int nfs4_xdr_dec_read(struct rpc_rqst *rqstp, __be32 *p, struct nfs_readr
status = decode_compound_hdr(&xdr, &hdr);
if (status)
goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
+ goto out;
status = decode_putfh(&xdr);
if (status)
goto out;
@@ -4533,7 +4799,8 @@ out:
/*
* Decode WRITE response
*/
-static int nfs4_xdr_dec_write(struct rpc_rqst *rqstp, __be32 *p, struct nfs_writeres *res)
+static int nfs4_xdr_dec_write(struct rpc_rqst *rqstp, __be32 *p,
+ struct nfs_writeres *res)
{
struct xdr_stream xdr;
struct compound_hdr hdr;
@@ -4543,6 +4810,9 @@ static int nfs4_xdr_dec_write(struct rpc_rqst *rqstp, __be32 *p, struct nfs_writ
status = decode_compound_hdr(&xdr, &hdr);
if (status)
goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
+ goto out;
status = decode_putfh(&xdr);
if (status)
goto out;
@@ -4559,7 +4829,8 @@ out:
/*
* Decode COMMIT response
*/
-static int nfs4_xdr_dec_commit(struct rpc_rqst *rqstp, __be32 *p, struct nfs_writeres *res)
+static int nfs4_xdr_dec_commit(struct rpc_rqst *rqstp, __be32 *p,
+ struct nfs_writeres *res)
{
struct xdr_stream xdr;
struct compound_hdr hdr;
@@ -4569,6 +4840,9 @@ static int nfs4_xdr_dec_commit(struct rpc_rqst *rqstp, __be32 *p, struct nfs_wri
status = decode_compound_hdr(&xdr, &hdr);
if (status)
goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
+ goto out;
status = decode_putfh(&xdr);
if (status)
goto out;
@@ -4583,7 +4857,8 @@ out:
/*
* FSINFO request
*/
-static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, __be32 *p, struct nfs_fsinfo *fsinfo)
+static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, __be32 *p,
+ struct nfs4_fsinfo_res *res)
{
struct xdr_stream xdr;
struct compound_hdr hdr;
@@ -4592,16 +4867,19 @@ static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, __be32 *p, struct nfs_fsinf
xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
status = decode_compound_hdr(&xdr, &hdr);
if (!status)
+ status = decode_sequence(&xdr, &res->seq_res, req);
+ if (!status)
status = decode_putfh(&xdr);
if (!status)
- status = decode_fsinfo(&xdr, fsinfo);
+ status = decode_fsinfo(&xdr, res->fsinfo);
return status;
}
/*
* PATHCONF request
*/
-static int nfs4_xdr_dec_pathconf(struct rpc_rqst *req, __be32 *p, struct nfs_pathconf *pathconf)
+static int nfs4_xdr_dec_pathconf(struct rpc_rqst *req, __be32 *p,
+ struct nfs4_pathconf_res *res)
{
struct xdr_stream xdr;
struct compound_hdr hdr;
@@ -4610,16 +4888,19 @@ static int nfs4_xdr_dec_pathconf(struct rpc_rqst *req, __be32 *p, struct nfs_pat
xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
status = decode_compound_hdr(&xdr, &hdr);
if (!status)
+ status = decode_sequence(&xdr, &res->seq_res, req);
+ if (!status)
status = decode_putfh(&xdr);
if (!status)
- status = decode_pathconf(&xdr, pathconf);
+ status = decode_pathconf(&xdr, res->pathconf);
return status;
}
/*
* STATFS request
*/
-static int nfs4_xdr_dec_statfs(struct rpc_rqst *req, __be32 *p, struct nfs_fsstat *fsstat)
+static int nfs4_xdr_dec_statfs(struct rpc_rqst *req, __be32 *p,
+ struct nfs4_statfs_res *res)
{
struct xdr_stream xdr;
struct compound_hdr hdr;
@@ -4628,23 +4909,30 @@ static int nfs4_xdr_dec_statfs(struct rpc_rqst *req, __be32 *p, struct nfs_fssta
xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
status = decode_compound_hdr(&xdr, &hdr);
if (!status)
+ status = decode_sequence(&xdr, &res->seq_res, req);
+ if (!status)
status = decode_putfh(&xdr);
if (!status)
- status = decode_statfs(&xdr, fsstat);
+ status = decode_statfs(&xdr, res->fsstat);
return status;
}
/*
* GETATTR_BITMAP request
*/
-static int nfs4_xdr_dec_server_caps(struct rpc_rqst *req, __be32 *p, struct nfs4_server_caps_res *res)
+static int nfs4_xdr_dec_server_caps(struct rpc_rqst *req, __be32 *p,
+ struct nfs4_server_caps_res *res)
{
struct xdr_stream xdr;
struct compound_hdr hdr;
int status;
xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
- if ((status = decode_compound_hdr(&xdr, &hdr)) != 0)
+ status = decode_compound_hdr(&xdr, &hdr);
+ if (status)
+ goto out;
+ status = decode_sequence(&xdr, &res->seq_res, req);
+ if (status)
goto out;
if ((status = decode_putfh(&xdr)) != 0)
goto out;
@@ -4709,7 +4997,8 @@ static int nfs4_xdr_dec_setclientid_confirm(struct rpc_rqst *req, __be32 *p, str
/*
* DELEGRETURN request
*/
-static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_delegreturnres *res)
+static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, __be32 *p,
+ struct nfs4_delegreturnres *res)
{
struct xdr_stream xdr;
struct compound_hdr hdr;
@@ -4717,7 +5006,10 @@ static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, __be32 *p, struct nf
xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
status = decode_compound_hdr(&xdr, &hdr);
- if (status != 0)
+ if (status)
+ goto out;
+ status = decode_sequence(&xdr, &res->seq_res, rqstp);
+ if (status)
goto out;
status = decode_putfh(&xdr);
if (status != 0)
@@ -4731,7 +5023,8 @@ out:
/*
* FS_LOCATIONS request
*/
-static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, __be32 *p, struct nfs4_fs_locations *res)
+static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, __be32 *p,
+ struct nfs4_fs_locations_res *res)
{
struct xdr_stream xdr;
struct compound_hdr hdr;
@@ -4739,14 +5032,18 @@ static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, __be32 *p, struct nfs
xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
status = decode_compound_hdr(&xdr, &hdr);
- if (status != 0)
+ if (status)
+ goto out;
+ status = decode_sequence(&xdr, &res->seq_res, req);
+ if (status)
goto out;
if ((status = decode_putfh(&xdr)) != 0)
goto out;
if ((status = decode_lookup(&xdr)) != 0)
goto out;
xdr_enter_page(&xdr, PAGE_SIZE);
- status = decode_getfattr(&xdr, &res->fattr, res->server);
+ status = decode_getfattr(&xdr, &res->fs_locations->fattr,
+ res->fs_locations->server);
out:
return status;
}
@@ -4877,10 +5174,10 @@ nfs4_stat_to_errno(int stat)
#define PROC(proc, argtype, restype) \
[NFSPROC4_CLNT_##proc] = { \
.p_proc = NFSPROC4_COMPOUND, \
- .p_encode = (kxdrproc_t) nfs4_xdr_##argtype, \
- .p_decode = (kxdrproc_t) nfs4_xdr_##restype, \
- .p_arglen = NFS4_##argtype##_sz, \
- .p_replen = NFS4_##restype##_sz, \
+ .p_encode = (kxdrproc_t) nfs4##_xdr_##argtype, \
+ .p_decode = (kxdrproc_t) nfs4##_xdr_##restype, \
+ .p_arglen = NFS4##_##argtype##_sz, \
+ .p_replen = NFS4##_##restype##_sz, \
.p_statidx = NFSPROC4_CLNT_##proc, \
.p_name = #proc, \
}
@@ -4922,11 +5219,6 @@ struct rpc_procinfo nfs4_procedures[] = {
PROC(FS_LOCATIONS, enc_fs_locations, dec_fs_locations),
};
-#if defined(CONFIG_NFS_V4_1)
-struct rpc_procinfo nfs41_procedures[] = {
-};
-#endif /* CONFIG_NFS_V4_1 */
-
struct rpc_version nfs_version4 = {
.number = 4,
.nrprocs = ARRAY_SIZE(nfs4_procedures),
@@ -4936,8 +5228,9 @@ struct rpc_version nfs_version4 = {
#ifdef CONFIG_NFS_V4_1
struct rpc_version nfs_version41 = {
.number = 4,
- .nrprocs = ARRAY_SIZE(nfs41_procedures),
- .procs = nfs41_procedures
+ .minorversion = 1,
+ .nrprocs = ARRAY_SIZE(nfs4_procedures),
+ .procs = nfs4_procedures
};
#endif /* CONFIG_NFS_V4_1 */
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index 99d4f9e..77c03a4 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -32,6 +32,7 @@ struct rpc_clnt {
struct rpc_procinfo * cl_procinfo; /* procedure info */
u32 cl_prog, /* RPC program number */
cl_vers, /* RPC version number */
+ cl_mvers, /* RPC minorversion number */
cl_maxproc; /* max procedure number */
char * cl_server; /* server machine name */
@@ -82,6 +83,7 @@ get_rpc_version(struct rpc_program *prog, u32 vers, int minorvers)
struct rpc_version {
u32 number; /* version number */
+ u32 minorversion; /* minorversion number */
unsigned int nrprocs; /* number of procs */
struct rpc_procinfo * procs; /* procedure array */
};
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 44f251d..0c8e5f1 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -177,6 +177,7 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru
clnt->cl_protname = program->name;
clnt->cl_prog = args->prognumber ? : program->number;
clnt->cl_vers = version->number;
+ clnt->cl_mvers = version->minorversion;
clnt->cl_stats = program->stats;
clnt->cl_metrics = rpc_alloc_iostats(clnt);
err = -ENOMEM;
@@ -491,6 +492,7 @@ struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old,
clnt->cl_protname = program->name;
clnt->cl_prog = program->number;
clnt->cl_vers = version->number;
+ clnt->cl_mvers = version->minorversion;
clnt->cl_stats = program->stats;
err = rpc_ping(clnt, RPC_TASK_SOFT);
if (err != 0) {
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* Re: [pnfs] [RFC 23/85] nfs41: minorversion support for xdr
2008-11-10 20:21 ` [RFC 23/85] nfs41: minorversion support for xdr Benny Halevy
@ 2008-11-17 13:48 ` Benny Halevy
0 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-17 13:48 UTC (permalink / raw)
To: pnfs; +Cc: trond.myklebust, linux-nfs
On Nov. 10, 2008, 22:21 +0200, Benny Halevy <bhalevy@panasas.com> wrote:
> From: Andy Adamson <andros@netapp.com>
>
> Add the minorversion to struct rpc_version and struct rpc_clnt, and struct
> compound_hdr. Switch on the minorversion to perfom NFSv4.0 vrs NFSv4.1
> encoding,
>
> Add the nfsv41 encode and decode sizes. Add encode_sequence to all
> nfs4_enc_* routines and decode_sequence to all nfs4_dec_* routines as required
> by v41.
>
> Signed-off-by: Andy Adamson<andros@netapp.com>
> Signed-off-by: Benny Halevy <bhalevy@panasas.com>
> ---
> fs/nfs/nfs4xdr.c | 641 +++++++++++++++++++++++++++++++------------
> include/linux/sunrpc/clnt.h | 2 +
> net/sunrpc/clnt.c | 2 +
> 3 files changed, 471 insertions(+), 174 deletions(-)
>
> diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
> index 30addf4..d3da7a5 100644
> --- a/fs/nfs/nfs4xdr.c
> +++ b/fs/nfs/nfs4xdr.c
> @@ -240,43 +240,63 @@ static int nfs4_stat_to_errno(int);
> (encode_getattr_maxsz)
> #define decode_fs_locations_maxsz \
> (0)
> +
> +#if defined(CONFIG_NFS_V4_1)
> +#define encode_sequence_maxsz 0 /* stub */
> +#define decode_sequence_maxsz 0 /* stub */
> +#else /* CONFIG_NFS_V4_1 */
> +#define encode_sequence_maxsz 0
> +#define decode_sequence_maxsz 0
> +#endif /* CONFIG_NFS_V4_1 */
> +
> #define NFS4_enc_compound_sz (1024) /* XXX: large enough? */
> #define NFS4_dec_compound_sz (1024) /* XXX: large enough? */
> #define NFS4_enc_read_sz (compound_encode_hdr_maxsz + \
> + encode_sequence_maxsz + \
> encode_putfh_maxsz + \
> encode_read_maxsz)
> #define NFS4_dec_read_sz (compound_decode_hdr_maxsz + \
> + decode_sequence_maxsz + \
> decode_putfh_maxsz + \
> decode_read_maxsz)
> #define NFS4_enc_readlink_sz (compound_encode_hdr_maxsz + \
> + encode_sequence_maxsz + \
> encode_putfh_maxsz + \
> encode_readlink_maxsz)
> #define NFS4_dec_readlink_sz (compound_decode_hdr_maxsz + \
> + decode_sequence_maxsz + \
> decode_putfh_maxsz + \
> decode_readlink_maxsz)
> #define NFS4_enc_readdir_sz (compound_encode_hdr_maxsz + \
> + encode_sequence_maxsz + \
> encode_putfh_maxsz + \
> encode_readdir_maxsz)
> #define NFS4_dec_readdir_sz (compound_decode_hdr_maxsz + \
> + decode_sequence_maxsz + \
> decode_putfh_maxsz + \
> decode_readdir_maxsz)
> #define NFS4_enc_write_sz (compound_encode_hdr_maxsz + \
> + encode_sequence_maxsz + \
> encode_putfh_maxsz + \
> encode_write_maxsz + \
> encode_getattr_maxsz)
> #define NFS4_dec_write_sz (compound_decode_hdr_maxsz + \
> + decode_sequence_maxsz + \
> decode_putfh_maxsz + \
> decode_write_maxsz + \
> decode_getattr_maxsz)
> #define NFS4_enc_commit_sz (compound_encode_hdr_maxsz + \
> + encode_sequence_maxsz + \
> encode_putfh_maxsz + \
> encode_commit_maxsz + \
> encode_getattr_maxsz)
> #define NFS4_dec_commit_sz (compound_decode_hdr_maxsz + \
> + decode_sequence_maxsz + \
> decode_putfh_maxsz + \
> decode_commit_maxsz + \
> decode_getattr_maxsz)
> -#define NFS4_enc_open_sz (compound_encode_hdr_maxsz + \
> +#define NFS4_enc_open_sz (compound_encode_hdr_maxsz + \
> + encode_sequence_maxsz + \
> encode_putfh_maxsz + \
> encode_savefh_maxsz + \
> encode_open_maxsz + \
> @@ -284,7 +304,8 @@ static int nfs4_stat_to_errno(int);
> encode_getattr_maxsz + \
> encode_restorefh_maxsz + \
> encode_getattr_maxsz)
> -#define NFS4_dec_open_sz (compound_decode_hdr_maxsz + \
> +#define NFS4_dec_open_sz (compound_decode_hdr_maxsz + \
> + decode_sequence_maxsz + \
> decode_putfh_maxsz + \
> decode_savefh_maxsz + \
> decode_open_maxsz + \
> @@ -301,43 +322,53 @@ static int nfs4_stat_to_errno(int);
> decode_putfh_maxsz + \
> decode_open_confirm_maxsz)
> #define NFS4_enc_open_noattr_sz (compound_encode_hdr_maxsz + \
> + encode_sequence_maxsz + \
> encode_putfh_maxsz + \
> encode_open_maxsz + \
> encode_getattr_maxsz)
> #define NFS4_dec_open_noattr_sz (compound_decode_hdr_maxsz + \
> + decode_sequence_maxsz + \
> decode_putfh_maxsz + \
> decode_open_maxsz + \
> decode_getattr_maxsz)
> #define NFS4_enc_open_downgrade_sz \
> (compound_encode_hdr_maxsz + \
> + encode_sequence_maxsz + \
> encode_putfh_maxsz + \
> encode_open_downgrade_maxsz + \
> encode_getattr_maxsz)
> #define NFS4_dec_open_downgrade_sz \
> (compound_decode_hdr_maxsz + \
> + decode_sequence_maxsz + \
> decode_putfh_maxsz + \
> decode_open_downgrade_maxsz + \
> decode_getattr_maxsz)
> #define NFS4_enc_close_sz (compound_encode_hdr_maxsz + \
> + encode_sequence_maxsz + \
> encode_putfh_maxsz + \
> encode_close_maxsz + \
> encode_getattr_maxsz)
> #define NFS4_dec_close_sz (compound_decode_hdr_maxsz + \
> + decode_sequence_maxsz + \
> decode_putfh_maxsz + \
> decode_close_maxsz + \
> decode_getattr_maxsz)
> #define NFS4_enc_setattr_sz (compound_encode_hdr_maxsz + \
> + encode_sequence_maxsz + \
> encode_putfh_maxsz + \
> encode_setattr_maxsz + \
> encode_getattr_maxsz)
> #define NFS4_dec_setattr_sz (compound_decode_hdr_maxsz + \
> + decode_sequence_maxsz + \
> decode_putfh_maxsz + \
> decode_setattr_maxsz + \
> decode_getattr_maxsz)
> #define NFS4_enc_fsinfo_sz (compound_encode_hdr_maxsz + \
> + encode_sequence_maxsz + \
> encode_putfh_maxsz + \
> encode_fsinfo_maxsz)
> #define NFS4_dec_fsinfo_sz (compound_decode_hdr_maxsz + \
> + decode_sequence_maxsz + \
> decode_putfh_maxsz + \
> decode_fsinfo_maxsz)
> #define NFS4_enc_renew_sz (compound_encode_hdr_maxsz + \
> @@ -359,64 +390,81 @@ static int nfs4_stat_to_errno(int);
> decode_putrootfh_maxsz + \
> decode_fsinfo_maxsz)
> #define NFS4_enc_lock_sz (compound_encode_hdr_maxsz + \
> + encode_sequence_maxsz + \
> encode_putfh_maxsz + \
> encode_lock_maxsz)
> #define NFS4_dec_lock_sz (compound_decode_hdr_maxsz + \
> + decode_sequence_maxsz + \
> decode_putfh_maxsz + \
> decode_lock_maxsz)
> #define NFS4_enc_lockt_sz (compound_encode_hdr_maxsz + \
> + encode_sequence_maxsz + \
> encode_putfh_maxsz + \
> encode_lockt_maxsz)
> #define NFS4_dec_lockt_sz (compound_decode_hdr_maxsz + \
> + decode_sequence_maxsz + \
> decode_putfh_maxsz + \
> decode_lockt_maxsz)
> #define NFS4_enc_locku_sz (compound_encode_hdr_maxsz + \
> + encode_sequence_maxsz + \
> encode_putfh_maxsz + \
> encode_locku_maxsz)
> #define NFS4_dec_locku_sz (compound_decode_hdr_maxsz + \
> + decode_sequence_maxsz + \
> decode_putfh_maxsz + \
> decode_locku_maxsz)
> #define NFS4_enc_access_sz (compound_encode_hdr_maxsz + \
> + encode_sequence_maxsz + \
> encode_putfh_maxsz + \
> encode_access_maxsz + \
> encode_getattr_maxsz)
> #define NFS4_dec_access_sz (compound_decode_hdr_maxsz + \
> + decode_sequence_maxsz + \
> decode_putfh_maxsz + \
> decode_access_maxsz + \
> decode_getattr_maxsz)
> #define NFS4_enc_getattr_sz (compound_encode_hdr_maxsz + \
> + encode_sequence_maxsz + \
> encode_putfh_maxsz + \
> encode_getattr_maxsz)
> #define NFS4_dec_getattr_sz (compound_decode_hdr_maxsz + \
> + decode_sequence_maxsz + \
> decode_putfh_maxsz + \
> decode_getattr_maxsz)
> #define NFS4_enc_lookup_sz (compound_encode_hdr_maxsz + \
> + encode_sequence_maxsz + \
> encode_putfh_maxsz + \
> encode_lookup_maxsz + \
> encode_getattr_maxsz + \
> encode_getfh_maxsz)
> #define NFS4_dec_lookup_sz (compound_decode_hdr_maxsz + \
> + decode_sequence_maxsz + \
> decode_putfh_maxsz + \
> decode_lookup_maxsz + \
> decode_getattr_maxsz + \
> decode_getfh_maxsz)
> #define NFS4_enc_lookup_root_sz (compound_encode_hdr_maxsz + \
> + encode_sequence_maxsz + \
> encode_putrootfh_maxsz + \
> encode_getattr_maxsz + \
> encode_getfh_maxsz)
> #define NFS4_dec_lookup_root_sz (compound_decode_hdr_maxsz + \
> + decode_sequence_maxsz + \
> decode_putrootfh_maxsz + \
> decode_getattr_maxsz + \
> decode_getfh_maxsz)
> #define NFS4_enc_remove_sz (compound_encode_hdr_maxsz + \
> + encode_sequence_maxsz + \
> encode_putfh_maxsz + \
> encode_remove_maxsz + \
> encode_getattr_maxsz)
> #define NFS4_dec_remove_sz (compound_decode_hdr_maxsz + \
> + decode_sequence_maxsz + \
> decode_putfh_maxsz + \
> op_decode_hdr_maxsz + 5 + \
> decode_getattr_maxsz)
> #define NFS4_enc_rename_sz (compound_encode_hdr_maxsz + \
> + encode_sequence_maxsz + \
> encode_putfh_maxsz + \
> encode_savefh_maxsz + \
> encode_putfh_maxsz + \
> @@ -425,6 +473,7 @@ static int nfs4_stat_to_errno(int);
> encode_restorefh_maxsz + \
> encode_getattr_maxsz)
> #define NFS4_dec_rename_sz (compound_decode_hdr_maxsz + \
> + decode_sequence_maxsz + \
> decode_putfh_maxsz + \
> decode_savefh_maxsz + \
> decode_putfh_maxsz + \
> @@ -433,6 +482,7 @@ static int nfs4_stat_to_errno(int);
> decode_restorefh_maxsz + \
> decode_getattr_maxsz)
> #define NFS4_enc_link_sz (compound_encode_hdr_maxsz + \
> + encode_sequence_maxsz + \
> encode_putfh_maxsz + \
> encode_savefh_maxsz + \
> encode_putfh_maxsz + \
> @@ -441,6 +491,7 @@ static int nfs4_stat_to_errno(int);
> encode_restorefh_maxsz + \
> decode_getattr_maxsz)
> #define NFS4_dec_link_sz (compound_decode_hdr_maxsz + \
> + decode_sequence_maxsz + \
> decode_putfh_maxsz + \
> decode_savefh_maxsz + \
> decode_putfh_maxsz + \
> @@ -449,16 +500,19 @@ static int nfs4_stat_to_errno(int);
> decode_restorefh_maxsz + \
> decode_getattr_maxsz)
> #define NFS4_enc_symlink_sz (compound_encode_hdr_maxsz + \
> + encode_sequence_maxsz + \
> encode_putfh_maxsz + \
> encode_symlink_maxsz + \
> encode_getattr_maxsz + \
> encode_getfh_maxsz)
> #define NFS4_dec_symlink_sz (compound_decode_hdr_maxsz + \
> + decode_sequence_maxsz + \
> decode_putfh_maxsz + \
> decode_symlink_maxsz + \
> decode_getattr_maxsz + \
> decode_getfh_maxsz)
> #define NFS4_enc_create_sz (compound_encode_hdr_maxsz + \
> + encode_sequence_maxsz + \
> encode_putfh_maxsz + \
> encode_savefh_maxsz + \
> encode_create_maxsz + \
> @@ -467,6 +521,7 @@ static int nfs4_stat_to_errno(int);
> encode_restorefh_maxsz + \
> encode_getattr_maxsz)
> #define NFS4_dec_create_sz (compound_decode_hdr_maxsz + \
> + decode_sequence_maxsz + \
> decode_putfh_maxsz + \
> decode_savefh_maxsz + \
> decode_create_maxsz + \
> @@ -475,49 +530,63 @@ static int nfs4_stat_to_errno(int);
> decode_restorefh_maxsz + \
> decode_getattr_maxsz)
> #define NFS4_enc_pathconf_sz (compound_encode_hdr_maxsz + \
> + encode_sequence_maxsz + \
> encode_putfh_maxsz + \
> encode_getattr_maxsz)
> #define NFS4_dec_pathconf_sz (compound_decode_hdr_maxsz + \
> + decode_sequence_maxsz + \
> decode_putfh_maxsz + \
> decode_getattr_maxsz)
> #define NFS4_enc_statfs_sz (compound_encode_hdr_maxsz + \
> + encode_sequence_maxsz + \
> encode_putfh_maxsz + \
> encode_statfs_maxsz)
> #define NFS4_dec_statfs_sz (compound_decode_hdr_maxsz + \
> + decode_sequence_maxsz + \
> decode_putfh_maxsz + \
> decode_statfs_maxsz)
> #define NFS4_enc_server_caps_sz (compound_encode_hdr_maxsz + \
> + encode_sequence_maxsz + \
> encode_putfh_maxsz + \
> encode_getattr_maxsz)
> #define NFS4_dec_server_caps_sz (compound_decode_hdr_maxsz + \
> + decode_sequence_maxsz + \
> decode_putfh_maxsz + \
> decode_getattr_maxsz)
> #define NFS4_enc_delegreturn_sz (compound_encode_hdr_maxsz + \
> + encode_sequence_maxsz + \
> encode_putfh_maxsz + \
> encode_delegreturn_maxsz + \
> encode_getattr_maxsz)
> #define NFS4_dec_delegreturn_sz (compound_decode_hdr_maxsz + \
> + decode_sequence_maxsz + \
> decode_delegreturn_maxsz + \
> decode_getattr_maxsz)
> #define NFS4_enc_getacl_sz (compound_encode_hdr_maxsz + \
> + encode_sequence_maxsz + \
> encode_putfh_maxsz + \
> encode_getacl_maxsz)
> #define NFS4_dec_getacl_sz (compound_decode_hdr_maxsz + \
> + decode_sequence_maxsz + \
> decode_putfh_maxsz + \
> decode_getacl_maxsz)
> #define NFS4_enc_setacl_sz (compound_encode_hdr_maxsz + \
> + encode_sequence_maxsz + \
> encode_putfh_maxsz + \
> encode_setacl_maxsz)
> #define NFS4_dec_setacl_sz (compound_decode_hdr_maxsz + \
> + decode_sequence_maxsz + \
> decode_putfh_maxsz + \
> decode_setacl_maxsz)
> #define NFS4_enc_fs_locations_sz \
> (compound_encode_hdr_maxsz + \
> + encode_sequence_maxsz + \
> encode_putfh_maxsz + \
> encode_lookup_maxsz + \
> encode_fs_locations_maxsz)
> #define NFS4_dec_fs_locations_sz \
> (compound_decode_hdr_maxsz + \
> + decode_sequence_maxsz + \
> decode_putfh_maxsz + \
> decode_lookup_maxsz + \
> decode_fs_locations_maxsz)
> @@ -543,6 +612,7 @@ struct compound_hdr {
> uint32_t nops;
> uint32_t taglen;
> char * tag;
> + u32 minorversion;
> };
>
> /*
> @@ -578,7 +648,7 @@ static void encode_string(struct xdr_stream *xdr, unsigned int len, const char *
> xdr_encode_opaque(p, str, len);
> }
>
> -static __u32 *
> +static __be32*
> encode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr)
> {
> __be32 *p, *nops;
> @@ -588,7 +658,7 @@ encode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr)
> RESERVE_SPACE(12+(XDR_QUADLEN(hdr->taglen)<<2));
> WRITE32(hdr->taglen);
> WRITEMEM(hdr->tag, hdr->taglen);
> - WRITE32(NFS4_MINOR_VERSION);
> + WRITE32(hdr->minorversion);
> nops = p;
> WRITE32(hdr->nops);
> return nops;
> @@ -1377,7 +1447,8 @@ encode_savefh(struct xdr_stream *xdr, struct compound_hdr *hdr)
>
> static int
> encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs *arg,
> - const struct nfs_server *server, struct compound_hdr *hdr)
> + const struct nfs_server *server,
> + struct compound_hdr *hdr)
> {
> int status;
> __be32 *p;
> @@ -1468,6 +1539,30 @@ encode_delegreturn(struct xdr_stream *xdr, const nfs4_stateid *stateid,
> return 0;
>
> }
> +
> +#if defined(CONFIG_NFS_V4_1)
> +/* NFSv4.1 operations */
> +static int encode_sequence(struct xdr_stream *xdr,
> + const struct nfs41_sequence_args *args,
> + struct compound_hdr *hdr)
> +{
> + if (hdr->minorversion == 0)
> + return 0;
> +
> + /* stub */
> + hdr->nops++;
> +
> + return 0;
> +}
> +#else /* CONFIG_NFS_V4_1 */
> +static inline int encode_sequence(struct xdr_stream *xdr,
> + const struct nfs41_sequence_args *args,
> + struct compound_hdr *hdr)
> +{
> + return 0;
> +}
> +#endif /* CONFIG_NFS_V4_1 */
> +
> /*
> * END OF "GENERIC" ENCODE ROUTINES.
> */
> @@ -1475,17 +1570,19 @@ encode_delegreturn(struct xdr_stream *xdr, const nfs4_stateid *stateid,
> /*
> * Encode an ACCESS request
> */
> -static int nfs4_xdr_enc_access(struct rpc_rqst *req, __be32 *p, const struct nfs4_accessargs *args)
> +static int nfs4_xdr_enc_access(struct rpc_rqst *req, __be32 *p,
> + const struct nfs4_accessargs *args)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 0,
> + .minorversion = req->rq_task->tk_client->cl_mvers,
> };
> int status;
> __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> nops = encode_compound_hdr(&xdr, &hdr);
> + encode_sequence(&xdr, &args->seq_args, &hdr);
> status = encode_putfh(&xdr, args->fh, &hdr);
> if (status != 0)
> goto out;
> @@ -1501,17 +1598,19 @@ out:
> /*
> * Encode LOOKUP request
> */
> -static int nfs4_xdr_enc_lookup(struct rpc_rqst *req, __be32 *p, const struct nfs4_lookup_arg *args)
> +static int nfs4_xdr_enc_lookup(struct rpc_rqst *req, __be32 *p,
> + const struct nfs4_lookup_arg *args)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 0,
> + .minorversion = req->rq_task->tk_client->cl_mvers,
> };
> int status;
> __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> nops = encode_compound_hdr(&xdr, &hdr);
> + encode_sequence(&xdr, &args->seq_args, &hdr);
> if ((status = encode_putfh(&xdr, args->dir_fh, &hdr)) != 0)
> goto out;
> if ((status = encode_lookup(&xdr, args->name, &hdr)) != 0)
> @@ -1527,17 +1626,19 @@ out:
> /*
> * Encode LOOKUP_ROOT request
> */
> -static int nfs4_xdr_enc_lookup_root(struct rpc_rqst *req, __be32 *p, const struct nfs4_lookup_root_arg *args)
> +static int nfs4_xdr_enc_lookup_root(struct rpc_rqst *req, __be32 *p,
> + const struct nfs4_lookup_root_arg *args)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 0,
> + .minorversion = req->rq_task->tk_client->cl_mvers,
> };
> int status;
> __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> nops = encode_compound_hdr(&xdr, &hdr);
> + encode_sequence(&xdr, &args->seq_args, &hdr);
> if ((status = encode_putrootfh(&xdr, &hdr)) != 0)
> goto out;
> if ((status = encode_getfh(&xdr, &hdr)) == 0)
> @@ -1550,17 +1651,19 @@ out:
> /*
> * Encode REMOVE request
> */
> -static int nfs4_xdr_enc_remove(struct rpc_rqst *req, __be32 *p, const struct nfs_removeargs *args)
> +static int nfs4_xdr_enc_remove(struct rpc_rqst *req, __be32 *p,
> + const struct nfs_removeargs *args)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 0,
> + .minorversion = req->rq_task->tk_client->cl_mvers,
> };
> int status;
> __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> nops = encode_compound_hdr(&xdr, &hdr);
> + encode_sequence(&xdr, &args->seq_args, &hdr);
> if ((status = encode_putfh(&xdr, args->fh, &hdr)) != 0)
> goto out;
> if ((status = encode_remove(&xdr, &args->name, &hdr)) != 0)
> @@ -1574,17 +1677,19 @@ out:
> /*
> * Encode RENAME request
> */
> -static int nfs4_xdr_enc_rename(struct rpc_rqst *req, __be32 *p, const struct nfs4_rename_arg *args)
> +static int nfs4_xdr_enc_rename(struct rpc_rqst *req, __be32 *p,
> + const struct nfs4_rename_arg *args)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 0,
> + .minorversion = req->rq_task->tk_client->cl_mvers,
> };
> int status;
> __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> nops = encode_compound_hdr(&xdr, &hdr);
> + encode_sequence(&xdr, &args->seq_args, &hdr);
> if ((status = encode_putfh(&xdr, args->old_dir, &hdr)) != 0)
> goto out;
> if ((status = encode_savefh(&xdr, &hdr)) != 0)
> @@ -1607,17 +1712,19 @@ out:
> /*
> * Encode LINK request
> */
> -static int nfs4_xdr_enc_link(struct rpc_rqst *req, __be32 *p, const struct nfs4_link_arg *args)
> +static int nfs4_xdr_enc_link(struct rpc_rqst *req, __be32 *p,
> + const struct nfs4_link_arg *args)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 0,
> + .minorversion = req->rq_task->tk_client->cl_mvers,
> };
> int status;
> __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> nops = encode_compound_hdr(&xdr, &hdr);
> + encode_sequence(&xdr, &args->seq_args, &hdr);
> if ((status = encode_putfh(&xdr, args->fh, &hdr)) != 0)
> goto out;
> if ((status = encode_savefh(&xdr, &hdr)) != 0)
> @@ -1639,17 +1746,19 @@ out:
> /*
> * Encode CREATE request
> */
> -static int nfs4_xdr_enc_create(struct rpc_rqst *req, __be32 *p, const struct nfs4_create_arg *args)
> +static int nfs4_xdr_enc_create(struct rpc_rqst *req, __be32 *p,
> + const struct nfs4_create_arg *args)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 0,
> + .minorversion = req->rq_task->tk_client->cl_mvers,
> };
> int status;
> __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> nops = encode_compound_hdr(&xdr, &hdr);
> + encode_sequence(&xdr, &args->seq_args, &hdr);
> if ((status = encode_putfh(&xdr, args->dir_fh, &hdr)) != 0)
> goto out;
> if ((status = encode_savefh(&xdr, &hdr)) != 0)
> @@ -1679,17 +1788,19 @@ static int nfs4_xdr_enc_symlink(struct rpc_rqst *req, __be32 *p, const struct nf
> /*
> * Encode GETATTR request
> */
> -static int nfs4_xdr_enc_getattr(struct rpc_rqst *req, __be32 *p, const struct nfs4_getattr_arg *args)
> +static int nfs4_xdr_enc_getattr(struct rpc_rqst *req, __be32 *p,
> + const struct nfs4_getattr_arg *args)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 0,
> + .minorversion = req->rq_task->tk_client->cl_mvers,
> };
> int status;
> __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> nops = encode_compound_hdr(&xdr, &hdr);
> + encode_sequence(&xdr, &args->seq_args, &hdr);
> if ((status = encode_putfh(&xdr, args->fh, &hdr)) == 0)
> status = encode_getfattr(&xdr, args->bitmask, &hdr);
> encode_nops(nops, &hdr);
> @@ -1699,17 +1810,19 @@ static int nfs4_xdr_enc_getattr(struct rpc_rqst *req, __be32 *p, const struct nf
> /*
> * Encode a CLOSE request
> */
> -static int nfs4_xdr_enc_close(struct rpc_rqst *req, __be32 *p, struct nfs_closeargs *args)
> +static int nfs4_xdr_enc_close(struct rpc_rqst *req, __be32 *p,
> + struct nfs_closeargs *args)
> {
> - struct xdr_stream xdr;
> - struct compound_hdr hdr = {
> - .nops = 0,
> - };
> + struct xdr_stream xdr;
> + struct compound_hdr hdr = {
> + .minorversion = req->rq_task->tk_client->cl_mvers,
> + };
> int status;
> __be32 *nops;
>
> - xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> + xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> nops = encode_compound_hdr(&xdr, &hdr);
> + encode_sequence(&xdr, &args->seq_args, &hdr);
> status = encode_putfh(&xdr, args->fh, &hdr);
> if(status)
> goto out;
> @@ -1725,17 +1838,19 @@ out:
> /*
> * Encode an OPEN request
> */
> -static int nfs4_xdr_enc_open(struct rpc_rqst *req, __be32 *p, struct nfs_openargs *args)
> +static int nfs4_xdr_enc_open(struct rpc_rqst *req, __be32 *p,
> + struct nfs_openargs *args)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 0,
> + .minorversion = req->rq_task->tk_client->cl_mvers,
> };
> int status;
> __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> nops = encode_compound_hdr(&xdr, &hdr);
> + encode_sequence(&xdr, &args->seq_args, &hdr);
> status = encode_putfh(&xdr, args->fh, &hdr);
> if (status)
> goto out;
> @@ -1767,7 +1882,7 @@ static int nfs4_xdr_enc_open_confirm(struct rpc_rqst *req, __be32 *p, struct nfs
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 0,
> + .minorversion = req->rq_task->tk_client->cl_mvers,
> };
> int status;
> __be32 *nops;
> @@ -1786,17 +1901,19 @@ out:
> /*
> * Encode an OPEN request with no attributes.
> */
> -static int nfs4_xdr_enc_open_noattr(struct rpc_rqst *req, __be32 *p, struct nfs_openargs *args)
> +static int nfs4_xdr_enc_open_noattr(struct rpc_rqst *req, __be32 *p,
> + struct nfs_openargs *args)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 0,
> + .minorversion = req->rq_task->tk_client->cl_mvers,
> };
> int status;
> __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> nops = encode_compound_hdr(&xdr, &hdr);
> + encode_sequence(&xdr, &args->seq_args, &hdr);
> status = encode_putfh(&xdr, args->fh, &hdr);
> if (status)
> goto out;
> @@ -1812,17 +1929,19 @@ out:
> /*
> * Encode an OPEN_DOWNGRADE request
> */
> -static int nfs4_xdr_enc_open_downgrade(struct rpc_rqst *req, __be32 *p, struct nfs_closeargs *args)
> +static int nfs4_xdr_enc_open_downgrade(struct rpc_rqst *req, __be32 *p,
> + struct nfs_closeargs *args)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 0,
> + .minorversion = req->rq_task->tk_client->cl_mvers,
> };
> int status;
> __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> nops = encode_compound_hdr(&xdr, &hdr);
> + encode_sequence(&xdr, &args->seq_args, &hdr);
> status = encode_putfh(&xdr, args->fh, &hdr);
> if (status)
> goto out;
> @@ -1838,17 +1957,19 @@ out:
> /*
> * Encode a LOCK request
> */
> -static int nfs4_xdr_enc_lock(struct rpc_rqst *req, __be32 *p, struct nfs_lock_args *args)
> +static int nfs4_xdr_enc_lock(struct rpc_rqst *req, __be32 *p,
> + struct nfs_lock_args *args)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 0,
> + .minorversion = req->rq_task->tk_client->cl_mvers,
> };
> int status;
> __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> nops = encode_compound_hdr(&xdr, &hdr);
> + encode_sequence(&xdr, &args->seq_args, &hdr);
> status = encode_putfh(&xdr, args->fh, &hdr);
> if(status)
> goto out;
> @@ -1861,17 +1982,19 @@ out:
> /*
> * Encode a LOCKT request
> */
> -static int nfs4_xdr_enc_lockt(struct rpc_rqst *req, __be32 *p, struct nfs_lockt_args *args)
> +static int nfs4_xdr_enc_lockt(struct rpc_rqst *req, __be32 *p,
> + struct nfs_lockt_args *args)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 0,
> + .minorversion = req->rq_task->tk_client->cl_mvers,
> };
> int status;
> __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> nops = encode_compound_hdr(&xdr, &hdr);
> + encode_sequence(&xdr, &args->seq_args, &hdr);
> status = encode_putfh(&xdr, args->fh, &hdr);
> if(status)
> goto out;
> @@ -1884,17 +2007,19 @@ out:
> /*
> * Encode a LOCKU request
> */
> -static int nfs4_xdr_enc_locku(struct rpc_rqst *req, __be32 *p, struct nfs_locku_args *args)
> +static int nfs4_xdr_enc_locku(struct rpc_rqst *req, __be32 *p,
> + struct nfs_locku_args *args)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 0,
> + .minorversion = req->rq_task->tk_client->cl_mvers,
> };
> int status;
> __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> nops = encode_compound_hdr(&xdr, &hdr);
> + encode_sequence(&xdr, &args->seq_args, &hdr);
> status = encode_putfh(&xdr, args->fh, &hdr);
> if(status)
> goto out;
> @@ -1907,11 +2032,12 @@ out:
> /*
> * Encode a READLINK request
> */
> -static int nfs4_xdr_enc_readlink(struct rpc_rqst *req, __be32 *p, const struct nfs4_readlink *args)
> +static int nfs4_xdr_enc_readlink(struct rpc_rqst *req, __be32 *p,
> + const struct nfs4_readlink *args)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 0,
> + .minorversion = req->rq_task->tk_client->cl_mvers,
> };
> struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
> unsigned int replen;
> @@ -1920,6 +2046,7 @@ static int nfs4_xdr_enc_readlink(struct rpc_rqst *req, __be32 *p, const struct n
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> nops = encode_compound_hdr(&xdr, &hdr);
> + encode_sequence(&xdr, &args->seq_args, &hdr);
> status = encode_putfh(&xdr, args->fh, &hdr);
> if(status)
> goto out;
> @@ -1941,11 +2068,12 @@ out:
> /*
> * Encode a READDIR request
> */
> -static int nfs4_xdr_enc_readdir(struct rpc_rqst *req, __be32 *p, const struct nfs4_readdir_arg *args)
> +static int nfs4_xdr_enc_readdir(struct rpc_rqst *req, __be32 *p,
> + const struct nfs4_readdir_arg *args)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 0,
> + .minorversion = req->rq_task->tk_client->cl_mvers,
> };
> struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
> int replen;
> @@ -1954,6 +2082,7 @@ static int nfs4_xdr_enc_readdir(struct rpc_rqst *req, __be32 *p, const struct nf
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> nops = encode_compound_hdr(&xdr, &hdr);
> + encode_sequence(&xdr, &args->seq_args, &hdr);
> status = encode_putfh(&xdr, args->fh, &hdr);
> if(status)
> goto out;
> @@ -1978,18 +2107,20 @@ out:
> /*
> * Encode a READ request
> */
> -static int nfs4_xdr_enc_read(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args)
> +static int nfs4_xdr_enc_read(struct rpc_rqst *req, __be32 *p,
> + struct nfs_readargs *args)
> {
> struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 0,
> + .minorversion = req->rq_task->tk_client->cl_mvers,
> };
> int replen, status;
> __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> nops = encode_compound_hdr(&xdr, &hdr);
> + encode_sequence(&xdr, &args->seq_args, &hdr);
> status = encode_putfh(&xdr, args->fh, &hdr);
> if (status)
> goto out;
> @@ -2013,18 +2144,20 @@ out:
> /*
> * Encode an SETATTR request
> */
> -static int nfs4_xdr_enc_setattr(struct rpc_rqst *req, __be32 *p, struct nfs_setattrargs *args)
> +static int nfs4_xdr_enc_setattr(struct rpc_rqst *req, __be32 *p,
> + struct nfs_setattrargs *args)
>
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 0,
> + .minorversion = req->rq_task->tk_client->cl_mvers,
> };
> int status;
> __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> nops = encode_compound_hdr(&xdr, &hdr);
> + encode_sequence(&xdr, &args->seq_args, &hdr);
> status = encode_putfh(&xdr, args->fh, &hdr);
> if (status)
> goto out;
> @@ -2042,18 +2175,19 @@ out:
> */
> static int
> nfs4_xdr_enc_getacl(struct rpc_rqst *req, __be32 *p,
> - struct nfs_getaclargs *args)
> + struct nfs_getaclargs *args)
> {
> struct xdr_stream xdr;
> struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
> struct compound_hdr hdr = {
> - .nops = 0,
> + .minorversion = req->rq_task->tk_client->cl_mvers,
> };
> int replen, status;
> __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> nops = encode_compound_hdr(&xdr, &hdr);
> + encode_sequence(&xdr, &args->seq_args, &hdr);
> status = encode_putfh(&xdr, args->fh, &hdr);
> if (status)
> goto out;
> @@ -2070,24 +2204,25 @@ out:
> /*
> * Encode a WRITE request
> */
> -static int nfs4_xdr_enc_write(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args)
> +static int nfs4_xdr_enc_write(struct rpc_rqst *req, __be32 *p,
> + struct nfs_writeargs *args)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 0,
> + .minorversion = req->rq_task->tk_client->cl_mvers,
> };
> int status;
> __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> nops = encode_compound_hdr(&xdr, &hdr);
> + encode_sequence(&xdr, &args->seq_args, &hdr);
> status = encode_putfh(&xdr, args->fh, &hdr);
> if (status)
> goto out;
> status = encode_write(&xdr, args, &hdr);
> if (status)
> goto out;
> - req->rq_snd_buf.flags |= XDRBUF_WRITE;
> status = encode_getfattr(&xdr, args->bitmask, &hdr);
> out:
> encode_nops(nops, &hdr);
> @@ -2097,17 +2232,19 @@ out:
> /*
> * a COMMIT request
> */
> -static int nfs4_xdr_enc_commit(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args)
> +static int nfs4_xdr_enc_commit(struct rpc_rqst *req, __be32 *p,
> + struct nfs_writeargs *args)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 0,
> + .minorversion = req->rq_task->tk_client->cl_mvers,
> };
> int status;
> __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> nops = encode_compound_hdr(&xdr, &hdr);
> + encode_sequence(&xdr, &args->seq_args, &hdr);
> status = encode_putfh(&xdr, args->fh, &hdr);
> if (status)
> goto out;
> @@ -2123,17 +2260,19 @@ out:
> /*
> * FSINFO request
> */
> -static int nfs4_xdr_enc_fsinfo(struct rpc_rqst *req, __be32 *p, struct nfs4_fsinfo_arg *args)
> +static int nfs4_xdr_enc_fsinfo(struct rpc_rqst *req, __be32 *p,
> + struct nfs4_fsinfo_arg *args)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 0,
> + .minorversion = req->rq_task->tk_client->cl_mvers,
> };
> int status;
> __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> nops = encode_compound_hdr(&xdr, &hdr);
> + encode_sequence(&xdr, &args->seq_args, &hdr);
> status = encode_putfh(&xdr, args->fh, &hdr);
> if (!status)
> status = encode_fsinfo(&xdr, args->bitmask, &hdr);
> @@ -2144,17 +2283,19 @@ static int nfs4_xdr_enc_fsinfo(struct rpc_rqst *req, __be32 *p, struct nfs4_fsin
> /*
> * a PATHCONF request
> */
> -static int nfs4_xdr_enc_pathconf(struct rpc_rqst *req, __be32 *p, const struct nfs4_pathconf_arg *args)
> +static int nfs4_xdr_enc_pathconf(struct rpc_rqst *req, __be32 *p,
> + const struct nfs4_pathconf_arg *args)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 0,
> + .minorversion = req->rq_task->tk_client->cl_mvers,
> };
> int status;
> __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> nops = encode_compound_hdr(&xdr, &hdr);
> + encode_sequence(&xdr, &args->seq_args, &hdr);
> status = encode_putfh(&xdr, args->fh, &hdr);
> if (!status)
> status = encode_getattr_one(&xdr,
> @@ -2167,22 +2308,25 @@ static int nfs4_xdr_enc_pathconf(struct rpc_rqst *req, __be32 *p, const struct n
> /*
> * a STATFS request
> */
> -static int nfs4_xdr_enc_statfs(struct rpc_rqst *req, __be32 *p, const struct nfs4_statfs_arg *args)
> +static int nfs4_xdr_enc_statfs(struct rpc_rqst *req, __be32 *p,
> + const struct nfs4_statfs_arg *args)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 0,
> + .minorversion = req->rq_task->tk_client->cl_mvers,
> };
> int status;
> __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> nops = encode_compound_hdr(&xdr, &hdr);
> + encode_sequence(&xdr, &args->seq_args, &hdr);
> status = encode_putfh(&xdr, args->fh, &hdr);
> if (status == 0)
> status = encode_getattr_two(&xdr,
> args->bitmask[0] & nfs4_statfs_bitmap[0],
> - args->bitmask[1] & nfs4_statfs_bitmap[1], &hdr);
> + args->bitmask[1] & nfs4_statfs_bitmap[1],
> + &hdr);
> encode_nops(nops, &hdr);
> return status;
> }
> @@ -2190,18 +2334,20 @@ static int nfs4_xdr_enc_statfs(struct rpc_rqst *req, __be32 *p, const struct nfs
> /*
> * GETATTR_BITMAP request
> */
> -static int nfs4_xdr_enc_server_caps(struct rpc_rqst *req, __be32 *p, const struct nfs_fh *fhandle)
> +static int nfs4_xdr_enc_server_caps(struct rpc_rqst *req, __be32 *p,
> + struct nfs4_server_caps_arg *args)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 0,
> + .minorversion = req->rq_task->tk_client->cl_mvers,
> };
> int status;
> __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> nops = encode_compound_hdr(&xdr, &hdr);
> - status = encode_putfh(&xdr, fhandle, &hdr);
> + encode_sequence(&xdr, &args->seq_args, &hdr);
> + status = encode_putfh(&xdr, args->fhandle, &hdr);
> if (status == 0)
> status = encode_getattr_one(&xdr, FATTR4_WORD0_SUPPORTED_ATTRS|
> FATTR4_WORD0_LINK_SUPPORT|
> @@ -2218,7 +2364,7 @@ static int nfs4_xdr_enc_renew(struct rpc_rqst *req, __be32 *p, struct nfs_client
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 0,
> + .minorversion = req->rq_task->tk_client->cl_mvers,
> };
> int status;
> __be32 *nops;
> @@ -2226,6 +2372,7 @@ static int nfs4_xdr_enc_renew(struct rpc_rqst *req, __be32 *p, struct nfs_client
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> nops = encode_compound_hdr(&xdr, &hdr);
> status = encode_renew(&xdr, clp, &hdr);
> +
> encode_nops(nops, &hdr);
> return status;
> }
> @@ -2237,7 +2384,7 @@ static int nfs4_xdr_enc_setclientid(struct rpc_rqst *req, __be32 *p, struct nfs4
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 0,
> + .minorversion = req->rq_task->tk_client->cl_mvers,
> };
> int status;
> __be32 *nops;
> @@ -2245,6 +2392,7 @@ static int nfs4_xdr_enc_setclientid(struct rpc_rqst *req, __be32 *p, struct nfs4
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> nops = encode_compound_hdr(&xdr, &hdr);
> status = encode_setclientid(&xdr, sc, &hdr);
> +
> encode_nops(nops, &hdr);
> return status;
> }
> @@ -2256,7 +2404,7 @@ static int nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, __be32 *p, str
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 0,
> + .minorversion = req->rq_task->tk_client->cl_mvers,
> };
> const u32 lease_bitmap[2] = { FATTR4_WORD0_LEASE_TIME, 0 };
> int status;
> @@ -2276,17 +2424,19 @@ static int nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, __be32 *p, str
> /*
> * DELEGRETURN request
> */
> -static int nfs4_xdr_enc_delegreturn(struct rpc_rqst *req, __be32 *p, const struct nfs4_delegreturnargs *args)
> +static int nfs4_xdr_enc_delegreturn(struct rpc_rqst *req, __be32 *p,
> + const struct nfs4_delegreturnargs *args)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 0,
> + .minorversion = req->rq_task->tk_client->cl_mvers,
> };
> int status;
> __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> nops = encode_compound_hdr(&xdr, &hdr);
> + encode_sequence(&xdr, &args->seq_args, &hdr);
> status = encode_putfh(&xdr, args->fhandle, &hdr);
> if (status != 0)
> goto out;
> @@ -2302,11 +2452,12 @@ out:
> /*
> * Encode FS_LOCATIONS request
> */
> -static int nfs4_xdr_enc_fs_locations(struct rpc_rqst *req, __be32 *p, struct nfs4_fs_locations_arg *args)
> +static int nfs4_xdr_enc_fs_locations(struct rpc_rqst *req, __be32 *p,
> + struct nfs4_fs_locations_arg *args)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 0,
> + .minorversion = req->rq_task->tk_client->cl_mvers,
> };
> struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
> int replen;
> @@ -2315,6 +2466,7 @@ static int nfs4_xdr_enc_fs_locations(struct rpc_rqst *req, __be32 *p, struct nfs
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> nops = encode_compound_hdr(&xdr, &hdr);
> + encode_sequence(&xdr, &args->seq_args, &hdr);
> if ((status = encode_putfh(&xdr, args->dir_fh, &hdr)) != 0)
> goto out;
> if ((status = encode_lookup(&xdr, args->name, &hdr)) != 0)
> @@ -2325,7 +2477,7 @@ static int nfs4_xdr_enc_fs_locations(struct rpc_rqst *req, __be32 *p, struct nfs
> * toplevel_status + OP_PUTFH + status
> * + OP_LOOKUP + status + OP_GETATTR + status = 7
> */
> - replen = (RPC_REPHDRSIZE + auth->au_rslack + 7) << 2;
> + replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS4_enc_fsinfo_sz) << 2;
> xdr_inline_pages(&req->rq_rcv_buf, replen, &args->page,
> 0, PAGE_SIZE);
> out:
> @@ -3963,19 +4115,48 @@ static int decode_delegreturn(struct xdr_stream *xdr)
> return decode_op_hdr(xdr, OP_DELEGRETURN);
> }
>
> +#if defined(CONFIG_NFS_V4_1)
> +static int decode_sequence(struct xdr_stream *xdr,
> + struct nfs41_sequence_res *res,
> + struct rpc_rqst *rqstp)
> +{
> + if (rqstp->rq_task->tk_client->cl_mvers == 0)
> + return 0;
> +
> + /* stub */
> +
> + return 0;
> +}
> +#else /* CONFIG_NFS_V4_1 */
> +static inline int decode_sequence(struct xdr_stream *xdr,
> + struct nfs41_sequence_res *res,
> + struct rpc_rqst *rqstp)
> +{
> + return 0;
> +}
> +#endif /* CONFIG_NFS_V4_1 */
> +
> +/*
> + * END OF "GENERIC" DECODE ROUTINES.
> + */
> +
> /*
> * Decode OPEN_DOWNGRADE response
> */
> -static int nfs4_xdr_dec_open_downgrade(struct rpc_rqst *rqstp, __be32 *p, struct nfs_closeres *res)
> +static int nfs4_xdr_dec_open_downgrade(struct rpc_rqst *rqstp, __be32 *p,
> + struct nfs_closeres *res)
> {
> - struct xdr_stream xdr;
> - struct compound_hdr hdr;
> - int status;
> + struct xdr_stream xdr;
> + struct compound_hdr hdr;
> + int status;
>
> - xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
> - status = decode_compound_hdr(&xdr, &hdr);
> - if (status)
> - goto out;
> + xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
> + status = decode_compound_hdr(&xdr, &hdr);
> + if (status)
> + goto out;
> + status = decode_sequence(&xdr, &res->seq_res, rqstp);
> + if (status)
> + goto out;
> status = decode_putfh(&xdr);
> if (status)
> goto out;
> @@ -3988,20 +4169,21 @@ out:
> }
>
> /*
> - * END OF "GENERIC" DECODE ROUTINES.
> - */
> -
> -/*
> * Decode ACCESS response
> */
> -static int nfs4_xdr_dec_access(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_accessres *res)
> +static int nfs4_xdr_dec_access(struct rpc_rqst *rqstp, __be32 *p,
> + struct nfs4_accessres *res)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr;
> int status;
>
> xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
> - if ((status = decode_compound_hdr(&xdr, &hdr)) != 0)
> + status = decode_compound_hdr(&xdr, &hdr);
> + if (status)
> + goto out;
> + status = decode_sequence(&xdr, &res->seq_res, rqstp);
> + if (status)
> goto out;
> status = decode_putfh(&xdr);
> if (status != 0)
> @@ -4017,14 +4199,19 @@ out:
> /*
> * Decode LOOKUP response
> */
> -static int nfs4_xdr_dec_lookup(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_lookup_res *res)
> +static int nfs4_xdr_dec_lookup(struct rpc_rqst *rqstp, __be32 *p,
> + struct nfs4_lookup_res *res)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr;
> int status;
>
> xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
> - if ((status = decode_compound_hdr(&xdr, &hdr)) != 0)
> + status = decode_compound_hdr(&xdr, &hdr);
> + if (status)
> + goto out;
> + status = decode_sequence(&xdr, &res->seq_res, rqstp);
> + if (status)
> goto out;
> if ((status = decode_putfh(&xdr)) != 0)
> goto out;
> @@ -4040,14 +4227,19 @@ out:
> /*
> * Decode LOOKUP_ROOT response
> */
> -static int nfs4_xdr_dec_lookup_root(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_lookup_res *res)
> +static int nfs4_xdr_dec_lookup_root(struct rpc_rqst *rqstp, __be32 *p,
> + struct nfs4_lookup_res *res)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr;
> int status;
>
> xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
> - if ((status = decode_compound_hdr(&xdr, &hdr)) != 0)
> + status = decode_compound_hdr(&xdr, &hdr);
> + if (status)
> + goto out;
> + status = decode_sequence(&xdr, &res->seq_res, rqstp);
> + if (status)
> goto out;
> if ((status = decode_putrootfh(&xdr)) != 0)
> goto out;
> @@ -4060,14 +4252,19 @@ out:
> /*
> * Decode REMOVE response
> */
> -static int nfs4_xdr_dec_remove(struct rpc_rqst *rqstp, __be32 *p, struct nfs_removeres *res)
> +static int nfs4_xdr_dec_remove(struct rpc_rqst *rqstp, __be32 *p,
> + struct nfs_removeres *res)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr;
> int status;
>
> xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
> - if ((status = decode_compound_hdr(&xdr, &hdr)) != 0)
> + status = decode_compound_hdr(&xdr, &hdr);
> + if (status)
> + goto out;
> + status = decode_sequence(&xdr, &res->seq_res, rqstp);
> + if (status)
> goto out;
> if ((status = decode_putfh(&xdr)) != 0)
> goto out;
> @@ -4081,14 +4278,19 @@ out:
> /*
> * Decode RENAME response
> */
> -static int nfs4_xdr_dec_rename(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_rename_res *res)
> +static int nfs4_xdr_dec_rename(struct rpc_rqst *rqstp, __be32 *p,
> + struct nfs4_rename_res *res)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr;
> int status;
> -
> +
> xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
> - if ((status = decode_compound_hdr(&xdr, &hdr)) != 0)
> + status = decode_compound_hdr(&xdr, &hdr);
> + if (status)
> + goto out;
> + status = decode_sequence(&xdr, &res->seq_res, rqstp);
> + if (status)
> goto out;
> if ((status = decode_putfh(&xdr)) != 0)
> goto out;
> @@ -4111,14 +4313,19 @@ out:
> /*
> * Decode LINK response
> */
> -static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_link_res *res)
> +static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, __be32 *p,
> + struct nfs4_link_res *res)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr;
> int status;
>
> xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
> - if ((status = decode_compound_hdr(&xdr, &hdr)) != 0)
> + status = decode_compound_hdr(&xdr, &hdr);
> + if (status)
> + goto out;
> + status = decode_sequence(&xdr, &res->seq_res, rqstp);
> + if (status)
> goto out;
> if ((status = decode_putfh(&xdr)) != 0)
> goto out;
> @@ -4144,14 +4351,19 @@ out:
> /*
> * Decode CREATE response
> */
> -static int nfs4_xdr_dec_create(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_create_res *res)
> +static int nfs4_xdr_dec_create(struct rpc_rqst *rqstp, __be32 *p,
> + struct nfs4_create_res *res)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr;
> int status;
> -
> +
> xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
> - if ((status = decode_compound_hdr(&xdr, &hdr)) != 0)
> + status = decode_compound_hdr(&xdr, &hdr);
> + if (status)
> + goto out;
> + status = decode_sequence(&xdr, &res->seq_res, rqstp);
> + if (status)
> goto out;
> if ((status = decode_putfh(&xdr)) != 0)
> goto out;
> @@ -4181,7 +4393,8 @@ static int nfs4_xdr_dec_symlink(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_c
> /*
> * Decode GETATTR response
> */
> -static int nfs4_xdr_dec_getattr(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_getattr_res *res)
> +static int nfs4_xdr_dec_getattr(struct rpc_rqst *rqstp, __be32 *p,
> + struct nfs4_getattr_res *res)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr;
> @@ -4191,56 +4404,65 @@ static int nfs4_xdr_dec_getattr(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_g
> status = decode_compound_hdr(&xdr, &hdr);
> if (status)
> goto out;
> + status = decode_sequence(&xdr, &res->seq_res, rqstp);
> + if (status)
> + goto out;
> status = decode_putfh(&xdr);
> if (status)
> goto out;
> status = decode_getfattr(&xdr, res->fattr, res->server);
> out:
> return status;
> -
> }
>
> /*
> * Encode an SETACL request
> */
> static int
> -nfs4_xdr_enc_setacl(struct rpc_rqst *req, __be32 *p, struct nfs_setaclargs *args)
> +nfs4_xdr_enc_setacl(struct rpc_rqst *req, __be32 *p,
> + struct nfs_setaclargs *args)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr = {
> - .nops = 0,
> + .minorversion = req->rq_task->tk_client->cl_mvers,
> };
> int status;
> __be32 *nops;
>
> xdr_init_encode(&xdr, &req->rq_snd_buf, p);
> nops = encode_compound_hdr(&xdr, &hdr);
> + encode_sequence(&xdr, &args->seq_args, &hdr);
> status = encode_putfh(&xdr, args->fh, &hdr);
> if (status)
> goto out;
> status = encode_setacl(&xdr, args, &hdr);
> out:
> - encode_nops(nops, &hdr);
> return status;
> }
> +
> /*
> * Decode SETACL response
> */
> static int
> -nfs4_xdr_dec_setacl(struct rpc_rqst *rqstp, __be32 *p, void *res)
> +nfs4_xdr_dec_setacl(struct rpc_rqst *rqstp, __be32 *p,
> + struct nfs_setaclres *res)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr;
> + struct nfs_setattrres *sattrp = NULL;
> int status;
>
> xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
> status = decode_compound_hdr(&xdr, &hdr);
> if (status)
> goto out;
> + status = decode_sequence(&xdr, &res->seq_res, rqstp);
> + if (status)
> + goto out;
> status = decode_putfh(&xdr);
> if (status)
> goto out;
> - status = decode_setattr(&xdr, res);
> + status = decode_setattr(&xdr, sattrp);
> out:
> return status;
> }
> @@ -4249,7 +4471,8 @@ out:
> * Decode GETACL response
> */
> static int
> -nfs4_xdr_dec_getacl(struct rpc_rqst *rqstp, __be32 *p, size_t *acl_len)
> +nfs4_xdr_dec_getacl(struct rpc_rqst *rqstp, __be32 *p,
> + struct nfs_getaclres *res)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr;
> @@ -4259,10 +4482,13 @@ nfs4_xdr_dec_getacl(struct rpc_rqst *rqstp, __be32 *p, size_t *acl_len)
> status = decode_compound_hdr(&xdr, &hdr);
> if (status)
> goto out;
> + status = decode_sequence(&xdr, &res->seq_res, rqstp);
> + if (status)
> + goto out;
> status = decode_putfh(&xdr);
> if (status)
> goto out;
> - status = decode_getacl(&xdr, rqstp, acl_len);
> + status = decode_getacl(&xdr, rqstp, res->acl_len);
>
> out:
> return status;
> @@ -4271,16 +4497,20 @@ out:
> /*
> * Decode CLOSE response
> */
> -static int nfs4_xdr_dec_close(struct rpc_rqst *rqstp, __be32 *p, struct nfs_closeres *res)
> +static int nfs4_xdr_dec_close(struct rpc_rqst *rqstp, __be32 *p,
> + struct nfs_closeres *res)
> {
> - struct xdr_stream xdr;
> - struct compound_hdr hdr;
> - int status;
> + struct xdr_stream xdr;
> + struct compound_hdr hdr;
> + int status;
>
> - xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
> - status = decode_compound_hdr(&xdr, &hdr);
> - if (status)
> - goto out;
> + xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
> + status = decode_compound_hdr(&xdr, &hdr);
> + if (status)
> + goto out;
> + status = decode_sequence(&xdr, &res->seq_res, rqstp);
> + if (status)
> + goto out;
> status = decode_putfh(&xdr);
> if (status)
> goto out;
> @@ -4301,16 +4531,20 @@ out:
> /*
> * Decode OPEN response
> */
> -static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, __be32 *p, struct nfs_openres *res)
> +static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, __be32 *p,
> + struct nfs_openres *res)
> {
> - struct xdr_stream xdr;
> - struct compound_hdr hdr;
> - int status;
> + struct xdr_stream xdr;
> + struct compound_hdr hdr;
> + int status;
>
> - xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
> - status = decode_compound_hdr(&xdr, &hdr);
> - if (status)
> - goto out;
> + xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
> + status = decode_compound_hdr(&xdr, &hdr);
> + if (status)
> + goto out;
> + status = decode_sequence(&xdr, &res->seq_res, rqstp);
> + if (status)
> + goto out;
> status = decode_putfh(&xdr);
> if (status)
> goto out;
> @@ -4355,16 +4589,20 @@ out:
> /*
> * Decode OPEN response
> */
> -static int nfs4_xdr_dec_open_noattr(struct rpc_rqst *rqstp, __be32 *p, struct nfs_openres *res)
> +static int nfs4_xdr_dec_open_noattr(struct rpc_rqst *rqstp, __be32 *p,
> + struct nfs_openres *res)
> {
> - struct xdr_stream xdr;
> - struct compound_hdr hdr;
> - int status;
> + struct xdr_stream xdr;
> + struct compound_hdr hdr;
> + int status;
>
> - xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
> - status = decode_compound_hdr(&xdr, &hdr);
> - if (status)
> - goto out;
> + xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
> + status = decode_compound_hdr(&xdr, &hdr);
> + if (status)
> + goto out;
> + status = decode_sequence(&xdr, &res->seq_res, rqstp);
> + if (status)
> + goto out;
> status = decode_putfh(&xdr);
> if (status)
> goto out;
> @@ -4379,16 +4617,20 @@ out:
> /*
> * Decode SETATTR response
> */
> -static int nfs4_xdr_dec_setattr(struct rpc_rqst *rqstp, __be32 *p, struct nfs_setattrres *res)
> +static int nfs4_xdr_dec_setattr(struct rpc_rqst *rqstp, __be32 *p,
> + struct nfs_setattrres *res)
> {
> - struct xdr_stream xdr;
> - struct compound_hdr hdr;
> - int status;
> + struct xdr_stream xdr;
> + struct compound_hdr hdr;
> + int status;
>
> - xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
> - status = decode_compound_hdr(&xdr, &hdr);
> - if (status)
> - goto out;
> + xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
> + status = decode_compound_hdr(&xdr, &hdr);
> + if (status)
> + goto out;
> + status = decode_sequence(&xdr, &res->seq_res, rqstp);
> + if (status)
> + goto out;
> status = decode_putfh(&xdr);
> if (status)
> goto out;
> @@ -4405,7 +4647,8 @@ out:
> /*
> * Decode LOCK response
> */
> -static int nfs4_xdr_dec_lock(struct rpc_rqst *rqstp, __be32 *p, struct nfs_lock_res *res)
> +static int nfs4_xdr_dec_lock(struct rpc_rqst *rqstp, __be32 *p,
> + struct nfs_lock_res *res)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr;
> @@ -4415,6 +4658,9 @@ static int nfs4_xdr_dec_lock(struct rpc_rqst *rqstp, __be32 *p, struct nfs_lock_
> status = decode_compound_hdr(&xdr, &hdr);
> if (status)
> goto out;
> + status = decode_sequence(&xdr, &res->seq_res, rqstp);
> + if (status)
> + goto out;
> status = decode_putfh(&xdr);
> if (status)
> goto out;
> @@ -4426,7 +4672,8 @@ out:
> /*
> * Decode LOCKT response
> */
> -static int nfs4_xdr_dec_lockt(struct rpc_rqst *rqstp, __be32 *p, struct nfs_lockt_res *res)
> +static int nfs4_xdr_dec_lockt(struct rpc_rqst *rqstp, __be32 *p,
> + struct nfs_lockt_res *res)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr;
> @@ -4436,6 +4683,9 @@ static int nfs4_xdr_dec_lockt(struct rpc_rqst *rqstp, __be32 *p, struct nfs_lock
> status = decode_compound_hdr(&xdr, &hdr);
> if (status)
> goto out;
> + status = decode_sequence(&xdr, &res->seq_res, rqstp);
> + if (status)
> + goto out;
> status = decode_putfh(&xdr);
> if (status)
> goto out;
> @@ -4447,7 +4697,8 @@ out:
> /*
> * Decode LOCKU response
> */
> -static int nfs4_xdr_dec_locku(struct rpc_rqst *rqstp, __be32 *p, struct nfs_locku_res *res)
> +static int nfs4_xdr_dec_locku(struct rpc_rqst *rqstp, __be32 *p,
> + struct nfs_locku_res *res)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr;
> @@ -4457,6 +4708,9 @@ static int nfs4_xdr_dec_locku(struct rpc_rqst *rqstp, __be32 *p, struct nfs_lock
> status = decode_compound_hdr(&xdr, &hdr);
> if (status)
> goto out;
> + status = decode_sequence(&xdr, &res->seq_res, rqstp);
> + if (status)
> + goto out;
> status = decode_putfh(&xdr);
> if (status)
> goto out;
> @@ -4468,7 +4722,8 @@ out:
> /*
> * Decode READLINK response
> */
> -static int nfs4_xdr_dec_readlink(struct rpc_rqst *rqstp, __be32 *p, void *res)
> +static int nfs4_xdr_dec_readlink(struct rpc_rqst *rqstp, __be32 *p,
> + struct nfs4_readlink_res *res)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr;
> @@ -4478,6 +4733,9 @@ static int nfs4_xdr_dec_readlink(struct rpc_rqst *rqstp, __be32 *p, void *res)
> status = decode_compound_hdr(&xdr, &hdr);
> if (status)
> goto out;
> + status = decode_sequence(&xdr, &res->seq_res, rqstp);
> + if (status)
> + goto out;
> status = decode_putfh(&xdr);
> if (status)
> goto out;
> @@ -4489,7 +4747,8 @@ out:
> /*
> * Decode READDIR response
> */
> -static int nfs4_xdr_dec_readdir(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_readdir_res *res)
> +static int nfs4_xdr_dec_readdir(struct rpc_rqst *rqstp, __be32 *p,
> + struct nfs4_readdir_res *res)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr;
> @@ -4499,6 +4758,9 @@ static int nfs4_xdr_dec_readdir(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_r
> status = decode_compound_hdr(&xdr, &hdr);
> if (status)
> goto out;
> + status = decode_sequence(&xdr, &res->seq_res, rqstp);
> + if (status)
> + goto out;
> status = decode_putfh(&xdr);
> if (status)
> goto out;
> @@ -4510,7 +4772,8 @@ out:
> /*
> * Decode Read response
> */
> -static int nfs4_xdr_dec_read(struct rpc_rqst *rqstp, __be32 *p, struct nfs_readres *res)
> +static int nfs4_xdr_dec_read(struct rpc_rqst *rqstp, __be32 *p,
> + struct nfs_readres *res)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr;
> @@ -4520,6 +4783,9 @@ static int nfs4_xdr_dec_read(struct rpc_rqst *rqstp, __be32 *p, struct nfs_readr
> status = decode_compound_hdr(&xdr, &hdr);
> if (status)
> goto out;
> + status = decode_sequence(&xdr, &res->seq_res, rqstp);
> + if (status)
> + goto out;
> status = decode_putfh(&xdr);
> if (status)
> goto out;
> @@ -4533,7 +4799,8 @@ out:
> /*
> * Decode WRITE response
> */
> -static int nfs4_xdr_dec_write(struct rpc_rqst *rqstp, __be32 *p, struct nfs_writeres *res)
> +static int nfs4_xdr_dec_write(struct rpc_rqst *rqstp, __be32 *p,
> + struct nfs_writeres *res)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr;
> @@ -4543,6 +4810,9 @@ static int nfs4_xdr_dec_write(struct rpc_rqst *rqstp, __be32 *p, struct nfs_writ
> status = decode_compound_hdr(&xdr, &hdr);
> if (status)
> goto out;
> + status = decode_sequence(&xdr, &res->seq_res, rqstp);
> + if (status)
> + goto out;
> status = decode_putfh(&xdr);
> if (status)
> goto out;
> @@ -4559,7 +4829,8 @@ out:
> /*
> * Decode COMMIT response
> */
> -static int nfs4_xdr_dec_commit(struct rpc_rqst *rqstp, __be32 *p, struct nfs_writeres *res)
> +static int nfs4_xdr_dec_commit(struct rpc_rqst *rqstp, __be32 *p,
> + struct nfs_writeres *res)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr;
> @@ -4569,6 +4840,9 @@ static int nfs4_xdr_dec_commit(struct rpc_rqst *rqstp, __be32 *p, struct nfs_wri
> status = decode_compound_hdr(&xdr, &hdr);
> if (status)
> goto out;
> + status = decode_sequence(&xdr, &res->seq_res, rqstp);
> + if (status)
> + goto out;
> status = decode_putfh(&xdr);
> if (status)
> goto out;
> @@ -4583,7 +4857,8 @@ out:
> /*
> * FSINFO request
> */
> -static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, __be32 *p, struct nfs_fsinfo *fsinfo)
> +static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, __be32 *p,
> + struct nfs4_fsinfo_res *res)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr;
> @@ -4592,16 +4867,19 @@ static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, __be32 *p, struct nfs_fsinf
> xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
> status = decode_compound_hdr(&xdr, &hdr);
> if (!status)
> + status = decode_sequence(&xdr, &res->seq_res, req);
> + if (!status)
> status = decode_putfh(&xdr);
> if (!status)
> - status = decode_fsinfo(&xdr, fsinfo);
> + status = decode_fsinfo(&xdr, res->fsinfo);
> return status;
> }
>
> /*
> * PATHCONF request
> */
> -static int nfs4_xdr_dec_pathconf(struct rpc_rqst *req, __be32 *p, struct nfs_pathconf *pathconf)
> +static int nfs4_xdr_dec_pathconf(struct rpc_rqst *req, __be32 *p,
> + struct nfs4_pathconf_res *res)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr;
> @@ -4610,16 +4888,19 @@ static int nfs4_xdr_dec_pathconf(struct rpc_rqst *req, __be32 *p, struct nfs_pat
> xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
> status = decode_compound_hdr(&xdr, &hdr);
> if (!status)
> + status = decode_sequence(&xdr, &res->seq_res, req);
> + if (!status)
> status = decode_putfh(&xdr);
> if (!status)
> - status = decode_pathconf(&xdr, pathconf);
> + status = decode_pathconf(&xdr, res->pathconf);
> return status;
> }
>
> /*
> * STATFS request
> */
> -static int nfs4_xdr_dec_statfs(struct rpc_rqst *req, __be32 *p, struct nfs_fsstat *fsstat)
> +static int nfs4_xdr_dec_statfs(struct rpc_rqst *req, __be32 *p,
> + struct nfs4_statfs_res *res)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr;
> @@ -4628,23 +4909,30 @@ static int nfs4_xdr_dec_statfs(struct rpc_rqst *req, __be32 *p, struct nfs_fssta
> xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
> status = decode_compound_hdr(&xdr, &hdr);
> if (!status)
> + status = decode_sequence(&xdr, &res->seq_res, req);
> + if (!status)
> status = decode_putfh(&xdr);
> if (!status)
> - status = decode_statfs(&xdr, fsstat);
> + status = decode_statfs(&xdr, res->fsstat);
> return status;
> }
>
> /*
> * GETATTR_BITMAP request
> */
> -static int nfs4_xdr_dec_server_caps(struct rpc_rqst *req, __be32 *p, struct nfs4_server_caps_res *res)
> +static int nfs4_xdr_dec_server_caps(struct rpc_rqst *req, __be32 *p,
> + struct nfs4_server_caps_res *res)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr;
> int status;
>
> xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
> - if ((status = decode_compound_hdr(&xdr, &hdr)) != 0)
> + status = decode_compound_hdr(&xdr, &hdr);
> + if (status)
> + goto out;
> + status = decode_sequence(&xdr, &res->seq_res, req);
> + if (status)
> goto out;
> if ((status = decode_putfh(&xdr)) != 0)
> goto out;
> @@ -4709,7 +4997,8 @@ static int nfs4_xdr_dec_setclientid_confirm(struct rpc_rqst *req, __be32 *p, str
> /*
> * DELEGRETURN request
> */
> -static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_delegreturnres *res)
> +static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, __be32 *p,
> + struct nfs4_delegreturnres *res)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr;
> @@ -4717,7 +5006,10 @@ static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, __be32 *p, struct nf
>
> xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
> status = decode_compound_hdr(&xdr, &hdr);
> - if (status != 0)
> + if (status)
> + goto out;
> + status = decode_sequence(&xdr, &res->seq_res, rqstp);
> + if (status)
> goto out;
> status = decode_putfh(&xdr);
> if (status != 0)
> @@ -4731,7 +5023,8 @@ out:
> /*
> * FS_LOCATIONS request
> */
> -static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, __be32 *p, struct nfs4_fs_locations *res)
> +static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, __be32 *p,
> + struct nfs4_fs_locations_res *res)
> {
> struct xdr_stream xdr;
> struct compound_hdr hdr;
> @@ -4739,14 +5032,18 @@ static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, __be32 *p, struct nfs
>
> xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
> status = decode_compound_hdr(&xdr, &hdr);
> - if (status != 0)
> + if (status)
> + goto out;
> + status = decode_sequence(&xdr, &res->seq_res, req);
> + if (status)
> goto out;
> if ((status = decode_putfh(&xdr)) != 0)
> goto out;
> if ((status = decode_lookup(&xdr)) != 0)
> goto out;
> xdr_enter_page(&xdr, PAGE_SIZE);
> - status = decode_getfattr(&xdr, &res->fattr, res->server);
> + status = decode_getfattr(&xdr, &res->fs_locations->fattr,
> + res->fs_locations->server);
> out:
> return status;
> }
> @@ -4877,10 +5174,10 @@ nfs4_stat_to_errno(int stat)
> #define PROC(proc, argtype, restype) \
> [NFSPROC4_CLNT_##proc] = { \
> .p_proc = NFSPROC4_COMPOUND, \
> - .p_encode = (kxdrproc_t) nfs4_xdr_##argtype, \
> - .p_decode = (kxdrproc_t) nfs4_xdr_##restype, \
> - .p_arglen = NFS4_##argtype##_sz, \
> - .p_replen = NFS4_##restype##_sz, \
> + .p_encode = (kxdrproc_t) nfs4##_xdr_##argtype, \
> + .p_decode = (kxdrproc_t) nfs4##_xdr_##restype, \
> + .p_arglen = NFS4##_##argtype##_sz, \
> + .p_replen = NFS4##_##restype##_sz, \
> .p_statidx = NFSPROC4_CLNT_##proc, \
> .p_name = #proc, \
> }
> @@ -4922,11 +5219,6 @@ struct rpc_procinfo nfs4_procedures[] = {
> PROC(FS_LOCATIONS, enc_fs_locations, dec_fs_locations),
> };
>
> -#if defined(CONFIG_NFS_V4_1)
> -struct rpc_procinfo nfs41_procedures[] = {
> -};
> -#endif /* CONFIG_NFS_V4_1 */
> -
> struct rpc_version nfs_version4 = {
> .number = 4,
> .nrprocs = ARRAY_SIZE(nfs4_procedures),
> @@ -4936,8 +5228,9 @@ struct rpc_version nfs_version4 = {
> #ifdef CONFIG_NFS_V4_1
> struct rpc_version nfs_version41 = {
> .number = 4,
> - .nrprocs = ARRAY_SIZE(nfs41_procedures),
> - .procs = nfs41_procedures
> + .minorversion = 1,
> + .nrprocs = ARRAY_SIZE(nfs4_procedures),
> + .procs = nfs4_procedures
> };
>
> #endif /* CONFIG_NFS_V4_1 */
> diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
> index 99d4f9e..77c03a4 100644
> --- a/include/linux/sunrpc/clnt.h
> +++ b/include/linux/sunrpc/clnt.h
> @@ -32,6 +32,7 @@ struct rpc_clnt {
> struct rpc_procinfo * cl_procinfo; /* procedure info */
> u32 cl_prog, /* RPC program number */
> cl_vers, /* RPC version number */
> + cl_mvers, /* RPC minorversion number */
review 11-14: this is problemtic.
Trond suggest passing a pointer to the nfs_server (as void *cl_private)
> cl_maxproc; /* max procedure number */
>
> char * cl_server; /* server machine name */
> @@ -82,6 +83,7 @@ get_rpc_version(struct rpc_program *prog, u32 vers, int minorvers)
>
> struct rpc_version {
> u32 number; /* version number */
> + u32 minorversion; /* minorversion number */
review 11-14: remove this.
> unsigned int nrprocs; /* number of procs */
> struct rpc_procinfo * procs; /* procedure array */
> };
> diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
> index 44f251d..0c8e5f1 100644
> --- a/net/sunrpc/clnt.c
> +++ b/net/sunrpc/clnt.c
> @@ -177,6 +177,7 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru
> clnt->cl_protname = program->name;
> clnt->cl_prog = args->prognumber ? : program->number;
> clnt->cl_vers = version->number;
> + clnt->cl_mvers = version->minorversion;
> clnt->cl_stats = program->stats;
> clnt->cl_metrics = rpc_alloc_iostats(clnt);
> err = -ENOMEM;
> @@ -491,6 +492,7 @@ struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old,
> clnt->cl_protname = program->name;
> clnt->cl_prog = program->number;
> clnt->cl_vers = version->number;
> + clnt->cl_mvers = version->minorversion;
> clnt->cl_stats = program->stats;
> err = rpc_ping(clnt, RPC_TASK_SOFT);
> if (err != 0) {
^ permalink raw reply [flat|nested] 115+ messages in thread
* [RFC 24/85] nfs41: stubs for nfs41 procedures
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (20 preceding siblings ...)
2008-11-10 20:21 ` [RFC 23/85] nfs41: minorversion support for xdr Benny Halevy
@ 2008-11-10 20:22 ` Benny Halevy
2008-11-10 20:22 ` [RFC 25/85] nfs41: make nfs4_wait_bit_killable public Benny Halevy
` (63 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:22 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
Signed-off-by: Andy Adamson<andros@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/nfs4_fs.h | 2 ++
fs/nfs/nfs4proc.c | 26 ++++++++++++++++++++++++++
2 files changed, 28 insertions(+), 0 deletions(-)
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index a28427f..dd3a6d0 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -192,6 +192,8 @@ extern struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops;
extern void nfs4_put_session(struct nfs4_session **session);
extern void nfs4_get_session(struct nfs_client *clp);
extern struct nfs4_session *nfs4_alloc_session(void);
+extern int nfs4_proc_create_session(struct nfs4_session *);
+extern int nfs4_proc_destroy_session(struct nfs4_session *);
#endif /* CONFIG_NFS_V4_1 */
extern const u32 nfs4_fattr_bitmap[2];
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index d26f61d..6418aa8 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -3825,6 +3825,11 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
}
#ifdef CONFIG_NFS_V4_1
+static int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)
+{
+ return -1; /* stub */
+}
+
/*
* Initialize slot table
*
@@ -3947,6 +3952,27 @@ void nfs4_get_session(struct nfs_client *clp)
if (clp->cl_minorversion == 1)
atomic_inc(&clp->cl_session->ref_count);
}
+
+int nfs4_proc_create_session(struct nfs4_session *session)
+{
+ return -1; /* stub */
+}
+
+int nfs4_proc_destroy_session(struct nfs4_session *session)
+{
+ return -1; /* stub */
+}
+
+static int nfs4_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred)
+{
+ return -1; /* stub */
+}
+
+static int nfs41_proc_async_sequence(struct nfs_client *clp,
+ struct rpc_cred *cred)
+{
+ return -1; /* stub */
+}
#endif /* CONFIG_NFS_V4_1 */
struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops = {
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 25/85] nfs41: make nfs4_wait_bit_killable public
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (21 preceding siblings ...)
2008-11-10 20:22 ` [RFC 24/85] nfs41: stubs for nfs41 procedures Benny Halevy
@ 2008-11-10 20:22 ` Benny Halevy
2008-11-10 20:22 ` [RFC 26/85] nfs41: introduce nfs4_call_sync Benny Halevy
` (62 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:22 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
From: Rahul Iyer <iyer@netapp.com>
nfs4_wait_bit_killable to be used by NFSv4.1 session recover logic.
Signed-off-by: Rahul Iyer <iyer@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/nfs4_fs.h | 1 +
fs/nfs/nfs4proc.c | 2 +-
2 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index dd3a6d0..bef2fca 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -179,6 +179,7 @@ extern int nfs4_proc_setclientid(struct nfs_client *, u32, unsigned short, struc
extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct rpc_cred *);
extern int nfs4_proc_async_renew(struct nfs_client *, struct rpc_cred *);
extern int nfs4_proc_renew(struct nfs_client *, struct rpc_cred *);
+extern int nfs4_wait_bit_killable(void *);
extern int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait);
extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *);
extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 6418aa8..1cc639e 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -2929,7 +2929,7 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server)
return 0;
}
-static int nfs4_wait_bit_killable(void *word)
+int nfs4_wait_bit_killable(void *word)
{
if (fatal_signal_pending(current))
return -ERESTARTSYS;
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 26/85] nfs41: introduce nfs4_call_sync
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (22 preceding siblings ...)
2008-11-10 20:22 ` [RFC 25/85] nfs41: make nfs4_wait_bit_killable public Benny Halevy
@ 2008-11-10 20:22 ` Benny Halevy
2008-11-17 13:49 ` [pnfs] " Benny Halevy
2008-11-10 20:22 ` [RFC 27/85] nfs41: nfs4_setup_sequence Benny Halevy
` (61 subsequent siblings)
85 siblings, 1 reply; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:22 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
Use nfs4_call_sync rather than rpc_call_sync to provide
for a nfs41 sessions-enabled interface for sessions manipulation.
The nfs41 rpc logic uses the rpc_call_validate_args method to
recover and create the session, as well as selecting a free slot id
and the rpc_call_done to free the slot and update slot table
related metadata.
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/nfs4proc.c | 127 ++++++++++++++++++++++++++++++++++++++++-------------
1 files changed, 96 insertions(+), 31 deletions(-)
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 1cc639e..3b7c7fa 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -349,6 +349,19 @@ nfs4_find_slot(struct nfs4_slot_table *tbl, struct rpc_task *task)
#endif /* CONFIG_NFS_V4_1 */
+static int _nfs4_call_sync(struct nfs_server *server,
+ struct rpc_message *msg,
+ struct nfs41_sequence_args *args,
+ struct nfs41_sequence_res *res,
+ int cache_reply)
+{
+ return rpc_call_sync(server->client, msg, 0);
+}
+
+#define nfs4_call_sync(server, msg, args, res, cache_reply) \
+ _nfs4_call_sync((server), (msg), &(args)->seq_args, \
+ &(res)->seq_res, (cache_reply))
+
static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo)
{
struct nfs_inode *nfsi = NFS_I(dir);
@@ -1318,7 +1331,7 @@ static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
} else
memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid));
- status = rpc_call_sync(server->client, &msg, 0);
+ status = nfs4_call_sync(server, &msg, &arg, &res, 1);
if (status == 0 && state != NULL)
renew_lease(server, timestamp);
return status;
@@ -1620,15 +1633,19 @@ out_drop:
static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle)
{
+ struct nfs4_server_caps_arg args = {
+ .fhandle = fhandle,
+ };
struct nfs4_server_caps_res res = {};
struct rpc_message msg = {
.rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_SERVER_CAPS),
- .rpc_argp = fhandle,
+ .rpc_argp = &args,
.rpc_resp = &res,
};
int status;
- status = rpc_call_sync(server->client, &msg, 0);
+ dprintk("--> %s\n", __func__);
+ status = nfs4_call_sync(server, &msg, &args, &res, 0);
if (status == 0) {
memcpy(server->attr_bitmask, res.attr_bitmask, sizeof(server->attr_bitmask));
if (res.attr_bitmask[0] & FATTR4_WORD0_ACL)
@@ -1639,6 +1656,8 @@ static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f
server->caps |= NFS_CAP_SYMLINKS;
server->acl_bitmask = res.acl_bitmask;
}
+
+ dprintk("<-- %s status= %d\n", __func__, status);
return status;
}
@@ -1670,8 +1689,13 @@ static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
.rpc_argp = &args,
.rpc_resp = &res,
};
+ int status;
+
+ dprintk("--> %s\n", __func__);
nfs_fattr_init(info->fattr);
- return rpc_call_sync(server->client, &msg, 0);
+ status = nfs4_call_sync(server, &msg, &args, &res, 0);
+ dprintk("<-- %s status= %d\n", __func__, status);
+ return status;
}
static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
@@ -1759,9 +1783,12 @@ static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
.rpc_argp = &args,
.rpc_resp = &res,
};
+ int status;
nfs_fattr_init(fattr);
- return rpc_call_sync(server->client, &msg, 0);
+ status = nfs4_call_sync(server, &msg, &args, &res, 0);
+
+ return status;
}
static int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
@@ -1843,10 +1870,10 @@ static int _nfs4_proc_lookupfh(struct nfs_server *server, const struct nfs_fh *d
};
nfs_fattr_init(fattr);
-
dprintk("NFS call lookupfh %s\n", name->name);
- status = rpc_call_sync(server->client, &msg, 0);
+ status = nfs4_call_sync(server, &msg, &args, &res, 0);
dprintk("NFS reply lookupfh: %d\n", status);
+
return status;
}
@@ -1931,7 +1958,7 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry
args.access |= NFS4_ACCESS_EXECUTE;
}
nfs_fattr_init(&fattr);
- status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
+ status = nfs4_call_sync(server, &msg, &args, &res, 0);
if (!status) {
entry->mask = 0;
if (res.access & NFS4_ACCESS_READ)
@@ -1991,13 +2018,17 @@ static int _nfs4_proc_readlink(struct inode *inode, struct page *page,
.pglen = pglen,
.pages = &page,
};
+ struct nfs4_readlink_res res;
struct rpc_message msg = {
.rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_READLINK),
.rpc_argp = &args,
- .rpc_resp = NULL,
+ .rpc_resp = &res,
};
+ int status;
+
+ status = nfs4_call_sync(server, &msg, &args, &res, 0);
- return rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
+ return status;
}
static int nfs4_proc_readlink(struct inode *inode, struct page *page,
@@ -2090,11 +2121,12 @@ static int _nfs4_proc_remove(struct inode *dir, struct qstr *name)
int status;
nfs_fattr_init(&res.dir_attr);
- status = rpc_call_sync(server->client, &msg, 0);
+ status = nfs4_call_sync(server, &msg, &args, &res, 1);
if (status == 0) {
update_changeattr(dir, &res.cinfo);
nfs_post_op_update_inode(dir, &res.dir_attr);
}
+
return status;
}
@@ -2158,14 +2190,14 @@ static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name,
nfs_fattr_init(res.old_fattr);
nfs_fattr_init(res.new_fattr);
- status = rpc_call_sync(server->client, &msg, 0);
-
+ status = nfs4_call_sync(server, &msg, &arg, &res, 1);
if (!status) {
update_changeattr(old_dir, &res.old_cinfo);
nfs_post_op_update_inode(old_dir, res.old_fattr);
update_changeattr(new_dir, &res.new_cinfo);
nfs_post_op_update_inode(new_dir, res.new_fattr);
}
+
return status;
}
@@ -2207,7 +2239,7 @@ static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *
nfs_fattr_init(res.fattr);
nfs_fattr_init(res.dir_attr);
- status = rpc_call_sync(server->client, &msg, 0);
+ status = nfs4_call_sync(server, &msg, &arg, &res, 1);
if (!status) {
update_changeattr(dir, &res.cinfo);
nfs_post_op_update_inode(dir, res.dir_attr);
@@ -2269,7 +2301,9 @@ static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir,
static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_createdata *data)
{
- int status = rpc_call_sync(NFS_CLIENT(dir), &data->msg, 0);
+ struct nfs_server *server = NFS_SERVER(dir);
+ int status = nfs4_call_sync(server, &data->msg,
+ &data->arg, &data->res, 1);
if (status == 0) {
update_changeattr(dir, &data->res.dir_cinfo);
nfs_post_op_update_inode(dir, data->res.dir_fattr);
@@ -2378,12 +2412,14 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
dentry->d_parent->d_name.name,
dentry->d_name.name,
(unsigned long long)cookie);
+
nfs4_setup_readdir(cookie, NFS_COOKIEVERF(dir), dentry, &args);
res.pgbase = args.pgbase;
- status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+ status = nfs4_call_sync(server, &msg, &args, &res, 0);
if (status == 0)
memcpy(NFS_COOKIEVERF(dir), res.verifier.data, NFS4_VERIFIER_SIZE);
+
nfs_invalidate_atime(dir);
dprintk("%s: returns %d\n", __func__, status);
@@ -2458,14 +2494,20 @@ static int _nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
.fh = fhandle,
.bitmask = server->attr_bitmask,
};
+ struct nfs4_statfs_res res = {
+ .fsstat = fsstat,
+ };
struct rpc_message msg = {
.rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_STATFS),
.rpc_argp = &args,
- .rpc_resp = fsstat,
+ .rpc_resp = &res,
};
+ int status;
nfs_fattr_init(fsstat->fattr);
- return rpc_call_sync(server->client, &msg, 0);
+ status = nfs4_call_sync(server, &msg, &args, &res, 0);
+
+ return status;
}
static int nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsstat *fsstat)
@@ -2487,13 +2529,21 @@ static int _nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle,
.fh = fhandle,
.bitmask = server->attr_bitmask,
};
+ struct nfs4_fsinfo_res res = {
+ .fsinfo = fsinfo,
+ };
struct rpc_message msg = {
.rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_FSINFO),
.rpc_argp = &args,
- .rpc_resp = fsinfo,
+ .rpc_resp = &res,
};
+ int status;
+
+ dprintk("--> %s\n", __func__);
+ status = nfs4_call_sync(server, &msg, &args, &res, 0);
- return rpc_call_sync(server->client, &msg, 0);
+ dprintk("<-- %s status= %d\n", __func__, status);
+ return status;
}
static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo)
@@ -2522,20 +2572,28 @@ static int _nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle
.fh = fhandle,
.bitmask = server->attr_bitmask,
};
+ struct nfs4_pathconf_res res = {
+ .pathconf = pathconf,
+ };
struct rpc_message msg = {
.rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_PATHCONF),
.rpc_argp = &args,
- .rpc_resp = pathconf,
+ .rpc_resp = &res,
};
+ int status = 0;
+ dprintk("--> %s\n", __func__);
/* None of the pathconf attributes are mandatory to implement */
if ((args.bitmask[0] & nfs4_pathconf_bitmap[0]) == 0) {
memset(pathconf, 0, sizeof(*pathconf));
- return 0;
+ goto out;
}
nfs_fattr_init(pathconf->fattr);
- return rpc_call_sync(server->client, &msg, 0);
+ status = nfs4_call_sync(server, &msg, &args, &res, 0);
+out:
+ dprintk("<-- %s status= %d\n", __func__, status);
+ return status;
}
static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
@@ -2778,18 +2836,21 @@ out:
static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t buflen)
{
struct page *pages[NFS4ACL_MAXPAGES];
+ size_t resp_len = buflen;
struct nfs_getaclargs args = {
.fh = NFS_FH(inode),
.acl_pages = pages,
.acl_len = buflen,
};
- size_t resp_len = buflen;
+ struct nfs_getaclres res = {
+ .acl_len = &resp_len,
+ };
void *resp_buf;
struct nfs_server *server = NFS_SERVER(inode);
struct rpc_message msg = {
.rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_GETACL),
.rpc_argp = &args,
- .rpc_resp = &resp_len,
+ .rpc_resp = &res,
};
struct page *localpage = NULL;
int ret;
@@ -2808,7 +2869,7 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu
resp_buf = buf;
buf_to_pages(buf, buflen, args.acl_pages, &args.acl_pgbase);
}
- ret = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
+ ret = nfs4_call_sync(server, &msg, &args, &res, 0);
if (ret)
goto out_free;
if (resp_len > args.acl_len)
@@ -2869,10 +2930,11 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl
.acl_pages = pages,
.acl_len = buflen,
};
+ struct nfs_setaclres res;
struct rpc_message msg = {
.rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_SETACL),
.rpc_argp = &arg,
- .rpc_resp = NULL,
+ .rpc_resp = &res,
};
int ret;
@@ -2880,7 +2942,7 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl
return -EOPNOTSUPP;
nfs_inode_return_delegation(inode);
buf_to_pages(buf, buflen, arg.acl_pages, &arg.acl_pgbase);
- ret = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
+ ret = nfs4_call_sync(server, &msg, &arg, &res, 1);
nfs_access_zap_cache(inode);
nfs_zap_acl_cache(inode);
return ret;
@@ -3240,7 +3302,7 @@ static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock
goto out;
lsp = request->fl_u.nfs4_fl.owner;
arg.lock_owner.id = lsp->ls_id.id;
- status = rpc_call_sync(server->client, &msg, 0);
+ status = nfs4_call_sync(server, &msg, &arg, &res, 1);
switch (status) {
case 0:
request->fl_type = F_UNLCK;
@@ -3808,10 +3870,13 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
.page = page,
.bitmask = bitmask,
};
+ struct nfs4_fs_locations_res res = {
+ .fs_locations = fs_locations,
+ };
struct rpc_message msg = {
.rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_FS_LOCATIONS),
.rpc_argp = &args,
- .rpc_resp = fs_locations,
+ .rpc_resp = &res,
};
int status;
@@ -3819,7 +3884,7 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
nfs_fattr_init(&fs_locations->fattr);
fs_locations->server = server;
fs_locations->nlocations = 0;
- status = rpc_call_sync(server->client, &msg, 0);
+ status = nfs4_call_sync(server, &msg, &args, &res, 0);
dprintk("%s: returned status = %d\n", __func__, status);
return status;
}
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* Re: [pnfs] [RFC 26/85] nfs41: introduce nfs4_call_sync
2008-11-10 20:22 ` [RFC 26/85] nfs41: introduce nfs4_call_sync Benny Halevy
@ 2008-11-17 13:49 ` Benny Halevy
0 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-17 13:49 UTC (permalink / raw)
To: pnfs; +Cc: trond.myklebust, linux-nfs
On Nov. 10, 2008, 22:22 +0200, Benny Halevy <bhalevy@panasas.com> wrote:
> Use nfs4_call_sync rather than rpc_call_sync to provide
> for a nfs41 sessions-enabled interface for sessions manipulation.
>
> The nfs41 rpc logic uses the rpc_call_validate_args method to
> recover and create the session, as well as selecting a free slot id
> and the rpc_call_done to free the slot and update slot table
> related metadata.
>
> Signed-off-by: Benny Halevy <bhalevy@panasas.com>
review 11-14: define two functions one for v4 and one for v41
add a pointer to struct nfs4_client to the correct one.
> ---
> fs/nfs/nfs4proc.c | 127 ++++++++++++++++++++++++++++++++++++++++-------------
> 1 files changed, 96 insertions(+), 31 deletions(-)
>
> diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
> index 1cc639e..3b7c7fa 100644
> --- a/fs/nfs/nfs4proc.c
> +++ b/fs/nfs/nfs4proc.c
> @@ -349,6 +349,19 @@ nfs4_find_slot(struct nfs4_slot_table *tbl, struct rpc_task *task)
>
> #endif /* CONFIG_NFS_V4_1 */
>
> +static int _nfs4_call_sync(struct nfs_server *server,
> + struct rpc_message *msg,
> + struct nfs41_sequence_args *args,
> + struct nfs41_sequence_res *res,
> + int cache_reply)
> +{
> + return rpc_call_sync(server->client, msg, 0);
> +}
> +
> +#define nfs4_call_sync(server, msg, args, res, cache_reply) \
> + _nfs4_call_sync((server), (msg), &(args)->seq_args, \
> + &(res)->seq_res, (cache_reply))
> +
> static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo)
> {
> struct nfs_inode *nfsi = NFS_I(dir);
> @@ -1318,7 +1331,7 @@ static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
> } else
> memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid));
>
> - status = rpc_call_sync(server->client, &msg, 0);
> + status = nfs4_call_sync(server, &msg, &arg, &res, 1);
> if (status == 0 && state != NULL)
> renew_lease(server, timestamp);
> return status;
> @@ -1620,15 +1633,19 @@ out_drop:
>
> static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle)
> {
> + struct nfs4_server_caps_arg args = {
> + .fhandle = fhandle,
> + };
> struct nfs4_server_caps_res res = {};
> struct rpc_message msg = {
> .rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_SERVER_CAPS),
> - .rpc_argp = fhandle,
> + .rpc_argp = &args,
> .rpc_resp = &res,
> };
> int status;
>
> - status = rpc_call_sync(server->client, &msg, 0);
> + dprintk("--> %s\n", __func__);
> + status = nfs4_call_sync(server, &msg, &args, &res, 0);
> if (status == 0) {
> memcpy(server->attr_bitmask, res.attr_bitmask, sizeof(server->attr_bitmask));
> if (res.attr_bitmask[0] & FATTR4_WORD0_ACL)
> @@ -1639,6 +1656,8 @@ static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f
> server->caps |= NFS_CAP_SYMLINKS;
> server->acl_bitmask = res.acl_bitmask;
> }
> +
> + dprintk("<-- %s status= %d\n", __func__, status);
> return status;
> }
>
> @@ -1670,8 +1689,13 @@ static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
> .rpc_argp = &args,
> .rpc_resp = &res,
> };
> + int status;
> +
> + dprintk("--> %s\n", __func__);
> nfs_fattr_init(info->fattr);
> - return rpc_call_sync(server->client, &msg, 0);
> + status = nfs4_call_sync(server, &msg, &args, &res, 0);
> + dprintk("<-- %s status= %d\n", __func__, status);
> + return status;
> }
>
> static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
> @@ -1759,9 +1783,12 @@ static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
> .rpc_argp = &args,
> .rpc_resp = &res,
> };
> + int status;
>
> nfs_fattr_init(fattr);
> - return rpc_call_sync(server->client, &msg, 0);
> + status = nfs4_call_sync(server, &msg, &args, &res, 0);
> +
> + return status;
> }
>
> static int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
> @@ -1843,10 +1870,10 @@ static int _nfs4_proc_lookupfh(struct nfs_server *server, const struct nfs_fh *d
> };
>
> nfs_fattr_init(fattr);
> -
> dprintk("NFS call lookupfh %s\n", name->name);
> - status = rpc_call_sync(server->client, &msg, 0);
> + status = nfs4_call_sync(server, &msg, &args, &res, 0);
> dprintk("NFS reply lookupfh: %d\n", status);
> +
> return status;
> }
>
> @@ -1931,7 +1958,7 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry
> args.access |= NFS4_ACCESS_EXECUTE;
> }
> nfs_fattr_init(&fattr);
> - status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
> + status = nfs4_call_sync(server, &msg, &args, &res, 0);
> if (!status) {
> entry->mask = 0;
> if (res.access & NFS4_ACCESS_READ)
> @@ -1991,13 +2018,17 @@ static int _nfs4_proc_readlink(struct inode *inode, struct page *page,
> .pglen = pglen,
> .pages = &page,
> };
> + struct nfs4_readlink_res res;
> struct rpc_message msg = {
> .rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_READLINK),
> .rpc_argp = &args,
> - .rpc_resp = NULL,
> + .rpc_resp = &res,
> };
> + int status;
> +
> + status = nfs4_call_sync(server, &msg, &args, &res, 0);
>
> - return rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
> + return status;
> }
>
> static int nfs4_proc_readlink(struct inode *inode, struct page *page,
> @@ -2090,11 +2121,12 @@ static int _nfs4_proc_remove(struct inode *dir, struct qstr *name)
> int status;
>
> nfs_fattr_init(&res.dir_attr);
> - status = rpc_call_sync(server->client, &msg, 0);
> + status = nfs4_call_sync(server, &msg, &args, &res, 1);
> if (status == 0) {
> update_changeattr(dir, &res.cinfo);
> nfs_post_op_update_inode(dir, &res.dir_attr);
> }
> +
> return status;
> }
>
> @@ -2158,14 +2190,14 @@ static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name,
>
> nfs_fattr_init(res.old_fattr);
> nfs_fattr_init(res.new_fattr);
> - status = rpc_call_sync(server->client, &msg, 0);
> -
> + status = nfs4_call_sync(server, &msg, &arg, &res, 1);
> if (!status) {
> update_changeattr(old_dir, &res.old_cinfo);
> nfs_post_op_update_inode(old_dir, res.old_fattr);
> update_changeattr(new_dir, &res.new_cinfo);
> nfs_post_op_update_inode(new_dir, res.new_fattr);
> }
> +
> return status;
> }
>
> @@ -2207,7 +2239,7 @@ static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *
>
> nfs_fattr_init(res.fattr);
> nfs_fattr_init(res.dir_attr);
> - status = rpc_call_sync(server->client, &msg, 0);
> + status = nfs4_call_sync(server, &msg, &arg, &res, 1);
> if (!status) {
> update_changeattr(dir, &res.cinfo);
> nfs_post_op_update_inode(dir, res.dir_attr);
> @@ -2269,7 +2301,9 @@ static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir,
>
> static int nfs4_do_create(struct inode *dir, struct dentry *dentry, struct nfs4_createdata *data)
> {
> - int status = rpc_call_sync(NFS_CLIENT(dir), &data->msg, 0);
> + struct nfs_server *server = NFS_SERVER(dir);
> + int status = nfs4_call_sync(server, &data->msg,
> + &data->arg, &data->res, 1);
> if (status == 0) {
> update_changeattr(dir, &data->res.dir_cinfo);
> nfs_post_op_update_inode(dir, data->res.dir_fattr);
> @@ -2378,12 +2412,14 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
> dentry->d_parent->d_name.name,
> dentry->d_name.name,
> (unsigned long long)cookie);
> +
> nfs4_setup_readdir(cookie, NFS_COOKIEVERF(dir), dentry, &args);
> res.pgbase = args.pgbase;
> - status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
> + status = nfs4_call_sync(server, &msg, &args, &res, 0);
> if (status == 0)
> memcpy(NFS_COOKIEVERF(dir), res.verifier.data, NFS4_VERIFIER_SIZE);
>
> +
> nfs_invalidate_atime(dir);
>
> dprintk("%s: returns %d\n", __func__, status);
> @@ -2458,14 +2494,20 @@ static int _nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
> .fh = fhandle,
> .bitmask = server->attr_bitmask,
> };
> + struct nfs4_statfs_res res = {
> + .fsstat = fsstat,
> + };
> struct rpc_message msg = {
> .rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_STATFS),
> .rpc_argp = &args,
> - .rpc_resp = fsstat,
> + .rpc_resp = &res,
> };
> + int status;
>
> nfs_fattr_init(fsstat->fattr);
> - return rpc_call_sync(server->client, &msg, 0);
> + status = nfs4_call_sync(server, &msg, &args, &res, 0);
> +
> + return status;
> }
>
> static int nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsstat *fsstat)
> @@ -2487,13 +2529,21 @@ static int _nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle,
> .fh = fhandle,
> .bitmask = server->attr_bitmask,
> };
> + struct nfs4_fsinfo_res res = {
> + .fsinfo = fsinfo,
> + };
> struct rpc_message msg = {
> .rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_FSINFO),
> .rpc_argp = &args,
> - .rpc_resp = fsinfo,
> + .rpc_resp = &res,
> };
> + int status;
> +
> + dprintk("--> %s\n", __func__);
> + status = nfs4_call_sync(server, &msg, &args, &res, 0);
>
> - return rpc_call_sync(server->client, &msg, 0);
> + dprintk("<-- %s status= %d\n", __func__, status);
> + return status;
> }
>
> static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo)
> @@ -2522,20 +2572,28 @@ static int _nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle
> .fh = fhandle,
> .bitmask = server->attr_bitmask,
> };
> + struct nfs4_pathconf_res res = {
> + .pathconf = pathconf,
> + };
> struct rpc_message msg = {
> .rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_PATHCONF),
> .rpc_argp = &args,
> - .rpc_resp = pathconf,
> + .rpc_resp = &res,
> };
> + int status = 0;
>
> + dprintk("--> %s\n", __func__);
> /* None of the pathconf attributes are mandatory to implement */
> if ((args.bitmask[0] & nfs4_pathconf_bitmap[0]) == 0) {
> memset(pathconf, 0, sizeof(*pathconf));
> - return 0;
> + goto out;
> }
>
> nfs_fattr_init(pathconf->fattr);
> - return rpc_call_sync(server->client, &msg, 0);
> + status = nfs4_call_sync(server, &msg, &args, &res, 0);
> +out:
> + dprintk("<-- %s status= %d\n", __func__, status);
> + return status;
> }
>
> static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
> @@ -2778,18 +2836,21 @@ out:
> static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t buflen)
> {
> struct page *pages[NFS4ACL_MAXPAGES];
> + size_t resp_len = buflen;
> struct nfs_getaclargs args = {
> .fh = NFS_FH(inode),
> .acl_pages = pages,
> .acl_len = buflen,
> };
> - size_t resp_len = buflen;
> + struct nfs_getaclres res = {
> + .acl_len = &resp_len,
> + };
> void *resp_buf;
> struct nfs_server *server = NFS_SERVER(inode);
> struct rpc_message msg = {
> .rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_GETACL),
> .rpc_argp = &args,
> - .rpc_resp = &resp_len,
> + .rpc_resp = &res,
> };
> struct page *localpage = NULL;
> int ret;
> @@ -2808,7 +2869,7 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu
> resp_buf = buf;
> buf_to_pages(buf, buflen, args.acl_pages, &args.acl_pgbase);
> }
> - ret = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
> + ret = nfs4_call_sync(server, &msg, &args, &res, 0);
> if (ret)
> goto out_free;
> if (resp_len > args.acl_len)
> @@ -2869,10 +2930,11 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl
> .acl_pages = pages,
> .acl_len = buflen,
> };
> + struct nfs_setaclres res;
> struct rpc_message msg = {
> .rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_SETACL),
> .rpc_argp = &arg,
> - .rpc_resp = NULL,
> + .rpc_resp = &res,
> };
> int ret;
>
> @@ -2880,7 +2942,7 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl
> return -EOPNOTSUPP;
> nfs_inode_return_delegation(inode);
> buf_to_pages(buf, buflen, arg.acl_pages, &arg.acl_pgbase);
> - ret = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
> + ret = nfs4_call_sync(server, &msg, &arg, &res, 1);
> nfs_access_zap_cache(inode);
> nfs_zap_acl_cache(inode);
> return ret;
> @@ -3240,7 +3302,7 @@ static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock
> goto out;
> lsp = request->fl_u.nfs4_fl.owner;
> arg.lock_owner.id = lsp->ls_id.id;
> - status = rpc_call_sync(server->client, &msg, 0);
> + status = nfs4_call_sync(server, &msg, &arg, &res, 1);
> switch (status) {
> case 0:
> request->fl_type = F_UNLCK;
> @@ -3808,10 +3870,13 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
> .page = page,
> .bitmask = bitmask,
> };
> + struct nfs4_fs_locations_res res = {
> + .fs_locations = fs_locations,
> + };
> struct rpc_message msg = {
> .rpc_proc = nfs4_proc(server->nfs_client, NFSPROC4_CLNT_FS_LOCATIONS),
> .rpc_argp = &args,
> - .rpc_resp = fs_locations,
> + .rpc_resp = &res,
> };
> int status;
>
> @@ -3819,7 +3884,7 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
> nfs_fattr_init(&fs_locations->fattr);
> fs_locations->server = server;
> fs_locations->nlocations = 0;
> - status = rpc_call_sync(server->client, &msg, 0);
> + status = nfs4_call_sync(server, &msg, &args, &res, 0);
> dprintk("%s: returned status = %d\n", __func__, status);
> return status;
> }
^ permalink raw reply [flat|nested] 115+ messages in thread
* [RFC 27/85] nfs41: nfs4_setup_sequence
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (23 preceding siblings ...)
2008-11-10 20:22 ` [RFC 26/85] nfs41: introduce nfs4_call_sync Benny Halevy
@ 2008-11-10 20:22 ` Benny Halevy
2008-11-17 13:49 ` [pnfs] " Benny Halevy
2008-11-10 20:22 ` [RFC 28/85] nfs41: setup_sequence method Benny Halevy
` (60 subsequent siblings)
85 siblings, 1 reply; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:22 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
Perform the nfs4_setup_sequence in the rpc_call_prepare state.
If a session slot is not available, we will rpc_sleep_on the
slot wait queue leaving the tk_action as rpc_call_prepare.
Once we have a session slot, hang on to it even through rpc_restart_calls.
Ensure the nfs41_sequence_res sr_slot pointer is NULL before rpc_run_task is
called as nfs41_setup_sequence will only find a new slot if it is NULL.
A future patch will call free slot after any rpc_restart_calls, and handle the
rpc restart that result from a sequence operation error.
Signed-off-by: Rahul Iyer <iyer@netapp.com>
Signed-off-by: Andy Adamson<andros@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
nfs41: simplify nfs4_call_sync
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/nfs4proc.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++
include/linux/nfs_xdr.h | 2 +-
2 files changed, 94 insertions(+), 1 deletions(-)
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 3b7c7fa..30f76e7 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -347,6 +347,70 @@ nfs4_find_slot(struct nfs4_slot_table *tbl, struct rpc_task *task)
return slot;
}
+static int nfs41_setup_sequence(struct nfs4_session *session,
+ struct nfs41_sequence_args *args,
+ struct nfs41_sequence_res *res,
+ int cache_reply,
+ struct rpc_task *task)
+{
+ /* stub */
+ return 0;
+}
+
+int nfs4_setup_sequence(struct nfs_client *clp,
+ struct nfs41_sequence_args *args,
+ struct nfs41_sequence_res *res,
+ int cache_reply,
+ struct rpc_task *task)
+{
+ int ret = 0;
+
+ dprintk("--> %s clp %p session %p cl_minorversion %d res->sr_slot %p\n",
+ __func__, clp, clp->cl_session, clp->cl_minorversion,
+ res->sr_slot);
+
+ if (clp->cl_minorversion == 0 || res->sr_slot)
+ goto out;
+ BUG_ON(clp->cl_minorversion != 1);
+ ret = nfs41_setup_sequence(clp->cl_session, args, res,
+ cache_reply, task);
+ if (ret) {
+ memset(res, 0, sizeof(*res));
+ if (ret != -EAGAIN) {
+ /* terminate rpc task */
+ task->tk_status = ret;
+ task->tk_action = NULL;
+ }
+ }
+out:
+ dprintk("<-- %s status=%d\n", __func__, ret);
+ return ret;
+}
+
+struct nfs41_call_sync_data {
+ struct nfs_server *server;
+ struct rpc_message *msg;
+ struct nfs41_sequence_args *seq_args;
+ struct nfs41_sequence_res *seq_res;
+ int cache_reply;
+};
+
+static void nfs41_call_sync_prepare(struct rpc_task *task, void *calldata)
+{
+ struct nfs41_call_sync_data *data = calldata;
+
+ dprintk("--> %s data->server->session %p\n", __func__,
+ data->server->nfs_client->cl_session);
+ if (nfs4_setup_sequence(data->server->nfs_client, data->seq_args,
+ data->seq_res, data->cache_reply, task))
+ return;
+ rpc_call_start(task);
+}
+
+struct rpc_call_ops nfs41_call_sync_ops = {
+ .rpc_call_prepare = nfs41_call_sync_prepare,
+};
+
#endif /* CONFIG_NFS_V4_1 */
static int _nfs4_call_sync(struct nfs_server *server,
@@ -355,6 +419,35 @@ static int _nfs4_call_sync(struct nfs_server *server,
struct nfs41_sequence_res *res,
int cache_reply)
{
+#ifdef CONFIG_NFS_V4_1
+ if (server->nfs_client->cl_minorversion) {
+ int ret;
+ struct rpc_task *task;
+ struct nfs41_call_sync_data data = {
+ .server = server,
+ .msg = msg,
+ .seq_args = args,
+ .seq_res = res,
+ .cache_reply = cache_reply,
+ };
+ struct rpc_task_setup task_setup = {
+ .rpc_client = server->client,
+ .rpc_message = msg,
+ .callback_ops = &nfs41_call_sync_ops,
+ .callback_data = &data
+ };
+
+ res->sr_slot = NULL;
+ task = rpc_run_task(&task_setup);
+ if (IS_ERR(task))
+ ret = PTR_ERR(task);
+ else {
+ ret = task->tk_status;
+ rpc_put_task(task);
+ }
+ return ret;
+ }
+#endif /* CONFIG_NFS_V4_1 */
return rpc_call_sync(server->client, msg, 0);
}
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index b401477..1ec56e5 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -134,7 +134,7 @@ struct nfs41_sequence_args {
#define SEQ4_STATUS_RESTART_RECLAIM_NEEDED 0x00000100
struct nfs41_sequence_res {
- /* stub */
+ struct nfs4_slot *sr_slot; /* slot used to send request */
};
#if defined(CONFIG_NFS_V4_1)
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* Re: [pnfs] [RFC 27/85] nfs41: nfs4_setup_sequence
2008-11-10 20:22 ` [RFC 27/85] nfs41: nfs4_setup_sequence Benny Halevy
@ 2008-11-17 13:49 ` Benny Halevy
0 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-17 13:49 UTC (permalink / raw)
To: pnfs; +Cc: trond.myklebust, linux-nfs
On Nov. 10, 2008, 22:22 +0200, Benny Halevy <bhalevy@panasas.com> wrote:
> Perform the nfs4_setup_sequence in the rpc_call_prepare state.
>
> If a session slot is not available, we will rpc_sleep_on the
> slot wait queue leaving the tk_action as rpc_call_prepare.
>
> Once we have a session slot, hang on to it even through rpc_restart_calls.
> Ensure the nfs41_sequence_res sr_slot pointer is NULL before rpc_run_task is
> called as nfs41_setup_sequence will only find a new slot if it is NULL.
>
> A future patch will call free slot after any rpc_restart_calls, and handle the
> rpc restart that result from a sequence operation error.
>
> Signed-off-by: Rahul Iyer <iyer@netapp.com>
> Signed-off-by: Andy Adamson<andros@netapp.com>
> Signed-off-by: Benny Halevy <bhalevy@panasas.com>
>
> nfs41: simplify nfs4_call_sync
>
> Signed-off-by: Benny Halevy <bhalevy@panasas.com>
> ---
> fs/nfs/nfs4proc.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++
> include/linux/nfs_xdr.h | 2 +-
> 2 files changed, 94 insertions(+), 1 deletions(-)
>
> diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
> index 3b7c7fa..30f76e7 100644
> --- a/fs/nfs/nfs4proc.c
> +++ b/fs/nfs/nfs4proc.c
> @@ -347,6 +347,70 @@ nfs4_find_slot(struct nfs4_slot_table *tbl, struct rpc_task *task)
> return slot;
> }
>
> +static int nfs41_setup_sequence(struct nfs4_session *session,
> + struct nfs41_sequence_args *args,
> + struct nfs41_sequence_res *res,
> + int cache_reply,
> + struct rpc_task *task)
> +{
> + /* stub */
> + return 0;
> +}
> +
> +int nfs4_setup_sequence(struct nfs_client *clp,
> + struct nfs41_sequence_args *args,
> + struct nfs41_sequence_res *res,
> + int cache_reply,
> + struct rpc_task *task)
> +{
> + int ret = 0;
> +
> + dprintk("--> %s clp %p session %p cl_minorversion %d res->sr_slot %p\n",
> + __func__, clp, clp->cl_session, clp->cl_minorversion,
> + res->sr_slot);
> +
> + if (clp->cl_minorversion == 0 || res->sr_slot)
> + goto out;
> + BUG_ON(clp->cl_minorversion != 1);
> + ret = nfs41_setup_sequence(clp->cl_session, args, res,
> + cache_reply, task);
> + if (ret) {
> + memset(res, 0, sizeof(*res));
> + if (ret != -EAGAIN) {
> + /* terminate rpc task */
> + task->tk_status = ret;
> + task->tk_action = NULL;
> + }
> + }
> +out:
> + dprintk("<-- %s status=%d\n", __func__, ret);
> + return ret;
> +}
> +
> +struct nfs41_call_sync_data {
> + struct nfs_server *server;
> + struct rpc_message *msg;
> + struct nfs41_sequence_args *seq_args;
> + struct nfs41_sequence_res *seq_res;
> + int cache_reply;
> +};
> +
> +static void nfs41_call_sync_prepare(struct rpc_task *task, void *calldata)
> +{
> + struct nfs41_call_sync_data *data = calldata;
> +
> + dprintk("--> %s data->server->session %p\n", __func__,
> + data->server->nfs_client->cl_session);
> + if (nfs4_setup_sequence(data->server->nfs_client, data->seq_args,
> + data->seq_res, data->cache_reply, task))
> + return;
> + rpc_call_start(task);
> +}
> +
> +struct rpc_call_ops nfs41_call_sync_ops = {
> + .rpc_call_prepare = nfs41_call_sync_prepare,
> +};
> +
> #endif /* CONFIG_NFS_V4_1 */
>
> static int _nfs4_call_sync(struct nfs_server *server,
> @@ -355,6 +419,35 @@ static int _nfs4_call_sync(struct nfs_server *server,
> struct nfs41_sequence_res *res,
> int cache_reply)
> {
> +#ifdef CONFIG_NFS_V4_1
> + if (server->nfs_client->cl_minorversion) {
> + int ret;
> + struct rpc_task *task;
> + struct nfs41_call_sync_data data = {
> + .server = server,
> + .msg = msg,
> + .seq_args = args,
> + .seq_res = res,
> + .cache_reply = cache_reply,
> + };
> + struct rpc_task_setup task_setup = {
> + .rpc_client = server->client,
> + .rpc_message = msg,
> + .callback_ops = &nfs41_call_sync_ops,
> + .callback_data = &data
> + };
> +
> + res->sr_slot = NULL;
> + task = rpc_run_task(&task_setup);
> + if (IS_ERR(task))
> + ret = PTR_ERR(task);
> + else {
> + ret = task->tk_status;
> + rpc_put_task(task);
> + }
> + return ret;
> + }
> +#endif /* CONFIG_NFS_V4_1 */
review 11-14: move out into _nfs4_call_sync_seq
> return rpc_call_sync(server->client, msg, 0);
> }
>
> diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
> index b401477..1ec56e5 100644
> --- a/include/linux/nfs_xdr.h
> +++ b/include/linux/nfs_xdr.h
> @@ -134,7 +134,7 @@ struct nfs41_sequence_args {
> #define SEQ4_STATUS_RESTART_RECLAIM_NEEDED 0x00000100
>
> struct nfs41_sequence_res {
> - /* stub */
> + struct nfs4_slot *sr_slot; /* slot used to send request */
> };
>
> #if defined(CONFIG_NFS_V4_1)
^ permalink raw reply [flat|nested] 115+ messages in thread
* [RFC 28/85] nfs41: setup_sequence method
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (24 preceding siblings ...)
2008-11-10 20:22 ` [RFC 27/85] nfs41: nfs4_setup_sequence Benny Halevy
@ 2008-11-10 20:22 ` Benny Halevy
2008-11-10 20:23 ` [RFC 02/85] nfs: return compound hdr.status when there are no op replies Benny Halevy
` (59 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:22 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
Allocate a slot in the session slot table and set the sequence op arguments.
Called at the rpc prepare stage.
Signed-off-by: Rahul Iyer <iyer@netapp.com>
Signed-off-by: Andy Adamson<andros@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/nfs4proc.c | 23 ++++++++++++++++++++++-
include/linux/nfs_xdr.h | 5 ++++-
2 files changed, 26 insertions(+), 2 deletions(-)
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 30f76e7..af9ee0e 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -353,7 +353,28 @@ static int nfs41_setup_sequence(struct nfs4_session *session,
int cache_reply,
struct rpc_task *task)
{
- /* stub */
+ struct nfs4_slot *slot;
+ struct nfs4_slot_table *tbl;
+
+ dprintk("--> %s\n", __func__);
+ tbl = &session->fore_channel.slot_table;
+ slot = nfs4_find_slot(tbl, task);
+
+ if (!slot) {
+ rpc_sleep_on(&tbl->slot_tbl_waitq, task, NULL);
+ dprintk("<-- %s: no free slots\n", __func__);
+ return -EAGAIN;
+ }
+
+ args->sa_session = session;
+ args->sa_slot = slot;
+ args->sa_cache_this = cache_reply;
+
+ dprintk("<-- %s slot=%p slotid=%d seqid=%d\n", __func__,
+ slot, slot_idx(tbl, slot), slot->seq_nr);
+
+ res->sr_slot = slot;
+ res->sr_renewal_time = jiffies;
return 0;
}
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 1ec56e5..9cefe0d 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -120,7 +120,9 @@ struct sessionid4 {
};
struct nfs41_sequence_args {
- /* stub */
+ struct nfs4_session *sa_session;
+ struct nfs4_slot *sa_slot;
+ u32 sa_cache_this;
};
#define SEQ4_STATUS_CB_PATH_DOWN 0x00000001
@@ -135,6 +137,7 @@ struct nfs41_sequence_args {
struct nfs41_sequence_res {
struct nfs4_slot *sr_slot; /* slot used to send request */
+ unsigned long sr_renewal_time;
};
#if defined(CONFIG_NFS_V4_1)
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 02/85] nfs: return compound hdr.status when there are no op replies
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (25 preceding siblings ...)
2008-11-10 20:22 ` [RFC 28/85] nfs41: setup_sequence method Benny Halevy
@ 2008-11-10 20:23 ` Benny Halevy
2008-11-10 20:23 ` [RFC 29/85] nfs41: nfs41_sequence_done Benny Halevy
` (58 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:23 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
When there are no op replies encoded in the compound reply
hdr.status still contains the overall status of the compound
rpc. This can happen, e.g., when the server returns a
NFS4ERR_MINOR_VERS_MISMATCH error.
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/nfs4xdr.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index b916297..ac2386b 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -2222,6 +2222,8 @@ static int decode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr)
hdr->tag = (char *)p;
p += XDR_QUADLEN(hdr->taglen);
READ32(hdr->nops);
+ if (unlikely(hdr->nops < 1))
+ return nfs4_stat_to_errno(hdr->status);
return 0;
}
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 29/85] nfs41: nfs41_sequence_done
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (26 preceding siblings ...)
2008-11-10 20:23 ` [RFC 02/85] nfs: return compound hdr.status when there are no op replies Benny Halevy
@ 2008-11-10 20:23 ` Benny Halevy
2008-11-17 13:50 ` [pnfs] " Benny Halevy
2008-11-10 20:23 ` [RFC 30/85] nfs41: nfs41_call_sync_done Benny Halevy
` (57 subsequent siblings)
85 siblings, 1 reply; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:23 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
Handle session level errors, update slot sequence id and
sessions bookeeping, free slot.
Signed-off-by: Andy Adamson<andros@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/nfs4proc.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++
include/linux/nfs_xdr.h | 3 ++
2 files changed, 64 insertions(+), 0 deletions(-)
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index af9ee0e..217f891 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -296,6 +296,66 @@ nfs41_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *slot)
rpc_wake_up_next(&tbl->slot_tbl_waitq);
}
+/* For pNFS filelayout data servers:
+ * the nfs_client is NULL - to signal no lease update.
+ * session is the data server.
+ */
+static void nfs41_sequence_done(struct nfs_client *clp,
+ struct nfs41_sequence_res *res,
+ int rpc_status)
+{
+ unsigned long timestamp;
+ struct nfs4_slot_table *tbl;
+ struct nfs4_slot *slot;
+ int status = NFS4_OK;
+
+ if (res->sr_flags & SEQ4_STATUS_USE_TK_STATUS)
+ status = rpc_status;
+
+ tbl = &res->sr_session->fore_channel.slot_table;
+ slot = res->sr_slot;
+
+ switch (status) {
+ case NFS4_OK:
+ /*
+ * The sequence call was successful,
+ * Update the slot's sequence and client's lease renewal timers
+ */
+ ++slot->seq_nr;
+ if (!clp)
+ break;
+ timestamp = res->sr_renewal_time;
+ spin_lock(&clp->cl_lock);
+ if (time_before(clp->cl_last_renewal, timestamp))
+ clp->cl_last_renewal = timestamp;
+ spin_unlock(&clp->cl_lock);
+ break;
+
+ case -NFS4ERR_BADSESSION:
+ case -NFS4ERR_BADSLOT:
+ case -NFS4ERR_BADXDR:
+ case -NFS4ERR_BAD_HIGH_SLOT:
+ case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
+ case -NFS4ERR_DEADSESSION:
+ case -NFS4ERR_DELAY:
+ case -NFS4ERR_REP_TOO_BIG:
+ case -NFS4ERR_REP_TOO_BIG_TO_CACHE:
+ case -NFS4ERR_REQ_TOO_BIG:
+ case -NFS4ERR_RETRY_UNCACHED_REP:
+ case -NFS4ERR_SEQUENCE_POS:
+ case -NFS4ERR_SEQ_FALSE_RETRY:
+ case -NFS4ERR_SEQ_MISORDERED:
+ case -NFS4ERR_TOO_MANY_OPS:
+ dprintk("%s: status %d\n", __func__, status);
+ break;
+
+ default:
+ printk(KERN_WARNING "%s: Unexpected status %d\n", __func__,
+ status);
+ }
+ nfs41_free_slot(tbl, slot);
+}
+
/*
* nfs4_find_slot - efficiently look for a free slot
*
@@ -373,6 +433,7 @@ static int nfs41_setup_sequence(struct nfs4_session *session,
dprintk("<-- %s slot=%p slotid=%d seqid=%d\n", __func__,
slot, slot_idx(tbl, slot), slot->seq_nr);
+ res->sr_session = session;
res->sr_slot = slot;
res->sr_renewal_time = jiffies;
return 0;
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 9cefe0d..4144ea2 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -134,8 +134,11 @@ struct nfs41_sequence_args {
#define SEQ4_STATUS_RECALLABLE_STATE_REVOKED 0x00000040
#define SEQ4_STATUS_LEASE_MOVED 0x00000080
#define SEQ4_STATUS_RESTART_RECLAIM_NEEDED 0x00000100
+#define SEQ4_STATUS_USE_TK_STATUS 0x10000000 /* internal error */
struct nfs41_sequence_res {
+ struct nfs4_session *sr_session;
+ u32 sr_flags;
struct nfs4_slot *sr_slot; /* slot used to send request */
unsigned long sr_renewal_time;
};
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* Re: [pnfs] [RFC 29/85] nfs41: nfs41_sequence_done
2008-11-10 20:23 ` [RFC 29/85] nfs41: nfs41_sequence_done Benny Halevy
@ 2008-11-17 13:50 ` Benny Halevy
0 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-17 13:50 UTC (permalink / raw)
To: pnfs; +Cc: trond.myklebust, linux-nfs
On Nov. 10, 2008, 22:23 +0200, Benny Halevy <bhalevy@panasas.com> wrote:
> Handle session level errors, update slot sequence id and
> sessions bookeeping, free slot.
>
> Signed-off-by: Andy Adamson<andros@netapp.com>
> Signed-off-by: Benny Halevy <bhalevy@panasas.com>
> ---
> fs/nfs/nfs4proc.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++
> include/linux/nfs_xdr.h | 3 ++
> 2 files changed, 64 insertions(+), 0 deletions(-)
>
> diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
> index af9ee0e..217f891 100644
> --- a/fs/nfs/nfs4proc.c
> +++ b/fs/nfs/nfs4proc.c
> @@ -296,6 +296,66 @@ nfs41_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *slot)
> rpc_wake_up_next(&tbl->slot_tbl_waitq);
> }
>
> +/* For pNFS filelayout data servers:
> + * the nfs_client is NULL - to signal no lease update.
> + * session is the data server.
> + */
> +static void nfs41_sequence_done(struct nfs_client *clp,
> + struct nfs41_sequence_res *res,
> + int rpc_status)
review 11-14: cache the seq_status in struct nfs41_sequence_res.
initialize to non zero so that we intercept rpc level failures
in which we do not go through decode_sequence, which will be the
only place where res->seq_status will be set to 0.
get rid of SEQ4_STATUS_USE_TK_STATUS.
no need to pass rpc_status either.
> +{
> + unsigned long timestamp;
> + struct nfs4_slot_table *tbl;
> + struct nfs4_slot *slot;
> + int status = NFS4_OK;
> +
> + if (res->sr_flags & SEQ4_STATUS_USE_TK_STATUS)
> + status = rpc_status;
> +
> + tbl = &res->sr_session->fore_channel.slot_table;
> + slot = res->sr_slot;
> +
> + switch (status) {
> + case NFS4_OK:
> + /*
> + * The sequence call was successful,
> + * Update the slot's sequence and client's lease renewal timers
> + */
> + ++slot->seq_nr;
> + if (!clp)
> + break;
> + timestamp = res->sr_renewal_time;
> + spin_lock(&clp->cl_lock);
> + if (time_before(clp->cl_last_renewal, timestamp))
> + clp->cl_last_renewal = timestamp;
> + spin_unlock(&clp->cl_lock);
> + break;
> +
> + case -NFS4ERR_BADSESSION:
> + case -NFS4ERR_BADSLOT:
> + case -NFS4ERR_BADXDR:
> + case -NFS4ERR_BAD_HIGH_SLOT:
> + case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
> + case -NFS4ERR_DEADSESSION:
> + case -NFS4ERR_DELAY:
> + case -NFS4ERR_REP_TOO_BIG:
> + case -NFS4ERR_REP_TOO_BIG_TO_CACHE:
> + case -NFS4ERR_REQ_TOO_BIG:
> + case -NFS4ERR_RETRY_UNCACHED_REP:
> + case -NFS4ERR_SEQUENCE_POS:
> + case -NFS4ERR_SEQ_FALSE_RETRY:
> + case -NFS4ERR_SEQ_MISORDERED:
> + case -NFS4ERR_TOO_MANY_OPS:
> + dprintk("%s: status %d\n", __func__, status);
> + break;
> +
> + default:
> + printk(KERN_WARNING "%s: Unexpected status %d\n", __func__,
> + status);
> + }
> + nfs41_free_slot(tbl, slot);
> +}
> +
> /*
> * nfs4_find_slot - efficiently look for a free slot
> *
> @@ -373,6 +433,7 @@ static int nfs41_setup_sequence(struct nfs4_session *session,
> dprintk("<-- %s slot=%p slotid=%d seqid=%d\n", __func__,
> slot, slot_idx(tbl, slot), slot->seq_nr);
>
> + res->sr_session = session;
> res->sr_slot = slot;
> res->sr_renewal_time = jiffies;
> return 0;
> diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
> index 9cefe0d..4144ea2 100644
> --- a/include/linux/nfs_xdr.h
> +++ b/include/linux/nfs_xdr.h
> @@ -134,8 +134,11 @@ struct nfs41_sequence_args {
> #define SEQ4_STATUS_RECALLABLE_STATE_REVOKED 0x00000040
> #define SEQ4_STATUS_LEASE_MOVED 0x00000080
> #define SEQ4_STATUS_RESTART_RECLAIM_NEEDED 0x00000100
> +#define SEQ4_STATUS_USE_TK_STATUS 0x10000000 /* internal error */
>
> struct nfs41_sequence_res {
> + struct nfs4_session *sr_session;
> + u32 sr_flags;
> struct nfs4_slot *sr_slot; /* slot used to send request */
> unsigned long sr_renewal_time;
> };
^ permalink raw reply [flat|nested] 115+ messages in thread
* [RFC 30/85] nfs41: nfs41_call_sync_done
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (27 preceding siblings ...)
2008-11-10 20:23 ` [RFC 29/85] nfs41: nfs41_sequence_done Benny Halevy
@ 2008-11-10 20:23 ` Benny Halevy
2008-11-10 20:23 ` [RFC 31/85] nfs41: separate free slot from sequence done Benny Halevy
` (56 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:23 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
Implement nfs4.1 synchronous rpc_call_done method
that essentially just calls nfs4_sequence_done, that turns
around and calls nfs41_sequence_done for minorversion1 rpcs.
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/nfs4proc.c | 18 ++++++++++++++++++
1 files changed, 18 insertions(+), 0 deletions(-)
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 217f891..5d9ca20 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -489,8 +489,17 @@ static void nfs41_call_sync_prepare(struct rpc_task *task, void *calldata)
rpc_call_start(task);
}
+static void nfs41_call_sync_done(struct rpc_task *task, void *calldata)
+{
+ struct nfs41_call_sync_data *data = calldata;
+ struct nfs_server *server = data->server;
+
+ nfs41_sequence_done(server->nfs_client, data->seq_res, task->tk_status);
+}
+
struct rpc_call_ops nfs41_call_sync_ops = {
.rpc_call_prepare = nfs41_call_sync_prepare,
+ .rpc_call_done = nfs41_call_sync_done,
};
#endif /* CONFIG_NFS_V4_1 */
@@ -537,6 +546,15 @@ static int _nfs4_call_sync(struct nfs_server *server,
_nfs4_call_sync((server), (msg), &(args)->seq_args, \
&(res)->seq_res, (cache_reply))
+static void nfs4_sequence_done(const struct nfs_server *server,
+ struct nfs41_sequence_res *res, int rpc_status)
+{
+#ifdef CONFIG_NFS_V4_1
+ if (server->nfs_client->cl_minorversion)
+ nfs41_sequence_done(server->nfs_client, res, rpc_status);
+#endif /* CONFIG_NFS_V4_1 */
+}
+
static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo)
{
struct nfs_inode *nfsi = NFS_I(dir);
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 31/85] nfs41: separate free slot from sequence done
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (28 preceding siblings ...)
2008-11-10 20:23 ` [RFC 30/85] nfs41: nfs41_call_sync_done Benny Halevy
@ 2008-11-10 20:23 ` Benny Halevy
2008-11-10 20:23 ` [RFC 32/85] nfs41: sequence setup/done support Benny Halevy
` (55 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:23 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
From: Andy Adamson <andros@netapp.com>
Don't free the slot until after all rpc_restart_calls have completed.
Session reset will require more work.
Signed-off-by: Andy Adamson<andros@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/internal.h | 14 ++++++++++++++
fs/nfs/nfs4proc.c | 36 +++++++++++++++++++++++++++++-------
fs/nfs/read.c | 8 ++++++--
fs/nfs/write.c | 1 +
4 files changed, 50 insertions(+), 9 deletions(-)
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 9b2228f..86cd70b 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -180,6 +180,20 @@ extern int nfs4_path_walk(struct nfs_server *server,
const char *path);
#endif
+/* nfs4proc.c */
+#ifdef CONFIG_NFS_V4_1
+extern void nfs41_sequence_free_slot(struct nfs41_sequence_res *res);
+#endif /* CONFIG_NFS_V4_1 */
+
+static inline void nfs4_sequence_free_slot(const struct nfs_server *server,
+ struct nfs41_sequence_res *res)
+{
+#ifdef CONFIG_NFS_V4_1
+ if (server->nfs_client->cl_minorversion)
+ nfs41_sequence_free_slot(res);
+#endif /* CONFIG_NFS_V4_1 */
+}
+
/*
* Determine the device name as a string
*/
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 5d9ca20..6d90b07 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -258,7 +258,7 @@ static inline int bmp2idx(unsigned long *base, unsigned long *bmp,
* word in the bitmap.
* If none found, highest_used_slotid is set to -1.
*/
-static void
+void
nfs41_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *slot)
{
int slotid = slot_idx(tbl, slot);
@@ -296,6 +296,17 @@ nfs41_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *slot)
rpc_wake_up_next(&tbl->slot_tbl_waitq);
}
+void nfs41_sequence_free_slot(struct nfs41_sequence_res *res)
+{
+ if (res->sr_session == NULL || res->sr_slot == NULL) {
+ dprintk("%s: %s\n", __func__,
+ res->sr_session == NULL ? "No session" : "No slot");
+ return;
+ }
+ nfs41_free_slot(&res->sr_session->fore_channel.slot_table,
+ res->sr_slot);
+}
+
/* For pNFS filelayout data servers:
* the nfs_client is NULL - to signal no lease update.
* session is the data server.
@@ -346,14 +357,18 @@ static void nfs41_sequence_done(struct nfs_client *clp,
case -NFS4ERR_SEQ_FALSE_RETRY:
case -NFS4ERR_SEQ_MISORDERED:
case -NFS4ERR_TOO_MANY_OPS:
- dprintk("%s: status %d\n", __func__, status);
+ dprintk("%s: Free Slot: status %d\n", __func__, status);
+ /* The session needs to be reset, so free the slot and set the
+ * sr_slot to NULL so that nfs4_setup_sequence calls
+ * nfs41_find_slot and kicks off session reset. */
+ nfs41_sequence_free_slot(res);
+ res->sr_slot = NULL;
break;
default:
printk(KERN_WARNING "%s: Unexpected status %d\n", __func__,
status);
}
- nfs41_free_slot(tbl, slot);
}
/*
@@ -495,6 +510,7 @@ static void nfs41_call_sync_done(struct rpc_task *task, void *calldata)
struct nfs_server *server = data->server;
nfs41_sequence_done(server->nfs_client, data->seq_res, task->tk_status);
+ nfs41_sequence_free_slot(data->seq_res);
}
struct rpc_call_ops nfs41_call_sync_ops = {
@@ -1592,6 +1608,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
return;
}
}
+ nfs4_sequence_free_slot(server, &calldata->res.seq_res);
nfs_refresh_inode(calldata->inode, calldata->res.fattr);
}
@@ -2352,6 +2369,7 @@ static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir)
if (nfs4_async_handle_error(task, res->server) == -EAGAIN)
return 0;
+ nfs4_sequence_free_slot(res->server, &res->seq_res);
update_changeattr(dir, &res->cinfo);
nfs_post_op_update_inode(dir, &res->dir_attr);
return 1;
@@ -2855,11 +2873,13 @@ static void nfs4_proc_write_setup(struct nfs_write_data *data, struct rpc_messag
static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data)
{
struct inode *inode = data->inode;
-
- if (nfs4_async_handle_error(task, NFS_SERVER(inode)) == -EAGAIN) {
+ struct nfs_server *server = NFS_SERVER(inode);
+
+ if (nfs4_async_handle_error(task, server) == -EAGAIN) {
rpc_restart_call(task);
return -EAGAIN;
}
+ nfs4_sequence_free_slot(server, &data->res.seq_res);
nfs_refresh_inode(inode, data->res.fattr);
return 0;
}
@@ -3585,6 +3605,7 @@ static void nfs4_locku_release_calldata(void *data)
static void nfs4_locku_done(struct rpc_task *task, void *data)
{
struct nfs4_unlockdata *calldata = data;
+ const struct nfs_server *server = calldata->server;
if (RPC_ASSASSINATED(task))
return;
@@ -3593,15 +3614,16 @@ static void nfs4_locku_done(struct rpc_task *task, void *data)
memcpy(calldata->lsp->ls_stateid.data,
calldata->res.stateid.data,
sizeof(calldata->lsp->ls_stateid.data));
- renew_lease(calldata->server, calldata->timestamp);
+ renew_lease(server, calldata->timestamp);
break;
case -NFS4ERR_STALE_STATEID:
case -NFS4ERR_EXPIRED:
break;
default:
- if (nfs4_async_handle_error(task, calldata->server) == -EAGAIN)
+ if (nfs4_async_handle_error(task, server) == -EAGAIN)
rpc_restart_call(task);
}
+ nfs4_sequence_free_slot(server, &calldata->res.seq_res);
}
static void nfs4_locku_prepare(struct rpc_task *task, void *data)
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 40d1798..8c2019c 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -351,19 +351,23 @@ static void nfs_readpage_retry(struct rpc_task *task, struct nfs_read_data *data
struct nfs_readres *resp = &data->res;
if (resp->eof || resp->count == argp->count)
- return;
+ goto out;
/* This is a short read! */
nfs_inc_stats(data->inode, NFSIOS_SHORTREAD);
/* Has the server at least made some progress? */
if (resp->count == 0)
- return;
+ goto out;
/* Yes, so retry the read at the end of the data */
argp->offset += resp->count;
argp->pgbase += resp->count;
argp->count -= resp->count;
rpc_restart_call(task);
+ return;
+out:
+ nfs4_sequence_free_slot(NFS_SERVER(data->inode), &data->res.seq_res);
+ return;
}
/*
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 9f98458..361a61b 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -1171,6 +1171,7 @@ int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data)
/* Can't do anything about it except throw an error. */
task->tk_status = -EIO;
}
+ nfs4_sequence_free_slot(NFS_SERVER(data->inode), &data->res.seq_res);
return 0;
}
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 32/85] nfs41: sequence setup/done support
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (29 preceding siblings ...)
2008-11-10 20:23 ` [RFC 31/85] nfs41: separate free slot from sequence done Benny Halevy
@ 2008-11-10 20:23 ` Benny Halevy
2008-11-10 20:23 ` [RFC 33/85] nfs41: Support sessions with O_DIRECT Benny Halevy
` (54 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:23 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
Imlpement the rpc_call_validate_args methods for
asynchronuos nfs rpcs, call nfs41_setup_sequence from
respective rpc_call_validate_args methods.
Call nfs4_sequence_done from respective rpc_call_done methods.
Note that we need to pass a pointer to the nfs_server in calls data
for passing on to nfs4_sequence_done.
Signed-off-by: Andy Adamson<andros@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/direct.c | 1 +
fs/nfs/nfs4_fs.h | 10 ++++++
fs/nfs/nfs4proc.c | 80 ++++++++++++++++++++++++++++++++++++++++++++---
fs/nfs/read.c | 23 +++++++++++++
fs/nfs/unlink.c | 16 +++++++++
fs/nfs/write.c | 23 +++++++++++++
include/linux/nfs_xdr.h | 7 ++--
7 files changed, 152 insertions(+), 8 deletions(-)
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 08f6b04..d4ae559 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -306,6 +306,7 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq,
if (unlikely(!data))
break;
+ data->args.server = NFS_SERVER(inode);
down_read(¤t->mm->mmap_sem);
result = get_user_pages(current, current->mm, user_addr,
data->npages, 1, 0, data->pagevec, NULL);
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index bef2fca..d0aac94 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -190,11 +190,21 @@ extern int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops;
extern struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops;
#if defined(CONFIG_NFS_V4_1)
+extern int nfs4_setup_sequence(struct nfs_client *clp,
+ struct nfs41_sequence_args *args, struct nfs41_sequence_res *res,
+ int cache_reply, struct rpc_task *task);
extern void nfs4_put_session(struct nfs4_session **session);
extern void nfs4_get_session(struct nfs_client *clp);
extern struct nfs4_session *nfs4_alloc_session(void);
extern int nfs4_proc_create_session(struct nfs4_session *);
extern int nfs4_proc_destroy_session(struct nfs4_session *);
+#else /* CONFIG_NFS_v4_1 */
+static inline int nfs4_setup_sequence(struct nfs_client *clp,
+ struct nfs41_sequence_args *args, struct nfs41_sequence_res *res,
+ int cache_reply, struct rpc_task *task)
+{
+ return 0;
+}
#endif /* CONFIG_NFS_V4_1 */
extern const u32 nfs4_fattr_bitmap[2];
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 6d90b07..19ed79c 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -1196,6 +1196,10 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
nfs_copy_fh(&data->o_res.fh, data->o_arg.fh);
}
data->timestamp = jiffies;
+ if (nfs4_setup_sequence(data->o_arg.server->nfs_client,
+ &data->o_arg.seq_args,
+ &data->o_res.seq_res, 1, task))
+ return;
rpc_call_start(task);
return;
out_no_action:
@@ -1206,8 +1210,15 @@ out_no_action:
static void nfs4_open_done(struct rpc_task *task, void *calldata)
{
struct nfs4_opendata *data = calldata;
+ struct nfs_server *server;
+ server = data->o_arg.server;
data->rpc_status = task->tk_status;
+
+ nfs4_sequence_done(server, &data->o_res.seq_res, task->tk_status);
+ /* no restart */
+ nfs4_sequence_free_slot(server, &data->o_res.seq_res);
+
if (RPC_ASSASSINATED(task))
return;
if (task->tk_status == 0) {
@@ -1589,6 +1600,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
struct nfs4_state *state = calldata->state;
struct nfs_server *server = NFS_SERVER(calldata->inode);
+ nfs4_sequence_done(server, &calldata->res.seq_res, task->tk_status);
if (RPC_ASSASSINATED(task))
return;
/* hmm. we are done with the inode, and in the process of freeing
@@ -1651,6 +1663,10 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
calldata->arg.open_flags = FMODE_WRITE;
}
calldata->timestamp = jiffies;
+ if (nfs4_setup_sequence((NFS_SERVER(calldata->inode))->nfs_client,
+ &calldata->arg.seq_args, &calldata->res.seq_res,
+ 1, task))
+ return;
rpc_call_start(task);
}
@@ -1690,7 +1706,7 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait)
};
int status = -ENOMEM;
- calldata = kmalloc(sizeof(*calldata), GFP_KERNEL);
+ calldata = kzalloc(sizeof(*calldata), GFP_KERNEL);
if (calldata == NULL)
goto out;
calldata->inode = state->inode;
@@ -2367,6 +2383,7 @@ static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir)
{
struct nfs_removeres *res = task->tk_msg.rpc_resp;
+ nfs4_sequence_done(res->server, &res->seq_res, task->tk_status);
if (nfs4_async_handle_error(task, res->server) == -EAGAIN)
return 0;
nfs4_sequence_free_slot(res->server, &res->seq_res);
@@ -2824,15 +2841,23 @@ static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data)
{
struct nfs_server *server = NFS_SERVER(data->inode);
+ int status;
+
+ dprintk("--> %s\n", __func__);
+ status = task->tk_status >= 0 ? 0 : task->tk_status;
+ /* nfs4_sequence_free_slot called in the read rpc_call_done */
+ nfs4_sequence_done(server, &data->res.seq_res, task->tk_status);
if (nfs4_async_handle_error(task, server) == -EAGAIN) {
rpc_restart_call(task);
+ dprintk("<-- %s status= %d\n", __func__, -EAGAIN);
return -EAGAIN;
}
nfs_invalidate_atime(data->inode);
if (task->tk_status > 0)
renew_lease(server, data->timestamp);
+ dprintk("<-- %s status= %d. returning 0\n", __func__, status);
return 0;
}
@@ -2847,8 +2872,11 @@ static void nfs4_proc_read_setup(struct nfs_read_data *data, struct rpc_message
static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data)
{
struct inode *inode = data->inode;
-
- if (nfs4_async_handle_error(task, NFS_SERVER(inode)) == -EAGAIN) {
+ struct nfs_server *server = NFS_SERVER(inode);
+
+ /* slot is freed in nfs_writeback_done */
+ nfs4_sequence_done(server, &data->res.seq_res, task->tk_status);
+ if (nfs4_async_handle_error(task, server) == -EAGAIN) {
rpc_restart_call(task);
return -EAGAIN;
}
@@ -2875,6 +2903,7 @@ static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data)
struct inode *inode = data->inode;
struct nfs_server *server = NFS_SERVER(inode);
+ nfs4_sequence_done(server, &data->res.seq_res, task->tk_status);
if (nfs4_async_handle_error(task, server) == -EAGAIN) {
rpc_restart_call(task);
return -EAGAIN;
@@ -3387,6 +3416,12 @@ struct nfs4_delegreturndata {
static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata)
{
struct nfs4_delegreturndata *data = calldata;
+ struct nfs_server *server = data->res.server;
+
+ nfs4_sequence_done(server, &data->res.seq_res, task->tk_status);
+ /* no restart */
+ nfs4_sequence_free_slot(server, &data->res.seq_res);
+
data->rpc_status = task->tk_status;
if (data->rpc_status == 0)
renew_lease(data->res.server, data->timestamp);
@@ -3397,9 +3432,28 @@ static void nfs4_delegreturn_release(void *calldata)
kfree(calldata);
}
+#if defined(CONFIG_NFS_V4_1)
+static void nfs4_delegreturn_prepare(struct rpc_task *task, void *data)
+{
+ struct nfs_server *server;
+ struct nfs4_delegreturndata *d_data;
+
+ d_data = (struct nfs4_delegreturndata *)data;
+ server = d_data->res.server;
+
+ if (nfs4_setup_sequence(server->nfs_client, &d_data->args.seq_args,
+ &d_data->res.seq_res, 1, task))
+ return;
+ rpc_call_start(task);
+}
+#endif /* CONFIG_NFS_V4_1 */
+
static const struct rpc_call_ops nfs4_delegreturn_ops = {
.rpc_call_done = nfs4_delegreturn_done,
.rpc_release = nfs4_delegreturn_release,
+#if defined(CONFIG_NFS_V4_1)
+ .rpc_call_prepare = nfs4_delegreturn_prepare,
+#endif
};
static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid, int issync)
@@ -3419,7 +3473,7 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co
};
int status = 0;
- data = kmalloc(sizeof(*data), GFP_KERNEL);
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
if (data == NULL)
return -ENOMEM;
data->args.fhandle = &data->fh;
@@ -3576,7 +3630,7 @@ static struct nfs4_unlockdata *nfs4_alloc_unlockdata(struct file_lock *fl,
struct nfs4_unlockdata *p;
struct inode *inode = lsp->ls_state->inode;
- p = kmalloc(sizeof(*p), GFP_KERNEL);
+ p = kzalloc(sizeof(*p), GFP_KERNEL);
if (p == NULL)
return NULL;
p->arg.fh = NFS_FH(inode);
@@ -3607,6 +3661,7 @@ static void nfs4_locku_done(struct rpc_task *task, void *data)
struct nfs4_unlockdata *calldata = data;
const struct nfs_server *server = calldata->server;
+ nfs4_sequence_done(server, &calldata->res.seq_res, task->tk_status);
if (RPC_ASSASSINATED(task))
return;
switch (task->tk_status) {
@@ -3638,6 +3693,10 @@ static void nfs4_locku_prepare(struct rpc_task *task, void *data)
return;
}
calldata->timestamp = jiffies;
+ if (nfs4_setup_sequence(calldata->server->nfs_client,
+ &calldata->arg.seq_args,
+ &calldata->res.seq_res, 1, task))
+ return;
rpc_call_start(task);
}
@@ -3726,6 +3785,7 @@ struct nfs4_lockdata {
unsigned long timestamp;
int rpc_status;
int cancelled;
+ struct nfs_server *server;
};
static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl,
@@ -3752,6 +3812,7 @@ static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl,
p->arg.lock_owner.id = lsp->ls_id.id;
p->res.lock_seqid = p->arg.lock_seqid;
p->lsp = lsp;
+ p->server = server;
atomic_inc(&lsp->ls_count);
p->ctx = get_nfs_open_context(ctx);
memcpy(&p->fl, fl, sizeof(p->fl));
@@ -3781,6 +3842,9 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata)
} else
data->arg.new_lock_owner = 0;
data->timestamp = jiffies;
+ if (nfs4_setup_sequence(data->server->nfs_client, &data->arg.seq_args,
+ &data->res.seq_res, 1, task))
+ return;
rpc_call_start(task);
dprintk("%s: done!, ret = %d\n", __func__, data->rpc_status);
}
@@ -3788,10 +3852,16 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata)
static void nfs4_lock_done(struct rpc_task *task, void *calldata)
{
struct nfs4_lockdata *data = calldata;
+ struct nfs_server *server = data->server;
dprintk("%s: begin!\n", __func__);
data->rpc_status = task->tk_status;
+
+ nfs4_sequence_done(server, &data->res.seq_res, task->tk_status);
+ /* No restart */
+ nfs4_sequence_free_slot(data->server, &data->res.seq_res);
+
if (RPC_ASSASSINATED(task))
goto out;
if (data->arg.new_lock_owner != 0) {
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 8c2019c..3c77b26 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -22,6 +22,7 @@
#include <asm/system.h>
+#include "nfs4_fs.h"
#include "internal.h"
#include "iostat.h"
@@ -175,6 +176,7 @@ static int nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
.flags = RPC_TASK_ASYNC | swap_flags,
};
+ BUG_ON(data->args.server == NULL);
data->req = req;
data->inode = inode;
data->cred = msg.rpc_cred;
@@ -254,6 +256,7 @@ static int nfs_pagein_multi(struct inode *inode, struct list_head *head, unsigne
data = nfs_readdata_alloc(1);
if (!data)
goto out_bad;
+ data->args.server = NFS_SERVER(inode);
list_add(&data->pages, &list);
requests++;
nbytes -= len;
@@ -305,6 +308,7 @@ static int nfs_pagein_one(struct inode *inode, struct list_head *head, unsigned
if (!data)
goto out_bad;
+ data->args.server = NFS_SERVER(inode);
pages = data->pagevec;
while (!list_empty(head)) {
req = nfs_list_entry(head->next);
@@ -404,7 +408,23 @@ static void nfs_readpage_release_partial(void *calldata)
nfs_readdata_release(calldata);
}
+#if defined(CONFIG_NFS_V4_1)
+void nfs_read_prepare(struct rpc_task *task, void *calldata)
+{
+ struct nfs_read_data *data = calldata;
+ struct nfs_server *server = data->args.server;
+
+ if (nfs4_setup_sequence(server->nfs_client, &data->args.seq_args,
+ &data->res.seq_res, 0, task))
+ return;
+ rpc_call_start(task);
+}
+#endif /* CONFIG_NFS_V4_1 */
+
static const struct rpc_call_ops nfs_read_partial_ops = {
+#if defined(CONFIG_NFS_V4_1)
+ .rpc_call_prepare = nfs_read_prepare,
+#endif
.rpc_call_done = nfs_readpage_result_partial,
.rpc_release = nfs_readpage_release_partial,
};
@@ -468,6 +488,9 @@ static void nfs_readpage_release_full(void *calldata)
}
static const struct rpc_call_ops nfs_read_full_ops = {
+#if defined(CONFIG_NFS_V4_1)
+ .rpc_call_prepare = nfs_read_prepare,
+#endif
.rpc_call_done = nfs_readpage_result_full,
.rpc_release = nfs_readpage_release_full,
};
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index ecc2953..3df3794 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -15,6 +15,7 @@
#include <linux/wait.h>
#include "internal.h"
+#include "nfs4_fs.h"
struct nfs_unlinkdata {
struct hlist_node list;
@@ -102,9 +103,24 @@ static void nfs_async_unlink_release(void *calldata)
nfs_sb_deactive(sb);
}
+#if defined(CONFIG_NFS_V4_1)
+void nfs_unlink_prepare(struct rpc_task *task, void *calldata)
+{
+ struct nfs_unlinkdata *data = calldata;
+ struct nfs_server *server = NFS_SERVER(data->dir);
+
+ if (nfs4_setup_sequence(server->nfs_client, &data->args.seq_args,
+ &data->res.seq_res, 1, task))
+ return;
+ rpc_call_start(task);
+}
+#endif /* CONFIG_NFS_V4_1 */
static const struct rpc_call_ops nfs_unlink_ops = {
.rpc_call_done = nfs_async_unlink_done,
.rpc_release = nfs_async_unlink_release,
+#if defined(CONFIG_NFS_V4_1)
+ .rpc_call_prepare = nfs_unlink_prepare,
+#endif
};
static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct nfs_unlinkdata *data)
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 361a61b..7d3fdc8 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -25,6 +25,7 @@
#include "delegation.h"
#include "internal.h"
#include "iostat.h"
+#include "nfs4_fs.h"
#define NFSDBG_FACILITY NFSDBG_PAGECACHE
@@ -1026,7 +1027,23 @@ out:
nfs_writedata_release(calldata);
}
+#if defined(CONFIG_NFS_V4_1)
+void nfs_write_prepare(struct rpc_task *task, void *calldata)
+{
+ struct nfs_write_data *data = calldata;
+ struct nfs_server *server = NFS_SERVER(data->inode);
+
+ if (nfs4_setup_sequence(server->nfs_client, &data->args.seq_args,
+ &data->res.seq_res, 1, task))
+ return;
+ rpc_call_start(task);
+}
+#endif /* CONFIG_NFS_V4_1 */
+
static const struct rpc_call_ops nfs_write_partial_ops = {
+#if defined(CONFIG_NFS_V4_1)
+ .rpc_call_prepare = nfs_write_prepare,
+#endif
.rpc_call_done = nfs_writeback_done_partial,
.rpc_release = nfs_writeback_release_partial,
};
@@ -1089,6 +1106,9 @@ remove_request:
}
static const struct rpc_call_ops nfs_write_full_ops = {
+#if defined(CONFIG_NFS_V4_1)
+ .rpc_call_prepare = nfs_write_prepare,
+#endif
.rpc_call_done = nfs_writeback_done_full,
.rpc_release = nfs_writeback_release_full,
};
@@ -1328,6 +1348,9 @@ static void nfs_commit_release(void *calldata)
}
static const struct rpc_call_ops nfs_commit_ops = {
+#if defined(CONFIG_NFS_V4_1)
+ .rpc_call_prepare = nfs_write_prepare,
+#endif
.rpc_call_done = nfs_commit_done,
.rpc_release = nfs_commit_release,
};
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 4144ea2..e932b0d 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -172,7 +172,7 @@ struct nfs_openargs {
int delegation_type; /* CLAIM_PREVIOUS */
} u;
const struct qstr * name;
- const struct nfs_server *server; /* Needed for ID mapping */
+ struct nfs_server * server; /* Needed for ID mapping */
const u32 * bitmask;
__u32 claim;
struct nfs41_sequence_args seq_args;
@@ -292,7 +292,7 @@ struct nfs4_delegreturnargs {
struct nfs4_delegreturnres {
struct nfs_fattr * fattr;
- const struct nfs_server *server;
+ struct nfs_server *server;
struct nfs41_sequence_res seq_res;
};
@@ -306,6 +306,7 @@ struct nfs_readargs {
__u32 count;
unsigned int pgbase;
struct page ** pages;
+ struct nfs_server *server;
struct nfs41_sequence_args seq_args;
};
@@ -355,7 +356,7 @@ struct nfs_removeargs {
};
struct nfs_removeres {
- const struct nfs_server *server;
+ struct nfs_server *server;
struct nfs4_change_info cinfo;
struct nfs_fattr dir_attr;
struct nfs41_sequence_res seq_res;
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 33/85] nfs41: Support sessions with O_DIRECT.
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (30 preceding siblings ...)
2008-11-10 20:23 ` [RFC 32/85] nfs41: sequence setup/done support Benny Halevy
@ 2008-11-10 20:23 ` Benny Halevy
2008-11-10 20:24 ` [RFC 34/85] nfs41: exchange_id operation Benny Halevy
` (53 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:23 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
From: Dean Hildebrand <seattleplus@gmail.com>
Signed-off-by: Dean Hildebrand <dhildeb@us.ibm.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/direct.c | 9 +++++++++
fs/nfs/internal.h | 6 ++++++
2 files changed, 15 insertions(+), 0 deletions(-)
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index d4ae559..b20c393 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -259,6 +259,9 @@ static void nfs_direct_read_release(void *calldata)
}
static const struct rpc_call_ops nfs_read_direct_ops = {
+#if defined(CONFIG_NFS_V4_1)
+ .rpc_call_prepare = nfs_read_prepare,
+#endif /* CONFIG_NFS_V4_1 */
.rpc_call_done = nfs_direct_read_result,
.rpc_release = nfs_direct_read_release,
};
@@ -536,6 +539,9 @@ static void nfs_direct_commit_release(void *calldata)
}
static const struct rpc_call_ops nfs_commit_direct_ops = {
+#if defined(CONFIG_NFS_V4_1)
+ .rpc_call_prepare = nfs_write_prepare,
+#endif /* CONFIG_NFS_V4_1 */
.rpc_call_done = nfs_direct_commit_result,
.rpc_release = nfs_direct_commit_release,
};
@@ -674,6 +680,9 @@ out_unlock:
}
static const struct rpc_call_ops nfs_write_direct_ops = {
+#if defined(CONFIG_NFS_V4_1)
+ .rpc_call_prepare = nfs_write_prepare,
+#endif /* CONFIG_NFS_V4_1 */
.rpc_call_done = nfs_direct_write_result,
.rpc_release = nfs_direct_write_release,
};
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 86cd70b..f78720b 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -180,6 +180,12 @@ extern int nfs4_path_walk(struct nfs_server *server,
const char *path);
#endif
+/* read.c */
+extern void nfs_read_prepare(struct rpc_task *task, void *calldata);
+
+/* write.c */
+extern void nfs_write_prepare(struct rpc_task *task, void *calldata);
+
/* nfs4proc.c */
#ifdef CONFIG_NFS_V4_1
extern void nfs41_sequence_free_slot(struct nfs41_sequence_res *res);
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 34/85] nfs41: exchange_id operation
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (31 preceding siblings ...)
2008-11-10 20:23 ` [RFC 33/85] nfs41: Support sessions with O_DIRECT Benny Halevy
@ 2008-11-10 20:24 ` Benny Halevy
2008-11-10 20:24 ` [RFC 35/85] nfs41: get_lease_time Benny Halevy
` (52 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:24 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
Implement the exchange_id operation conforming to
http://tools.ietf.org/html/draft-ietf-nfsv4-minorversion1-26
Unlike NFSv4.0, NFSv4.1 requires machine credentials. RPC_AUTH_GSS machine
credentials will be passed into the kernel at mount time to be available for
the exchange_id operation.
RPC_AUTH_UNIX root mounts can use the UNIX root credential. Store the root
credential in the nfs_client struct.
Without a credential, NFSv4.1 state renewal fails.
nfs41: establish clientid via exchange id only if cred != NULL
>From 2.6.26 reclaimer() uses machine cred for setting up the client id
therefore it is never expected to be NULL.
Note: NFS4_OPAQUE_LIMIT moved from include/linux/nfsd/state.h
to include/linux/nfs4.h since it's now used also for client side
exchange_id xdr data type.
Signed-off-by: Andy Adamson<andros@umich.edu>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/nfs4proc.c | 63 +++++++++++++++++++-
fs/nfs/nfs4xdr.c | 143 ++++++++++++++++++++++++++++++++++++++++++++
include/linux/nfs4.h | 1 +
include/linux/nfs_fs_sb.h | 6 ++
include/linux/nfs_xdr.h | 42 +++++++++++++
include/linux/nfsd/state.h | 1 -
6 files changed, 254 insertions(+), 2 deletions(-)
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 19ed79c..d2e11c3 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -48,6 +48,7 @@
#include <linux/smp_lock.h>
#include <linux/namei.h>
#include <linux/mount.h>
+#include <linux/module.h>
#include "nfs4_fs.h"
#include "delegation.h"
@@ -4175,9 +4176,69 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
}
#ifdef CONFIG_NFS_V4_1
+/*
+ * nfs4_proc_exchange_id()
+ *
+ * Since the clientid has expired, all compounds using sessions
+ * associated with the stale clientid will be returning
+ * NFS4ERR_BADSESSION in the sequence operation, and will therefore
+ * be in some phase of session reset.
+ */
static int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)
{
- return -1; /* stub */
+ nfs4_verifier verifier;
+ struct nfs41_exchange_id_args args = {
+ .flags = clp->cl_exchange_flags,
+ };
+ struct nfs41_exchange_id_res res = {
+ .client = clp,
+ };
+ int status;
+ int loop = 0;
+ struct rpc_message msg = {
+ .rpc_proc = nfs4_proc(clp, NFSPROC4_CLNT_EXCHANGE_ID),
+ .rpc_argp = &args,
+ .rpc_resp = &res,
+ .rpc_cred = cred,
+ };
+ __be32 *p;
+
+ dprintk("--> %s\n", __func__);
+ BUG_ON(clp == NULL);
+ p = (u32 *)verifier.data;
+ *p++ = htonl((u32)clp->cl_boot_time.tv_sec);
+ *p = htonl((u32)clp->cl_boot_time.tv_nsec);
+ args.verifier = &verifier;
+
+ while (1) {
+ args.id_len = scnprintf(args.id, sizeof(args.id),
+ "%s/%s %u",
+ clp->cl_ipaddr,
+ rpc_peeraddr2str(clp->cl_rpcclient,
+ RPC_DISPLAY_ADDR),
+ clp->cl_id_uniquifier);
+
+ status = rpc_call_sync(clp->cl_rpcclient, &msg, 0);
+
+ if (status != NFS4ERR_CLID_INUSE)
+ break;
+
+ if (signalled())
+ break;
+
+ /* Andy Adamson <andros at netapp.com>: Waiting a lease period
+ * allows the server to throw away a clientid previously
+ * established by this client. Of course, it doesn't help when
+ * the conflicting clientid was established by another client.
+ */
+ if (loop++ & 1)
+ ssleep(clp->cl_lease_time + 1);
+ else if (++clp->cl_id_uniquifier == 0)
+ break;
+ }
+
+ dprintk("<-- %s status= %d\n", __func__, status);
+ return status;
}
/*
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index d3da7a5..31ca211 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -242,6 +242,27 @@ static int nfs4_stat_to_errno(int);
(0)
#if defined(CONFIG_NFS_V4_1)
+#define encode_exchange_id_maxsz (op_encode_hdr_maxsz + \
+ encode_verifier_maxsz + \
+ 1 /* co_ownerid.len */ + \
+ XDR_QUADLEN(NFS4_EXCHANGE_ID_LEN) + \
+ 1 /* flags */ + \
+ 1 /* spa_how */ + \
+ 0 /* SP4_NONE (for now) */ + \
+ 1 /* zero implemetation id array */)
+#define decode_exchange_id_maxsz (op_decode_hdr_maxsz + \
+ 2 /* eir_clientid */ + \
+ 1 /* eir_sequenceid */ + \
+ 1 /* eir_flags */ + \
+ 1 /* spr_how */ + \
+ 0 /* SP4_NONE (for now) */ + \
+ 2 /* eir_server_owner.so_minor_id */ + \
+ /* eir_server_owner.so_major_id<> */ \
+ XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 + \
+ /* eir_server_scope<> */ \
+ XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 + \
+ 1 /* eir_server_impl_id array length */ + \
+ 0 /* ignored eir_server_impl_id contents */)
#define encode_sequence_maxsz 0 /* stub */
#define decode_sequence_maxsz 0 /* stub */
#else /* CONFIG_NFS_V4_1 */
@@ -590,6 +611,14 @@ static int nfs4_stat_to_errno(int);
decode_putfh_maxsz + \
decode_lookup_maxsz + \
decode_fs_locations_maxsz)
+#if defined(CONFIG_NFS_V4_1)
+#define NFS4_enc_exchange_id_sz \
+ (compound_encode_hdr_maxsz + \
+ encode_exchange_id_maxsz)
+#define NFS4_dec_exchange_id_sz \
+ (compound_decode_hdr_maxsz + \
+ decode_exchange_id_maxsz)
+#endif /* CONFIG_NFS_V4_1 */
static struct {
unsigned int mode;
@@ -1542,6 +1571,28 @@ encode_delegreturn(struct xdr_stream *xdr, const nfs4_stateid *stateid,
#if defined(CONFIG_NFS_V4_1)
/* NFSv4.1 operations */
+static int encode_exchange_id(struct xdr_stream *xdr,
+ struct nfs41_exchange_id_args *args,
+ struct compound_hdr *hdr)
+{
+
+ uint32_t *p;
+
+ RESERVE_SPACE(4 + sizeof(args->verifier->data));
+ WRITE32(OP_EXCHANGE_ID);
+ WRITEMEM(args->verifier->data, sizeof(args->verifier->data));
+
+ encode_string(xdr, args->id_len, args->id);
+
+ RESERVE_SPACE(12);
+ WRITE32(args->flags);
+ WRITE32(0); /* zero length state_protect4_a */
+ WRITE32(0); /* zero length implementation id array */
+ hdr->nops++;
+
+ return 0;
+}
+
static int encode_sequence(struct xdr_stream *xdr,
const struct nfs41_sequence_args *args,
struct compound_hdr *hdr)
@@ -2485,6 +2536,29 @@ out:
return status;
}
+#if defined(CONFIG_NFS_V4_1)
+/*
+ * EXCHANGE_ID request
+ */
+static int nfs4_xdr_enc_exchange_id(struct rpc_rqst *req, uint32_t *p,
+ void *args)
+{
+ struct xdr_stream xdr;
+ struct compound_hdr hdr = {
+ .minorversion = req->rq_task->tk_client->cl_mvers,
+ };
+ __be32 *nops;
+
+ xdr_init_encode(&xdr, &req->rq_snd_buf, p);
+ nops = encode_compound_hdr(&xdr, &hdr);
+
+ encode_exchange_id(&xdr, args, &hdr);
+
+ encode_nops(nops, &hdr);
+ return 0;
+}
+#endif /* CONFIG_NFS_V4_1 */
+
/*
* START OF "GENERIC" DECODE ROUTINES.
* These may look a little ugly since they are imported from a "generic"
@@ -4116,6 +4190,52 @@ static int decode_delegreturn(struct xdr_stream *xdr)
}
#if defined(CONFIG_NFS_V4_1)
+static int decode_exchange_id(struct xdr_stream *xdr,
+ struct nfs41_exchange_id_res *res)
+{
+ uint32_t *p;
+ int status, dummy;
+ struct nfs_client *clp = res->client;
+
+ status = decode_op_hdr(xdr, OP_EXCHANGE_ID);
+ if (status)
+ return status;
+
+ READ_BUF(8);
+ READ64(clp->cl_ex_clid);
+ READ_BUF(12);
+ READ32(clp->cl_seqid);
+ READ32(clp->cl_exchange_flags);
+
+ /* We ask for SP4_NONE */
+ READ32(dummy);
+ if (dummy != SP4_NONE)
+ return -EIO;
+
+ /* minor_id */
+ READ_BUF(8);
+ READ64(res->server_owner.minor_id);
+
+ /* Major id */
+ READ_BUF(4);
+ READ32(res->server_owner.major_id_sz);
+ READ_BUF(res->server_owner.major_id_sz);
+ COPYMEM(res->server_owner.major_id, res->server_owner.major_id_sz);
+
+ /* server_scope */
+ READ_BUF(4);
+ READ32(res->server_scope.server_scope_sz);
+ READ_BUF(res->server_scope.server_scope_sz);
+ COPYMEM(res->server_scope.server_scope,
+ res->server_scope.server_scope_sz);
+ /* Throw away Implementation id array */
+ READ_BUF(4);
+ READ32(dummy);
+ p += XDR_QUADLEN(dummy);
+
+ return 0;
+}
+
static int decode_sequence(struct xdr_stream *xdr,
struct nfs41_sequence_res *res,
struct rpc_rqst *rqstp)
@@ -4974,6 +5094,26 @@ static int nfs4_xdr_dec_setclientid(struct rpc_rqst *req, __be32 *p,
return status;
}
+/* FIXME: move down at the bottom after all nfs40 funcs */
+#if defined(CONFIG_NFS_V4_1)
+/*
+ * EXCHANGE_ID request
+ */
+static int nfs4_xdr_dec_exchange_id(struct rpc_rqst *rqstp, uint32_t *p,
+ void *res)
+{
+ struct xdr_stream xdr;
+ struct compound_hdr hdr;
+ int status;
+
+ xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
+ status = decode_compound_hdr(&xdr, &hdr);
+ if (!status)
+ status = decode_exchange_id(&xdr, res);
+ return status;
+}
+#endif /* CONFIG_NFS_V4_1 */
+
/*
* a SETCLIENTID_CONFIRM request
*/
@@ -5217,6 +5357,9 @@ struct rpc_procinfo nfs4_procedures[] = {
PROC(GETACL, enc_getacl, dec_getacl),
PROC(SETACL, enc_setacl, dec_setacl),
PROC(FS_LOCATIONS, enc_fs_locations, dec_fs_locations),
+#if defined(CONFIG_NFS_V4_1)
+ PROC(EXCHANGE_ID, enc_exchange_id, dec_exchange_id),
+#endif /* CONFIG_NFS_V4_1 */
};
struct rpc_version nfs_version4 = {
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
index a69bbfa..be4af09 100644
--- a/include/linux/nfs4.h
+++ b/include/linux/nfs4.h
@@ -21,6 +21,7 @@
#define NFS4_FHSIZE 128
#define NFS4_MAXPATHLEN PATH_MAX
#define NFS4_MAXNAMLEN NAME_MAX
+#define NFS4_OPAQUE_LIMIT 1024
#define NFS4_MAX_SESSIONID_LEN 16
#define NFS4_ACCESS_READ 0x0001
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index 15c0aa5..9917c09 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -75,6 +75,12 @@ struct nfs_client {
#endif /* CONFIG_NFS_V4 */
#ifdef CONFIG_NFS_V4_1
+ /* clientid returned from EXCHANGE_ID, used by session operations */
+ u64 cl_ex_clid;
+ /* The sequence id to use for the next CREATE_SESSION */
+ u32 cl_seqid;
+ /* The flags used for obtaining the clientid during EXCHANGE_ID */
+ u32 cl_exchange_flags;
struct nfs4_session *cl_session; /* sharred session */
#endif /* CONFIG_NFS_V4_1 */
};
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index e932b0d..976ced7 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -859,6 +859,48 @@ struct nfs4_fs_locations_res {
#endif /* CONFIG_NFS_V4 */
+#ifdef CONFIG_NFS_V4_1
+struct nfstime4 {
+ u64 seconds;
+ u32 nseconds;
+};
+
+struct nfs_impl_id4 {
+ u32 domain_len;
+ char *domain;
+ u32 name_len;
+ char *name;
+ struct nfstime4 date;
+};
+
+#define NFS4_EXCHANGE_ID_LEN (48)
+struct nfs41_exchange_id_args {
+ nfs4_verifier *verifier;
+ unsigned int id_len;
+ char id[NFS4_EXCHANGE_ID_LEN];
+ u32 flags;
+};
+
+struct server_owner {
+ uint64_t minor_id;
+ uint32_t major_id_sz;
+ char major_id[NFS4_OPAQUE_LIMIT];
+};
+
+struct server_scope {
+ uint32_t server_scope_sz;
+ char server_scope[NFS4_OPAQUE_LIMIT];
+};
+
+struct nfs41_exchange_id_res {
+ struct nfs_client *client;
+ u32 flags;
+ struct server_owner server_owner;
+ struct server_scope server_scope;
+ struct nfs_impl_id4 impl_id;
+};
+#endif /* CONFIG_NFS_V4_1 */
+
struct nfs_page;
#define NFS_PAGEVEC_SIZE (8U)
diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
index d0fe2e3..8f492e3 100644
--- a/include/linux/nfsd/state.h
+++ b/include/linux/nfsd/state.h
@@ -41,7 +41,6 @@
#include <linux/kref.h>
#include <linux/sunrpc/clnt.h>
-#define NFS4_OPAQUE_LIMIT 1024
typedef struct {
u32 cl_boot;
u32 cl_id;
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 35/85] nfs41: get_lease_time
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (32 preceding siblings ...)
2008-11-10 20:24 ` [RFC 34/85] nfs41: exchange_id operation Benny Halevy
@ 2008-11-10 20:24 ` Benny Halevy
2008-11-10 20:24 ` [RFC 36/85] nfs41: create_session operation Benny Halevy
` (51 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:24 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
get_lease_time uses the FSINFO rpc operation to
get the lease time attribute.
Signed-off-by: Andy Adamson<andros@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/nfs4proc.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++
fs/nfs/nfs4xdr.c | 56 +++++++++++++++++++++++++++++++++++
2 files changed, 140 insertions(+), 0 deletions(-)
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index d2e11c3..f1918fa 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -4241,6 +4241,90 @@ static int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)
return status;
}
+struct nfs4_get_lease_time_data {
+ struct nfs4_get_lease_time_args *args;
+ struct nfs4_get_lease_time_res *res;
+ struct nfs_client *clp;
+ struct nfs4_session *session;
+};
+
+static void nfs4_get_lease_time_prepare(struct rpc_task *task,
+ void *calldata)
+{
+ int ret;
+ struct nfs4_get_lease_time_data *data =
+ (struct nfs4_get_lease_time_data *)calldata;
+
+ dprintk("--> %s\n", __func__);
+ /* just setup sequence, do not trigger session recovery
+ since we're invoked within one */
+ ret = nfs41_setup_sequence(data->session,
+ &data->args->la_seq_args,
+ &data->res->lr_seq_res, 0, task);
+
+ BUG_ON(ret == -EAGAIN);
+ rpc_call_start(task);
+ dprintk("<-- %s\n", __func__);
+}
+
+static void nfs4_get_lease_time_done(struct rpc_task *task,
+ void *calldata)
+{
+ struct nfs4_get_lease_time_data *data =
+ (struct nfs4_get_lease_time_data *)calldata;
+
+ dprintk("--> %s\n", __func__);
+ nfs41_sequence_done(data->clp, &data->res->lr_seq_res, task->tk_status);
+ nfs41_sequence_free_slot(&data->res->lr_seq_res);
+ dprintk("<-- %s\n", __func__);
+}
+
+struct rpc_call_ops nfs4_get_lease_time_ops = {
+ .rpc_call_prepare = nfs4_get_lease_time_prepare,
+ .rpc_call_done = nfs4_get_lease_time_done,
+};
+
+int nfs4_proc_get_lease_time(struct nfs_client *clp,
+ struct nfs4_session *session, struct nfs_fsinfo *fsinfo)
+{
+ struct rpc_task *task;
+ struct nfs4_get_lease_time_args args;
+ struct nfs4_get_lease_time_res res = {
+ .lr_fsinfo = fsinfo,
+ };
+ struct nfs4_get_lease_time_data data = {
+ .args = &args,
+ .res = &res,
+ .clp = clp,
+ .session = session,
+ };
+ struct rpc_message msg = {
+ .rpc_proc = nfs4_proc(clp, NFSPROC4_CLNT_GET_LEASE_TIME),
+ .rpc_argp = &args,
+ .rpc_resp = &res,
+ };
+ struct rpc_task_setup task_setup = {
+ .rpc_client = session->clnt,
+ .rpc_message = &msg,
+ .callback_ops = &nfs4_get_lease_time_ops,
+ .callback_data = &data
+ };
+ int status;
+
+ dprintk("--> %s\n", __func__);
+ task = rpc_run_task(&task_setup);
+
+ if (IS_ERR(task))
+ status = PTR_ERR(task);
+ else {
+ status = task->tk_status;
+ rpc_put_task(task);
+ }
+ dprintk("<-- %s return %d\n", __func__, status);
+
+ return status;
+}
+
/*
* Initialize slot table
*
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 31ca211..7b7d4e8 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -618,6 +618,14 @@ static int nfs4_stat_to_errno(int);
#define NFS4_dec_exchange_id_sz \
(compound_decode_hdr_maxsz + \
decode_exchange_id_maxsz)
+#define NFS4_enc_get_lease_time_sz (compound_encode_hdr_maxsz + \
+ encode_sequence_maxsz + \
+ encode_putrootfh_maxsz + \
+ encode_fsinfo_maxsz)
+#define NFS4_dec_get_lease_time_sz (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz + \
+ decode_putrootfh_maxsz + \
+ decode_fsinfo_maxsz)
#endif /* CONFIG_NFS_V4_1 */
static struct {
@@ -2557,6 +2565,32 @@ static int nfs4_xdr_enc_exchange_id(struct rpc_rqst *req, uint32_t *p,
encode_nops(nops, &hdr);
return 0;
}
+
+/*
+ * a GET_LEASE_TIME request
+ */
+static int nfs4_xdr_enc_get_lease_time(struct rpc_rqst *req, uint32_t *p,
+ struct nfs4_get_lease_time_args *args)
+{
+ struct xdr_stream xdr;
+ struct compound_hdr hdr = {
+ .minorversion = req->rq_task->tk_client->cl_mvers,
+ };
+ int status;
+ const u32 lease_bitmap[2] = { FATTR4_WORD0_LEASE_TIME, 0 };
+ __be32 *nops;
+
+ xdr_init_encode(&xdr, &req->rq_snd_buf, p);
+ nops = encode_compound_hdr(&xdr, &hdr);
+ encode_sequence(&xdr, &args->la_seq_args, &hdr);
+ status = encode_putrootfh(&xdr, &hdr);
+ if (status)
+ goto out;
+ status = encode_fsinfo(&xdr, lease_bitmap, &hdr);
+ out:
+ encode_nops(nops, &hdr);
+ return status;
+}
#endif /* CONFIG_NFS_V4_1 */
/*
@@ -5112,6 +5146,27 @@ static int nfs4_xdr_dec_exchange_id(struct rpc_rqst *rqstp, uint32_t *p,
status = decode_exchange_id(&xdr, res);
return status;
}
+
+/*
+ * a GET_LEASE_TIME request
+ */
+static int nfs4_xdr_dec_get_lease_time(struct rpc_rqst *rqstp, uint32_t *p,
+ struct nfs4_get_lease_time_res *res)
+{
+ struct xdr_stream xdr;
+ struct compound_hdr hdr;
+ int status;
+
+ xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
+ status = decode_compound_hdr(&xdr, &hdr);
+ if (!status)
+ status = decode_sequence(&xdr, &res->lr_seq_res, rqstp);
+ if (!status)
+ status = decode_putrootfh(&xdr);
+ if (!status)
+ status = decode_fsinfo(&xdr, res->lr_fsinfo);
+ return status;
+}
#endif /* CONFIG_NFS_V4_1 */
/*
@@ -5359,6 +5414,7 @@ struct rpc_procinfo nfs4_procedures[] = {
PROC(FS_LOCATIONS, enc_fs_locations, dec_fs_locations),
#if defined(CONFIG_NFS_V4_1)
PROC(EXCHANGE_ID, enc_exchange_id, dec_exchange_id),
+ PROC(GET_LEASE_TIME, enc_get_lease_time, dec_get_lease_time),
#endif /* CONFIG_NFS_V4_1 */
};
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 36/85] nfs41: create_session operation
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (33 preceding siblings ...)
2008-11-10 20:24 ` [RFC 35/85] nfs41: get_lease_time Benny Halevy
@ 2008-11-10 20:24 ` Benny Halevy
2008-11-10 20:24 ` [RFC 37/85] nfs41: destroy_session operation Benny Halevy
` (50 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:24 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
From: Andy Adamson <andros@netapp.com>
Implement the create_session operation conforming to
http://tools.ietf.org/html/draft-ietf-nfsv4-minorversion1-26
Signed-off-by: Ricardo Labiaga <ricardo.labiaga@netapp.com>
Signed-off-by: Andy Adamson<andros@umich.edu>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/nfs4proc.c | 141 ++++++++++++++++++++++++++++++++++-
fs/nfs/nfs4xdr.c | 193 +++++++++++++++++++++++++++++++++++++++++++++++
include/linux/nfs_xdr.h | 17 ++++
3 files changed, 350 insertions(+), 1 deletions(-)
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index f1918fa..7607dfd 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -55,6 +55,7 @@
#include "internal.h"
#include "iostat.h"
#if defined(CONFIG_NFS_V4_1)
+#include "callback.h"
#include <linux/nfs4_session.h>
#endif /* CONFIG_NFS_V4_1 */
@@ -4448,9 +4449,147 @@ void nfs4_get_session(struct nfs_client *clp)
atomic_inc(&clp->cl_session->ref_count);
}
+/* Initialize the values to be used by the client in CREATE_SESSION */
+static void nfs4_init_channel_attrs(struct nfs_client *clp,
+ struct nfs4_channel_attrs *fc_attrs,
+ struct nfs4_channel_attrs *bc_attrs)
+{
+ /* XXX: We need to have good values here... 32K is a wild guess */
+ fc_attrs->headerpadsz = bc_attrs->headerpadsz = 0;
+ fc_attrs->max_rqst_sz = bc_attrs->max_rqst_sz = NFS_MAX_FILE_IO_SIZE;
+ fc_attrs->max_resp_sz = bc_attrs->max_resp_sz = NFS_MAX_FILE_IO_SIZE;
+ fc_attrs->max_resp_sz_cached = bc_attrs->max_resp_sz_cached =
+ NFS_MAX_FILE_IO_SIZE;
+ fc_attrs->max_ops = bc_attrs->max_ops = 0xFFFFFFFF;
+ fc_attrs->max_reqs = bc_attrs->max_reqs =
+ clp->cl_rpcclient->cl_xprt->max_reqs;
+ fc_attrs->rdma_attrs = bc_attrs->rdma_attrs = 0;
+}
+
+/* Check the values returned by the server for CREATE_SESSION. Since we made
+ * our needs known, if the server gives us more than we need, we don't bother
+ * with it.
+ */
+static void nfs4_adjust_channel_attrs(struct nfs4_channel_attrs *req_attrs,
+ struct nfs4_channel_attrs *resp_attrs)
+{
+ dprintk("%s: before adjusting: max_rqst_sz=%u max_resp_sz=%u "
+ "max_resp_sz_cached=%u max_ops=%u max_reqs=%u\n",
+ __func__,
+ resp_attrs->max_rqst_sz, resp_attrs->max_resp_sz,
+ resp_attrs->max_resp_sz_cached, resp_attrs->max_ops,
+ resp_attrs->max_reqs);
+
+ if (req_attrs->max_rqst_sz < resp_attrs->max_rqst_sz)
+ resp_attrs->max_rqst_sz = req_attrs->max_rqst_sz;
+
+ if (req_attrs->max_resp_sz < resp_attrs->max_resp_sz)
+ resp_attrs->max_resp_sz = req_attrs->max_resp_sz;
+
+ if (req_attrs->max_resp_sz_cached < resp_attrs->max_resp_sz)
+ resp_attrs->max_resp_sz = req_attrs->max_resp_sz_cached;
+
+ if (req_attrs->max_ops < resp_attrs->max_ops)
+ resp_attrs->max_ops = req_attrs->max_ops;
+
+ if (req_attrs->max_reqs < resp_attrs->max_reqs)
+ resp_attrs->max_reqs = req_attrs->max_reqs;
+
+ dprintk("%s: after adjusting: max_rqst_sz=%u max_resp_sz=%u "
+ "max_resp_sz_cached=%u max_ops=%u max_reqs=%u\n",
+ __func__,
+ resp_attrs->max_rqst_sz, resp_attrs->max_resp_sz,
+ resp_attrs->max_resp_sz_cached, resp_attrs->max_ops,
+ resp_attrs->max_reqs);
+
+ /* We ignore the rdma channel attributes */
+}
+
+static int _nfs4_proc_create_session(struct nfs4_session *session)
+{
+ struct nfs_client *clp = session->clp;
+ struct nfs41_create_session_args args = {
+ .client = clp,
+ .session = session,
+ .cb_program = NFS4_CALLBACK,
+ };
+
+ struct nfs41_create_session_res res = {
+ .client = clp,
+ .session = session,
+ };
+
+ struct rpc_message msg = {
+ .rpc_proc = nfs4_proc(clp, NFSPROC4_CLNT_CREATE_SESSION),
+ .rpc_argp = &args,
+ .rpc_resp = &res,
+ };
+ int status;
+
+ nfs4_init_channel_attrs(clp, &args.fc_attrs, &args.bc_attrs);
+ args.flags = (SESSION4_PERSIST);
+
+ status = rpc_call_sync(session->clnt, &msg, 0);
+
+ /* Set the negotiated values in the session's channel_attrs struct */
+
+ if (!status) {
+ nfs4_adjust_channel_attrs(&args.fc_attrs,
+ &session->fore_channel.chan_attrs);
+ nfs4_adjust_channel_attrs(&args.bc_attrs,
+ &session->back_channel.chan_attrs);
+ /* Increment the clientid slot sequence id */
+ clp->cl_seqid++;
+ }
+
+ return status;
+}
+
+/*
+ * Issues a CREATE_SESSION operation to the server.
+ * It is the responsibility of the caller to verify the session is
+ * expired before calling this routine.
+ */
int nfs4_proc_create_session(struct nfs4_session *session)
{
- return -1; /* stub */
+ int status;
+ u32 *ptr;
+ struct nfs_fsinfo fsinfo;
+ struct nfs_client *clp = session->clp;
+
+ dprintk("--> %s clp=%p session=%p\n", __func__, clp, session);
+
+ status = _nfs4_proc_create_session(session);
+ if (status)
+ goto out;
+
+ session->clnt = clp->cl_rpcclient;
+
+ /* Init the fore channel */
+ status = nfs4_init_slot_table(&session->fore_channel);
+ dprintk("fore channel initialization returned %d\n", status);
+ if (status)
+ goto out;
+
+ dprintk("%s client>seqid %d\n", __func__, clp->cl_seqid);
+ ptr = (int *)session->sess_id;
+ dprintk("sessionid is: %u:%u:%u:%u\n", ptr[0], ptr[1], ptr[2], ptr[3]);
+
+ /* Get the lease time */
+ status = nfs4_proc_get_lease_time(clp, session, &fsinfo);
+ if (status == 0) {
+ /* Update lease time and schedule renewal */
+ spin_lock(&clp->cl_lock);
+ clp->cl_lease_time = fsinfo.lease_time * HZ;
+ clp->cl_last_renewal = jiffies;
+ clear_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
+ spin_unlock(&clp->cl_lock);
+
+ nfs4_schedule_state_renewal(clp);
+ }
+out:
+ dprintk("<-- %s\n", __func__);
+ return status;
}
int nfs4_proc_destroy_session(struct nfs4_session *session)
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 7b7d4e8..4dfb04e 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -242,6 +242,8 @@ static int nfs4_stat_to_errno(int);
(0)
#if defined(CONFIG_NFS_V4_1)
+#define NFS4_MAX_MACHINE_NAME_LEN (64)
+
#define encode_exchange_id_maxsz (op_encode_hdr_maxsz + \
encode_verifier_maxsz + \
1 /* co_ownerid.len */ + \
@@ -263,6 +265,31 @@ static int nfs4_stat_to_errno(int);
XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 + \
1 /* eir_server_impl_id array length */ + \
0 /* ignored eir_server_impl_id contents */)
+#define encode_channel_attrs_maxsz (6 + 1 /* ca_rdma_ird.len (0) */)
+#define decode_channel_attrs_maxsz (6 + \
+ 1 /* ca_rdma_ird.len */ + \
+ 1 /* ca_rdma_ird */)
+#define encode_create_session_maxsz (op_encode_hdr_maxsz + \
+ 2 /* csa_clientid */ + \
+ 1 /* csa_sequence */ + \
+ 1 /* csa_flags */ + \
+ encode_channel_attrs_maxsz + \
+ encode_channel_attrs_maxsz + \
+ 1 /* csa_cb_program */ + \
+ 1 /* csa_sec_parms.len (1) */ + \
+ 1 /* cb_secflavor (AUTH_SYS) */ + \
+ 1 /* stamp */ + \
+ 1 /* machinename.len */ + \
+ XDR_QUADLEN(NFS4_MAX_MACHINE_NAME_LEN) + \
+ 1 /* uid */ + \
+ 1 /* gid */ + \
+ 1 /* gids.len (0) */)
+#define decode_create_session_maxsz (op_decode_hdr_maxsz + \
+ XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + \
+ 1 /* csr_sequence */ + \
+ 1 /* csr_flags */ + \
+ decode_channel_attrs_maxsz + \
+ decode_channel_attrs_maxsz)
#define encode_sequence_maxsz 0 /* stub */
#define decode_sequence_maxsz 0 /* stub */
#else /* CONFIG_NFS_V4_1 */
@@ -618,6 +645,12 @@ static int nfs4_stat_to_errno(int);
#define NFS4_dec_exchange_id_sz \
(compound_decode_hdr_maxsz + \
decode_exchange_id_maxsz)
+#define NFS4_enc_create_session_sz \
+ (compound_encode_hdr_maxsz + \
+ encode_create_session_maxsz)
+#define NFS4_dec_create_session_sz \
+ (compound_decode_hdr_maxsz + \
+ decode_create_session_maxsz)
#define NFS4_enc_get_lease_time_sz (compound_encode_hdr_maxsz + \
encode_sequence_maxsz + \
encode_putrootfh_maxsz + \
@@ -1601,6 +1634,69 @@ static int encode_exchange_id(struct xdr_stream *xdr,
return 0;
}
+static int encode_create_session(struct xdr_stream *xdr,
+ struct nfs41_create_session_args *args,
+ struct compound_hdr *hdr)
+{
+ uint32_t *p;
+ char machine_name[NFS4_MAX_MACHINE_NAME_LEN];
+ uint32_t len;
+ struct nfs_client *clp = args->client;
+
+ RESERVE_SPACE(4);
+ WRITE32(OP_CREATE_SESSION);
+
+ RESERVE_SPACE(8);
+ WRITE64(clp->cl_ex_clid);
+
+ RESERVE_SPACE(8);
+ WRITE32(clp->cl_seqid); /*Sequence id */
+ WRITE32(args->flags); /*flags */
+
+ RESERVE_SPACE(2*28); /* 2 channel_attrs */
+ /* Fore Channel */
+ WRITE32(args->fc_attrs.headerpadsz); /* header padding size */
+ WRITE32(args->fc_attrs.max_rqst_sz); /* max req size */
+ WRITE32(args->fc_attrs.max_resp_sz); /* max resp size */
+ WRITE32(args->fc_attrs.max_resp_sz_cached); /* Max resp sz cached */
+ WRITE32(args->fc_attrs.max_ops); /* max operations */
+ WRITE32(args->fc_attrs.max_reqs); /* max requests */
+ WRITE32(0); /* rdmachannel_attrs */
+
+ /* Back Channel */
+ WRITE32(args->fc_attrs.headerpadsz); /* header padding size */
+ WRITE32(args->bc_attrs.max_rqst_sz); /* max req size */
+ WRITE32(args->bc_attrs.max_resp_sz); /* max resp size */
+ WRITE32(args->bc_attrs.max_resp_sz_cached); /* Max resp sz cached */
+ WRITE32(args->bc_attrs.max_ops); /* max operations */
+ WRITE32(args->bc_attrs.max_reqs); /* max requests */
+ WRITE32(0); /* rdmachannel_attrs */
+
+ RESERVE_SPACE(4);
+ WRITE32(args->cb_program); /* cb_program */
+
+ RESERVE_SPACE(4); /* # of security flavors */
+ WRITE32(1);
+
+ RESERVE_SPACE(4);
+ WRITE32(RPC_AUTH_UNIX); /* auth_sys */
+
+ /* authsys_parms rfc1831 */
+ RESERVE_SPACE(4);
+ WRITE32((u32)clp->cl_boot_time.tv_nsec); /* stamp */
+ len = scnprintf(machine_name, sizeof(machine_name), "%s",
+ clp->cl_ipaddr);
+ RESERVE_SPACE(16 + len);
+ WRITE32(len);
+ WRITEMEM(machine_name, len);
+ WRITE32(0); /* UID */
+ WRITE32(0); /* GID */
+ WRITE32(0); /* No more gids */
+ hdr->nops++;
+
+ return 0;
+}
+
static int encode_sequence(struct xdr_stream *xdr,
const struct nfs41_sequence_args *args,
struct compound_hdr *hdr)
@@ -2567,6 +2663,27 @@ static int nfs4_xdr_enc_exchange_id(struct rpc_rqst *req, uint32_t *p,
}
/*
+ * a CREATE_SESSION request
+ */
+static int nfs4_xdr_enc_create_session(struct rpc_rqst *req, uint32_t *p,
+ struct nfs41_create_session_args *args)
+{
+ struct xdr_stream xdr;
+ struct compound_hdr hdr = {
+ .minorversion = req->rq_task->tk_client->cl_mvers,
+ };
+ int status;
+ __be32 *nops;
+
+ xdr_init_encode(&xdr, &req->rq_snd_buf, p);
+ nops = encode_compound_hdr(&xdr, &hdr);
+
+ status = encode_create_session(&xdr, args, &hdr);
+ encode_nops(nops, &hdr);
+ return status;
+}
+
+/*
* a GET_LEASE_TIME request
*/
static int nfs4_xdr_enc_get_lease_time(struct rpc_rqst *req, uint32_t *p,
@@ -4270,6 +4387,64 @@ static int decode_exchange_id(struct xdr_stream *xdr,
return 0;
}
+static int decode_create_session(struct xdr_stream *xdr,
+ struct nfs41_create_session_res *res)
+{
+ uint32_t *p;
+ int status;
+ u32 nr_attrs;
+
+ struct nfs4_session *session = res->session;
+ struct nfs_client *clp = res->client;
+
+ status = decode_op_hdr(xdr, OP_CREATE_SESSION);
+
+ if (status)
+ return status;
+
+ /* sessionid */
+ READ_BUF(NFS4_MAX_SESSIONID_LEN);
+ COPYMEM(&session->sess_id, NFS4_MAX_SESSIONID_LEN);
+
+ /* seqid, flags */
+ READ_BUF(8);
+ READ32(clp->cl_seqid);
+ READ32(session->flags);
+
+ /* Channel attributes */
+ /* fore channel */
+ READ_BUF(24);
+ READ32(session->fore_channel.chan_attrs.headerpadsz);
+ READ32(session->fore_channel.chan_attrs.max_rqst_sz);
+ READ32(session->fore_channel.chan_attrs.max_resp_sz);
+ READ32(session->fore_channel.chan_attrs.max_resp_sz_cached);
+ READ32(session->fore_channel.chan_attrs.max_ops);
+ READ32(session->fore_channel.chan_attrs.max_reqs);
+ READ_BUF(4);
+ READ32(nr_attrs);
+ if (nr_attrs == 1) {
+ READ_BUF(4);
+ READ32(session->fore_channel.chan_attrs.rdma_attrs);
+ }
+
+ /* back channel */
+ READ_BUF(24);
+ READ32(session->fore_channel.chan_attrs.headerpadsz);
+ READ32(session->back_channel.chan_attrs.max_rqst_sz);
+ READ32(session->back_channel.chan_attrs.max_resp_sz);
+ READ32(session->back_channel.chan_attrs.max_resp_sz_cached);
+ READ32(session->back_channel.chan_attrs.max_ops);
+ READ32(session->back_channel.chan_attrs.max_reqs);
+ READ_BUF(4);
+ READ32(nr_attrs);
+ if (nr_attrs == 1) {
+ READ_BUF(4);
+ READ32(session->back_channel.chan_attrs.rdma_attrs);
+ }
+
+ return 0;
+}
+
static int decode_sequence(struct xdr_stream *xdr,
struct nfs41_sequence_res *res,
struct rpc_rqst *rqstp)
@@ -5148,6 +5323,23 @@ static int nfs4_xdr_dec_exchange_id(struct rpc_rqst *rqstp, uint32_t *p,
}
/*
+ * a CREATE_SESSION request
+ */
+static int nfs4_xdr_dec_create_session(struct rpc_rqst *rqstp, uint32_t *p,
+ struct nfs41_create_session_res *res)
+{
+ struct xdr_stream xdr;
+ struct compound_hdr hdr;
+ int status;
+
+ xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
+ status = decode_compound_hdr(&xdr, &hdr);
+ if (!status)
+ status = decode_create_session(&xdr, res);
+ return status;
+}
+
+/*
* a GET_LEASE_TIME request
*/
static int nfs4_xdr_dec_get_lease_time(struct rpc_rqst *rqstp, uint32_t *p,
@@ -5414,6 +5606,7 @@ struct rpc_procinfo nfs4_procedures[] = {
PROC(FS_LOCATIONS, enc_fs_locations, dec_fs_locations),
#if defined(CONFIG_NFS_V4_1)
PROC(EXCHANGE_ID, enc_exchange_id, dec_exchange_id),
+ PROC(CREATE_SESSION, enc_create_session, dec_create_session),
PROC(GET_LEASE_TIME, enc_get_lease_time, dec_get_lease_time),
#endif /* CONFIG_NFS_V4_1 */
};
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 976ced7..18fcc96 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -2,6 +2,9 @@
#define _LINUX_NFS_XDR_H
#include <linux/nfsacl.h>
+#ifdef CONFIG_NFS_V4_1
+#include <linux/nfs4_session.h>
+#endif
/*
* To change the maximum rsize and wsize supported by the NFS client, adjust
@@ -899,6 +902,20 @@ struct nfs41_exchange_id_res {
struct server_scope server_scope;
struct nfs_impl_id4 impl_id;
};
+
+struct nfs41_create_session_args {
+ struct nfs_client *client;
+ struct nfs4_session *session;
+ uint32_t flags;
+ uint32_t cb_program;
+ struct nfs4_channel_attrs fc_attrs; /* Fore Channel */
+ struct nfs4_channel_attrs bc_attrs; /* Back Channel */
+};
+
+struct nfs41_create_session_res {
+ struct nfs_client *client;
+ struct nfs4_session *session;
+};
#endif /* CONFIG_NFS_V4_1 */
struct nfs_page;
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 37/85] nfs41: destroy_session operation
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (34 preceding siblings ...)
2008-11-10 20:24 ` [RFC 36/85] nfs41: create_session operation Benny Halevy
@ 2008-11-10 20:24 ` Benny Halevy
2008-11-10 20:24 ` [RFC 38/85] nfs41: sequence operation Benny Halevy
` (49 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:24 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
Implement the destroy_session operation conforming to
http://tools.ietf.org/html/draft-ietf-nfsv4-minorversion1-26
Signed-off-by: Ricardo Labiaga <ricardo.labiaga@netapp.com>
Signed-off-by: Andy Adamson<andros@umich.edu>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/nfs4proc.c | 23 ++++++++++++++++++-
fs/nfs/nfs4xdr.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++
fs/nfs/super.c | 2 +
3 files changed, 86 insertions(+), 1 deletions(-)
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 7607dfd..a205328 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -4592,9 +4592,30 @@ out:
return status;
}
+/*
+ * Issue the over-the-wire RPC DESTROY_SESSION.
+ * The caller must serialize access to this routine.
+ */
int nfs4_proc_destroy_session(struct nfs4_session *session)
{
- return -1; /* stub */
+ int status = 0;
+ struct rpc_message msg;
+
+ dprintk("--> nfs4_proc_destroy_session\n");
+
+ msg.rpc_proc = nfs4_proc(session->clp, NFSPROC4_CLNT_DESTROY_SESSION);
+ msg.rpc_argp = session;
+ msg.rpc_resp = NULL;
+ msg.rpc_cred = NULL;
+ status = rpc_call_sync(session->clnt, &msg, 0);
+
+ if (status)
+ printk(KERN_WARNING
+ "Got error %d from the server on DESTROY_SESSION. "
+ "Session has been destroyed regardless...\n", status);
+
+ dprintk("<-- nfs4_proc_destroy_session\n");
+ return status;
}
static int nfs4_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred)
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 4dfb04e..d34856e 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -290,6 +290,8 @@ static int nfs4_stat_to_errno(int);
1 /* csr_flags */ + \
decode_channel_attrs_maxsz + \
decode_channel_attrs_maxsz)
+#define encode_destroy_session_maxsz (op_encode_hdr_maxsz + 4)
+#define decode_destroy_session_maxsz (op_decode_hdr_maxsz)
#define encode_sequence_maxsz 0 /* stub */
#define decode_sequence_maxsz 0 /* stub */
#else /* CONFIG_NFS_V4_1 */
@@ -651,6 +653,10 @@ static int nfs4_stat_to_errno(int);
#define NFS4_dec_create_session_sz \
(compound_decode_hdr_maxsz + \
decode_create_session_maxsz)
+#define NFS4_enc_destroy_session_sz (compound_encode_hdr_maxsz + \
+ encode_destroy_session_maxsz)
+#define NFS4_dec_destroy_session_sz (compound_decode_hdr_maxsz + \
+ decode_destroy_session_maxsz)
#define NFS4_enc_get_lease_time_sz (compound_encode_hdr_maxsz + \
encode_sequence_maxsz + \
encode_putrootfh_maxsz + \
@@ -1697,6 +1703,19 @@ static int encode_create_session(struct xdr_stream *xdr,
return 0;
}
+static int encode_destroy_session(struct xdr_stream *xdr,
+ struct nfs4_session *session,
+ struct compound_hdr *hdr)
+{
+ uint32_t *p;
+ RESERVE_SPACE(4 + NFS4_MAX_SESSIONID_LEN);
+ WRITE32(OP_DESTROY_SESSION);
+ WRITEMEM(session->sess_id, NFS4_MAX_SESSIONID_LEN);
+ hdr->nops++;
+
+ return 0;
+}
+
static int encode_sequence(struct xdr_stream *xdr,
const struct nfs41_sequence_args *args,
struct compound_hdr *hdr)
@@ -2684,6 +2703,26 @@ static int nfs4_xdr_enc_create_session(struct rpc_rqst *req, uint32_t *p,
}
/*
+ * a DESTROY_SESSION request
+ */
+static int nfs4_xdr_enc_destroy_session(struct rpc_rqst *req, uint32_t *p,
+ struct nfs4_session *session)
+{
+ struct xdr_stream xdr;
+ struct compound_hdr hdr = {
+ .minorversion = req->rq_task->tk_client->cl_mvers,
+ };
+ __be32 *nops;
+
+ xdr_init_encode(&xdr, &req->rq_snd_buf, p);
+ nops = encode_compound_hdr(&xdr, &hdr);
+
+ encode_destroy_session(&xdr, session, &hdr);
+ encode_nops(nops, &hdr);
+ return 0;
+}
+
+/*
* a GET_LEASE_TIME request
*/
static int nfs4_xdr_enc_get_lease_time(struct rpc_rqst *req, uint32_t *p,
@@ -4445,6 +4484,11 @@ static int decode_create_session(struct xdr_stream *xdr,
return 0;
}
+static int decode_destroy_session(struct xdr_stream *xdr, void *dummy)
+{
+ return decode_op_hdr(xdr, OP_DESTROY_SESSION);
+}
+
static int decode_sequence(struct xdr_stream *xdr,
struct nfs41_sequence_res *res,
struct rpc_rqst *rqstp)
@@ -5340,6 +5384,23 @@ static int nfs4_xdr_dec_create_session(struct rpc_rqst *rqstp, uint32_t *p,
}
/*
+ * a DESTROY_SESSION request
+ */
+static int nfs4_xdr_dec_destroy_session(struct rpc_rqst *rqstp, uint32_t *p,
+ void *dummy)
+{
+ struct xdr_stream xdr;
+ struct compound_hdr hdr;
+ int status;
+
+ xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
+ status = decode_compound_hdr(&xdr, &hdr);
+ if (!status)
+ status = decode_destroy_session(&xdr, dummy);
+ return status;
+}
+
+/*
* a GET_LEASE_TIME request
*/
static int nfs4_xdr_dec_get_lease_time(struct rpc_rqst *rqstp, uint32_t *p,
@@ -5607,6 +5668,7 @@ struct rpc_procinfo nfs4_procedures[] = {
#if defined(CONFIG_NFS_V4_1)
PROC(EXCHANGE_ID, enc_exchange_id, dec_exchange_id),
PROC(CREATE_SESSION, enc_create_session, dec_create_session),
+ PROC(DESTROY_SESSION, enc_destroy_session, dec_destroy_session),
PROC(GET_LEASE_TIME, enc_get_lease_time, dec_get_lease_time),
#endif /* CONFIG_NFS_V4_1 */
};
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 03f143d..d7f99f8 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -2431,11 +2431,13 @@ static void nfs4_kill_super(struct super_block *sb)
{
struct nfs_server *server = NFS_SB(sb);
+ dprintk("--> %s\n", __func__);
nfs_return_all_delegations(sb);
kill_anon_super(sb);
nfs4_renewd_prepare_shutdown(server);
nfs_free_server(server);
+ dprintk("<-- %s\n", __func__);
}
/*
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 38/85] nfs41: sequence operation
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (35 preceding siblings ...)
2008-11-10 20:24 ` [RFC 37/85] nfs41: destroy_session operation Benny Halevy
@ 2008-11-10 20:24 ` Benny Halevy
2008-11-10 20:25 ` [RFC 39/85] nfs41: session recovery infrastructure Benny Halevy
` (48 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:24 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
Implement the sequence operation conforming to
http://tools.ietf.org/html/draft-ietf-nfsv4-minorversion1-26
Check returned sessionid, slotid and slot sequenceid in decode_sequence.
Pass the sequence operation status to nfs41_sequence_done in order to
determine when to increment the slot sequence ID.
Free slot is separated from sequence done.
Signed-off-by: Rahul Iyer <iyer@netapp.com>
Signed-off-by: Ricardo Labiaga <ricardo.labiaga@netapp.com>
Signed-off-by: Andy Adamson<andros@umich.edu>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/nfs4proc.c | 92 +++++++++++++++++++++++++++++++++++++++++-
fs/nfs/nfs4xdr.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 201 insertions(+), 6 deletions(-)
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index a205328..836f4f3 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -4620,13 +4620,101 @@ int nfs4_proc_destroy_session(struct nfs4_session *session)
static int nfs4_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred)
{
- return -1; /* stub */
+ struct nfs41_sequence_args args;
+ struct nfs41_sequence_res res;
+ struct nfs_server *server;
+
+ struct rpc_message msg = {
+ .rpc_proc = nfs4_proc(clp, NFSPROC4_CLNT_SEQUENCE),
+ .rpc_argp = &args,
+ .rpc_resp = &res,
+ .rpc_cred = cred,
+ };
+ int status;
+
+ /*
+ * We need to renew the lease on the server. For this, we use any
+ * session we have on the server to send the SEQUENCE op
+ */
+ BUG_ON(list_empty(&clp->cl_superblocks));
+
+ server = list_entry(clp->cl_superblocks.next, struct nfs_server,
+ client_link);
+
+ args.sa_cache_this = 0;
+
+ status = _nfs4_call_sync(server, &msg, &args, &res, 0);
+ return status;
+}
+
+void nfs41_sequence_call_done(struct rpc_task *task, void *data)
+{
+ struct nfs_server *server = (struct nfs_server *)data;
+
+ nfs4_sequence_done(server, task->tk_msg.rpc_resp, task->tk_status);
+ nfs4_sequence_free_slot(server, task->tk_msg.rpc_resp);
+ dprintk("%s rpc_cred %p\n", __func__, task->tk_msg.rpc_cred);
+
+ put_rpccred(task->tk_msg.rpc_cred);
+ kfree(task->tk_msg.rpc_argp);
+ kfree(task->tk_msg.rpc_resp);
+
+ dprintk("<-- %s\n", __func__);
+}
+
+static void nfs41_sequence_prepare(struct rpc_task *task, void *data)
+{
+ struct nfs_server *server;
+ struct nfs41_sequence_args *args;
+ struct nfs41_sequence_res *res;
+
+ server = (struct nfs_server *)data;
+ args = task->tk_msg.rpc_argp;
+ res = task->tk_msg.rpc_resp;
+
+ if (nfs4_setup_sequence(server->nfs_client, args, res, 0, task))
+ return;
+ rpc_call_start(task);
}
+static const struct rpc_call_ops nfs41_sequence_ops = {
+ .rpc_call_done = nfs41_sequence_call_done,
+ .rpc_call_prepare = nfs41_sequence_prepare,
+};
+
static int nfs41_proc_async_sequence(struct nfs_client *clp,
struct rpc_cred *cred)
{
- return -1; /* stub */
+ struct nfs41_sequence_args *args;
+ struct nfs41_sequence_res *res;
+ struct nfs_server *server;
+ struct rpc_message msg = {
+ .rpc_proc = nfs4_proc(clp, NFSPROC4_CLNT_SEQUENCE),
+ .rpc_cred = cred,
+ };
+
+ args = kzalloc(sizeof(*args), GFP_KERNEL);
+ if (!args)
+ return -ENOMEM;
+ res = kzalloc(sizeof(*res), GFP_KERNEL);
+ if (!res) {
+ kfree(args);
+ return -ENOMEM;
+ }
+ msg.rpc_argp = args;
+ msg.rpc_resp = res;
+
+ /*
+ * We need to renew the lease on the server. For this, we use any
+ * session we have on the server to send the SEQUENCE op
+ */
+ BUG_ON(list_empty(&clp->cl_superblocks));
+
+ server = list_entry(clp->cl_superblocks.next, struct nfs_server,
+ client_link);
+
+ return rpc_call_async(server->client, &msg, RPC_TASK_SOFT,
+ &nfs41_sequence_ops, (void *)server);
}
#endif /* CONFIG_NFS_V4_1 */
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index d34856e..81cf09d 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -292,8 +292,10 @@ static int nfs4_stat_to_errno(int);
decode_channel_attrs_maxsz)
#define encode_destroy_session_maxsz (op_encode_hdr_maxsz + 4)
#define decode_destroy_session_maxsz (op_decode_hdr_maxsz)
-#define encode_sequence_maxsz 0 /* stub */
-#define decode_sequence_maxsz 0 /* stub */
+#define encode_sequence_maxsz (op_encode_hdr_maxsz + \
+ XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 4)
+#define decode_sequence_maxsz (op_decode_hdr_maxsz + \
+ XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 5)
#else /* CONFIG_NFS_V4_1 */
#define encode_sequence_maxsz 0
#define decode_sequence_maxsz 0
@@ -657,6 +659,12 @@ static int nfs4_stat_to_errno(int);
encode_destroy_session_maxsz)
#define NFS4_dec_destroy_session_sz (compound_decode_hdr_maxsz + \
decode_destroy_session_maxsz)
+#define NFS4_enc_sequence_sz \
+ (compound_decode_hdr_maxsz + \
+ encode_sequence_maxsz)
+#define NFS4_dec_sequence_sz \
+ (compound_decode_hdr_maxsz + \
+ decode_sequence_maxsz)
#define NFS4_enc_get_lease_time_sz (compound_encode_hdr_maxsz + \
encode_sequence_maxsz + \
encode_putrootfh_maxsz + \
@@ -1720,10 +1728,34 @@ static int encode_sequence(struct xdr_stream *xdr,
const struct nfs41_sequence_args *args,
struct compound_hdr *hdr)
{
+ struct nfs4_slot_table *tp = &args->sa_session->fore_channel.slot_table;
+ __be32 *p;
+
if (hdr->minorversion == 0)
return 0;
- /* stub */
+ WARN_ON(slot_idx(tp, args->sa_slot) < 0);
+
+ RESERVE_SPACE(4);
+ WRITE32(OP_SEQUENCE);
+
+ /*
+ * Sessionid + seqid + slotid + max slotid + cache_this
+ */
+ dprintk("%s: sessionid=%u:%u:%u:%u seqid=%d slotid=%d "
+ "max_slotid=%d cache_this=%d\n",
+ __func__, ((u32 *)args->sa_session->sess_id)[0],
+ ((u32 *)args->sa_session->sess_id)[1],
+ ((u32 *)args->sa_session->sess_id)[2],
+ ((u32 *)args->sa_session->sess_id)[3],
+ args->sa_slot->seq_nr, slot_idx(tp, args->sa_slot),
+ tp->highest_used_slotid, args->sa_cache_this);
+ RESERVE_SPACE(NFS4_MAX_SESSIONID_LEN + 16);
+ WRITEMEM(args->sa_session->sess_id, NFS4_MAX_SESSIONID_LEN);
+ WRITE32(args->sa_slot->seq_nr);
+ WRITE32(slot_idx(tp, args->sa_slot));
+ WRITE32(tp->highest_used_slotid);
+ WRITE32(args->sa_cache_this);
hdr->nops++;
return 0;
@@ -2723,6 +2755,25 @@ static int nfs4_xdr_enc_destroy_session(struct rpc_rqst *req, uint32_t *p,
}
/*
+ * a SEQUENCE request
+ */
+static int nfs4_xdr_enc_sequence(struct rpc_rqst *req, uint32_t *p,
+ struct nfs41_sequence_args *args)
+{
+ struct xdr_stream xdr;
+ struct compound_hdr hdr = {
+ .minorversion = req->rq_task->tk_client->cl_mvers,
+ };
+ __be32 *nops;
+
+ xdr_init_encode(&xdr, &req->rq_snd_buf, p);
+ nops = encode_compound_hdr(&xdr, &hdr);
+ encode_sequence(&xdr, args, &hdr);
+ encode_nops(nops, &hdr);
+ return 0;
+}
+
+/*
* a GET_LEASE_TIME request
*/
static int nfs4_xdr_enc_get_lease_time(struct rpc_rqst *req, uint32_t *p,
@@ -4493,12 +4544,50 @@ static int decode_sequence(struct xdr_stream *xdr,
struct nfs41_sequence_res *res,
struct rpc_rqst *rqstp)
{
+ struct nfs4_slot_table *tp = &res->sr_session->fore_channel.slot_table;
+ struct sessionid4 id;
+ u32 dummy;
+ int status;
+ __be32 *p;
+
if (rqstp->rq_task->tk_client->cl_mvers == 0)
return 0;
- /* stub */
+ status = decode_op_hdr(xdr, OP_SEQUENCE);
+ if (status)
+ goto out_err;
+
+ status = -EIO;
+
+ READ_BUF(NFS4_MAX_SESSIONID_LEN + 20);
+ COPYMEM(id.data, NFS4_MAX_SESSIONID_LEN);
+ if (memcmp(id.data, res->sr_session->sess_id, NFS4_MAX_SESSIONID_LEN)) {
+ dprintk("%s Invalid session id\n", __func__);
+ goto out_err;
+ }
+ /* seqid */
+ READ32(dummy);
+ if (dummy != res->sr_slot->seq_nr) {
+ dprintk("%s Invalid sequence number\n", __func__);
+ goto out_err;
+ }
+ /* slot id */
+ READ32(dummy);
+ if (dummy != slot_idx(tp, res->sr_slot)) {
+ dprintk("%s Invalid slot id\n", __func__);
+ goto out_err;
+ }
+ /* highest slot id - currently not processed */
+ READ32(dummy);
+ /* target highest slot id - currently not processed */
+ READ32(dummy);
+ READ32(res->sr_flags);
return 0;
+out_err:
+ /* task->tk_status is from the sequence operation */
+ res->sr_flags = SEQ4_STATUS_USE_TK_STATUS;
+ return status;
}
#else /* CONFIG_NFS_V4_1 */
static inline int decode_sequence(struct xdr_stream *xdr,
@@ -5401,6 +5490,23 @@ static int nfs4_xdr_dec_destroy_session(struct rpc_rqst *rqstp, uint32_t *p,
}
/*
+ * a SEQUENCE request
+ */
+static int nfs4_xdr_dec_sequence(struct rpc_rqst *rqstp, uint32_t *p,
+ struct nfs41_sequence_res *res)
+{
+ struct xdr_stream xdr;
+ struct compound_hdr hdr;
+ int status;
+
+ xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
+ status = decode_compound_hdr(&xdr, &hdr);
+ if (!status)
+ status = decode_sequence(&xdr, res, rqstp);
+ return status;
+}
+
+/*
* a GET_LEASE_TIME request
*/
static int nfs4_xdr_dec_get_lease_time(struct rpc_rqst *rqstp, uint32_t *p,
@@ -5669,6 +5775,7 @@ struct rpc_procinfo nfs4_procedures[] = {
PROC(EXCHANGE_ID, enc_exchange_id, dec_exchange_id),
PROC(CREATE_SESSION, enc_create_session, dec_create_session),
PROC(DESTROY_SESSION, enc_destroy_session, dec_destroy_session),
+ PROC(SEQUENCE, enc_sequence, dec_sequence),
PROC(GET_LEASE_TIME, enc_get_lease_time, dec_get_lease_time),
#endif /* CONFIG_NFS_V4_1 */
};
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 39/85] nfs41: session recovery infrastructure
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (36 preceding siblings ...)
2008-11-10 20:24 ` [RFC 38/85] nfs41: sequence operation Benny Halevy
@ 2008-11-10 20:25 ` Benny Halevy
2008-11-10 20:25 ` [RFC 40/85] nfs41: schedule async session reset Benny Halevy
` (47 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:25 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
From: Andy Adamson <andros@netapp.com>
FIXME: review comment message.
NFSv4.1 session recovery.
Sessions are created in the "alloc" state and session recovery
is used to initiate session creation as well.
nfs41: Correctly use new session in exception handling
We will need to handle several layers of session recovery depending on the
error. As a last resort, we will need to use the big hammer; destroy
an existing session and create a new one.
The current code creates a new session without destroying the old one.
Destroy the existing session and initialize a new session before calling
nfs41_recover_session_sync.
nfs41: correctly expire and validate session
Do not expire session in session_reclaimer error case where the session could
be ok (create session succeeded) but nfs4_proc_get_lease_time failed. Leave
the session expiration (as well as new session initialization) to callers.
The session is valid as soon as the create session rpc completes successfully,
and is not dependant upon a successful nfs4_proc_get_lease_time rpc.
Move session validation from nfs4_proc_create_session to the success case of
_nfs4_proc_create_session.
nfs41: add nfs_client pointer to struct nfs4_session
The session is always associated with a struct nfs_client that holds
the exchange_id results. Add an nfs_client struct backpointer to the session
and refactor the session recovery routines to only require a struct
nfs4_sessions parameter.
Signed-off-by: Rahul Iyer <iyer@netapp.com>
Signed-off-by: Andy Adamson<andros@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/Makefile | 1 +
fs/nfs/client.c | 2 +-
fs/nfs/nfs41_session_recovery.c | 186 ++++++++++++++++++++++++++++++++
fs/nfs/nfs4proc.c | 17 +++-
include/linux/nfs41_session_recovery.h | 40 +++++++
5 files changed, 242 insertions(+), 4 deletions(-)
create mode 100644 fs/nfs/nfs41_session_recovery.c
create mode 100644 include/linux/nfs41_session_recovery.h
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index ac6170c..de5ea30 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -14,4 +14,5 @@ nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \
delegation.o idmap.o \
callback.o callback_xdr.o callback_proc.o \
nfs4namespace.o
+nfs-$(CONFIG_NFS_V4_1) += nfs41_session_recovery.o
nfs-$(CONFIG_SYSCTL) += sysctl.o
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 62bdf31..560b10b 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -38,7 +38,7 @@
#include <net/ipv6.h>
#include <linux/nfs_xdr.h>
#if defined(CONFIG_NFS_V4_1)
-#include <linux/nfs4_session.h>
+#include <linux/nfs41_session_recovery.h>
#endif /* CONFIG_NFS_V4_1 */
#include <asm/system.h>
diff --git a/fs/nfs/nfs41_session_recovery.c b/fs/nfs/nfs41_session_recovery.c
new file mode 100644
index 0000000..39ad45f
--- /dev/null
+++ b/fs/nfs/nfs41_session_recovery.c
@@ -0,0 +1,186 @@
+/*
+ * NFSv4.1 session recovery code
+ *
+ * Author: Rahul Iyer <iyer@netapp.com>
+ *
+ * This code is released under GPL. For details see Documentation/COPYING
+ */
+
+#if defined(CONFIG_NFS_V4_1)
+
+#include <linux/module.h>
+#include <linux/kthread.h>
+#include <linux/in.h>
+#include <linux/fs.h>
+#include <linux/sunrpc/xdr.h>
+#include <linux/sunrpc/clnt.h>
+#include <linux/nfs3.h>
+#include <linux/nfs_xdr.h>
+#include <linux/nfs.h>
+#include <linux/nfs_fs.h>
+#include <linux/namei.h>
+#include <linux/nfs_fs_sb.h>
+#include <linux/nfs41_session_recovery.h>
+#include "nfs4_fs.h"
+#include "internal.h"
+
+#define NFSDBG_FACILITY NFSDBG_PROC
+
+/*
+ * Set the session state == valid. Returns previous value of the session state
+ */
+int nfs41_set_session_valid(struct nfs4_session *session)
+{
+ int ret;
+ smp_mb__before_clear_bit();
+ ret = test_and_clear_bit(NFS41_SESSION_ALLOC,
+ &session->session_state);
+ smp_mb__after_clear_bit();
+
+ return ret;
+}
+
+static int nfs41_start_session_recovery(struct nfs4_session *session)
+{
+ int ret;
+ ret = test_and_set_bit(NFS41_SESSION_RECOVER, &session->session_state);
+
+ return ret;
+}
+
+struct reclaimer_arg {
+ struct nfs4_session *session;
+};
+
+static int nfs41_end_session_recovery(struct nfs4_session *session)
+{
+ smp_mb__before_clear_bit();
+ clear_bit(NFS41_SESSION_RECOVER, &session->session_state);
+ smp_mb__after_clear_bit();
+
+ /*
+ * Wake up sync tasks
+ */
+ wake_up_bit(&session->session_state, NFS41_SESSION_RECOVER);
+ return 0;
+}
+
+static int nfs41_wait_session_recover_sync(struct nfs4_session *session)
+{
+ might_sleep();
+ return wait_on_bit(&session->session_state, NFS41_SESSION_RECOVER,
+ nfs4_wait_bit_killable, TASK_KILLABLE);
+}
+
+static int session_reclaimer(void *arg)
+{
+ int ret;
+ struct reclaimer_arg *rec = (struct reclaimer_arg *)arg;
+
+ dprintk("--> %s\n", __func__);
+ allow_signal(SIGKILL);
+
+ ret = nfs4_proc_create_session(rec->session);
+ if (ret)
+ goto out_error;
+
+out:
+ nfs41_end_session_recovery(rec->session);
+ kfree(rec);
+ module_put_and_exit(0);
+ dprintk("<-- %s: status=%d\n", __func__, ret);
+ return ret;
+out_error:
+ printk(KERN_WARNING "Error: session recovery failed on "
+ "NFSv4.1 server with error %d\n", ret);
+
+ switch (ret) {
+ case -NFS4ERR_STALE_CLIENTID:
+ case -NFS4ERR_STALE_STATEID:
+ case -NFS4ERR_EXPIRED:
+ set_bit(NFS4CLNT_LEASE_EXPIRED, &rec->session->clp->cl_state);
+ break;
+ }
+ goto out;
+}
+
+static int nfs41_schedule_session_recovery(struct reclaimer_arg *rec)
+{
+ struct task_struct *task;
+
+ dprintk("--> %s: spawning session_reclaimer\n", __func__);
+ __module_get(THIS_MODULE);
+ task = kthread_run(session_reclaimer, rec, "%llx-session-reclaim",
+ *(unsigned long long *)&rec->session->sess_id);
+
+ if (!IS_ERR(task)) {
+ dprintk("<-- %s\n", __func__);
+ return 0;
+ }
+
+ module_put(THIS_MODULE);
+ dprintk("--> %s: failed spawning session_reclaimer: error=%ld\n",
+ __func__, PTR_ERR(task));
+ return PTR_ERR(task);
+}
+
+/*
+ * Session recovery
+ * Called when an op receives a session related error
+ */
+int nfs41_recover_session(struct nfs4_session *session)
+{
+ struct reclaimer_arg *rec = NULL;
+ int ret;
+
+ dprintk("--> %s: clp=%p session=%p\n", __func__, session->clp, session);
+
+ ret = nfs41_start_session_recovery(session);
+
+ /*
+ * If we get 1, it means some other thread beat us to us here, so we
+ * just sit back and wait for completion of the recovery process
+ */
+ if (ret) {
+ dprintk("%s: session_recovery already started\n", __func__);
+ ret = 0;
+ goto out;
+ }
+
+ ret = -ENOMEM;
+ rec = kmalloc(sizeof(*rec), GFP_KERNEL);
+ if (!rec)
+ goto err;
+ rec->session = session;
+
+ ret = nfs41_schedule_session_recovery(rec);
+ /*
+ * We got an error creating the reclaiming thread, so end the recovery
+ * and bail out
+ */
+ if (ret)
+ goto err;
+out:
+ dprintk("<-- %s status=%d\n", __func__, ret);
+ return ret;
+err:
+ nfs41_end_session_recovery(session);
+ kfree(rec);
+ goto out;
+}
+
+int nfs41_recover_session_sync(struct nfs4_session *session)
+{
+ int ret;
+
+ dprintk("--> %s\n", __func__);
+
+ ret = nfs41_recover_session(session);
+ if (!ret)
+ ret = nfs41_wait_session_recover_sync(session);
+
+ dprintk("<-- %s: status=%d\n", __func__, ret);
+ return ret;
+}
+
+#endif /* CONFIG_NFS_V4_1 */
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 836f4f3..ede017c 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -56,7 +56,7 @@
#include "iostat.h"
#if defined(CONFIG_NFS_V4_1)
#include "callback.h"
-#include <linux/nfs4_session.h>
+#include <linux/nfs41_session_recovery.h>
#endif /* CONFIG_NFS_V4_1 */
#define NFSDBG_FACILITY NFSDBG_PROC
@@ -68,7 +68,7 @@ struct nfs4_opendata;
static int _nfs4_proc_open(struct nfs4_opendata *data);
static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *);
static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *);
-static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception);
+static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struct nfs4_exception *exception);
static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs_client *clp);
static int _nfs4_proc_lookup(struct inode *dir, const struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr);
static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr);
@@ -3280,7 +3280,7 @@ static int nfs4_delay(struct rpc_clnt *clnt, long *timeout)
/* This is the error handling routine for processes that are allowed
* to sleep.
*/
-static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception)
+static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struct nfs4_exception *exception)
{
struct nfs_client *clp = server->nfs_client;
int ret = errorcode;
@@ -4420,6 +4420,8 @@ struct nfs4_session *nfs4_alloc_session(void)
if (!session)
return NULL;
+ nfs41_set_session_alloc(session);
+
atomic_set(&session->ref_count, 1);
nfs4_init_channel(&session->fore_channel);
@@ -4538,6 +4540,8 @@ static int _nfs4_proc_create_session(struct nfs4_session *session)
&session->fore_channel.chan_attrs);
nfs4_adjust_channel_attrs(&args.bc_attrs,
&session->back_channel.chan_attrs);
+ nfs41_set_session_valid(session); /* Activate session */
+
/* Increment the clientid slot sequence id */
clp->cl_seqid++;
}
@@ -4603,6 +4607,10 @@ int nfs4_proc_destroy_session(struct nfs4_session *session)
dprintk("--> nfs4_proc_destroy_session\n");
+ /* session is still being created */
+ if (nfs41_test_session_alloc(session))
+ return status;
+
msg.rpc_proc = nfs4_proc(session->clp, NFSPROC4_CLNT_DESTROY_SESSION);
msg.rpc_argp = session;
msg.rpc_resp = NULL;
@@ -4641,6 +4649,9 @@ static int nfs4_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred)
server = list_entry(clp->cl_superblocks.next, struct nfs_server,
client_link);
+ if (nfs41_test_session_alloc(clp->cl_session))
+ return -NFS4ERR_STALE_CLIENTID;
+
args.sa_cache_this = 0;
status = _nfs4_call_sync(server, &msg, &args, &res, 0);
diff --git a/include/linux/nfs41_session_recovery.h b/include/linux/nfs41_session_recovery.h
new file mode 100644
index 0000000..2d91e80
--- /dev/null
+++ b/include/linux/nfs41_session_recovery.h
@@ -0,0 +1,40 @@
+/*
+ * Session Recovery header file
+ *
+ * Author: Rahul Iyer <iyer@netapp.com>
+ *
+ * This code is released under GPL. For details see Documentation/COPYING
+ */
+
+#ifndef __NFS41_SESSION_RECOVERY_H__
+#define __NFS41_SESSION_RECOVERY_H__
+
+#if defined(CONFIG_NFS_V4_1)
+
+/*
+ * Session state bits
+ */
+enum nfs41_session_state {
+ NFS41_SESSION_ALLOC = 0,
+ NFS41_SESSION_RECOVER,
+};
+
+/*
+ * Set the session state to alloc
+ */
+static inline int nfs41_set_session_alloc(struct nfs4_session *session)
+{
+ return test_and_set_bit(NFS41_SESSION_ALLOC, &session->session_state);
+}
+
+static inline int nfs41_test_session_alloc(struct nfs4_session *session)
+{
+ return test_bit(NFS41_SESSION_ALLOC, &session->session_state);
+}
+
+int nfs41_set_session_valid(struct nfs4_session *);
+int nfs41_recover_session(struct nfs4_session *);
+int nfs41_recover_session_sync(struct nfs4_session *);
+
+#endif /* CONFIG_NFS_V4_1 */
+#endif /* __NFS41_SESSION_RECOVERY_H__ */
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 40/85] nfs41: schedule async session reset
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (37 preceding siblings ...)
2008-11-10 20:25 ` [RFC 39/85] nfs41: session recovery infrastructure Benny Halevy
@ 2008-11-10 20:25 ` Benny Halevy
2008-11-10 20:25 ` [RFC 41/85] nfs41: lease renewal Benny Halevy
` (46 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:25 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
From: Andy Adamson <andros@netapp.com>
Define a new session reset state which is set upon a sequence operation error
in both the sync and async error handlers.
Place all new requests and all but the last outstanding rpc on the
slot_tbl_waitq. Spawn the recovery thread when the last slot is free.
Call nfs4_proc_destroy_session, reinitialize the session, call
nfs4_proc_create_session, clear the session reset state, and wake up the next
task on the slot_tbl_waitq.
Return the nfs4_proc_destroy_session status to the session reclaimer and
check for NFS4ERR_BADSESSION and NFS4ERR_DEADSESSION. Other destroy session
errors should be handled in nfs4_proc_destroy_session where the call can
be retried with adjusted arguments.
Signed-off-by: Andy Adamson<andros@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/nfs41_session_recovery.c | 51 +++++++++++++++++++++--
fs/nfs/nfs4_fs.h | 2 +-
fs/nfs/nfs4proc.c | 69 +++++++++++++++++++++++++++++--
include/linux/nfs41_session_recovery.h | 30 ++++++++++++++
4 files changed, 141 insertions(+), 11 deletions(-)
diff --git a/fs/nfs/nfs41_session_recovery.c b/fs/nfs/nfs41_session_recovery.c
index 39ad45f..a54572b 100644
--- a/fs/nfs/nfs41_session_recovery.c
+++ b/fs/nfs/nfs41_session_recovery.c
@@ -48,6 +48,17 @@ static int nfs41_start_session_recovery(struct nfs4_session *session)
return ret;
}
+/*
+ * Session reset
+ */
+
+int nfs41_wait_session_reset(struct nfs4_session *session)
+{
+ might_sleep();
+ return wait_on_bit(&session->session_state, NFS41_SESSION_RESET,
+ nfs4_wait_bit_killable, TASK_KILLABLE);
+}
+
struct reclaimer_arg {
struct nfs4_session *session;
};
@@ -74,17 +85,49 @@ static int nfs41_wait_session_recover_sync(struct nfs4_session *session)
static int session_reclaimer(void *arg)
{
- int ret;
+ int ret, reset;
struct reclaimer_arg *rec = (struct reclaimer_arg *)arg;
- dprintk("--> %s\n", __func__);
+ dprintk("--> %s session %p\n", __func__, rec->session);
allow_signal(SIGKILL);
- ret = nfs4_proc_create_session(rec->session);
+ reset = nfs41_test_session_reset(rec->session);
+ if (reset) {
+ dprintk("%s Session Reset\n", __func__);
+ /* Reset is called only when all slots are clear.
+ *
+ * Bail on the reset if destroy session op fails or if
+ * the session ref_count is not 1
+ *
+ * Of course since we are resetting the session,
+ * it's OK if the session is already destroyed
+ * on the server.
+ */
+ ret = nfs4_proc_destroy_session(rec->session);
+ switch (ret) {
+ case 0:
+ case -NFS4ERR_BADSESSION:
+ case -NFS4ERR_DEADSESSION:
+ break;
+ default:
+ goto out_error;
+ }
+ memset(rec->session->sess_id, 0, sizeof(nfs41_sessionid));
+ }
+ ret = nfs4_proc_create_session(rec->session, reset);
if (ret)
goto out_error;
out:
+ if (reset) {
+ struct nfs4_slot_table *tbl;
+
+ tbl = &rec->session->fore_channel.slot_table;
+ /* Need to clear reset bit and wake up the next rpc task
+ * even on error */
+ nfs41_clear_session_reset(rec->session);
+ rpc_wake_up_next(&tbl->slot_tbl_waitq);
+ }
nfs41_end_session_recovery(rec->session);
kfree(rec);
module_put_and_exit(0);
@@ -96,8 +139,6 @@ out_error:
switch (ret) {
case -NFS4ERR_STALE_CLIENTID:
- case -NFS4ERR_STALE_STATEID:
- case -NFS4ERR_EXPIRED:
set_bit(NFS4CLNT_LEASE_EXPIRED, &rec->session->clp->cl_state);
break;
}
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index d0aac94..8cdc3c4 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -196,7 +196,7 @@ extern int nfs4_setup_sequence(struct nfs_client *clp,
extern void nfs4_put_session(struct nfs4_session **session);
extern void nfs4_get_session(struct nfs_client *clp);
extern struct nfs4_session *nfs4_alloc_session(void);
-extern int nfs4_proc_create_session(struct nfs4_session *);
+extern int nfs4_proc_create_session(struct nfs4_session *, int reset);
extern int nfs4_proc_destroy_session(struct nfs4_session *);
#else /* CONFIG_NFS_v4_1 */
static inline int nfs4_setup_sequence(struct nfs_client *clp,
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index ede017c..41f4f74 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -386,13 +386,32 @@ static void nfs41_sequence_done(struct nfs_client *clp,
* A pointer to the slot's seqid is returned if found, or NULL otherwise.
*/
static struct nfs4_slot *
-nfs4_find_slot(struct nfs4_slot_table *tbl, struct rpc_task *task)
+nfs4_find_slot(struct nfs4_slot_table *tbl, struct rpc_task *task,
+ struct nfs4_session *session)
{
int bit, slotid;
struct nfs4_slot *slot = NULL;
unsigned long *used, u;
spin_lock(&tbl->slot_tbl_lock);
+ if (nfs41_test_session_reset(session)) {
+ dprintk("%s Session Reset\n", __func__);
+ if (tbl->highest_used_slotid == -1) {
+ int ret;
+
+ /* The slot table is empty; start the reset thread */
+ dprintk("%s Slot Table Empty\n", __func__);
+ spin_unlock(&tbl->slot_tbl_lock);
+ ret = nfs41_recover_session_sync(session);
+ if (ret)
+ return slot;
+ nfs41_wait_session_reset(session);
+ spin_lock(&tbl->slot_tbl_lock);
+ } else {
+ /* Wait on the slot_tbl_waitq */
+ goto out;
+ }
+ }
slotid = tbl->lowest_free_slotid;
while (slotid < tbl->max_slots) {
used = idx2bmp(tbl->used_slots, slotid, NULL);
@@ -418,6 +437,7 @@ nfs4_find_slot(struct nfs4_slot_table *tbl, struct rpc_task *task)
break;
}
tbl->lowest_free_slotid = slotid;
+out:
spin_unlock(&tbl->slot_tbl_lock);
dprintk("<-- %s slot %p slotid %d\n", __func__,
slot, slot ? slot_idx(tbl, slot) : -1);
@@ -435,7 +455,7 @@ static int nfs41_setup_sequence(struct nfs4_session *session,
dprintk("--> %s\n", __func__);
tbl = &session->fore_channel.slot_table;
- slot = nfs4_find_slot(tbl, task);
+ slot = nfs4_find_slot(tbl, task, session);
if (!slot) {
rpc_sleep_on(&tbl->slot_tbl_waitq, task, NULL);
@@ -4326,6 +4346,38 @@ int nfs4_proc_get_lease_time(struct nfs_client *clp,
return status;
}
+/* Reset a slot table */
+static int nfs4_reset_slot_table(struct nfs4_channel *channel)
+{
+ struct nfs4_slot_table *tbl = &channel->slot_table;
+ int i, max_slots = channel->chan_attrs.max_reqs;
+ int old_max_slots = channel->slot_table.max_slots;
+ int ret = 0;
+
+ dprintk("--> %s: max_reqs=%u, tbl %p\n", __func__,
+ channel->chan_attrs.max_reqs, tbl);
+
+ /* Until we have dynamic slot table adjustment, insist
+ * upon the same slot table size */
+ if (max_slots != old_max_slots) {
+ dprintk("%s reset slot table does't match old\n",
+ __func__);
+ ret = -EINVAL; /*XXX NFS4ERR_REQ_TOO_BIG ? */
+ goto out;
+ }
+ spin_lock(&tbl->slot_tbl_lock);
+ for (i = 0; i < max_slots; ++i)
+ tbl->slots[i].seq_nr = 1;
+ tbl->lowest_free_slotid = 0;
+ tbl->highest_used_slotid = -1;
+ spin_unlock(&tbl->slot_tbl_lock);
+ dprintk("%s: tbl=%p slots=%p max_slots=%d\n", __func__,
+ tbl, tbl->slots, tbl->max_slots);
+out:
+ dprintk("<-- %s: return %d\n", __func__, ret);
+ return ret;
+}
+
/*
* Initialize slot table
*
@@ -4554,7 +4606,7 @@ static int _nfs4_proc_create_session(struct nfs4_session *session)
* It is the responsibility of the caller to verify the session is
* expired before calling this routine.
*/
-int nfs4_proc_create_session(struct nfs4_session *session)
+int nfs4_proc_create_session(struct nfs4_session *session, int reset)
{
int status;
u32 *ptr;
@@ -4569,8 +4621,11 @@ int nfs4_proc_create_session(struct nfs4_session *session)
session->clnt = clp->cl_rpcclient;
- /* Init the fore channel */
- status = nfs4_init_slot_table(&session->fore_channel);
+ /* Init or reset the fore channel */
+ if (reset)
+ status = nfs4_reset_slot_table(&session->fore_channel);
+ else
+ status = nfs4_init_slot_table(&session->fore_channel);
dprintk("fore channel initialization returned %d\n", status);
if (status)
goto out;
@@ -4579,6 +4634,10 @@ int nfs4_proc_create_session(struct nfs4_session *session)
ptr = (int *)session->sess_id;
dprintk("sessionid is: %u:%u:%u:%u\n", ptr[0], ptr[1], ptr[2], ptr[3]);
+ if (reset)
+ /* Lease time is aleady set */
+ goto out;
+
/* Get the lease time */
status = nfs4_proc_get_lease_time(clp, session, &fsinfo);
if (status == 0) {
diff --git a/include/linux/nfs41_session_recovery.h b/include/linux/nfs41_session_recovery.h
index 2d91e80..a0f61b3 100644
--- a/include/linux/nfs41_session_recovery.h
+++ b/include/linux/nfs41_session_recovery.h
@@ -13,10 +13,17 @@
/*
* Session state bits
+ *
+ * State machine.
+ * NFS41_SESSION_ALLOC bit set: session is ready for create_session call.
+ * NFS41_SESSION_RECOVER bit set: session is being reset/recovered
+ * NFS41_SESSION_ALLOC bit unset: valid session in use.
+ * NFS41_SESSION_RESET bit set: session is being reset.
*/
enum nfs41_session_state {
NFS41_SESSION_ALLOC = 0,
NFS41_SESSION_RECOVER,
+ NFS41_SESSION_RESET,
};
/*
@@ -32,6 +39,29 @@ static inline int nfs41_test_session_alloc(struct nfs4_session *session)
return test_bit(NFS41_SESSION_ALLOC, &session->session_state);
}
+/*
+ * Set, test, and clear the session reset state
+ */
+static inline int nfs41_set_session_reset(struct nfs4_session *session)
+{
+ return test_and_set_bit(NFS41_SESSION_RESET, &session->session_state);
+}
+
+static inline int nfs41_test_session_reset(struct nfs4_session *session)
+{
+ return test_bit(NFS41_SESSION_RESET, &session->session_state);
+}
+
+static inline void nfs41_clear_session_reset(struct nfs4_session *session)
+{
+ smp_mb__before_clear_bit();
+ clear_bit(NFS41_SESSION_RESET,
+ &session->session_state);
+ smp_mb__after_clear_bit();
+ wake_up_bit(&session->session_state, NFS41_SESSION_RESET);
+}
+
+int nfs41_wait_session_reset(struct nfs4_session *session);
int nfs41_set_session_valid(struct nfs4_session *);
int nfs41_recover_session(struct nfs4_session *);
int nfs41_recover_session_sync(struct nfs4_session *);
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 41/85] nfs41: lease renewal
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (38 preceding siblings ...)
2008-11-10 20:25 ` [RFC 40/85] nfs41: schedule async session reset Benny Halevy
@ 2008-11-10 20:25 ` Benny Halevy
2008-11-10 20:25 ` [RFC 42/85] nfs41: sunrpc: Export the call prepare state for session reset Benny Halevy
` (45 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:25 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
Send a NFSv4.1 SEQUENCE op rather than RENEW that was deprecated in
minorversion 1.
Use the nfs_client minorversion to select reboot_recover/
network_partition_recovery/state_renewal ops.
Note: we use reclaimer to create the nfs41 session before there are any
cl_superblocks for the nfs_client.
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/nfs4_fs.h | 11 +++++++-
fs/nfs/nfs4proc.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++-
fs/nfs/nfs4renewd.c | 5 ++-
fs/nfs/nfs4state.c | 21 +++++++++--------
4 files changed, 81 insertions(+), 16 deletions(-)
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 8cdc3c4..ff367df 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -162,6 +162,11 @@ struct nfs4_exception {
struct nfs4_state_recovery_ops {
int (*recover_open)(struct nfs4_state_owner *, struct nfs4_state *);
int (*recover_lock)(struct nfs4_state *, struct file_lock *);
+ int (*renew_lease)(struct nfs_client *, struct rpc_cred *);
+};
+
+struct nfs4_state_maintenance_ops {
+ int (*sched_state_renewal)(struct nfs_client *, struct rpc_cred *);
};
extern struct dentry_operations nfs4_dentry_operations;
@@ -187,8 +192,8 @@ extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fh
extern int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
struct nfs4_fs_locations *fs_locations, struct page *page);
-extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops;
-extern struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops;
+extern struct nfs4_state_recovery_ops *nfs4_reboot_recovery_ops[];
+extern struct nfs4_state_recovery_ops *nfs4_network_partition_recovery_ops[];
#if defined(CONFIG_NFS_V4_1)
extern int nfs4_setup_sequence(struct nfs_client *clp,
struct nfs41_sequence_args *args, struct nfs41_sequence_res *res,
@@ -207,6 +212,8 @@ static inline int nfs4_setup_sequence(struct nfs_client *clp,
}
#endif /* CONFIG_NFS_V4_1 */
+extern struct nfs4_state_maintenance_ops *nfs4_state_renewal_ops[];
+
extern const u32 nfs4_fattr_bitmap[2];
extern const u32 nfs4_statfs_bitmap[2];
extern const u32 nfs4_pathconf_bitmap[2];
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 41f4f74..f6107b0 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -2966,6 +2966,9 @@ static void nfs4_renew_done(struct rpc_task *task, void *data)
if (time_before(clp->cl_last_renewal,timestamp))
clp->cl_last_renewal = timestamp;
spin_unlock(&clp->cl_lock);
+ dprintk("%s calling put_rpccred on rpc_cred %p\n", __func__,
+ task->tk_msg.rpc_cred);
+ put_rpccred(task->tk_msg.rpc_cred);
}
static const struct rpc_call_ops nfs4_renew_ops = {
@@ -4788,14 +4791,67 @@ static int nfs41_proc_async_sequence(struct nfs_client *clp,
}
#endif /* CONFIG_NFS_V4_1 */
-struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops = {
+struct nfs4_state_recovery_ops nfs40_reboot_recovery_ops = {
.recover_open = nfs4_open_reclaim,
.recover_lock = nfs4_lock_reclaim,
+ .renew_lease = nfs4_proc_renew,
};
-struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops = {
+#if defined(CONFIG_NFS_V4_1)
+struct nfs4_state_recovery_ops nfs41_reboot_recovery_ops = {
+ .recover_open = nfs4_open_reclaim,
+ .recover_lock = nfs4_lock_reclaim,
+ .renew_lease = nfs4_proc_sequence,
+};
+#endif /* CONFIG_NFS_V4_1 */
+
+struct nfs4_state_recovery_ops nfs40_network_partition_recovery_ops = {
.recover_open = nfs4_open_expired,
.recover_lock = nfs4_lock_expired,
+ .renew_lease = nfs4_proc_renew,
+};
+
+#if defined(CONFIG_NFS_V4_1)
+struct nfs4_state_recovery_ops nfs41_network_partition_recovery_ops = {
+ .recover_open = nfs4_open_expired,
+ .recover_lock = nfs4_lock_expired,
+ .renew_lease = nfs4_proc_sequence,
+};
+#endif /* CONFIG_NFS_V4_1 */
+
+struct nfs4_state_maintenance_ops nfs40_state_renewal_ops = {
+ .sched_state_renewal = nfs4_proc_async_renew,
+};
+
+#if defined(CONFIG_NFS_V4_1)
+struct nfs4_state_maintenance_ops nfs41_state_renewal_ops = {
+ .sched_state_renewal = nfs41_proc_async_sequence,
+};
+#endif
+
+/*
+ * Per minor version reboot and network partition recovery ops
+ */
+
+struct nfs4_state_recovery_ops *nfs4_reboot_recovery_ops[] = {
+ &nfs40_reboot_recovery_ops,
+#if defined(CONFIG_NFS_V4_1)
+ &nfs41_reboot_recovery_ops,
+#endif
+};
+
+struct nfs4_state_recovery_ops *nfs4_network_partition_recovery_ops[] = {
+ &nfs40_network_partition_recovery_ops,
+#if defined(CONFIG_NFS_V4_1)
+ &nfs41_network_partition_recovery_ops,
+#endif
+};
+
+struct nfs4_state_maintenance_ops *nfs4_state_renewal_ops[] = {
+ &nfs40_state_renewal_ops,
+#if defined(CONFIG_NFS_V4_1)
+ &nfs41_state_renewal_ops,
+#endif
};
static const struct inode_operations nfs4_file_inode_operations = {
diff --git a/fs/nfs/nfs4renewd.c b/fs/nfs/nfs4renewd.c
index 3305acb..a1bab0c 100644
--- a/fs/nfs/nfs4renewd.c
+++ b/fs/nfs/nfs4renewd.c
@@ -59,12 +59,14 @@
void
nfs4_renew_state(struct work_struct *work)
{
+ struct nfs4_state_maintenance_ops *ops;
struct nfs_client *clp =
container_of(work, struct nfs_client, cl_renewd.work);
struct rpc_cred *cred;
long lease, timeout;
unsigned long last, now;
+ ops = nfs4_state_renewal_ops[clp->cl_minorversion];
down_read(&clp->cl_sem);
dprintk("%s: start\n", __func__);
/* Are there any active superblocks? */
@@ -86,8 +88,7 @@ nfs4_renew_state(struct work_struct *work)
}
spin_unlock(&clp->cl_lock);
/* Queue an asynchronous RENEW. */
- nfs4_proc_async_renew(clp, cred);
- put_rpccred(cred);
+ ops->sched_state_renewal(clp, cred);
timeout = (2 * lease) / 3;
spin_lock(&clp->cl_lock);
} else
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 09ca7b1..cf6666d 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -952,24 +952,24 @@ static int reclaimer(void *ptr)
/* Ensure exclusive access to NFSv4 state */
down_write(&clp->cl_sem);
/* Are there any NFS mounts out there? */
- if (list_empty(&clp->cl_superblocks))
+ if (clp->cl_minorversion == 0 && list_empty(&clp->cl_superblocks))
goto out;
restart_loop:
dprintk("%s: starting loop\n", __func__);
- ops = &nfs4_network_partition_recovery_ops;
+ ops = nfs4_network_partition_recovery_ops[clp->cl_minorversion];
/* Are there any open files on this volume? */
cred = nfs4_get_renew_cred(clp);
if (cred != NULL) {
/* Yes there are: try to renew the old lease */
- status = nfs4_proc_renew(clp, cred);
+ status = ops->renew_lease(clp, cred);
put_rpccred(cred);
switch (status) {
- case 0:
- case -NFS4ERR_CB_PATH_DOWN:
- goto out;
- case -NFS4ERR_STALE_CLIENTID:
- case -NFS4ERR_LEASE_MOVED:
- ops = &nfs4_reboot_recovery_ops;
+ case 0:
+ case -NFS4ERR_CB_PATH_DOWN:
+ goto out;
+ case -NFS4ERR_STALE_CLIENTID:
+ case -NFS4ERR_LEASE_MOVED:
+ ops = nfs4_reboot_recovery_ops[clp->cl_minorversion];
}
} else {
/* "reboot" to ensure we clear all state on the server */
@@ -998,7 +998,8 @@ restart_loop:
status = nfs4_reclaim_open_state(ops, sp);
if (status < 0) {
if (status == -NFS4ERR_NO_GRACE) {
- ops = &nfs4_network_partition_recovery_ops;
+ ops = nfs4_network_partition_recovery_ops[
+ clp->cl_minorversion];
status = nfs4_reclaim_open_state(ops, sp);
}
if (status == -NFS4ERR_STALE_CLIENTID)
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 42/85] nfs41: sunrpc: Export the call prepare state for session reset
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (39 preceding siblings ...)
2008-11-10 20:25 ` [RFC 41/85] nfs41: lease renewal Benny Halevy
@ 2008-11-10 20:25 ` Benny Halevy
2008-11-10 20:25 ` [RFC 43/85] nfs41: use rpc prepare call " Benny Halevy
` (44 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:25 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
From: Andy Adamson <andros@netapp.com>
Signed-off-by: Andy Adamson<andros@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
include/linux/sunrpc/clnt.h | 1 +
include/linux/sunrpc/sched.h | 1 +
net/sunrpc/clnt.c | 13 +++++++++++++
net/sunrpc/sched.c | 2 +-
4 files changed, 16 insertions(+), 1 deletions(-)
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index 77c03a4..c6a1179 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -151,6 +151,7 @@ int rpc_call_sync(struct rpc_clnt *clnt,
const struct rpc_message *msg, int flags);
struct rpc_task *rpc_call_null(struct rpc_clnt *clnt, struct rpc_cred *cred,
int flags);
+void rpc_restart_call_prepare(struct rpc_task *);
void rpc_restart_call(struct rpc_task *);
void rpc_setbufsize(struct rpc_clnt *, unsigned int, unsigned int);
size_t rpc_max_payload(struct rpc_clnt *);
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
index 64981a2..1773768 100644
--- a/include/linux/sunrpc/sched.h
+++ b/include/linux/sunrpc/sched.h
@@ -237,6 +237,7 @@ void rpc_show_tasks(void);
int rpc_init_mempool(void);
void rpc_destroy_mempool(void);
extern struct workqueue_struct *rpciod_workqueue;
+void rpc_prepare_task(struct rpc_task *task);
static inline void rpc_exit(struct rpc_task *task, int status)
{
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 0c8e5f1..c31ded3 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -684,6 +684,19 @@ void rpc_force_rebind(struct rpc_clnt *clnt)
EXPORT_SYMBOL_GPL(rpc_force_rebind);
/*
+ * Restart an (async) RPC call from the call_prepare state.
+ * Usually called from within the exit handler.
+ */
+void
+rpc_restart_call_prepare(struct rpc_task *task)
+{
+ if (RPC_ASSASSINATED(task))
+ return;
+ task->tk_action = rpc_prepare_task;
+}
+EXPORT_SYMBOL_GPL(rpc_restart_call_prepare);
+
+/*
* Restart an (async) RPC call. Usually called from within the
* exit handler.
*/
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index 385f427..e476aae 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -574,7 +574,7 @@ EXPORT_SYMBOL_GPL(rpc_delay);
/*
* Helper to call task->tk_ops->rpc_call_prepare
*/
-static void rpc_prepare_task(struct rpc_task *task)
+void rpc_prepare_task(struct rpc_task *task)
{
task->tk_ops->rpc_call_prepare(task, task->tk_calldata);
}
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 43/85] nfs41: use rpc prepare call state for session reset
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (40 preceding siblings ...)
2008-11-10 20:25 ` [RFC 42/85] nfs41: sunrpc: Export the call prepare state for session reset Benny Halevy
@ 2008-11-10 20:25 ` Benny Halevy
2008-11-11 8:01 ` [pnfs] [RFC 43/85] nfs41: use rpc prepare call state for sessionreset Halevy, Benny
2008-11-10 20:25 ` [RFC 44/85] nfs41: kick start nfs41 session recovery when handling errors Benny Halevy
` (43 subsequent siblings)
85 siblings, 1 reply; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:25 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
From: Andy Adamson <andros@netapp.com>
Signed-off-by: Andy Adamson<andros@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/internal.h | 4 ++++
fs/nfs/nfs4proc.c | 22 +++++++++++++++++-----
fs/nfs/read.c | 2 +-
fs/nfs/unlink.c | 2 +-
fs/nfs/write.c | 2 +-
5 files changed, 24 insertions(+), 8 deletions(-)
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index f78720b..133ad76 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -130,6 +130,10 @@ extern __be32 * nfs_decode_dirent(__be32 *, struct nfs_entry *, int);
extern struct rpc_procinfo nfs3_procedures[];
extern __be32 *nfs3_decode_dirent(__be32 *, struct nfs_entry *, int);
+/* nfs4proc.c */
+extern void nfs4_restart_rpc(struct rpc_task *task,
+ const struct nfs_server *server);
+
/* nfs4xdr.c */
#ifdef CONFIG_NFS_V4
extern __be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index f6107b0..917d630 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -593,6 +593,18 @@ static void nfs4_sequence_done(const struct nfs_server *server,
#endif /* CONFIG_NFS_V4_1 */
}
+void nfs4_restart_rpc(struct rpc_task *task, const struct nfs_server *server)
+{
+#ifdef CONFIG_NFS_V4_1
+ if (server->nfs_client->cl_minorversion &&
+ nfs41_test_session_reset(server->nfs_client->cl_session)) {
+ rpc_restart_call_prepare(task);
+ return;
+ }
+#endif /* CONFIG_NFS_V4_1 */
+ rpc_restart_call(task);
+}
+
static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo)
{
struct nfs_inode *nfsi = NFS_I(dir);
@@ -1638,7 +1650,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
break;
default:
if (nfs4_async_handle_error(task, server) == -EAGAIN) {
- rpc_restart_call(task);
+ nfs4_restart_rpc(task, server);
return;
}
}
@@ -2871,7 +2883,7 @@ static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data)
/* nfs4_sequence_free_slot called in the read rpc_call_done */
nfs4_sequence_done(server, &data->res.seq_res, task->tk_status);
if (nfs4_async_handle_error(task, server) == -EAGAIN) {
- rpc_restart_call(task);
+ nfs4_restart_rpc(task, server);
dprintk("<-- %s status= %d\n", __func__, -EAGAIN);
return -EAGAIN;
}
@@ -2899,7 +2911,7 @@ static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data)
/* slot is freed in nfs_writeback_done */
nfs4_sequence_done(server, &data->res.seq_res, task->tk_status);
if (nfs4_async_handle_error(task, server) == -EAGAIN) {
- rpc_restart_call(task);
+ nfs4_restart_rpc(task, server);
return -EAGAIN;
}
if (task->tk_status >= 0) {
@@ -2927,7 +2939,7 @@ static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data)
nfs4_sequence_done(server, &data->res.seq_res, task->tk_status);
if (nfs4_async_handle_error(task, server) == -EAGAIN) {
- rpc_restart_call(task);
+ nfs4_restart_rpc(task, server);
return -EAGAIN;
}
nfs4_sequence_free_slot(server, &data->res.seq_res);
@@ -3701,7 +3713,7 @@ static void nfs4_locku_done(struct rpc_task *task, void *data)
break;
default:
if (nfs4_async_handle_error(task, server) == -EAGAIN)
- rpc_restart_call(task);
+ nfs4_restart_rpc(task, server);
}
nfs4_sequence_free_slot(server, &calldata->res.seq_res);
}
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 3c77b26..5b8db19 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -367,7 +367,7 @@ static void nfs_readpage_retry(struct rpc_task *task, struct nfs_read_data *data
argp->offset += resp->count;
argp->pgbase += resp->count;
argp->count -= resp->count;
- rpc_restart_call(task);
+ nfs4_restart_rpc(task, NFS_SERVER(data->inode));
return;
out:
nfs4_sequence_free_slot(NFS_SERVER(data->inode), &data->res.seq_res);
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index 3df3794..2ac5dd5 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -83,7 +83,7 @@ static void nfs_async_unlink_done(struct rpc_task *task, void *calldata)
struct inode *dir = data->dir;
if (!NFS_PROTO(dir)->unlink_done(task, dir))
- rpc_restart_call(task);
+ nfs4_restart_rpc(task, NFS_SERVER(dir));
}
/**
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 7d3fdc8..86573f7 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -1179,7 +1179,7 @@ int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data)
*/
argp->stable = NFS_FILE_SYNC;
}
- rpc_restart_call(task);
+ nfs4_restart_rpc(task, NFS_SERVER(data->inode));
return -EAGAIN;
}
if (time_before(complain, jiffies)) {
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* RE: [pnfs] [RFC 43/85] nfs41: use rpc prepare call state for sessionreset
2008-11-10 20:25 ` [RFC 43/85] nfs41: use rpc prepare call " Benny Halevy
@ 2008-11-11 8:01 ` Halevy, Benny
0 siblings, 0 replies; 115+ messages in thread
From: Halevy, Benny @ 2008-11-11 8:01 UTC (permalink / raw)
To: Benny Halevy, trond.myklebust; +Cc: linux-nfs, pnfs
http://linux-nfs.org/pipermail/pnfs/2008-November/005264.html
from Andy should probably be squashed into this patch.
Benny
________________________________
From: pnfs-bounces@linux-nfs.org on behalf of Benny Halevy
Sent: Mon 2008-11-10 22:25
To: trond.myklebust@fys.uio.no
Cc: linux-nfs@vger.kernel.org; pnfs@linux-nfs.org
Subject: [pnfs] [RFC 43/85] nfs41: use rpc prepare call state for sessionreset
From: Andy Adamson <andros@netapp.com>
Signed-off-by: Andy Adamson<andros@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/internal.h | 4 ++++
fs/nfs/nfs4proc.c | 22 +++++++++++++++++-----
fs/nfs/read.c | 2 +-
fs/nfs/unlink.c | 2 +-
fs/nfs/write.c | 2 +-
5 files changed, 24 insertions(+), 8 deletions(-)
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index f78720b..133ad76 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -130,6 +130,10 @@ extern __be32 * nfs_decode_dirent(__be32 *, struct nfs_entry *, int);
extern struct rpc_procinfo nfs3_procedures[];
extern __be32 *nfs3_decode_dirent(__be32 *, struct nfs_entry *, int);
+/* nfs4proc.c */
+extern void nfs4_restart_rpc(struct rpc_task *task,
+ const struct nfs_server *server);
+
/* nfs4xdr.c */
#ifdef CONFIG_NFS_V4
extern __be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index f6107b0..917d630 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -593,6 +593,18 @@ static void nfs4_sequence_done(const struct nfs_server *server,
#endif /* CONFIG_NFS_V4_1 */
}
+void nfs4_restart_rpc(struct rpc_task *task, const struct nfs_server *server)
+{
+#ifdef CONFIG_NFS_V4_1
+ if (server->nfs_client->cl_minorversion &&
+ nfs41_test_session_reset(server->nfs_client->cl_session)) {
+ rpc_restart_call_prepare(task);
+ return;
+ }
+#endif /* CONFIG_NFS_V4_1 */
+ rpc_restart_call(task);
+}
+
static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo)
{
struct nfs_inode *nfsi = NFS_I(dir);
@@ -1638,7 +1650,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
break;
default:
if (nfs4_async_handle_error(task, server) == -EAGAIN) {
- rpc_restart_call(task);
+ nfs4_restart_rpc(task, server);
return;
}
}
@@ -2871,7 +2883,7 @@ static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data)
/* nfs4_sequence_free_slot called in the read rpc_call_done */
nfs4_sequence_done(server, &data->res.seq_res, task->tk_status);
if (nfs4_async_handle_error(task, server) == -EAGAIN) {
- rpc_restart_call(task);
+ nfs4_restart_rpc(task, server);
dprintk("<-- %s status= %d\n", __func__, -EAGAIN);
return -EAGAIN;
}
@@ -2899,7 +2911,7 @@ static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data)
/* slot is freed in nfs_writeback_done */
nfs4_sequence_done(server, &data->res.seq_res, task->tk_status);
if (nfs4_async_handle_error(task, server) == -EAGAIN) {
- rpc_restart_call(task);
+ nfs4_restart_rpc(task, server);
return -EAGAIN;
}
if (task->tk_status >= 0) {
@@ -2927,7 +2939,7 @@ static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data)
nfs4_sequence_done(server, &data->res.seq_res, task->tk_status);
if (nfs4_async_handle_error(task, server) == -EAGAIN) {
- rpc_restart_call(task);
+ nfs4_restart_rpc(task, server);
return -EAGAIN;
}
nfs4_sequence_free_slot(server, &data->res.seq_res);
@@ -3701,7 +3713,7 @@ static void nfs4_locku_done(struct rpc_task *task, void *data)
break;
default:
if (nfs4_async_handle_error(task, server) == -EAGAIN)
- rpc_restart_call(task);
+ nfs4_restart_rpc(task, server);
}
nfs4_sequence_free_slot(server, &calldata->res.seq_res);
}
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 3c77b26..5b8db19 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -367,7 +367,7 @@ static void nfs_readpage_retry(struct rpc_task *task, struct nfs_read_data *data
argp->offset += resp->count;
argp->pgbase += resp->count;
argp->count -= resp->count;
- rpc_restart_call(task);
+ nfs4_restart_rpc(task, NFS_SERVER(data->inode));
return;
out:
nfs4_sequence_free_slot(NFS_SERVER(data->inode), &data->res.seq_res);
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index 3df3794..2ac5dd5 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -83,7 +83,7 @@ static void nfs_async_unlink_done(struct rpc_task *task, void *calldata)
struct inode *dir = data->dir;
if (!NFS_PROTO(dir)->unlink_done(task, dir))
- rpc_restart_call(task);
+ nfs4_restart_rpc(task, NFS_SERVER(dir));
}
/**
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 7d3fdc8..86573f7 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -1179,7 +1179,7 @@ int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data)
*/
argp->stable = NFS_FILE_SYNC;
}
- rpc_restart_call(task);
+ nfs4_restart_rpc(task, NFS_SERVER(data->inode));
return -EAGAIN;
}
if (time_before(complain, jiffies)) {
--
1.6.0.2
_______________________________________________
pNFS mailing list
pNFS@linux-nfs.org
http://linux-nfs.org/cgi-bin/mailman/listinfo/pnfs
^ permalink raw reply related [flat|nested] 115+ messages in thread
* [RFC 44/85] nfs41: kick start nfs41 session recovery when handling errors
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (41 preceding siblings ...)
2008-11-10 20:25 ` [RFC 43/85] nfs41: use rpc prepare call " Benny Halevy
@ 2008-11-10 20:25 ` Benny Halevy
2008-11-10 20:26 ` [RFC 45/85] nfs41: start session recovery from nfs4_setup_sequence Benny Halevy
` (42 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:25 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
From: Andy Adamson <andros@netapp.com>
Signed-off-by: Andy Adamson<andros@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/nfs4proc.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 71 insertions(+), 0 deletions(-)
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 917d630..a4f5b15 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -3256,6 +3256,25 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server)
rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task);
task->tk_status = 0;
return -EAGAIN;
+#if defined(CONFIG_NFS_V4_1)
+ case -NFS4ERR_BADSESSION:
+ case -NFS4ERR_BADSLOT:
+ case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
+ case -NFS4ERR_BACK_CHAN_BUSY:
+ case -NFS4ERR_SEQ_MISORDERED:
+ case -NFS4ERR_SEQUENCE_POS:
+ case -NFS4ERR_REQ_TOO_BIG:
+ case -NFS4ERR_REP_TOO_BIG:
+ case -NFS4ERR_REP_TOO_BIG_TO_CACHE:
+ case -NFS4ERR_RETRY_UNCACHED_REP:
+ case -NFS4ERR_TOO_MANY_OPS:
+ case -NFS4ERR_OP_NOT_IN_SESSION:
+ dprintk("%s ERROR %d, Reset session\n", __func__,
+ task->tk_status);
+ nfs41_set_session_reset(clp->cl_session);
+ task->tk_status = 0;
+ return -EAGAIN;
+#endif /* CONFIG_NFS_V4_1 */
case -NFS4ERR_DELAY:
nfs_inc_server_stats(server, NFSIOS_DELAY);
case -NFS4ERR_GRACE:
@@ -3331,7 +3350,30 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc
ret = nfs4_wait_clnt_recover(server->client, clp);
if (ret == 0)
exception->retry = 1;
+#if !defined(CONFIG_NFS_V4_1)
break;
+#else /* !defined(CONFIG_NFS_V4_1) */
+ if (!server->nfs_client->cl_minorversion)
+ break;
+ /* FALLTHROUGH */
+ case -NFS4ERR_BADSESSION:
+ case -NFS4ERR_BADSLOT:
+ case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
+ case -NFS4ERR_BACK_CHAN_BUSY:
+ case -NFS4ERR_SEQ_MISORDERED:
+ case -NFS4ERR_SEQUENCE_POS:
+ case -NFS4ERR_REQ_TOO_BIG:
+ case -NFS4ERR_REP_TOO_BIG:
+ case -NFS4ERR_REP_TOO_BIG_TO_CACHE:
+ case -NFS4ERR_RETRY_UNCACHED_REP:
+ case -NFS4ERR_TOO_MANY_OPS:
+ case -NFS4ERR_OP_NOT_IN_SESSION:
+ dprintk("%s ERROR: %d Reset session\n", __func__,
+ errorcode);
+ nfs41_set_session_reset(clp->cl_session);
+ exception->retry = 1;
+ /* FALLTHROUGH */
+#endif /* !defined(CONFIG_NFS_V4_1) */
case -NFS4ERR_FILE_OPEN:
case -NFS4ERR_GRACE:
case -NFS4ERR_DELAY:
@@ -4735,8 +4777,37 @@ static int nfs4_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred)
void nfs41_sequence_call_done(struct rpc_task *task, void *data)
{
struct nfs_server *server = (struct nfs_server *)data;
+ struct nfs_client *clp = server->nfs_client;
nfs4_sequence_done(server, task->tk_msg.rpc_resp, task->tk_status);
+
+ if (task->tk_status < 0) {
+ switch (task->tk_status) {
+ case -NFS4ERR_STALE_CLIENTID:
+ case -NFS4ERR_EXPIRED:
+ case -NFS4ERR_CB_PATH_DOWN:
+ nfs4_schedule_state_recovery(clp);
+ case -NFS4ERR_BADSLOT:
+ case -NFS4ERR_BADSESSION:
+ case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
+ case -NFS4ERR_BACK_CHAN_BUSY:
+ case -NFS4ERR_SEQ_MISORDERED:
+ case -NFS4ERR_SEQUENCE_POS:
+ case -NFS4ERR_REQ_TOO_BIG:
+ case -NFS4ERR_REP_TOO_BIG:
+ case -NFS4ERR_REP_TOO_BIG_TO_CACHE:
+ case -NFS4ERR_RETRY_UNCACHED_REP:
+ case -NFS4ERR_TOO_MANY_OPS:
+ case -NFS4ERR_OP_NOT_IN_SESSION:
+ dprintk("%s ERROR %d Reset session\n", __func__,
+ task->tk_status);
+
+ if (nfs4_async_handle_error(task, server) == -EAGAIN) {
+ nfs4_restart_rpc(task, server);
+ return;
+ }
+ }
+ }
nfs4_sequence_free_slot(server, task->tk_msg.rpc_resp);
dprintk("%s rpc_cred %p\n", __func__, task->tk_msg.rpc_cred);
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 45/85] nfs41: start session recovery from nfs4_setup_sequence
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (42 preceding siblings ...)
2008-11-10 20:25 ` [RFC 44/85] nfs41: kick start nfs41 session recovery when handling errors Benny Halevy
@ 2008-11-10 20:26 ` Benny Halevy
2008-11-10 20:26 ` [RFC 46/85] nfs41: introduce get_state_renewal_cred Benny Halevy
` (41 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:26 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
Signed-off-by: Rahul Iyer <iyer@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/nfs4proc.c | 7 +++++--
1 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index a4f5b15..12f3b9f 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -491,8 +491,11 @@ int nfs4_setup_sequence(struct nfs_client *clp,
if (clp->cl_minorversion == 0 || res->sr_slot)
goto out;
BUG_ON(clp->cl_minorversion != 1);
- ret = nfs41_setup_sequence(clp->cl_session, args, res,
- cache_reply, task);
+ if (nfs41_test_session_alloc(clp->cl_session))
+ ret = nfs41_recover_session_sync(clp->cl_session);
+ if (!ret)
+ ret = nfs41_setup_sequence(clp->cl_session, args, res,
+ cache_reply, task);
if (ret) {
memset(res, 0, sizeof(*res));
if (ret != -EAGAIN) {
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 46/85] nfs41: introduce get_state_renewal_cred
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (43 preceding siblings ...)
2008-11-10 20:26 ` [RFC 45/85] nfs41: start session recovery from nfs4_setup_sequence Benny Halevy
@ 2008-11-10 20:26 ` Benny Halevy
2008-11-10 20:26 ` [RFC 47/85] nfs41: get cred in exchange_id when cred arg is NULL Benny Halevy
` (40 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:26 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
From: Andy Adamson <andros@netapp.com>
Reuse the cred used at exchange_id time for
sending SEQUENCE to renew the client's lease.
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/client.c | 4 ++++
fs/nfs/nfs4_fs.h | 4 ++++
fs/nfs/nfs4proc.c | 13 +++++++++++++
fs/nfs/nfs4renewd.c | 2 +-
fs/nfs/nfs4state.c | 14 +++++++++++++-
include/linux/nfs_fs_sb.h | 1 +
6 files changed, 36 insertions(+), 2 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 560b10b..c69424d 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -207,6 +207,10 @@ static void nfs_free_client(struct nfs_client *clp)
if (clp->cl_machine_cred != NULL)
put_rpccred(clp->cl_machine_cred);
+#ifdef CONFIG_NFS_V4_1
+ if (clp->cl_ex_cred != NULL)
+ put_rpccred(clp->cl_ex_cred);
+#endif /* CONFIG_NFS_V4_1 */
kfree(clp->cl_hostname);
kfree(clp);
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index ff367df..904b19e 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -167,6 +167,7 @@ struct nfs4_state_recovery_ops {
struct nfs4_state_maintenance_ops {
int (*sched_state_renewal)(struct nfs_client *, struct rpc_cred *);
+ struct rpc_cred * (*get_state_renewal_cred)(struct nfs_client *);
};
extern struct dentry_operations nfs4_dentry_operations;
@@ -228,6 +229,9 @@ extern void nfs4_renew_state(struct work_struct *);
/* nfs4state.c */
struct rpc_cred *nfs4_get_renew_cred(struct nfs_client *clp);
+#ifdef CONFIG_NFS_V4_1
+struct rpc_cred *nfs41_get_state_renewal_cred(struct nfs_client *clp);
+#endif /* CONFIG_NFS_V4_1 */
extern struct nfs4_state_owner * nfs4_get_state_owner(struct nfs_server *, struct rpc_cred *);
extern void nfs4_put_state_owner(struct nfs4_state_owner *);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 12f3b9f..5b1f6d0 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -4317,6 +4317,17 @@ static int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)
else if (++clp->cl_id_uniquifier == 0)
break;
}
+ if (status == 0) {
+ if (clp->cl_ex_cred) {
+ dprintk("%s put cl_ex_cred %p\n", __func__,
+ clp->cl_ex_cred);
+ put_rpccred(clp->cl_ex_cred);
+ }
+
+ BUG_ON(cred == NULL);
+ clp->cl_ex_cred = get_rpccred(cred);
+ dprintk("%s set cl_ex_cred %p\n", __func__, clp->cl_ex_cred);
+ }
dprintk("<-- %s status= %d\n", __func__, status);
return status;
@@ -4907,11 +4918,13 @@ struct nfs4_state_recovery_ops nfs41_network_partition_recovery_ops = {
struct nfs4_state_maintenance_ops nfs40_state_renewal_ops = {
.sched_state_renewal = nfs4_proc_async_renew,
+ .get_state_renewal_cred = nfs4_get_renew_cred,
};
#if defined(CONFIG_NFS_V4_1)
struct nfs4_state_maintenance_ops nfs41_state_renewal_ops = {
.sched_state_renewal = nfs41_proc_async_sequence,
+ .get_state_renewal_cred = nfs41_get_state_renewal_cred,
};
#endif
diff --git a/fs/nfs/nfs4renewd.c b/fs/nfs/nfs4renewd.c
index a1bab0c..1d609ed 100644
--- a/fs/nfs/nfs4renewd.c
+++ b/fs/nfs/nfs4renewd.c
@@ -79,7 +79,7 @@ nfs4_renew_state(struct work_struct *work)
timeout = (2 * lease) / 3 + (long)last - (long)now;
/* Are we close to a lease timeout? */
if (time_after(now, last + lease/3)) {
- cred = nfs4_get_renew_cred(clp);
+ cred = ops->get_state_renewal_cred(clp);
if (cred == NULL) {
set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
spin_unlock(&clp->cl_lock);
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index cf6666d..5a91072 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -73,6 +73,16 @@ static int nfs4_init_client(struct nfs_client *clp, struct rpc_cred *cred)
return status;
}
+#if defined(CONFIG_NFS_V4_1)
+struct rpc_cred *
+nfs41_get_state_renewal_cred(struct nfs_client *clp)
+{
+ if (clp->cl_ex_cred)
+ get_rpccred(clp->cl_ex_cred);
+ return (clp->cl_ex_cred);
+}
+#endif /* CONFIG_NFS_V4_1 */
+
static struct rpc_cred *nfs4_get_machine_cred(struct nfs_client *clp)
{
struct rpc_cred *cred = NULL;
@@ -943,6 +953,7 @@ static int reclaimer(void *ptr)
struct nfs4_state_owner *sp;
struct rb_node *pos;
struct nfs4_state_recovery_ops *ops;
+ struct nfs4_state_maintenance_ops *m_ops;
struct rpc_cred *cred;
int status = 0;
@@ -957,8 +968,9 @@ static int reclaimer(void *ptr)
restart_loop:
dprintk("%s: starting loop\n", __func__);
ops = nfs4_network_partition_recovery_ops[clp->cl_minorversion];
+ m_ops = nfs4_state_renewal_ops[clp->cl_minorversion];
/* Are there any open files on this volume? */
- cred = nfs4_get_renew_cred(clp);
+ cred = m_ops->get_state_renewal_cred(clp);
if (cred != NULL) {
/* Yes there are: try to renew the old lease */
status = ops->renew_lease(clp, cred);
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index 9917c09..17720b9 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -81,6 +81,7 @@ struct nfs_client {
u32 cl_seqid;
/* The flags used for obtaining the clientid during EXCHANGE_ID */
u32 cl_exchange_flags;
+ struct rpc_cred *cl_ex_cred; /* exchange_id credential */
struct nfs4_session *cl_session; /* sharred session */
#endif /* CONFIG_NFS_V4_1 */
};
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 47/85] nfs41: get cred in exchange_id when cred arg is NULL
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (44 preceding siblings ...)
2008-11-10 20:26 ` [RFC 46/85] nfs41: introduce get_state_renewal_cred Benny Halevy
@ 2008-11-10 20:26 ` Benny Halevy
2008-11-10 20:26 ` [RFC 48/85] nfs41: establish sessions-based clientid Benny Halevy
` (39 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:26 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
When creating a session to a pnfs data server, the cred is passed
down as NULL. Either use the saved cl_ex_cred or get a new one
using nfs4_get_setclientid_cred.
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/nfs4_fs.h | 1 +
fs/nfs/nfs4proc.c | 18 +++++++++++++++---
fs/nfs/nfs4state.c | 2 +-
3 files changed, 17 insertions(+), 4 deletions(-)
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 904b19e..b9771f2 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -229,6 +229,7 @@ extern void nfs4_renew_state(struct work_struct *);
/* nfs4state.c */
struct rpc_cred *nfs4_get_renew_cred(struct nfs_client *clp);
+struct rpc_cred *nfs4_get_setclientid_cred(struct nfs_client *clp);
#ifdef CONFIG_NFS_V4_1
struct rpc_cred *nfs41_get_state_renewal_cred(struct nfs_client *clp);
#endif /* CONFIG_NFS_V4_1 */
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 5b1f6d0..8c28d0c 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -4276,6 +4276,7 @@ static int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)
};
int status;
int loop = 0;
+ int got_cred = 0;
struct rpc_message msg = {
.rpc_proc = nfs4_proc(clp, NFSPROC4_CLNT_EXCHANGE_ID),
.rpc_argp = &args,
@@ -4286,6 +4287,16 @@ static int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)
dprintk("--> %s\n", __func__);
BUG_ON(clp == NULL);
+
+ if (!cred) {
+ /* FIXME: do we need to lock clp and take a ref count on cl_ex_cred? */
+ cred = clp->cl_ex_cred;
+ if (!cred) {
+ cred = nfs4_get_setclientid_cred(clp);
+ got_cred = (cred != NULL);
+ }
+ }
+
p = (u32 *)verifier.data;
*p++ = htonl((u32)clp->cl_boot_time.tv_sec);
*p = htonl((u32)clp->cl_boot_time.tv_nsec);
@@ -4317,17 +4328,18 @@ static int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)
else if (++clp->cl_id_uniquifier == 0)
break;
}
- if (status == 0) {
+ if ((status == 0) && (cred != clp->cl_ex_cred) && (cred != NULL)) {
+ /* FIXME: do we need to lock clp here? */
if (clp->cl_ex_cred) {
dprintk("%s put cl_ex_cred %p\n", __func__,
clp->cl_ex_cred);
put_rpccred(clp->cl_ex_cred);
}
-
- BUG_ON(cred == NULL);
clp->cl_ex_cred = get_rpccred(cred);
dprintk("%s set cl_ex_cred %p\n", __func__, clp->cl_ex_cred);
}
+ if (got_cred)
+ put_rpccred(cred);
dprintk("<-- %s status= %d\n", __func__, status);
return status;
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 5a91072..693e5a6 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -122,7 +122,7 @@ struct rpc_cred *nfs4_get_renew_cred(struct nfs_client *clp)
return cred;
}
-static struct rpc_cred *nfs4_get_setclientid_cred(struct nfs_client *clp)
+struct rpc_cred *nfs4_get_setclientid_cred(struct nfs_client *clp)
{
struct nfs4_state_owner *sp;
struct rb_node *pos;
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 48/85] nfs41: establish sessions-based clientid
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (45 preceding siblings ...)
2008-11-10 20:26 ` [RFC 47/85] nfs41: get cred in exchange_id when cred arg is NULL Benny Halevy
@ 2008-11-10 20:26 ` Benny Halevy
2008-11-10 20:26 ` [RFC 49/85] nfs41: recover lease in _nfs4_lookup_root Benny Halevy
` (38 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:26 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
nfsv4.1 clientid is established via EXCHANGE_ID rather than
SETCLIENTID{,_CONFIRM}
This is implemented using a new establish_clid method in
nfs4_state_recovery_ops.
nfs41: establish clientid via exchange id only if cred != NULL
>From 2.6.26 reclaimer() uses machine cred for setting up the client id
therefore it is never expected to be NULL.
Signed-off-by: Rahul Iyer <iyer@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/nfs4_fs.h | 2 ++
fs/nfs/nfs4proc.c | 4 ++++
fs/nfs/nfs4state.c | 5 +++--
3 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index b9771f2..44282b0 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -163,6 +163,7 @@ struct nfs4_state_recovery_ops {
int (*recover_open)(struct nfs4_state_owner *, struct nfs4_state *);
int (*recover_lock)(struct nfs4_state *, struct file_lock *);
int (*renew_lease)(struct nfs_client *, struct rpc_cred *);
+ int (*establish_clid)(struct nfs_client *, struct rpc_cred *);
};
struct nfs4_state_maintenance_ops {
@@ -186,6 +187,7 @@ extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct rpc_cred *)
extern int nfs4_proc_async_renew(struct nfs_client *, struct rpc_cred *);
extern int nfs4_proc_renew(struct nfs_client *, struct rpc_cred *);
extern int nfs4_wait_bit_killable(void *);
+extern int nfs4_init_clientid(struct nfs_client *, struct rpc_cred *);
extern int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait);
extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *);
extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 8c28d0c..749027d 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -4904,6 +4904,7 @@ struct nfs4_state_recovery_ops nfs40_reboot_recovery_ops = {
.recover_open = nfs4_open_reclaim,
.recover_lock = nfs4_lock_reclaim,
.renew_lease = nfs4_proc_renew,
+ .establish_clid = nfs4_init_clientid,
};
#if defined(CONFIG_NFS_V4_1)
@@ -4911,6 +4912,7 @@ struct nfs4_state_recovery_ops nfs41_reboot_recovery_ops = {
.recover_open = nfs4_open_reclaim,
.recover_lock = nfs4_lock_reclaim,
.renew_lease = nfs4_proc_sequence,
+ .establish_clid = nfs4_proc_exchange_id,
};
#endif /* CONFIG_NFS_V4_1 */
@@ -4918,6 +4920,7 @@ struct nfs4_state_recovery_ops nfs40_network_partition_recovery_ops = {
.recover_open = nfs4_open_expired,
.recover_lock = nfs4_lock_expired,
.renew_lease = nfs4_proc_renew,
+ .establish_clid = nfs4_init_clientid,
};
#if defined(CONFIG_NFS_V4_1)
@@ -4925,6 +4928,7 @@ struct nfs4_state_recovery_ops nfs41_network_partition_recovery_ops = {
.recover_open = nfs4_open_expired,
.recover_lock = nfs4_lock_expired,
.renew_lease = nfs4_proc_sequence,
+ .establish_clid = nfs4_proc_exchange_id,
};
#endif /* CONFIG_NFS_V4_1 */
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 693e5a6..d3c5e92 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -62,7 +62,7 @@ const nfs4_stateid zero_stateid;
static LIST_HEAD(nfs4_clientid_list);
-static int nfs4_init_client(struct nfs_client *clp, struct rpc_cred *cred)
+int nfs4_init_clientid(struct nfs_client *clp, struct rpc_cred *cred)
{
int status = nfs4_proc_setclientid(clp, NFS4_CALLBACK,
nfs_callback_tcpport, cred);
@@ -991,8 +991,9 @@ restart_loop:
nfs4_state_mark_reclaim(clp);
status = -ENOENT;
cred = nfs4_get_setclientid_cred(clp);
+ dprintk("%s: setclientid_cred %p\n", __func__, cred);
if (cred != NULL) {
- status = nfs4_init_client(clp, cred);
+ status = ops->establish_clid(clp, cred);
put_rpccred(cred);
/* Handle case where the user hasn't set up machine creds */
if (status == -EACCES && cred == clp->cl_machine_cred) {
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 49/85] nfs41: recover lease in _nfs4_lookup_root
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (46 preceding siblings ...)
2008-11-10 20:26 ` [RFC 48/85] nfs41: establish sessions-based clientid Benny Halevy
@ 2008-11-10 20:26 ` Benny Halevy
2008-11-17 13:51 ` [pnfs] " Benny Halevy
2008-11-10 20:27 ` [RFC 50/85] nfs41: schedule state recovery on BAD or DEAD session Benny Halevy
` (37 subsequent siblings)
85 siblings, 1 reply; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:26 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
This creates the nfsv4.1 session on mount.
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/nfs4proc.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 749027d..179ea6c 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -1956,7 +1956,11 @@ static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
dprintk("--> %s\n", __func__);
nfs_fattr_init(info->fattr);
+ status = nfs4_recover_expired_lease(server);
+ if (status != 0)
+ goto out;
status = nfs4_call_sync(server, &msg, &args, &res, 0);
+out:
dprintk("<-- %s status= %d\n", __func__, status);
return status;
}
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* Re: [pnfs] [RFC 49/85] nfs41: recover lease in _nfs4_lookup_root
2008-11-10 20:26 ` [RFC 49/85] nfs41: recover lease in _nfs4_lookup_root Benny Halevy
@ 2008-11-17 13:51 ` Benny Halevy
0 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-17 13:51 UTC (permalink / raw)
To: pnfs; +Cc: trond.myklebust, linux-nfs
On Nov. 10, 2008, 22:26 +0200, Benny Halevy <bhalevy@panasas.com> wrote:
> This creates the nfsv4.1 session on mount.
>
> Signed-off-by: Benny Halevy <bhalevy@panasas.com>
> ---
> fs/nfs/nfs4proc.c | 4 ++++
> 1 files changed, 4 insertions(+), 0 deletions(-)
>
> diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
> index 749027d..179ea6c 100644
> --- a/fs/nfs/nfs4proc.c
> +++ b/fs/nfs/nfs4proc.c
> @@ -1956,7 +1956,11 @@ static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
>
> dprintk("--> %s\n", __func__);
> nfs_fattr_init(info->fattr);
> + status = nfs4_recover_expired_lease(server);
> + if (status != 0)
> + goto out;
review 11-14: do that *only* for minorversion != 0
> status = nfs4_call_sync(server, &msg, &args, &res, 0);
> +out:
> dprintk("<-- %s status= %d\n", __func__, status);
> return status;
> }
^ permalink raw reply [flat|nested] 115+ messages in thread
* [RFC 50/85] nfs41: schedule state recovery on BAD or DEAD session
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (47 preceding siblings ...)
2008-11-10 20:26 ` [RFC 49/85] nfs41: recover lease in _nfs4_lookup_root Benny Halevy
@ 2008-11-10 20:27 ` Benny Halevy
2008-11-10 20:27 ` [RFC 51/85] nfs41: state reclaimer renew lease error handling Benny Halevy
` (36 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:27 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
From: Andy Adamson <andros@netapp.com>
When a clientid is stale, the sequence operation will return NFS4ERR_BADSESSION
or NFS4ERR_DEADSESSION. This will put the session into reset mode, and
run the session_reclaimer thread which calls destroy_session and
create_session. Destroy_session will also return NFS4ERR_BADSESSION or
NFS4ERR_DEADSESSION which is ignored by the session reset. Create_session
will return NFS4ERR_STALE_CLIENTID and the session reclaimer sets the
nfs_client cl_state to NFS4CLNT_LEASE_EXPIRED.
Catch the NFS4CLNT_LEASE_EXPIRED cl_state in nfs4_find_slot, and attempt to
recover the expired client id.
Signed-off-by: Andy Adamson<andros@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/nfs4proc.c | 7 +++++++
1 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 179ea6c..699bbe7 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -403,6 +403,13 @@ nfs4_find_slot(struct nfs4_slot_table *tbl, struct rpc_task *task,
dprintk("%s Slot Table Empty\n", __func__);
spin_unlock(&tbl->slot_tbl_lock);
ret = nfs41_recover_session_sync(session);
+ if (test_and_clear_bit(NFS4CLNT_LEASE_EXPIRED,
+ &session->clp->cl_state)) {
+
+ printk(KERN_WARNING "%s Clientid Reset\n",
+ __func__);
+ nfs4_schedule_state_recovery(session->clp);
+ }
if (ret)
return slot;
nfs41_wait_session_reset(session);
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 51/85] nfs41: state reclaimer renew lease error handling
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (48 preceding siblings ...)
2008-11-10 20:27 ` [RFC 50/85] nfs41: schedule state recovery on BAD or DEAD session Benny Halevy
@ 2008-11-10 20:27 ` Benny Halevy
2008-11-10 20:27 ` [RFC 52/85] nfs41: increment_{open,lock}_seqid Benny Halevy
` (35 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:27 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
From: Andy Adamson <andros@netapp.com>
The state reclaimer has been called due to a NFS4_STALE_CLIENTID or NFS4_EXPIRE
error. First it tries to renew the old lease (network partion case) which for
v4.1 means an nfs4_proc_sequence call. Any error from the sequence operation
means that the lease cannot be renewed.
Switch on the minorversion to handle the error return from the renew lease call.
Signed-off-by: Andy Adamson<andros@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/nfs4state.c | 20 +++++++++++++-------
1 files changed, 13 insertions(+), 7 deletions(-)
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index d3c5e92..0d6b902 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -975,18 +975,24 @@ restart_loop:
/* Yes there are: try to renew the old lease */
status = ops->renew_lease(clp, cred);
put_rpccred(cred);
- switch (status) {
- case 0:
- case -NFS4ERR_CB_PATH_DOWN:
+ if (!status)
goto out;
- case -NFS4ERR_STALE_CLIENTID:
- case -NFS4ERR_LEASE_MOVED:
- ops = nfs4_reboot_recovery_ops[clp->cl_minorversion];
- }
+ if (clp->cl_minorversion == 0)
+ switch (status) {
+ case -NFS4ERR_CB_PATH_DOWN:
+ goto out;
+ case -NFS4ERR_STALE_CLIENTID:
+ case -NFS4ERR_LEASE_MOVED:
+ break;
+ default:
+ goto establish_clid;
+ }
+ ops = nfs4_reboot_recovery_ops[clp->cl_minorversion];
} else {
/* "reboot" to ensure we clear all state on the server */
clp->cl_boot_time = CURRENT_TIME;
}
+establish_clid:
/* We're going to have to re-establish a clientid */
nfs4_state_mark_reclaim(clp);
status = -ENOENT;
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 52/85] nfs41: increment_{open,lock}_seqid
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (49 preceding siblings ...)
2008-11-10 20:27 ` [RFC 51/85] nfs41: state reclaimer renew lease error handling Benny Halevy
@ 2008-11-10 20:27 ` Benny Halevy
2008-11-10 20:27 ` [RFC 53/85] nfs41: Add ability to read RPC call direction on TCP stream Benny Halevy
` (34 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:27 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
Unlike minorversion0, in nfsv4.1 the open and lock seqids need
not be incremented by the client and should always be set to zero.
This is implemented using a new nfs_rpc_ops methods -
increment_open_seqid and increment_lock_seqid
Signed-off-by: Rahul Iyer <iyer@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/nfs4proc.c | 4 ++++
fs/nfs/nfs4state.c | 14 +++++++++-----
2 files changed, 13 insertions(+), 5 deletions(-)
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 699bbe7..28c3cf8 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -1757,6 +1757,10 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, int wait)
calldata->state = state;
calldata->arg.fh = NFS_FH(state->inode);
calldata->arg.stateid = &state->open_stateid;
+ if (server->minorversion) {
+ BUG_ON(server->minorversion != 1);
+ memset(calldata->arg.stateid->data, 0, 4); /* clear seqid */
+ }
/* Serialization for the sequence id */
calldata->arg.seqid = nfs_alloc_seqid(&state->owner->so_seqid);
if (calldata->arg.seqid == NULL)
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 0d6b902..6035634 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -747,12 +747,16 @@ static void nfs_increment_seqid(int status, struct nfs_seqid *seqid)
void nfs_increment_open_seqid(int status, struct nfs_seqid *seqid)
{
- if (status == -NFS4ERR_BAD_SEQID) {
- struct nfs4_state_owner *sp = container_of(seqid->sequence,
- struct nfs4_state_owner, so_seqid);
+ struct nfs4_state_owner *sp = container_of(seqid->sequence,
+ struct nfs4_state_owner, so_seqid);
+ struct nfs_server *server = sp->so_server;
+
+ if (status == -NFS4ERR_BAD_SEQID)
nfs4_drop_state_owner(sp);
- }
- nfs_increment_seqid(status, seqid);
+ if (server->minorversion == 0)
+ nfs_increment_seqid(status, seqid);
+ else
+ BUG_ON(server->minorversion != 1);
}
/*
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 53/85] nfs41: Add ability to read RPC call direction on TCP stream.
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (50 preceding siblings ...)
2008-11-10 20:27 ` [RFC 52/85] nfs41: increment_{open,lock}_seqid Benny Halevy
@ 2008-11-10 20:27 ` Benny Halevy
2008-11-17 13:52 ` [pnfs] " Benny Halevy
2008-11-10 20:27 ` [RFC 54/85] nfs41: Skip past the RPC call direction Benny Halevy
` (33 subsequent siblings)
85 siblings, 1 reply; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:27 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
NFSv4.1 callbacks can arrive over an existing connection. This patch adds
the logic to read the RPC call direction (call or reply). It does this by
updating the state machine to look for the call direction invoking
xs_tcp_read_calldir(...) after reading the XID.
To avoid confusion, keep tcp_calldir in code in host order.
Signed-off-by: Ricardo Labiaga <ricardo.labiaga@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
net/sunrpc/xprtsock.c | 49 +++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 45 insertions(+), 4 deletions(-)
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 0a50361..1ce05d7 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -222,7 +222,8 @@ struct sock_xprt {
* State of TCP reply receive
*/
__be32 tcp_fraghdr,
- tcp_xid;
+ tcp_xid,
+ tcp_calldir; /* Is this a call or a reply? */
u32 tcp_offset,
tcp_reclen;
@@ -259,6 +260,7 @@ struct sock_xprt {
#define TCP_RCV_COPY_FRAGHDR (1UL << 1)
#define TCP_RCV_COPY_XID (1UL << 2)
#define TCP_RCV_COPY_DATA (1UL << 3)
+#define TCP_RCV_COPY_CALLDIR (1UL << 4)
static inline struct sockaddr *xs_addr(struct rpc_xprt *xprt)
{
@@ -919,7 +921,7 @@ static inline void xs_tcp_read_fraghdr(struct rpc_xprt *xprt, struct xdr_skb_rea
transport->tcp_offset = 0;
/* Sanity check of the record length */
- if (unlikely(transport->tcp_reclen < 4)) {
+ if (unlikely(transport->tcp_reclen < 8)) {
dprintk("RPC: invalid TCP record fragment length\n");
xprt_force_disconnect(xprt);
return;
@@ -954,13 +956,47 @@ static inline void xs_tcp_read_xid(struct sock_xprt *transport, struct xdr_skb_r
if (used != len)
return;
transport->tcp_flags &= ~TCP_RCV_COPY_XID;
- transport->tcp_flags |= TCP_RCV_COPY_DATA;
+ transport->tcp_flags |= TCP_RCV_COPY_CALLDIR;
transport->tcp_copied = 4;
- dprintk("RPC: reading reply for XID %08x\n",
+ dprintk("RPC: reading %s XID %08x\n",
+ (transport->tcp_calldir == RPC_REPLY) ? "reply for"
+ : "request with",
ntohl(transport->tcp_xid));
xs_tcp_check_fraghdr(transport);
}
+static inline void xs_tcp_read_calldir(struct sock_xprt *transport,
+ struct xdr_skb_reader *desc)
+{
+ size_t len, used;
+ u32 offset;
+ char *p;
+
+ /*
+ * We want transport->tcp_offset to be 8 at the end of this routine
+ * (4 bytes for the xid and 4 bytes for the call/reply flag).
+ * When this function is called for the first time,
+ * transport->tcp_offset is 4 (after having already read the xid).
+ */
+ offset = transport->tcp_offset - sizeof(transport->tcp_xid);
+ len = sizeof(transport->tcp_calldir) - offset;
+ dprintk("RPC: reading CALL/REPLY flag (%Zu bytes)\n", len);
+ p = ((char *) &transport->tcp_calldir) + offset;
+ used = xdr_skb_read_bits(desc, p, len);
+ transport->tcp_offset += used;
+ if (used != len)
+ return;
+ transport->tcp_flags &= ~TCP_RCV_COPY_CALLDIR;
+ transport->tcp_flags |= TCP_RCV_COPY_DATA;
+ transport->tcp_copied += 4;
+ transport->tcp_calldir = ntohl(transport->tcp_calldir);
+ dprintk("RPC: reading %s CALL/REPLY flag %08x\n",
+ (transport->tcp_calldir == RPC_REPLY) ? "reply for"
+ : "request with",
+ transport->tcp_calldir);
+ xs_tcp_check_fraghdr(transport);
+}
+
static inline void xs_tcp_read_request(struct rpc_xprt *xprt, struct xdr_skb_reader *desc)
{
struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
@@ -1077,6 +1113,11 @@ static int xs_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, uns
xs_tcp_read_xid(transport, &desc);
continue;
}
+ /* Read in the call/reply flag */
+ if (transport->tcp_flags & TCP_RCV_COPY_CALLDIR) {
+ xs_tcp_read_calldir(transport, &desc);
+ continue;
+ }
/* Read in the request data */
if (transport->tcp_flags & TCP_RCV_COPY_DATA) {
xs_tcp_read_request(xprt, &desc);
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* Re: [pnfs] [RFC 53/85] nfs41: Add ability to read RPC call direction on TCP stream.
2008-11-10 20:27 ` [RFC 53/85] nfs41: Add ability to read RPC call direction on TCP stream Benny Halevy
@ 2008-11-17 13:52 ` Benny Halevy
0 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-17 13:52 UTC (permalink / raw)
To: pnfs; +Cc: trond.myklebust, linux-nfs
On Nov. 10, 2008, 22:27 +0200, Benny Halevy <bhalevy@panasas.com> wrote:
> NFSv4.1 callbacks can arrive over an existing connection. This patch adds
> the logic to read the RPC call direction (call or reply). It does this by
> updating the state machine to look for the call direction invoking
> xs_tcp_read_calldir(...) after reading the XID.
>
> To avoid confusion, keep tcp_calldir in code in host order.
>
> Signed-off-by: Ricardo Labiaga <ricardo.labiaga@netapp.com>
> Signed-off-by: Benny Halevy <bhalevy@panasas.com>
> ---
> net/sunrpc/xprtsock.c | 49 +++++++++++++++++++++++++++++++++++++++++++++----
> 1 files changed, 45 insertions(+), 4 deletions(-)
>
> diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
> index 0a50361..1ce05d7 100644
> --- a/net/sunrpc/xprtsock.c
> +++ b/net/sunrpc/xprtsock.c
> @@ -222,7 +222,8 @@ struct sock_xprt {
> * State of TCP reply receive
> */
> __be32 tcp_fraghdr,
> - tcp_xid;
> + tcp_xid,
> + tcp_calldir; /* Is this a call or a reply? */
>
> u32 tcp_offset,
> tcp_reclen;
> @@ -259,6 +260,7 @@ struct sock_xprt {
> #define TCP_RCV_COPY_FRAGHDR (1UL << 1)
> #define TCP_RCV_COPY_XID (1UL << 2)
> #define TCP_RCV_COPY_DATA (1UL << 3)
> +#define TCP_RCV_COPY_CALLDIR (1UL << 4)
>
> static inline struct sockaddr *xs_addr(struct rpc_xprt *xprt)
> {
> @@ -919,7 +921,7 @@ static inline void xs_tcp_read_fraghdr(struct rpc_xprt *xprt, struct xdr_skb_rea
> transport->tcp_offset = 0;
>
> /* Sanity check of the record length */
> - if (unlikely(transport->tcp_reclen < 4)) {
> + if (unlikely(transport->tcp_reclen < 8)) {
> dprintk("RPC: invalid TCP record fragment length\n");
> xprt_force_disconnect(xprt);
> return;
> @@ -954,13 +956,47 @@ static inline void xs_tcp_read_xid(struct sock_xprt *transport, struct xdr_skb_r
> if (used != len)
> return;
> transport->tcp_flags &= ~TCP_RCV_COPY_XID;
> - transport->tcp_flags |= TCP_RCV_COPY_DATA;
> + transport->tcp_flags |= TCP_RCV_COPY_CALLDIR;
> transport->tcp_copied = 4;
> - dprintk("RPC: reading reply for XID %08x\n",
> + dprintk("RPC: reading %s XID %08x\n",
> + (transport->tcp_calldir == RPC_REPLY) ? "reply for"
> + : "request with",
> ntohl(transport->tcp_xid));
> xs_tcp_check_fraghdr(transport);
> }
>
> +static inline void xs_tcp_read_calldir(struct sock_xprt *transport,
> + struct xdr_skb_reader *desc)
> +{
> + size_t len, used;
> + u32 offset;
> + char *p;
> +
> + /*
> + * We want transport->tcp_offset to be 8 at the end of this routine
> + * (4 bytes for the xid and 4 bytes for the call/reply flag).
> + * When this function is called for the first time,
> + * transport->tcp_offset is 4 (after having already read the xid).
> + */
> + offset = transport->tcp_offset - sizeof(transport->tcp_xid);
> + len = sizeof(transport->tcp_calldir) - offset;
> + dprintk("RPC: reading CALL/REPLY flag (%Zu bytes)\n", len);
> + p = ((char *) &transport->tcp_calldir) + offset;
> + used = xdr_skb_read_bits(desc, p, len);
> + transport->tcp_offset += used;
> + if (used != len)
> + return;
> + transport->tcp_flags &= ~TCP_RCV_COPY_CALLDIR;
> + transport->tcp_flags |= TCP_RCV_COPY_DATA;
> + transport->tcp_copied += 4;
> + transport->tcp_calldir = ntohl(transport->tcp_calldir);
review 11-14: introduce direction flag, no need to save the
actual value of calldir.
> + dprintk("RPC: reading %s CALL/REPLY flag %08x\n",
> + (transport->tcp_calldir == RPC_REPLY) ? "reply for"
> + : "request with",
> + transport->tcp_calldir);
> + xs_tcp_check_fraghdr(transport);
> +}
> +
> static inline void xs_tcp_read_request(struct rpc_xprt *xprt, struct xdr_skb_reader *desc)
> {
> struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
> @@ -1077,6 +1113,11 @@ static int xs_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, uns
> xs_tcp_read_xid(transport, &desc);
> continue;
> }
> + /* Read in the call/reply flag */
> + if (transport->tcp_flags & TCP_RCV_COPY_CALLDIR) {
> + xs_tcp_read_calldir(transport, &desc);
> + continue;
> + }
> /* Read in the request data */
> if (transport->tcp_flags & TCP_RCV_COPY_DATA) {
> xs_tcp_read_request(xprt, &desc);
^ permalink raw reply [flat|nested] 115+ messages in thread
* [RFC 54/85] nfs41: Skip past the RPC call direction
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (51 preceding siblings ...)
2008-11-10 20:27 ` [RFC 53/85] nfs41: Add ability to read RPC call direction on TCP stream Benny Halevy
@ 2008-11-10 20:27 ` Benny Halevy
2008-11-10 20:27 ` [RFC 55/85] nfs41: Refactor NFSv4 callback service Benny Halevy
` (32 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:27 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
From: Ricardo Labiaga <Ricardo.Labiaga@netapp.com>
xs_tcp_read_calldir() is now responsible for reading the RPC call
direction and determining whether it is a reply or a callback request.
The call to xdr_skb_read_bits() inside xs_tcp_read_calldir() moves the
xdr_skb_reader offset past the RPC call direction (offset should be
equal to 8). Therefore xs_tcp_read_common() called from
xs_tcp_ready_reply() should be copying the TCP buffer starting past the
RPC call direction. It is now necessary to read the RPC call direction
earlier to determine whether to call the reply handler or the callback
handler.
call_verify() should therefore skip past the XID and call/reply flag.
Signed-off-by: Ricardo Labiaga <Ricardo.Labiaga@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
net/sunrpc/clnt.c | 13 +++++++------
1 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index c31ded3..dd0ff2d 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -1371,13 +1371,14 @@ rpc_verify_header(struct rpc_task *task)
}
if ((len -= 3) < 0)
goto out_overflow;
- p += 1; /* skip XID */
- if ((n = ntohl(*p++)) != RPC_REPLY) {
- dprintk("RPC: %5u %s: not an RPC reply: %x\n",
- task->tk_pid, __func__, n);
- goto out_garbage;
- }
+ /*
+ * Skip the XID and call direction.
+ * The underlying transport has read the XID and RPC call direction
+ * to determine this is an RPC reply.
+ */
+ p += 2;
+
if ((n = ntohl(*p++)) != RPC_MSG_ACCEPTED) {
if (--len < 0)
goto out_overflow;
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 55/85] nfs41: Refactor NFSv4 callback service
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (52 preceding siblings ...)
2008-11-10 20:27 ` [RFC 54/85] nfs41: Skip past the RPC call direction Benny Halevy
@ 2008-11-10 20:27 ` Benny Halevy
2008-11-10 20:28 ` [RFC 56/85] nfs41: client callback structures Benny Halevy
` (31 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:27 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
Prepare the NFSv4 callback service mechanism to understand v4.0 and v4.1
callbacks. Create a new function nfs4_callback_up() that contains the
minor version 0 specific logic. It is invoked by nfs_callback_up().
Augment the list of arguments passed to nfs_callback_up() since it will need
to deal with minor version 1 as well. Move the creation of the backchannel
after the rpc_client has been initialized since the rpc_xprt structure will be
needed to crated the NFSv4.1 callback.
Keep a pointer to the callback_svc that will be set
as per the minor version used.
Signed-off-by: Ricardo Labiaga <ricardo.labiaga@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/callback.c | 62 +++++++++++++++++++++++++++++++++++++---------------
fs/nfs/callback.h | 2 +-
fs/nfs/client.c | 23 ++++++++++---------
3 files changed, 57 insertions(+), 30 deletions(-)
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index c2e9cfd..e792706 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -67,7 +67,7 @@ module_param_call(callback_tcpport, param_set_port, param_get_int,
* This is the callback kernel thread.
*/
static int
-nfs_callback_svc(void *vrqstp)
+nfs4_callback_svc(void *vrqstp)
{
int err, preverr = 0;
struct svc_rqst *rqstp = vrqstp;
@@ -104,12 +104,37 @@ nfs_callback_svc(void *vrqstp)
return 0;
}
+
+/*
+ * Prepare to bring up the NFSv4 callback service
+ */
+struct svc_rqst *
+nfs4_callback_up(struct svc_serv *serv)
+{
+ int ret;
+
+ ret = svc_create_xprt(serv, "tcp", nfs_callback_set_tcpport,
+ SVC_SOCK_ANONYMOUS);
+ if (unlikely(ret <= 0)) {
+ if (ret == 0)
+ ret = -EIO;
+ return ERR_PTR(ret);
+ }
+ nfs_callback_tcpport = ret;
+ dprintk("NFS: Callback listener port = %u (af %u)\n",
+ nfs_callback_tcpport, nfs_callback_family);
+ return svc_prepare_thread(serv, &serv->sv_pools[0]);
+}
+
/*
* Bring up the callback thread if it is not already up.
*/
-int nfs_callback_up(void)
+int nfs_callback_up(u32 minorversion, void *args)
{
struct svc_serv *serv = NULL;
+ struct svc_rqst *rqstp;
+ int (* callback_svc)(void *vrqstp);
+ char svc_name[12];
int ret = 0;
mutex_lock(&nfs_callback_mutex);
@@ -117,30 +142,31 @@ int nfs_callback_up(void)
goto out;
serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE,
nfs_callback_family, NULL);
- ret = -ENOMEM;
- if (!serv)
- goto out_err;
-
- ret = svc_create_xprt(serv, "tcp", nfs_callback_set_tcpport,
- SVC_SOCK_ANONYMOUS);
- if (ret <= 0)
+ if (!serv) {
+ ret = -ENOMEM;
goto out_err;
- nfs_callback_tcpport = ret;
- dprintk("NFS: Callback listener port = %u (af %u)\n",
- nfs_callback_tcpport, nfs_callback_family);
+ }
- nfs_callback_info.rqst = svc_prepare_thread(serv, &serv->sv_pools[0]);
- if (IS_ERR(nfs_callback_info.rqst)) {
- ret = PTR_ERR(nfs_callback_info.rqst);
- nfs_callback_info.rqst = NULL;
+ /* FIXME: either 4.0 or 4.1 callback service can be up at a time
+ * need to monitor and control them both */
+ if (!minorversion) {
+ rqstp = nfs4_callback_up(serv);
+ callback_svc = nfs4_callback_svc;
+ } else {
+ BUG(); /* for now */
+ }
+ if (IS_ERR(rqstp)) {
+ ret = PTR_ERR(rqstp);
goto out_err;
}
svc_sock_update_bufs(serv);
- nfs_callback_info.task = kthread_run(nfs_callback_svc,
+ sprintf(svc_name, "nfsv4.%u-svc", minorversion);
+ nfs_callback_info.rqst = rqstp;
+ nfs_callback_info.task = kthread_run(callback_svc,
nfs_callback_info.rqst,
- "nfsv4-svc");
+ svc_name);
if (IS_ERR(nfs_callback_info.task)) {
ret = PTR_ERR(nfs_callback_info.task);
svc_exit_thread(nfs_callback_info.rqst);
diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h
index bb25d21..a2b3ce4 100644
--- a/fs/nfs/callback.h
+++ b/fs/nfs/callback.h
@@ -63,7 +63,7 @@ extern __be32 nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getat
extern __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy);
#ifdef CONFIG_NFS_V4
-extern int nfs_callback_up(void);
+extern int nfs_callback_up(u32 minorversion, void *args);
extern void nfs_callback_down(void);
#else
#define nfs_callback_up() (0)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index c69424d..1c0cae9 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -129,12 +129,6 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
clp->rpc_ops = cl_init->rpc_ops;
- if (cl_init->rpc_ops->version == 4) {
- if (nfs_callback_up() < 0)
- goto error_2;
- __set_bit(NFS_CS_CALLBACK, &clp->cl_res_state);
- }
-
atomic_set(&clp->cl_count, 1);
clp->cl_cons_state = NFS_CS_INITING;
@@ -144,7 +138,7 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
if (cl_init->hostname) {
clp->cl_hostname = kstrdup(cl_init->hostname, GFP_KERNEL);
if (!clp->cl_hostname)
- goto error_3;
+ goto error_cleanup;
}
INIT_LIST_HEAD(&clp->cl_superblocks);
@@ -167,10 +161,7 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
return clp;
-error_3:
- if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state))
- nfs_callback_down();
-error_2:
+error_cleanup:
kfree(clp);
error_0:
return NULL;
@@ -1008,6 +999,16 @@ static int nfs4_init_client(struct nfs_client *clp,
goto error;
memcpy(clp->cl_ipaddr, ip_addr, sizeof(clp->cl_ipaddr));
+ /* Start the callback server */
+ error = nfs_callback_up(clp->cl_minorversion,
+ clp->cl_rpcclient->cl_xprt);
+ if (error < 0) {
+ dprintk("%s: failed to start callback. Error = %d\n",
+ __func__, error);
+ goto error;
+ }
+ __set_bit(NFS_CS_CALLBACK, &clp->cl_res_state);
+
error = nfs_idmap_new(clp);
if (error < 0) {
dprintk("%s: failed to create idmapper. Error = %d\n",
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 56/85] nfs41: client callback structures
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (53 preceding siblings ...)
2008-11-10 20:27 ` [RFC 55/85] nfs41: Refactor NFSv4 callback service Benny Halevy
@ 2008-11-10 20:28 ` Benny Halevy
2008-11-10 20:28 ` [RFC 57/85] nfs41: Initialize new rpc_xprt callback related fields Benny Halevy
` (30 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:28 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
From: Ricardo Labiaga <ricardo.labiaga@netapp.com>
Adds new list of rpc_xprt structures, and a readers/writers lock to
protect the list. The list is used to preallocate resources for
the backchannel during backchannel requests. Callbacks are not
expected to cause significant latency, so only one callback will
be allowed at this time.
It also adds a pointer to the NFS callback service so that
requests can be directed to it for processing.
Signed-off-by: Ricardo Labiaga <ricardo.labiaga@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
nfs41: NFSv4.1 callback support
New callback members added to svc_serv. The NFSv4.1 callback service will
sleep on the svc_serv->svc_cb_waitq until new callback requests arrive.
The request will be queued in svc_serv->svc_cb_list. This patch adds this
list, the sleep queue and spinlock to svc_serv.
Signed-off-by: Ricardo Labiaga <ricardo.labiaga@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
include/linux/sunrpc/svc.h | 10 ++++++++++
include/linux/sunrpc/xprt.h | 22 ++++++++++++++++++++++
2 files changed, 32 insertions(+), 0 deletions(-)
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index 3afe7fb..1d3b971 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -81,6 +81,16 @@ struct svc_serv {
struct module * sv_module; /* optional module to count when
* adding threads */
svc_thread_fn sv_function; /* main function for threads */
+#if defined(CONFIG_NFS_V4_1)
+ struct list_head sv_cb_list; /* queue for callback requests
+ * that arrive over the same
+ * connection
+ */
+ spinlock_t sv_cb_lock; /* protects the svc_cb_list */
+ wait_queue_head_t sv_cb_waitq; /* sleep here if there are no
+ * entries in the svc_cb_list
+ */
+#endif /* CONFIG_NFS_V4_1 */
};
/*
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index 11fc71d..c5d3c7c 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -97,6 +97,12 @@ struct rpc_rqst {
unsigned long rq_xtime; /* when transmitted */
int rq_ntrans;
+
+#if defined(CONFIG_NFS_V4_1)
+ struct list_head rq_bc_list; /* Callback service list */
+ unsigned long rq_bc_pa_state; /* Backchannel prealloc state */
+ struct list_head rq_bc_pa_list; /* Backchannel prealloc list */
+#endif /* CONFIG_NFS_V4_1 */
};
#define rq_svec rq_snd_buf.head
#define rq_slen rq_snd_buf.len
@@ -174,6 +180,14 @@ struct rpc_xprt {
spinlock_t reserve_lock; /* lock slot table */
u32 xid; /* Next XID value to use */
struct rpc_task * snd_task; /* Task blocked in send */
+#if defined(CONFIG_NFS_V4_1)
+ struct svc_serv *bc_serv; /* The RPC service which will */
+ /* process the callback */
+ spinlock_t bc_pa_lock; /* Protects the preallocated */
+ /* items */
+ struct list_head bc_pa_list; /* List of preallocated */
+ /* backchannel rpc_rqst's */
+#endif /* CONFIG_NFS_V4_1 */
struct list_head recv;
struct {
@@ -192,6 +206,14 @@ struct rpc_xprt {
const char *address_strings[RPC_DISPLAY_MAX];
};
+#if defined(CONFIG_NFS_V4_1)
+/*
+ * Backchannel flags
+ */
+#define RPC_BC_PA_IN_USE 0x0001 /* Preallocated backchannel */
+ /* buffer in use */
+#endif /* CONFIG_NFS_V4_1 */
+
struct xprt_create {
int ident; /* XPRT_TRANSPORT identifier */
struct sockaddr * srcaddr; /* optional local address */
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 57/85] nfs41: Initialize new rpc_xprt callback related fields
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (54 preceding siblings ...)
2008-11-10 20:28 ` [RFC 56/85] nfs41: client callback structures Benny Halevy
@ 2008-11-10 20:28 ` Benny Halevy
2008-11-10 20:28 ` [RFC 58/85] nfs41: New backchannel helper routines Benny Halevy
` (29 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:28 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
From: Ricardo Labiaga <ricardo.labiaga@netapp.com>
Signed-off-by: Ricardo Labiaga <ricardo.labiaga@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
net/sunrpc/xprt.c | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 29e401b..848a7af 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -1034,6 +1034,11 @@ found:
INIT_LIST_HEAD(&xprt->free);
INIT_LIST_HEAD(&xprt->recv);
+#if defined(CONFIG_NFS_V4_1)
+ spin_lock_init(&xprt->bc_pa_lock);
+ INIT_LIST_HEAD(&xprt->bc_pa_list);
+#endif /* CONFIG_NFS_V4_1 */
+
INIT_WORK(&xprt->task_cleanup, xprt_autoclose);
setup_timer(&xprt->timer, xprt_init_autodisconnect,
(unsigned long)xprt);
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 58/85] nfs41: New backchannel helper routines
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (55 preceding siblings ...)
2008-11-10 20:28 ` [RFC 57/85] nfs41: Initialize new rpc_xprt callback related fields Benny Halevy
@ 2008-11-10 20:28 ` Benny Halevy
2008-11-10 20:28 ` [RFC 59/85] nfs41: New include/linux/sunrpc/bc_xprt.h Benny Halevy
` (28 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:28 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
From: Ricardo Labiaga <Ricardo.Labiaga@netapp.com>
This patch introduces support to setup the callback xprt on the client side.
It allocates/ destroys the preallocated memory structures used to process
backchannel requests.
At setup time, xprt_setup_backchannel() is invoked to allocate one or
more rpc_rqst structures and substructures. This ensures that they
are available when an RPC callback arrives. The rpc_rqst structures
are maintained in a linked list attached to the rpc_xprt structure.
We keep track of the number of allocations so that they can be correctly
removed when the channel is destroyed.
When an RPC callback arrives, xprt_alloc_bc_request() is invoked to
obtain a preallocated rpc_rqst structure. An rpc_xprt structure is
returned, and its RPC_BC_PREALLOC_IN_USE bit is set in
rpc_xprt->bc_flags. The structure is removed from the the list
since it is now in use, and it will be later added back when its
user is done with it.
After the RPC callback replies, the rpc_rqst structure is returned
by invoking xprt_free_bc_request(). This clears the
RPC_BC_PREALLOC_IN_USE bit and adds it back to the list, allowing it
to be reused by a subsequent RPC callback request.
Signed-off-by: Ricardo Labiaga <ricardo.labiaga@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
include/linux/sunrpc/xprt.h | 1 +
net/sunrpc/Makefile | 1 +
net/sunrpc/backchannel_rqst.c | 268 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 270 insertions(+), 0 deletions(-)
create mode 100644 net/sunrpc/backchannel_rqst.c
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index c5d3c7c..035431b 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -183,6 +183,7 @@ struct rpc_xprt {
#if defined(CONFIG_NFS_V4_1)
struct svc_serv *bc_serv; /* The RPC service which will */
/* process the callback */
+ unsigned int bc_alloc_count; /* Total number of preallocs */
spinlock_t bc_pa_lock; /* Protects the preallocated */
/* items */
struct list_head bc_pa_list; /* List of preallocated */
diff --git a/net/sunrpc/Makefile b/net/sunrpc/Makefile
index 5369aa3..4a01f96 100644
--- a/net/sunrpc/Makefile
+++ b/net/sunrpc/Makefile
@@ -13,5 +13,6 @@ sunrpc-y := clnt.o xprt.o socklib.o xprtsock.o sched.o \
rpcb_clnt.o timer.o xdr.o \
sunrpc_syms.o cache.o rpc_pipe.o \
svc_xprt.o
+sunrpc-$(CONFIG_NFS_V4_1) += backchannel_rqst.o
sunrpc-$(CONFIG_PROC_FS) += stats.o
sunrpc-$(CONFIG_SYSCTL) += sysctl.o
diff --git a/net/sunrpc/backchannel_rqst.c b/net/sunrpc/backchannel_rqst.c
new file mode 100644
index 0000000..e444059
--- /dev/null
+++ b/net/sunrpc/backchannel_rqst.c
@@ -0,0 +1,268 @@
+/******************************************************************************
+
+(c) 2007 Network Appliance, Inc. All Rights Reserved.
+
+Network Appliance provides this source code under the GPL v2 License.
+The GPL v2 license is available at
+http://opensource.org/licenses/gpl-license.php.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+#include <linux/tcp.h>
+#include <linux/sunrpc/xprt.h>
+
+#ifdef RPC_DEBUG
+#define RPCDBG_FACILITY RPCDBG_TRANS
+#endif
+
+#if defined(CONFIG_NFS_V4_1)
+
+/*
+ * Helper routines that track the number of preallocation elements
+ * on the transport.
+ */
+static inline int xprt_need_to_requeue(struct rpc_xprt *xprt)
+{
+ return xprt->bc_alloc_count > 0;
+}
+
+static inline void xprt_inc_alloc_count(struct rpc_xprt *xprt, unsigned int n)
+{
+ xprt->bc_alloc_count += n;
+}
+
+static inline int xprt_dec_alloc_count(struct rpc_xprt *xprt, unsigned int n)
+{
+ return xprt->bc_alloc_count -= n;
+}
+
+/*
+ * Free the preallocated rpc_rqst structure and the memory
+ * buffers hanging off of it.
+ */
+static void xprt_free_allocation(struct rpc_rqst *req)
+{
+ struct xdr_buf *xbufp;
+
+ dprintk("RPC: free allocations for req= %p\n", req);
+ BUG_ON(test_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state));
+ xbufp = &req->rq_private_buf;
+ free_page((unsigned long)xbufp->head[0].iov_base);
+ xbufp = &req->rq_snd_buf;
+ free_page((unsigned long)xbufp->head[0].iov_base);
+ list_del(&req->rq_bc_pa_list);
+ kfree(req);
+}
+
+/*
+ * Preallocate up to min_reqs structures and related buffers for use
+ * by the backchannel. This function can be called multiple times
+ * when creating new sessions that use the same rpc_xprt. The
+ * preallocated buffers are added to the pool of resources used by
+ * the rpc_xprt. Anyone of these resources may be used used by an
+ * incoming callback request. It's up to the higher levels in the
+ * stack to enforce that the maximum number of session slots is not
+ * being exceeded.
+ */
+int xprt_setup_backchannel(struct rpc_xprt *xprt, unsigned int min_reqs)
+{
+ struct page *page_priv = NULL, *page_snd = NULL;
+ struct xdr_buf *xbufp = NULL;
+ struct rpc_rqst *req, *tmp;
+ struct list_head tmp_list;
+ int i;
+
+ dprintk("RPC: setup backchannel transport\n");
+
+ /*
+ * We use a temporary list to keep track of the preallocated
+ * buffers. Once we're done building the list we splice it
+ * into the backchannel preallocation list off of the rpc_xprt
+ * struct. This helps minimize the amount of time the list
+ * lock is held on the rpc_xprt struct. It also makes cleanup
+ * easier in case of memory allocation errors.
+ */
+ INIT_LIST_HEAD(&tmp_list);
+ for (i = 0; i < min_reqs; i++) {
+ /* Pre-allocate one backchannel rpc_rqst */
+ req = kzalloc(sizeof(struct rpc_rqst), GFP_KERNEL);
+ if (req == NULL) {
+ printk(KERN_ERR "Failed to create bc rpc_rqst\n");
+ goto out_free;
+ }
+
+ /* Add the allocated buffer to the tmp list */
+ dprintk("RPC: adding req= %p\n", req);
+ list_add(&req->rq_bc_pa_list, &tmp_list);
+
+ req->rq_xprt = xprt;
+ INIT_LIST_HEAD(&req->rq_list);
+ INIT_LIST_HEAD(&req->rq_bc_list);
+
+ /* Preallocate one XDR private buffer */
+ page_priv = alloc_page(GFP_KERNEL);
+ if (page_priv == NULL) {
+ printk(KERN_ERR "Failed to create bc priv xbuf\n");
+ goto out_free;
+ }
+ xbufp = &req->rq_private_buf;
+ xbufp->head[0].iov_base = page_address(page_priv);
+ xbufp->head[0].iov_len = PAGE_SIZE;
+ xbufp->tail[0].iov_base = NULL;
+ xbufp->tail[0].iov_len = 0;
+ xbufp->page_len = 0;
+ xbufp->len = PAGE_SIZE;
+ xbufp->buflen = PAGE_SIZE;
+
+ /* Preallocate one XDR send buffer */
+ page_snd = alloc_page(GFP_KERNEL);
+ if (page_snd == NULL) {
+ printk(KERN_ERR "Failed to create bc snd xbuf\n");
+ goto out_free;
+ }
+
+ xbufp = &req->rq_snd_buf;
+ xbufp->head[0].iov_base = page_address(page_snd);
+ xbufp->head[0].iov_len = 0;
+ xbufp->tail[0].iov_base = NULL;
+ xbufp->tail[0].iov_len = 0;
+ xbufp->page_len = 0;
+ xbufp->len = 0;
+ xbufp->buflen = PAGE_SIZE;
+ }
+
+ /*
+ * Add the temporary list to the backchannel preallocation list
+ */
+ spin_lock_bh(&xprt->bc_pa_lock);
+ list_splice(&tmp_list, &xprt->bc_pa_list);
+ xprt_inc_alloc_count(xprt, min_reqs);
+ spin_unlock_bh(&xprt->bc_pa_lock);
+
+ dprintk("RPC: setup backchannel transport done\n");
+ return 0;
+
+out_free:
+ /*
+ * Memory allocation failed, free the temporary list
+ */
+ list_for_each_entry_safe(req, tmp, &tmp_list, rq_bc_pa_list)
+ xprt_free_allocation(req);
+
+ dprintk("RPC: setup backchannel transport failed\n");
+ return -1;
+}
+EXPORT_SYMBOL(xprt_setup_backchannel);
+
+/*
+ * Destroys the backchannel preallocated structures.
+ * Since these structures may have been allocated by multiple calls
+ * to xprt_setup_backchannel, we only destroy up to the maximum number
+ * of reqs specified by the caller.
+ * @xprt: the transport holding the preallocated strucures
+ * @max_reqs the maximum number of preallocated structures to destroy
+ */
+void xprt_destroy_backchannel(struct rpc_xprt *xprt, unsigned int max_reqs)
+{
+ struct rpc_rqst *req = NULL, *tmp = NULL;
+
+ dprintk("RPC: destroy backchannel transport\n");
+
+ BUG_ON(max_reqs == 0);
+ spin_lock_bh(&xprt->bc_pa_lock);
+ xprt_dec_alloc_count(xprt, max_reqs);
+ list_for_each_entry_safe(req, tmp, &xprt->bc_pa_list, rq_bc_pa_list) {
+ dprintk("RPC: req=%p\n", req);
+ xprt_free_allocation(req);
+ if (--max_reqs == 0)
+ break;
+ }
+ spin_unlock_bh(&xprt->bc_pa_lock);
+
+ dprintk("RPC: backchannel list empty= %s\n",
+ list_empty(&xprt->bc_pa_list) ? "true" : "false");
+}
+EXPORT_SYMBOL(xprt_destroy_backchannel);
+
+/*
+ * One or more rpc_rqst structure have been preallocated during the
+ * backchannel setup. Buffer space for the send and private XDR buffers
+ * has been preallocated as well. Use xprt_alloc_bc_request to allocate
+ * to this request. Use xprt_free_bc_request to return it.
+ *
+ * Return an available rpc_rqst, otherwise NULL if non are available.
+ */
+struct rpc_rqst *xprt_alloc_bc_request(struct rpc_xprt *xprt)
+{
+ struct rpc_rqst *req;
+
+ dprintk("RPC: allocate a backchannel request\n");
+ spin_lock_bh(&xprt->bc_pa_lock);
+ if (!list_empty(&xprt->bc_pa_list)) {
+ req = list_first_entry(&xprt->bc_pa_list, struct rpc_rqst,
+ rq_bc_pa_list);
+ list_del(&req->rq_bc_pa_list);
+ } else {
+ req = NULL;
+ }
+ spin_unlock_bh(&xprt->bc_pa_lock);
+
+ if (req != NULL) {
+ set_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state);
+ req->rq_received = 0;
+ req->rq_bytes_sent = 0;
+ }
+ dprintk("RPC: backchannel req=%p\n", req);
+ return req;
+}
+
+/*
+ * Return the preallocated rpc_rqst structure and XDR buffers
+ * associated with this rpc_task.
+ */
+void xprt_free_bc_request(struct rpc_rqst *req)
+{
+ struct rpc_xprt *xprt = req->rq_xprt;
+
+ dprintk("RPC: free backchannel req=%p\n", req);
+
+ smp_mb__before_clear_bit();
+ BUG_ON(!test_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state));
+ clear_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state);
+ smp_mb__after_clear_bit();
+
+ if (!xprt_need_to_requeue(xprt)) {
+ /*
+ * The last remaining session was destroyed while this
+ * entry was in use. Free the entry and don't attempt
+ * to add back to the list because there is no need to
+ * have anymore preallocated entries.
+ */
+ dprintk("RPC: Last session removed req=%p\n", req);
+ xprt_free_allocation(req);
+ return;
+ }
+
+ /*
+ * Return it to the list of preallocations so that it
+ * may be reused by a new callback request.
+ */
+ spin_lock_bh(&xprt->bc_pa_lock);
+ list_add(&req->rq_bc_pa_list, &xprt->bc_pa_list);
+ spin_unlock_bh(&xprt->bc_pa_lock);
+}
+EXPORT_SYMBOL(xprt_free_bc_request);
+
+#endif /* CONFIG_NFS_V4_1 */
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 59/85] nfs41: New include/linux/sunrpc/bc_xprt.h
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (56 preceding siblings ...)
2008-11-10 20:28 ` [RFC 58/85] nfs41: New backchannel helper routines Benny Halevy
@ 2008-11-10 20:28 ` Benny Halevy
2008-11-10 20:28 ` [RFC 60/85] nfs41: New xs_tcp_read_data() Benny Halevy
` (27 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:28 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
From: Ricardo Labiaga <ricardo.labiaga@netapp.com>
Contains prototype for backchannel helper routines.
Signed-off-by: Ricardo Labiaga <ricardo.labiaga@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
include/linux/sunrpc/bc_xprt.h | 40 ++++++++++++++++++++++++++++++++++++++++
1 files changed, 40 insertions(+), 0 deletions(-)
create mode 100644 include/linux/sunrpc/bc_xprt.h
diff --git a/include/linux/sunrpc/bc_xprt.h b/include/linux/sunrpc/bc_xprt.h
new file mode 100644
index 0000000..8ad9337
--- /dev/null
+++ b/include/linux/sunrpc/bc_xprt.h
@@ -0,0 +1,40 @@
+/******************************************************************************
+
+(c) 2008 Network Appliance, Inc. All Rights Reserved.
+
+Network Appliance provides this source code under the GPL v2 License.
+The GPL v2 license is available at
+http://opensource.org/licenses/gpl-license.php.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/*
+ * Functions to create and manage the backchannel
+ */
+
+#ifndef _LINUX_SUNRPC_BC_XPRT_H
+#define _LINUX_SUNRPC_BC_XPRT_H
+
+#include <linux/sunrpc/svcsock.h>
+#include <linux/sunrpc/xprt.h>
+
+#ifdef CONFIG_NFS_V4_1
+struct rpc_rqst *xprt_alloc_bc_request(struct rpc_xprt *xprt);
+void xprt_free_bc_request(struct rpc_rqst *req);
+int xprt_setup_backchannel(struct rpc_xprt *, unsigned int min_reqs);
+void xprt_destroy_backchannel(struct rpc_xprt *, int max_reqs);
+#endif /* CONFIG_NFS_V4_1 */
+#endif /* _LINUX_SUNRPC_BC_XPRT_H */
+
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 60/85] nfs41: New xs_tcp_read_data()
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (57 preceding siblings ...)
2008-11-10 20:28 ` [RFC 59/85] nfs41: New include/linux/sunrpc/bc_xprt.h Benny Halevy
@ 2008-11-10 20:28 ` Benny Halevy
2008-11-10 20:29 ` [RFC 61/85] nfs41: Add backchannel processing support to RPC state machine Benny Halevy
` (26 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:28 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
Handles RPC replies and backchannel callbacks. Traditionally the NFS
client has expected only RPC replies on its open connections. With
NFSv4.1, callbacks can arrive over an existing open connection.
This patch refactors the old xs_tcp_read_request() into an RPC reply handler:
xs_tcp_read_reply(), a new backchannel callback handler: xs_tcp_read_callback(),
and a common routine to read the data off the transport: xs_tcp_read_common().
The new xs_tcp_read_callback() queues callback requests onto a queue where
the callback service (a separate thread) is listening for the processing.
This patch incorporates work and suggestions from Rahul Iyer (iyer@netapp.com)
and Benny Halevy (bhalevy@panasas.com).
Note that we need to update the printk warning message to throttle the
number of warnings printed to avoid overflowing syslog with it.
Signed-off-by: Ricardo Labiaga <ricardo.labiaga@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
net/sunrpc/xprtsock.c | 139 ++++++++++++++++++++++++++++++++++++++++++------
1 files changed, 121 insertions(+), 18 deletions(-)
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 1ce05d7..6ccdec8 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -34,6 +34,9 @@
#include <linux/sunrpc/sched.h>
#include <linux/sunrpc/xprtsock.h>
#include <linux/file.h>
+#ifdef CONFIG_NFS_V4_1
+#include <linux/sunrpc/bc_xprt.h>
+#endif
#include <net/sock.h>
#include <net/checksum.h>
@@ -997,25 +1000,16 @@ static inline void xs_tcp_read_calldir(struct sock_xprt *transport,
xs_tcp_check_fraghdr(transport);
}
-static inline void xs_tcp_read_request(struct rpc_xprt *xprt, struct xdr_skb_reader *desc)
+static inline void xs_tcp_read_common(struct rpc_xprt *xprt,
+ struct xdr_skb_reader *desc,
+ struct rpc_rqst *req)
{
- struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
- struct rpc_rqst *req;
+ struct sock_xprt *transport =
+ container_of(xprt, struct sock_xprt, xprt);
struct xdr_buf *rcvbuf;
size_t len;
ssize_t r;
- /* Find and lock the request corresponding to this xid */
- spin_lock(&xprt->transport_lock);
- req = xprt_lookup_rqst(xprt, transport->tcp_xid);
- if (!req) {
- transport->tcp_flags &= ~TCP_RCV_COPY_DATA;
- dprintk("RPC: XID %08x request not found!\n",
- ntohl(transport->tcp_xid));
- spin_unlock(&xprt->transport_lock);
- return;
- }
-
rcvbuf = &req->rq_private_buf;
len = desc->count;
if (len > transport->tcp_reclen - transport->tcp_offset) {
@@ -1053,7 +1047,7 @@ static inline void xs_tcp_read_request(struct rpc_xprt *xprt, struct xdr_skb_rea
"tcp_offset = %u, tcp_reclen = %u\n",
xprt, transport->tcp_copied,
transport->tcp_offset, transport->tcp_reclen);
- goto out;
+ return;
}
dprintk("RPC: XID %08x read %Zd bytes\n",
@@ -1069,11 +1063,120 @@ static inline void xs_tcp_read_request(struct rpc_xprt *xprt, struct xdr_skb_rea
transport->tcp_flags &= ~TCP_RCV_COPY_DATA;
}
-out:
+ return;
+}
+
+/*
+ * Finds the request corresponding to the RPC xid and invokes the common
+ * tcp read code to read the data.
+ */
+static inline int xs_tcp_read_reply(struct rpc_xprt *xprt,
+ struct xdr_skb_reader *desc)
+{
+ struct sock_xprt *transport =
+ container_of(xprt, struct sock_xprt, xprt);
+ struct rpc_rqst *req;
+
+ dprintk("RPC: read reply XID %08x\n", ntohl(transport->tcp_xid));
+
+ /* Find and lock the request corresponding to this xid */
+ spin_lock(&xprt->transport_lock);
+ req = xprt_lookup_rqst(xprt, transport->tcp_xid);
+ if (!req) {
+ dprintk("RPC: XID %08x request not found!\n",
+ ntohl(transport->tcp_xid));
+ spin_unlock(&xprt->transport_lock);
+ return -1;
+ }
+
+ xs_tcp_read_common(xprt, desc, req);
+
if (!(transport->tcp_flags & TCP_RCV_COPY_DATA))
xprt_complete_rqst(req->rq_task, transport->tcp_copied);
+
spin_unlock(&xprt->transport_lock);
- xs_tcp_check_fraghdr(transport);
+ return 0;
+}
+
+#if defined(CONFIG_NFS_V4_1)
+/*
+ * Obtains an rpc_rqst previously allocated and invokes the common
+ * tcp read code to read the data. The result is placed in the callback
+ * queue.
+ * If we're unable to obtain the rpc_rqst we schedule the closing of the
+ * connection and return -1.
+ */
+static inline int xs_tcp_read_callback(struct rpc_xprt *xprt,
+ struct xdr_skb_reader *desc)
+{
+ struct sock_xprt *transport =
+ container_of(xprt, struct sock_xprt, xprt);
+ struct rpc_rqst *req;
+
+ req = xprt_alloc_bc_request(xprt);
+ if (req == NULL) {
+ /*
+ * Schedule an autoclose RPC call
+ */
+ printk(KERN_WARNING "Callback slot table overflowed\n");
+ set_bit(XPRT_CLOSE_WAIT, &xprt->state);
+ if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0)
+ queue_work(rpciod_workqueue, &xprt->task_cleanup);
+ return -1;
+ }
+
+ req->rq_xid = transport->tcp_xid;
+ dprintk("RPC: read callback XID %08x\n", ntohl(req->rq_xid));
+ xs_tcp_read_common(xprt, desc, req);
+
+ if (!(transport->tcp_flags & TCP_RCV_COPY_DATA)) {
+ struct svc_serv *bc_serv = xprt->bc_serv;
+
+ /*
+ * Add callback request to callback list. The callback
+ * service sleeps on the sv_cb_waitq waiting for new
+ * requests. Wake it up after adding enqueing the
+ * request.
+ */
+ dprintk("RPC: add callback request to list\n");
+ spin_lock(&bc_serv->sv_cb_lock);
+ list_add(&req->rq_bc_list, &bc_serv->sv_cb_list);
+ spin_unlock(&bc_serv->sv_cb_lock);
+ wake_up(&bc_serv->sv_cb_waitq);
+ }
+
+ return 0;
+}
+#endif /* CONFIG_NFS_V4_1 */
+
+/*
+ * Read data off the transport. This can be either an RPC_CALL or an
+ * RPC_REPLY. Relay the processing to helper functions.
+ */
+static void xs_tcp_read_data(struct rpc_xprt *xprt,
+ struct xdr_skb_reader *desc)
+{
+ struct sock_xprt *transport =
+ container_of(xprt, struct sock_xprt, xprt);
+ int status;
+
+#if defined(CONFIG_NFS_V4_1)
+ status = (transport->tcp_calldir == RPC_REPLY) ?
+ xs_tcp_read_reply(xprt, desc) :
+ xs_tcp_read_callback(xprt, desc);
+#else
+ status = xs_tcp_read_reply(xprt, desc);
+#endif /* CONFIG_NFS_V4_1 */
+
+ if (status == 0)
+ xs_tcp_check_fraghdr(transport);
+ else {
+ /*
+ * The transport_lock protects the request handling.
+ * There's no need to hold it to update the tcp_flags.
+ */
+ transport->tcp_flags &= ~TCP_RCV_COPY_DATA;
+ }
}
static inline void xs_tcp_read_discard(struct sock_xprt *transport, struct xdr_skb_reader *desc)
@@ -1120,7 +1223,7 @@ static int xs_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, uns
}
/* Read in the request data */
if (transport->tcp_flags & TCP_RCV_COPY_DATA) {
- xs_tcp_read_request(xprt, &desc);
+ xs_tcp_read_data(xprt, &desc);
continue;
}
/* Skip over any trailing bytes on short reads */
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 61/85] nfs41: Add backchannel processing support to RPC state machine
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (58 preceding siblings ...)
2008-11-10 20:28 ` [RFC 60/85] nfs41: New xs_tcp_read_data() Benny Halevy
@ 2008-11-10 20:29 ` Benny Halevy
2008-11-17 13:53 ` [pnfs] " Benny Halevy
2008-11-10 20:29 ` [RFC 62/85] nfs41: Backchannel callback service helper routines Benny Halevy
` (25 subsequent siblings)
85 siblings, 1 reply; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:29 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
Adds rpc_run_bc_task() which is called by the NFS callback service to
process backchannel requests. It performs similar work to rpc_run_task()
though "schedules" the backchannel task to be executed starting at the
call_trasmit state in the RPC state machine.
It also introduces some miscellaneous updates to the argument validation,
call_transmit, and transport cleanup functions to take into account
that there are now forechannel and backchannel tasks.
Backchannel requests do not carry an RPC message structure, since the
payload has already been XDR encoded using the existing NFSv4 callback
mechanism.
Signed-off-by: Ricardo Labiaga <ricardo.labiaga@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
include/linux/sunrpc/sched.h | 2 +
include/linux/sunrpc/xprt.h | 12 +++++++++
net/sunrpc/clnt.c | 52 ++++++++++++++++++++++++++++++++++++++++-
net/sunrpc/stats.c | 6 +++-
net/sunrpc/sunrpc.h | 35 ++++++++++++++++++++++++++++
net/sunrpc/xprt.c | 36 ++++++++++++++++++++++++-----
6 files changed, 133 insertions(+), 10 deletions(-)
create mode 100644 net/sunrpc/sunrpc.h
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
index 1773768..4010977 100644
--- a/include/linux/sunrpc/sched.h
+++ b/include/linux/sunrpc/sched.h
@@ -210,6 +210,8 @@ struct rpc_wait_queue {
*/
struct rpc_task *rpc_new_task(const struct rpc_task_setup *);
struct rpc_task *rpc_run_task(const struct rpc_task_setup *);
+struct rpc_task *rpc_run_bc_task(struct rpc_rqst *req,
+ const struct rpc_call_ops *ops);
void rpc_put_task(struct rpc_task *);
void rpc_exit_task(struct rpc_task *);
void rpc_release_calldata(const struct rpc_call_ops *, void *);
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index 035431b..45a92e2 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -215,6 +215,18 @@ struct rpc_xprt {
/* buffer in use */
#endif /* CONFIG_NFS_V4_1 */
+#if defined(CONFIG_NFS_V4_1)
+static inline int bc_prealloc(struct rpc_rqst *req)
+{
+ return test_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state);
+}
+#else
+static inline int bc_prealloc(struct rpc_rqst *req)
+{
+ return 0;
+}
+#endif /* CONFIG_NFS_V4_1 */
+
struct xprt_create {
int ident; /* XPRT_TRANSPORT identifier */
struct sockaddr * srcaddr; /* optional local address */
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index dd0ff2d..f5418ac 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -36,7 +36,9 @@
#include <linux/sunrpc/clnt.h>
#include <linux/sunrpc/rpc_pipe_fs.h>
#include <linux/sunrpc/metrics.h>
+#include <linux/sunrpc/bc_xprt.h>
+#include "sunrpc.h"
#ifdef RPC_DEBUG
# define RPCDBG_FACILITY RPCDBG_CALL
@@ -602,6 +604,51 @@ rpc_call_async(struct rpc_clnt *clnt, const struct rpc_message *msg, int flags,
}
EXPORT_SYMBOL_GPL(rpc_call_async);
+#if defined(CONFIG_NFS_V4_1)
+/**
+ * rpc_run_bc_task - Allocate a new RPC task for backchannel use, then run
+ * rpc_execute against it
+ * @ops: RPC call ops
+ */
+struct rpc_task *rpc_run_bc_task(struct rpc_rqst *req,
+ const struct rpc_call_ops *tk_ops)
+{
+ struct rpc_task *task;
+ struct xdr_buf *xbufp = &req->rq_snd_buf;
+ struct rpc_task_setup task_setup_data = {
+ .callback_ops = tk_ops,
+ };
+
+ dprintk("RPC: rpc_run_bc_task req= %p\n", req);
+ /*
+ * Create an rpc_task to send the data
+ */
+ task = rpc_new_task(&task_setup_data);
+ if (!task) {
+ xprt_free_bc_request(req);
+ goto out;
+ }
+ task->tk_rqstp = req;
+
+ /*
+ * Set up the xdr_buf length.
+ * This also indicates that the buffer is XDR encoded already.
+ */
+ xbufp->len = xbufp->head[0].iov_len + xbufp->page_len +
+ xbufp->tail[0].iov_len;
+
+ task->tk_action = call_transmit;
+ atomic_inc(&task->tk_count);
+ BUG_ON(atomic_read(&task->tk_count) != 2);
+ rpc_execute(task);
+
+out:
+ dprintk("RPC: rpc_run_bc_task: task= %p\n", task);
+ return task;
+}
+EXPORT_SYMBOL_GPL(rpc_run_bc_task);
+#endif /* CONFIG_NFS_V4_1 */
+
void
rpc_call_start(struct rpc_task *task)
{
@@ -1094,10 +1141,11 @@ call_transmit(struct rpc_task *task)
* in order to allow access to the socket to other RPC requests.
*/
call_transmit_status(task);
- if (task->tk_msg.rpc_proc->p_decode != NULL)
+ if (rpc_reply_expected(task))
return;
task->tk_action = rpc_exit_task;
- rpc_wake_up_queued_task(&task->tk_xprt->pending, task);
+ if (task->tk_client != NULL)
+ rpc_wake_up_queued_task(&task->tk_xprt->pending, task);
}
/*
diff --git a/net/sunrpc/stats.c b/net/sunrpc/stats.c
index 50b049c..89dc28e 100644
--- a/net/sunrpc/stats.c
+++ b/net/sunrpc/stats.c
@@ -141,12 +141,14 @@ EXPORT_SYMBOL_GPL(rpc_free_iostats);
void rpc_count_iostats(struct rpc_task *task)
{
struct rpc_rqst *req = task->tk_rqstp;
- struct rpc_iostats *stats = task->tk_client->cl_metrics;
+ struct rpc_iostats *stats;
struct rpc_iostats *op_metrics;
long rtt, execute, queue;
- if (!stats || !req)
+ if (!task->tk_client || task->tk_client->cl_metrics || !req)
return;
+
+ stats = task->tk_client->cl_metrics;
op_metrics = &stats[task->tk_msg.rpc_proc->p_statidx];
op_metrics->om_ops++;
diff --git a/net/sunrpc/sunrpc.h b/net/sunrpc/sunrpc.h
new file mode 100644
index 0000000..b462de4
--- /dev/null
+++ b/net/sunrpc/sunrpc.h
@@ -0,0 +1,35 @@
+/******************************************************************************
+
+(c) 2008 Network Appliance, Inc. All Rights Reserved.
+
+Network Appliance provides this source code under the GPL v2 License.
+The GPL v2 license is available at
+http://opensource.org/licenses/gpl-license.php.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/*
+ * Functions and macros used internally by RPC
+ */
+
+#ifndef _NET_SUNRPC_SUNRPC_H
+#define _NET_SUNRPC_SUNRPC_H
+
+#define rpc_reply_expected(task) \
+ (((task)->tk_msg.rpc_proc != NULL) && \
+ ((task)->tk_msg.rpc_proc->p_decode != NULL))
+
+#endif /* _NET_SUNRPC_SUNRPC_H */
+
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 848a7af..cc1e5f2 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -12,8 +12,9 @@
* - Next, the caller puts together the RPC message, stuffs it into
* the request struct, and calls xprt_transmit().
* - xprt_transmit sends the message and installs the caller on the
- * transport's wait list. At the same time, it installs a timer that
- * is run after the packet's timeout has expired.
+ * transport's wait list. At the same time, if a reply is expected,
+ * it installs a timer that is run after the packet's timeout has
+ * expired.
* - When a packet arrives, the data_ready handler walks the list of
* pending requests for that transport. If a matching XID is found, the
* caller is woken up, and the timer removed.
@@ -46,6 +47,8 @@
#include <linux/sunrpc/clnt.h>
#include <linux/sunrpc/metrics.h>
+#include "sunrpc.h"
+
/*
* Local variables
*/
@@ -852,7 +855,10 @@ void xprt_transmit(struct rpc_task *task)
dprintk("RPC: %5u xprt_transmit(%u)\n", task->tk_pid, req->rq_slen);
if (!req->rq_received) {
- if (list_empty(&req->rq_list)) {
+ if (list_empty(&req->rq_list) && rpc_reply_expected(task)) {
+ /*
+ * Add to the list only if we're expecting a reply
+ */
spin_lock_bh(&xprt->transport_lock);
/* Update the softirq receive buffer */
memcpy(&req->rq_private_buf, &req->rq_rcv_buf,
@@ -883,8 +889,13 @@ void xprt_transmit(struct rpc_task *task)
/* Don't race with disconnect */
if (!xprt_connected(xprt))
task->tk_status = -ENOTCONN;
- else if (!req->rq_received)
+ else if (!req->rq_received && rpc_reply_expected(task)) {
+ /*
+ * Sleep on the pending queue since
+ * we're expecting a reply.
+ */
rpc_sleep_on(&xprt->pending, task, xprt_timer);
+ }
spin_unlock_bh(&xprt->transport_lock);
return;
}
@@ -967,11 +978,15 @@ static void xprt_request_init(struct rpc_task *task, struct rpc_xprt *xprt)
*/
void xprt_release(struct rpc_task *task)
{
- struct rpc_xprt *xprt = task->tk_xprt;
+ struct rpc_xprt *xprt;
struct rpc_rqst *req;
+ int prealloc;
+ BUG_ON(atomic_read(&task->tk_count) < 0);
if (!(req = task->tk_rqstp))
return;
+ prealloc = bc_prealloc(req); /* Preallocated backchannel request? */
+ xprt = req->rq_xprt;
rpc_count_iostats(task);
spin_lock_bh(&xprt->transport_lock);
xprt->ops->release_xprt(xprt, task);
@@ -984,10 +999,19 @@ void xprt_release(struct rpc_task *task)
mod_timer(&xprt->timer,
xprt->last_used + xprt->idle_timeout);
spin_unlock_bh(&xprt->transport_lock);
- xprt->ops->buf_free(req->rq_buffer);
+ if (!bc_prealloc(req))
+ xprt->ops->buf_free(req->rq_buffer);
task->tk_rqstp = NULL;
if (req->rq_release_snd_buf)
req->rq_release_snd_buf(req);
+
+ /*
+ * Early exit if this is a backchannel preallocated request.
+ * There is no need to have it added to the RPC slot list.
+ */
+ if (prealloc)
+ return;
+
memset(req, 0, sizeof(*req)); /* mark unused */
dprintk("RPC: %5u release request %p\n", task->tk_pid, req);
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* Re: [pnfs] [RFC 61/85] nfs41: Add backchannel processing support to RPC state machine
2008-11-10 20:29 ` [RFC 61/85] nfs41: Add backchannel processing support to RPC state machine Benny Halevy
@ 2008-11-17 13:53 ` Benny Halevy
0 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-17 13:53 UTC (permalink / raw)
To: pnfs; +Cc: trond.myklebust, linux-nfs
On Nov. 10, 2008, 22:29 +0200, Benny Halevy <bhalevy@panasas.com> wrote:
> Adds rpc_run_bc_task() which is called by the NFS callback service to
> process backchannel requests. It performs similar work to rpc_run_task()
> though "schedules" the backchannel task to be executed starting at the
> call_trasmit state in the RPC state machine.
>
> It also introduces some miscellaneous updates to the argument validation,
> call_transmit, and transport cleanup functions to take into account
> that there are now forechannel and backchannel tasks.
>
> Backchannel requests do not carry an RPC message structure, since the
> payload has already been XDR encoded using the existing NFSv4 callback
> mechanism.
>
> Signed-off-by: Ricardo Labiaga <ricardo.labiaga@netapp.com>
> Signed-off-by: Benny Halevy <bhalevy@panasas.com>
> ---
> include/linux/sunrpc/sched.h | 2 +
> include/linux/sunrpc/xprt.h | 12 +++++++++
> net/sunrpc/clnt.c | 52 ++++++++++++++++++++++++++++++++++++++++-
> net/sunrpc/stats.c | 6 +++-
> net/sunrpc/sunrpc.h | 35 ++++++++++++++++++++++++++++
> net/sunrpc/xprt.c | 36 ++++++++++++++++++++++++-----
> 6 files changed, 133 insertions(+), 10 deletions(-)
> create mode 100644 net/sunrpc/sunrpc.h
>
> diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
> index 1773768..4010977 100644
> --- a/include/linux/sunrpc/sched.h
> +++ b/include/linux/sunrpc/sched.h
> @@ -210,6 +210,8 @@ struct rpc_wait_queue {
> */
> struct rpc_task *rpc_new_task(const struct rpc_task_setup *);
> struct rpc_task *rpc_run_task(const struct rpc_task_setup *);
> +struct rpc_task *rpc_run_bc_task(struct rpc_rqst *req,
> + const struct rpc_call_ops *ops);
> void rpc_put_task(struct rpc_task *);
> void rpc_exit_task(struct rpc_task *);
> void rpc_release_calldata(const struct rpc_call_ops *, void *);
> diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
> index 035431b..45a92e2 100644
> --- a/include/linux/sunrpc/xprt.h
> +++ b/include/linux/sunrpc/xprt.h
> @@ -215,6 +215,18 @@ struct rpc_xprt {
> /* buffer in use */
> #endif /* CONFIG_NFS_V4_1 */
>
> +#if defined(CONFIG_NFS_V4_1)
> +static inline int bc_prealloc(struct rpc_rqst *req)
> +{
> + return test_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state);
> +}
> +#else
> +static inline int bc_prealloc(struct rpc_rqst *req)
> +{
> + return 0;
> +}
> +#endif /* CONFIG_NFS_V4_1 */
> +
> struct xprt_create {
> int ident; /* XPRT_TRANSPORT identifier */
> struct sockaddr * srcaddr; /* optional local address */
> diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
> index dd0ff2d..f5418ac 100644
> --- a/net/sunrpc/clnt.c
> +++ b/net/sunrpc/clnt.c
> @@ -36,7 +36,9 @@
> #include <linux/sunrpc/clnt.h>
> #include <linux/sunrpc/rpc_pipe_fs.h>
> #include <linux/sunrpc/metrics.h>
> +#include <linux/sunrpc/bc_xprt.h>
>
> +#include "sunrpc.h"
>
> #ifdef RPC_DEBUG
> # define RPCDBG_FACILITY RPCDBG_CALL
> @@ -602,6 +604,51 @@ rpc_call_async(struct rpc_clnt *clnt, const struct rpc_message *msg, int flags,
> }
> EXPORT_SYMBOL_GPL(rpc_call_async);
>
> +#if defined(CONFIG_NFS_V4_1)
> +/**
> + * rpc_run_bc_task - Allocate a new RPC task for backchannel use, then run
> + * rpc_execute against it
> + * @ops: RPC call ops
> + */
> +struct rpc_task *rpc_run_bc_task(struct rpc_rqst *req,
> + const struct rpc_call_ops *tk_ops)
> +{
> + struct rpc_task *task;
> + struct xdr_buf *xbufp = &req->rq_snd_buf;
> + struct rpc_task_setup task_setup_data = {
> + .callback_ops = tk_ops,
> + };
> +
> + dprintk("RPC: rpc_run_bc_task req= %p\n", req);
> + /*
> + * Create an rpc_task to send the data
> + */
> + task = rpc_new_task(&task_setup_data);
review 11-14: we can't do that.
Trond suggests to factor out what we need in call_transmit
i.e. never call call_status. (only error we need to handle is -EAGAIN
setting up a task for that is the easiest way to go.
we should be able to reuse the existing marshalled stuff that the svc
prepared rather than copying the data.
> + if (!task) {
> + xprt_free_bc_request(req);
> + goto out;
> + }
> + task->tk_rqstp = req;
> +
> + /*
> + * Set up the xdr_buf length.
> + * This also indicates that the buffer is XDR encoded already.
> + */
> + xbufp->len = xbufp->head[0].iov_len + xbufp->page_len +
> + xbufp->tail[0].iov_len;
> +
> + task->tk_action = call_transmit;
> + atomic_inc(&task->tk_count);
> + BUG_ON(atomic_read(&task->tk_count) != 2);
> + rpc_execute(task);
> +
> +out:
> + dprintk("RPC: rpc_run_bc_task: task= %p\n", task);
> + return task;
> +}
> +EXPORT_SYMBOL_GPL(rpc_run_bc_task);
> +#endif /* CONFIG_NFS_V4_1 */
> +
> void
> rpc_call_start(struct rpc_task *task)
> {
> @@ -1094,10 +1141,11 @@ call_transmit(struct rpc_task *task)
> * in order to allow access to the socket to other RPC requests.
> */
> call_transmit_status(task);
> - if (task->tk_msg.rpc_proc->p_decode != NULL)
> + if (rpc_reply_expected(task))
> return;
> task->tk_action = rpc_exit_task;
> - rpc_wake_up_queued_task(&task->tk_xprt->pending, task);
> + if (task->tk_client != NULL)
> + rpc_wake_up_queued_task(&task->tk_xprt->pending, task);
> }
>
> /*
> diff --git a/net/sunrpc/stats.c b/net/sunrpc/stats.c
> index 50b049c..89dc28e 100644
> --- a/net/sunrpc/stats.c
> +++ b/net/sunrpc/stats.c
> @@ -141,12 +141,14 @@ EXPORT_SYMBOL_GPL(rpc_free_iostats);
> void rpc_count_iostats(struct rpc_task *task)
> {
> struct rpc_rqst *req = task->tk_rqstp;
> - struct rpc_iostats *stats = task->tk_client->cl_metrics;
> + struct rpc_iostats *stats;
> struct rpc_iostats *op_metrics;
> long rtt, execute, queue;
>
> - if (!stats || !req)
> + if (!task->tk_client || task->tk_client->cl_metrics || !req)
> return;
> +
> + stats = task->tk_client->cl_metrics;
> op_metrics = &stats[task->tk_msg.rpc_proc->p_statidx];
>
> op_metrics->om_ops++;
> diff --git a/net/sunrpc/sunrpc.h b/net/sunrpc/sunrpc.h
> new file mode 100644
> index 0000000..b462de4
> --- /dev/null
> +++ b/net/sunrpc/sunrpc.h
> @@ -0,0 +1,35 @@
> +/******************************************************************************
> +
> +(c) 2008 Network Appliance, Inc. All Rights Reserved.
> +
> +Network Appliance provides this source code under the GPL v2 License.
> +The GPL v2 license is available at
> +http://opensource.org/licenses/gpl-license.php.
> +
> +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
> +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
> +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
> +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
> +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
> +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
> +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
> +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
> +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> +
> +******************************************************************************/
> +
> +/*
> + * Functions and macros used internally by RPC
> + */
> +
> +#ifndef _NET_SUNRPC_SUNRPC_H
> +#define _NET_SUNRPC_SUNRPC_H
> +
> +#define rpc_reply_expected(task) \
> + (((task)->tk_msg.rpc_proc != NULL) && \
> + ((task)->tk_msg.rpc_proc->p_decode != NULL))
> +
> +#endif /* _NET_SUNRPC_SUNRPC_H */
> +
> diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
> index 848a7af..cc1e5f2 100644
> --- a/net/sunrpc/xprt.c
> +++ b/net/sunrpc/xprt.c
> @@ -12,8 +12,9 @@
> * - Next, the caller puts together the RPC message, stuffs it into
> * the request struct, and calls xprt_transmit().
> * - xprt_transmit sends the message and installs the caller on the
> - * transport's wait list. At the same time, it installs a timer that
> - * is run after the packet's timeout has expired.
> + * transport's wait list. At the same time, if a reply is expected,
> + * it installs a timer that is run after the packet's timeout has
> + * expired.
> * - When a packet arrives, the data_ready handler walks the list of
> * pending requests for that transport. If a matching XID is found, the
> * caller is woken up, and the timer removed.
> @@ -46,6 +47,8 @@
> #include <linux/sunrpc/clnt.h>
> #include <linux/sunrpc/metrics.h>
>
> +#include "sunrpc.h"
> +
> /*
> * Local variables
> */
> @@ -852,7 +855,10 @@ void xprt_transmit(struct rpc_task *task)
> dprintk("RPC: %5u xprt_transmit(%u)\n", task->tk_pid, req->rq_slen);
>
> if (!req->rq_received) {
> - if (list_empty(&req->rq_list)) {
> + if (list_empty(&req->rq_list) && rpc_reply_expected(task)) {
> + /*
> + * Add to the list only if we're expecting a reply
> + */
> spin_lock_bh(&xprt->transport_lock);
> /* Update the softirq receive buffer */
> memcpy(&req->rq_private_buf, &req->rq_rcv_buf,
> @@ -883,8 +889,13 @@ void xprt_transmit(struct rpc_task *task)
> /* Don't race with disconnect */
> if (!xprt_connected(xprt))
> task->tk_status = -ENOTCONN;
> - else if (!req->rq_received)
> + else if (!req->rq_received && rpc_reply_expected(task)) {
> + /*
> + * Sleep on the pending queue since
> + * we're expecting a reply.
> + */
> rpc_sleep_on(&xprt->pending, task, xprt_timer);
> + }
> spin_unlock_bh(&xprt->transport_lock);
> return;
> }
> @@ -967,11 +978,15 @@ static void xprt_request_init(struct rpc_task *task, struct rpc_xprt *xprt)
> */
> void xprt_release(struct rpc_task *task)
> {
> - struct rpc_xprt *xprt = task->tk_xprt;
> + struct rpc_xprt *xprt;
> struct rpc_rqst *req;
> + int prealloc;
>
> + BUG_ON(atomic_read(&task->tk_count) < 0);
> if (!(req = task->tk_rqstp))
> return;
> + prealloc = bc_prealloc(req); /* Preallocated backchannel request? */
> + xprt = req->rq_xprt;
> rpc_count_iostats(task);
> spin_lock_bh(&xprt->transport_lock);
> xprt->ops->release_xprt(xprt, task);
> @@ -984,10 +999,19 @@ void xprt_release(struct rpc_task *task)
> mod_timer(&xprt->timer,
> xprt->last_used + xprt->idle_timeout);
> spin_unlock_bh(&xprt->transport_lock);
> - xprt->ops->buf_free(req->rq_buffer);
> + if (!bc_prealloc(req))
> + xprt->ops->buf_free(req->rq_buffer);
> task->tk_rqstp = NULL;
> if (req->rq_release_snd_buf)
> req->rq_release_snd_buf(req);
> +
> + /*
> + * Early exit if this is a backchannel preallocated request.
> + * There is no need to have it added to the RPC slot list.
> + */
> + if (prealloc)
> + return;
> +
> memset(req, 0, sizeof(*req)); /* mark unused */
>
> dprintk("RPC: %5u release request %p\n", task->tk_pid, req);
^ permalink raw reply [flat|nested] 115+ messages in thread
* [RFC 62/85] nfs41: Backchannel callback service helper routines
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (59 preceding siblings ...)
2008-11-10 20:29 ` [RFC 61/85] nfs41: Add backchannel processing support to RPC state machine Benny Halevy
@ 2008-11-10 20:29 ` Benny Halevy
2008-11-10 20:29 ` [RFC 63/85] FIXME: nfs41: sunrpc: handle clnt==NULL in call_status Benny Halevy
` (24 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:29 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
From: Ricardo Labiaga <Ricardo.Labiaga@netapp.com>
Executes the backchannel task on the RPC state machine using
the existing open connection previously established by the client.
Signed-off-by: Ricardo Labiaga <ricardo.labiaga@netapp.com>
nfs41: Add bc_svc.o to sunrpc Makefile.
Signed-off-by: Ricardo Labiaga <Ricardo.Labiaga@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
include/linux/sunrpc/bc_xprt.h | 3 +
net/sunrpc/Makefile | 2 +-
net/sunrpc/bc_svc.c | 81 ++++++++++++++++++++++++++++++++++++++++
net/sunrpc/xprtsock.c | 3 +
4 files changed, 88 insertions(+), 1 deletions(-)
create mode 100644 net/sunrpc/bc_svc.c
diff --git a/include/linux/sunrpc/bc_xprt.h b/include/linux/sunrpc/bc_xprt.h
index 8ad9337..9dbeb77 100644
--- a/include/linux/sunrpc/bc_xprt.h
+++ b/include/linux/sunrpc/bc_xprt.h
@@ -29,12 +29,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <linux/sunrpc/svcsock.h>
#include <linux/sunrpc/xprt.h>
+#include <linux/sunrpc/sched.h>
#ifdef CONFIG_NFS_V4_1
struct rpc_rqst *xprt_alloc_bc_request(struct rpc_xprt *xprt);
void xprt_free_bc_request(struct rpc_rqst *req);
int xprt_setup_backchannel(struct rpc_xprt *, unsigned int min_reqs);
void xprt_destroy_backchannel(struct rpc_xprt *, int max_reqs);
+void bc_release_request(struct rpc_task *);
+int bc_send(struct rpc_rqst *req);
#endif /* CONFIG_NFS_V4_1 */
#endif /* _LINUX_SUNRPC_BC_XPRT_H */
diff --git a/net/sunrpc/Makefile b/net/sunrpc/Makefile
index 4a01f96..db73fd2 100644
--- a/net/sunrpc/Makefile
+++ b/net/sunrpc/Makefile
@@ -13,6 +13,6 @@ sunrpc-y := clnt.o xprt.o socklib.o xprtsock.o sched.o \
rpcb_clnt.o timer.o xdr.o \
sunrpc_syms.o cache.o rpc_pipe.o \
svc_xprt.o
-sunrpc-$(CONFIG_NFS_V4_1) += backchannel_rqst.o
+sunrpc-$(CONFIG_NFS_V4_1) += backchannel_rqst.o bc_svc.o
sunrpc-$(CONFIG_PROC_FS) += stats.o
sunrpc-$(CONFIG_SYSCTL) += sysctl.o
diff --git a/net/sunrpc/bc_svc.c b/net/sunrpc/bc_svc.c
new file mode 100644
index 0000000..669722e
--- /dev/null
+++ b/net/sunrpc/bc_svc.c
@@ -0,0 +1,81 @@
+/******************************************************************************
+
+(c) 2007 Network Appliance, Inc. All Rights Reserved.
+
+Network Appliance provides this source code under the GPL v2 License.
+The GPL v2 license is available at
+http://opensource.org/licenses/gpl-license.php.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+******************************************************************************/
+
+/*
+ * The NFSv4.1 callback service helper routines.
+ * They implement the transport level processing required to send the
+ * reply over an existing open connection previously established by the client.
+ */
+
+#if defined(CONFIG_NFS_V4_1)
+
+#include <linux/module.h>
+
+#include <linux/sunrpc/xprt.h>
+#include <linux/sunrpc/sched.h>
+#include <linux/sunrpc/bc_xprt.h>
+
+#define RPCDBG_FACILITY RPCDBG_SVCDSP
+
+void bc_release_request(struct rpc_task *task)
+{
+ struct rpc_rqst *req = task->tk_rqstp;
+
+ dprintk("RPC: bc_release_request: task= %p\n", task);
+
+ /*
+ * Release this request only if it's a backchannel
+ * preallocated request
+ */
+ if (!bc_prealloc(req))
+ return;
+ xprt_free_bc_request(req);
+}
+
+/* Empty callback ops */
+static const struct rpc_call_ops nfs41_callback_ops = {
+};
+
+
+/*
+ * Send the callback reply
+ */
+int bc_send(struct rpc_rqst *req)
+{
+ struct rpc_task *task;
+ int ret;
+
+ dprintk("RPC: bc_send req= %p\n", req);
+ task = rpc_run_bc_task(req, &nfs41_callback_ops);
+ if (IS_ERR(task))
+ ret = PTR_ERR(task);
+ else {
+ BUG_ON(atomic_read(&task->tk_count) != 1);
+ ret = task->tk_status;
+ rpc_put_task(task);
+ }
+ return ret;
+ dprintk("RPC: bc_send ret= %d \n", ret);
+}
+EXPORT_SYMBOL_GPL(bc_send);
+
+#endif /* CONFIG_NFS_V4_1 */
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 6ccdec8..8513d50 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -2046,6 +2046,9 @@ static struct rpc_xprt_ops xs_tcp_ops = {
.buf_free = rpc_free,
.send_request = xs_tcp_send_request,
.set_retrans_timeout = xprt_set_retrans_timeout_def,
+#if defined(CONFIG_NFS_V4_1)
+ .release_request = bc_release_request,
+#endif /* CONFIG_NFS_V4_1 */
.close = xs_tcp_shutdown,
.destroy = xs_destroy,
.print_stats = xs_tcp_print_stats,
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 63/85] FIXME: nfs41: sunrpc: handle clnt==NULL in call_status
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (60 preceding siblings ...)
2008-11-10 20:29 ` [RFC 62/85] nfs41: Backchannel callback service helper routines Benny Halevy
@ 2008-11-10 20:29 ` Benny Halevy
2008-11-10 20:29 ` [RFC 64/85] nfs41: Refactor svc_process() Benny Halevy
` (23 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:29 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
FIXME: pending discussion. This patch might not be needed if
backchannel usage of rpc mechanisms for sending bc_svc
replies (on the nfs client / callback svc side)
On the following error path task->tk_client == NULL causing NULL deref:
Nov 4 14:14:32 tl1 kernel: Callback slot table overflowed
Nov 4 14:14:32 tl1 kernel: BUG: unable to handle kernel NULL pointer dereference at 0000000000000078
Nov 4 14:14:32 tl1 kernel: IP: [<ffffffffa02b4dd2>] call_status+0xe1/0x145 [sunrpc]
Nov 4 14:14:32 tl1 kernel: PGD 2f973067 PUD 2f974067 PMD 0
Nov 4 14:14:32 tl1 kernel: Oops: 0000 [1] SMP
Nov 4 14:14:32 tl1 kernel: CPU 0
Nov 4 14:14:32 tl1 kernel: Modules linked in: panfs(P) panlayoutdriver nfslayoutdriver nfsd auth_rpcgss exportfs nfs lockd nfs_acl fuse sunrpc ipv6 cpufreq_ondemand powernow_k8 freq_table dm_mirror dm_log dm_multipath dm_mod snd_hda_intel snd_seq_dummy sr_mod snd_seq_oss cdrom snd_seq_midi_event snd_seq snd_seq_device snd_pcm_oss snd_mixer_oss snd_pcm snd_timer snd_page_alloc snd_hwdep snd pcspkr serio_raw k8temp hwmon forcedeth soundcore pata_amd sg jedec_probe cfi_probe gen_probe mtd i2c_nforce2 chipreg i2c_core button map_funcs sata_nv ata_generic pata_acpi libata sd_mod scsi_mod ext3 jbd mbcache uhci_hcd ohci_hcd ehci_hcd [last unloaded: scsi_wait_scan]
Nov 4 14:14:32 tl1 kernel: Pid: 3405, comm: nfsv4.1-svc Tainted: P 2.6.27-pnfs #1
Nov 4 14:14:32 tl1 kernel: RIP: 0010:[<ffffffffa02b4dd2>] [<ffffffffa02b4dd2>] call_status+0xe1/0x145 [sunrpc]
Nov 4 14:14:32 tl1 kernel: RSP: 0018:ffff88002a70bd60 EFLAGS: 00010246
Nov 4 14:14:32 tl1 kernel: RAX: 0000000000000000 RBX: 00000000ffffff95 RCX: 0000000000000000
Nov 4 14:14:32 tl1 kernel: RDX: ffff88002a70bd10 RSI: ffff88002fc52dc0 RDI: ffff88002fc52dc0
Nov 4 14:14:32 tl1 kernel: RBP: ffff88002a70bd80 R08: ffff88002f9dae40 R09: ffffffff81489e60
Nov 4 14:14:32 tl1 kernel: R10: ffff880038497800 R11: ffff88002a70bd30 R12: ffff88002fc52dc0
Nov 4 14:14:32 tl1 kernel: R13: 0000000000000000 R14: ffff88002f57fa00 R15: ffff88002fc52e50
Nov 4 14:14:32 tl1 kernel: FS: 00007fe78ffac6f0(0000) GS:ffffffff8148da80(0000) knlGS:0000000000000000
Nov 4 14:14:32 tl1 kernel: CS: 0010 DS: 0018 ES: 0018 CR0: 000000008005003b
Nov 4 14:14:32 tl1 kernel: CR2: 0000000000000078 CR3: 000000002f971000 CR4: 00000000000006e0
Nov 4 14:14:32 tl1 kernel: DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
Nov 4 14:14:32 tl1 kernel: DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
Nov 4 14:14:32 tl1 kernel: Process nfsv4.1-svc (pid: 3405, threadinfo ffff88002a70a000, task ffff88003694d900)
Nov 4 14:14:32 tl1 kernel: Stack: 0000000000000000 ffff88002f57fa00 ffff88002fc52dc0 ffff880030450ce8
Nov 4 14:14:32 tl1 kernel: ffff88002a70bdc0 ffffffffa02bb9db ffff88002a70bdf0 ffff88002fc52dc0
Nov 4 14:14:32 tl1 kernel: ffff88002f57fa00 ffff88002f57fa00 ffff880030450ce8 ffff88002a734000
Nov 4 14:14:32 tl1 kernel: Call Trace:
Nov 4 14:14:32 tl1 kernel: [<ffffffffa02bb9db>] __rpc_execute+0x7e/0x21f [sunrpc]
Nov 4 14:14:32 tl1 kernel: [<ffffffffa02bbba4>] rpc_execute+0x28/0x2c [sunrpc]
Nov 4 14:14:32 tl1 kernel: [<ffffffffa02b5596>] rpc_run_bc_task+0x88/0xae [sunrpc]
Nov 4 14:14:32 tl1 kernel: [<ffffffffa02c923d>] bc_send+0x35/0x5a [sunrpc]
Nov 4 14:14:32 tl1 kernel: [<ffffffffa02bdc92>] bc_svc_process+0xf6/0x101 [sunrpc]
Nov 4 14:14:32 tl1 kernel: [<ffffffff81048a6c>] ? prepare_to_wait+0x5c/0x65
Nov 4 14:14:32 tl1 kernel: [<ffffffffa033a4c9>] nfs41_callback_svc+0xda/0x131 [nfs]
Nov 4 14:14:32 tl1 kernel: [<ffffffff810488a0>] ? autoremove_wake_function+0x0/0x38
Nov 4 14:14:32 tl1 kernel: [<ffffffffa033a3ef>] ? nfs41_callback_svc+0x0/0x131 [nfs]
Nov 4 14:14:32 tl1 kernel: [<ffffffff81048561>] kthread+0x49/0x76
Nov 4 14:14:32 tl1 kernel: [<ffffffff8100cf49>] child_rip+0xa/0x11
Nov 4 14:14:32 tl1 kernel: [<ffffffff8102a401>] ? pick_next_task_fair+0x93/0xa3
Nov 4 14:14:32 tl1 kernel: [<ffffffff81048518>] ? kthread+0x0/0x76
Nov 4 14:14:32 tl1 kernel: [<ffffffff8100cf3f>] ? child_rip+0x0/0x11
Nov 4 14:14:32 tl1 kernel:
Nov 4 14:14:32 tl1 kernel:
Nov 4 14:14:32 tl1 kernel: Code: e8 7c 70 00 00 49 8b 44 24 20 49 c7 44 24 68 dc 48 2b a0 f6 40 78 02 74 6d 41 8b b6 34 01 00 00 48 8b 78 30 e8 b9 2a 00 00 eb 5b <41> f6 45 78 04 74 13 49 8b 55 30 48 8d 82 80 04 00 00 f0 80 a2
Nov 4 14:14:32 tl1 kernel: RIP [<ffffffffa02b4dd2>] call_status+0xe1/0x145 [sunrpc]
Nov 4 14:14:32 tl1 kernel: RSP <ffff88002a70bd60>
Nov 4 14:14:32 tl1 kernel: CR2: 0000000000000078
Nov 4 14:14:32 tl1 kernel: ---[ end trace 1584c489f2573aaf ]---
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
net/sunrpc/clnt.c | 8 +++++---
1 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index f5418ac..fcadd8e 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -1204,7 +1204,8 @@ call_status(struct rpc_task *task)
break;
case -ECONNREFUSED:
case -ENOTCONN:
- rpc_force_rebind(clnt);
+ if (clnt)
+ rpc_force_rebind(clnt);
task->tk_action = call_bind;
break;
case -EAGAIN:
@@ -1215,9 +1216,10 @@ call_status(struct rpc_task *task)
rpc_exit(task, status);
break;
default:
- if (clnt->cl_chatty)
+ if (!clnt || clnt->cl_chatty)
printk("%s: RPC call returned error %d\n",
- clnt->cl_protname, -status);
+ clnt ? clnt->cl_protname : "<unknown protocol>",
+ -status);
rpc_exit(task, status);
}
}
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 64/85] nfs41: Refactor svc_process()
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (61 preceding siblings ...)
2008-11-10 20:29 ` [RFC 63/85] FIXME: nfs41: sunrpc: handle clnt==NULL in call_status Benny Halevy
@ 2008-11-10 20:29 ` Benny Halevy
2008-11-17 13:54 ` [pnfs] " Benny Halevy
2008-11-10 20:29 ` [RFC 65/85] nfs41: Backchannel bc_svc_process() Benny Halevy
` (22 subsequent siblings)
85 siblings, 1 reply; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:29 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
From: Ricardo Labiaga <ricardo.labiaga@netapp.com>
net/sunrpc/svc.c:svc_process() is used by the NFSv4 callback service
to process RPC requests arriving over connections initiated by the
server. NFSv4.1 supports callbacks over the backchannel on connections
initiated by the client. This patch refactors svc_process() so that
common code can also be used by the backchannel.
Signed-off-by: Ricardo Labiaga <ricardo.labiaga@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/callback.c | 10 +++---
net/sunrpc/svc.c | 80 +++++++++++++++++++++++++++++++++--------------------
2 files changed, 55 insertions(+), 35 deletions(-)
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index e792706..2f5acd3 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -132,7 +132,7 @@ nfs4_callback_up(struct svc_serv *serv)
int nfs_callback_up(u32 minorversion, void *args)
{
struct svc_serv *serv = NULL;
- struct svc_rqst *rqstp;
+ struct svc_rqst *rqst;
int (* callback_svc)(void *vrqstp);
char svc_name[12];
int ret = 0;
@@ -150,20 +150,20 @@ int nfs_callback_up(u32 minorversion, void *args)
/* FIXME: either 4.0 or 4.1 callback service can be up at a time
* need to monitor and control them both */
if (!minorversion) {
- rqstp = nfs4_callback_up(serv);
+ rqst = nfs4_callback_up(serv);
callback_svc = nfs4_callback_svc;
} else {
BUG(); /* for now */
}
- if (IS_ERR(rqstp)) {
- ret = PTR_ERR(rqstp);
+ if (IS_ERR(rqst)) {
+ ret = PTR_ERR(rqst);
goto out_err;
}
svc_sock_update_bufs(serv);
sprintf(svc_name, "nfsv4.%u-svc", minorversion);
- nfs_callback_info.rqst = rqstp;
+ nfs_callback_info.rqst = rqst;
nfs_callback_info.task = kthread_run(callback_svc,
nfs_callback_info.rqst,
svc_name);
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index 54c98d8..e4efeeb 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -985,20 +985,18 @@ svc_printk(struct svc_rqst *rqstp, const char *fmt, ...)
}
/*
- * Process the RPC request.
+ * Common routine for processing the RPC request.
*/
-int
-svc_process(struct svc_rqst *rqstp)
+static int
+svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv)
{
struct svc_program *progp;
struct svc_version *versp = NULL; /* compiler food */
struct svc_procedure *procp = NULL;
- struct kvec * argv = &rqstp->rq_arg.head[0];
- struct kvec * resv = &rqstp->rq_res.head[0];
struct svc_serv *serv = rqstp->rq_server;
kxdrproc_t xdr;
__be32 *statp;
- u32 dir, prog, vers, proc;
+ u32 prog, vers, proc;
__be32 auth_stat, rpc_stat;
int auth_res;
__be32 *reply_statp;
@@ -1008,36 +1006,19 @@ svc_process(struct svc_rqst *rqstp)
if (argv->iov_len < 6*4)
goto err_short_len;
- /* setup response xdr_buf.
- * Initially it has just one page
- */
- rqstp->rq_resused = 1;
- resv->iov_base = page_address(rqstp->rq_respages[0]);
- resv->iov_len = 0;
- rqstp->rq_res.pages = rqstp->rq_respages + 1;
- rqstp->rq_res.len = 0;
- rqstp->rq_res.page_base = 0;
- rqstp->rq_res.page_len = 0;
- rqstp->rq_res.buflen = PAGE_SIZE;
- rqstp->rq_res.tail[0].iov_base = NULL;
- rqstp->rq_res.tail[0].iov_len = 0;
/* Will be turned off only in gss privacy case: */
rqstp->rq_splice_ok = 1;
/* Setup reply header */
rqstp->rq_xprt->xpt_ops->xpo_prep_reply_hdr(rqstp);
- rqstp->rq_xid = svc_getu32(argv);
svc_putu32(resv, rqstp->rq_xid);
- dir = svc_getnl(argv);
vers = svc_getnl(argv);
/* First words of reply: */
svc_putnl(resv, 1); /* REPLY */
- if (dir != 0) /* direction != CALL */
- goto err_bad_dir;
if (vers != 2) /* RPC version number */
goto err_bad_rpc;
@@ -1161,7 +1142,7 @@ svc_process(struct svc_rqst *rqstp)
sendit:
if (svc_authorise(rqstp))
goto dropit;
- return svc_send(rqstp);
+ return 1; /* Caller can now send it */
dropit:
svc_authorise(rqstp); /* doesn't hurt to call this twice */
@@ -1175,12 +1156,6 @@ err_short_len:
goto dropit; /* drop request */
-err_bad_dir:
- svc_printk(rqstp, "bad direction %d, dropping request\n", dir);
-
- serv->sv_stats->rpcbadfmt++;
- goto dropit; /* drop request */
-
err_bad_rpc:
serv->sv_stats->rpcbadfmt++;
svc_putnl(resv, 1); /* REJECT */
@@ -1234,6 +1209,51 @@ err_bad:
EXPORT_SYMBOL(svc_process);
/*
+ * Process the RPC request.
+ */
+int
+svc_process(struct svc_rqst *rqstp)
+{
+ struct kvec *argv = &rqstp->rq_arg.head[0];
+ struct kvec *resv = &rqstp->rq_res.head[0];
+ struct svc_serv *serv = rqstp->rq_server;
+ u32 dir;
+ int error;
+
+ /*
+ * Setup response xdr_buf.
+ * Initially it has just one page
+ */
+ rqstp->rq_resused = 1;
+ resv->iov_base = page_address(rqstp->rq_respages[0]);
+ resv->iov_len = 0;
+ rqstp->rq_res.pages = rqstp->rq_respages + 1;
+ rqstp->rq_res.len = 0;
+ rqstp->rq_res.page_base = 0;
+ rqstp->rq_res.page_len = 0;
+ rqstp->rq_res.buflen = PAGE_SIZE;
+ rqstp->rq_res.tail[0].iov_base = NULL;
+ rqstp->rq_res.tail[0].iov_len = 0;
+
+ rqstp->rq_xid = svc_getu32(argv);
+
+ dir = svc_getnl(argv);
+ if (dir != 0) {
+ /* direction != CALL */
+ svc_printk(rqstp, "bad direction %d, dropping request\n", dir);
+ serv->sv_stats->rpcbadfmt++;
+ svc_drop(rqstp);
+ return 0;
+ }
+
+ error = svc_process_common(rqstp, argv, resv);
+ if (error <= 0)
+ return error;
+
+ return svc_send(rqstp);
+}
+
+/*
* Return (transport-specific) limit on the rpc payload.
*/
u32 svc_max_payload(const struct svc_rqst *rqstp)
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* Re: [pnfs] [RFC 64/85] nfs41: Refactor svc_process()
2008-11-10 20:29 ` [RFC 64/85] nfs41: Refactor svc_process() Benny Halevy
@ 2008-11-17 13:54 ` Benny Halevy
0 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-17 13:54 UTC (permalink / raw)
To: pnfs; +Cc: trond.myklebust, linux-nfs
On Nov. 10, 2008, 22:29 +0200, Benny Halevy <bhalevy@panasas.com> wrote:
> From: Ricardo Labiaga <ricardo.labiaga@netapp.com>
>
> net/sunrpc/svc.c:svc_process() is used by the NFSv4 callback service
> to process RPC requests arriving over connections initiated by the
> server. NFSv4.1 supports callbacks over the backchannel on connections
> initiated by the client. This patch refactors svc_process() so that
> common code can also be used by the backchannel.
>
> Signed-off-by: Ricardo Labiaga <ricardo.labiaga@netapp.com>
> Signed-off-by: Benny Halevy <bhalevy@panasas.com>
> ---
> fs/nfs/callback.c | 10 +++---
> net/sunrpc/svc.c | 80 +++++++++++++++++++++++++++++++++--------------------
> 2 files changed, 55 insertions(+), 35 deletions(-)
>
> diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
> index e792706..2f5acd3 100644
> --- a/fs/nfs/callback.c
> +++ b/fs/nfs/callback.c
> @@ -132,7 +132,7 @@ nfs4_callback_up(struct svc_serv *serv)
> int nfs_callback_up(u32 minorversion, void *args)
> {
> struct svc_serv *serv = NULL;
> - struct svc_rqst *rqstp;
> + struct svc_rqst *rqst;
> int (* callback_svc)(void *vrqstp);
> char svc_name[12];
> int ret = 0;
> @@ -150,20 +150,20 @@ int nfs_callback_up(u32 minorversion, void *args)
> /* FIXME: either 4.0 or 4.1 callback service can be up at a time
> * need to monitor and control them both */
> if (!minorversion) {
> - rqstp = nfs4_callback_up(serv);
> + rqst = nfs4_callback_up(serv);
> callback_svc = nfs4_callback_svc;
> } else {
> BUG(); /* for now */
> }
> - if (IS_ERR(rqstp)) {
> - ret = PTR_ERR(rqstp);
> + if (IS_ERR(rqst)) {
> + ret = PTR_ERR(rqst);
> goto out_err;
> }
>
> svc_sock_update_bufs(serv);
>
> sprintf(svc_name, "nfsv4.%u-svc", minorversion);
> - nfs_callback_info.rqst = rqstp;
> + nfs_callback_info.rqst = rqst;
> nfs_callback_info.task = kthread_run(callback_svc,
> nfs_callback_info.rqst,
> svc_name);
> diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
> index 54c98d8..e4efeeb 100644
> --- a/net/sunrpc/svc.c
> +++ b/net/sunrpc/svc.c
> @@ -985,20 +985,18 @@ svc_printk(struct svc_rqst *rqstp, const char *fmt, ...)
> }
>
> /*
> - * Process the RPC request.
> + * Common routine for processing the RPC request.
> */
> -int
> -svc_process(struct svc_rqst *rqstp)
> +static int
> +svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv)
review 11-14: we have a problem with authenticating here over gss.
to support gss we need to factor out (everything but authentication?)
we need to keep the header part and processing part.
> {
> struct svc_program *progp;
> struct svc_version *versp = NULL; /* compiler food */
> struct svc_procedure *procp = NULL;
> - struct kvec * argv = &rqstp->rq_arg.head[0];
> - struct kvec * resv = &rqstp->rq_res.head[0];
> struct svc_serv *serv = rqstp->rq_server;
> kxdrproc_t xdr;
> __be32 *statp;
> - u32 dir, prog, vers, proc;
> + u32 prog, vers, proc;
> __be32 auth_stat, rpc_stat;
> int auth_res;
> __be32 *reply_statp;
> @@ -1008,36 +1006,19 @@ svc_process(struct svc_rqst *rqstp)
> if (argv->iov_len < 6*4)
> goto err_short_len;
>
> - /* setup response xdr_buf.
> - * Initially it has just one page
> - */
> - rqstp->rq_resused = 1;
> - resv->iov_base = page_address(rqstp->rq_respages[0]);
> - resv->iov_len = 0;
> - rqstp->rq_res.pages = rqstp->rq_respages + 1;
> - rqstp->rq_res.len = 0;
> - rqstp->rq_res.page_base = 0;
> - rqstp->rq_res.page_len = 0;
> - rqstp->rq_res.buflen = PAGE_SIZE;
> - rqstp->rq_res.tail[0].iov_base = NULL;
> - rqstp->rq_res.tail[0].iov_len = 0;
> /* Will be turned off only in gss privacy case: */
> rqstp->rq_splice_ok = 1;
>
> /* Setup reply header */
> rqstp->rq_xprt->xpt_ops->xpo_prep_reply_hdr(rqstp);
>
> - rqstp->rq_xid = svc_getu32(argv);
> svc_putu32(resv, rqstp->rq_xid);
>
> - dir = svc_getnl(argv);
> vers = svc_getnl(argv);
>
> /* First words of reply: */
> svc_putnl(resv, 1); /* REPLY */
>
> - if (dir != 0) /* direction != CALL */
> - goto err_bad_dir;
> if (vers != 2) /* RPC version number */
> goto err_bad_rpc;
>
> @@ -1161,7 +1142,7 @@ svc_process(struct svc_rqst *rqstp)
> sendit:
> if (svc_authorise(rqstp))
> goto dropit;
> - return svc_send(rqstp);
> + return 1; /* Caller can now send it */
>
> dropit:
> svc_authorise(rqstp); /* doesn't hurt to call this twice */
> @@ -1175,12 +1156,6 @@ err_short_len:
>
> goto dropit; /* drop request */
>
> -err_bad_dir:
> - svc_printk(rqstp, "bad direction %d, dropping request\n", dir);
> -
> - serv->sv_stats->rpcbadfmt++;
> - goto dropit; /* drop request */
> -
> err_bad_rpc:
> serv->sv_stats->rpcbadfmt++;
> svc_putnl(resv, 1); /* REJECT */
> @@ -1234,6 +1209,51 @@ err_bad:
> EXPORT_SYMBOL(svc_process);
>
> /*
> + * Process the RPC request.
> + */
> +int
> +svc_process(struct svc_rqst *rqstp)
> +{
> + struct kvec *argv = &rqstp->rq_arg.head[0];
> + struct kvec *resv = &rqstp->rq_res.head[0];
> + struct svc_serv *serv = rqstp->rq_server;
> + u32 dir;
> + int error;
> +
> + /*
> + * Setup response xdr_buf.
> + * Initially it has just one page
> + */
> + rqstp->rq_resused = 1;
> + resv->iov_base = page_address(rqstp->rq_respages[0]);
> + resv->iov_len = 0;
> + rqstp->rq_res.pages = rqstp->rq_respages + 1;
> + rqstp->rq_res.len = 0;
> + rqstp->rq_res.page_base = 0;
> + rqstp->rq_res.page_len = 0;
> + rqstp->rq_res.buflen = PAGE_SIZE;
> + rqstp->rq_res.tail[0].iov_base = NULL;
> + rqstp->rq_res.tail[0].iov_len = 0;
> +
> + rqstp->rq_xid = svc_getu32(argv);
> +
> + dir = svc_getnl(argv);
> + if (dir != 0) {
> + /* direction != CALL */
> + svc_printk(rqstp, "bad direction %d, dropping request\n", dir);
> + serv->sv_stats->rpcbadfmt++;
> + svc_drop(rqstp);
> + return 0;
> + }
> +
> + error = svc_process_common(rqstp, argv, resv);
> + if (error <= 0)
> + return error;
> +
> + return svc_send(rqstp);
> +}
> +
> +/*
> * Return (transport-specific) limit on the rpc payload.
> */
> u32 svc_max_payload(const struct svc_rqst *rqstp)
^ permalink raw reply [flat|nested] 115+ messages in thread
* [RFC 65/85] nfs41: Backchannel bc_svc_process()
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (62 preceding siblings ...)
2008-11-10 20:29 ` [RFC 64/85] nfs41: Refactor svc_process() Benny Halevy
@ 2008-11-10 20:29 ` Benny Halevy
2008-11-17 13:55 ` [pnfs] " Benny Halevy
2008-11-10 20:30 ` [RFC 66/85] nfs41: Implement NFSv4.1 callback service process Benny Halevy
` (21 subsequent siblings)
85 siblings, 1 reply; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:29 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
From: Ricardo Labiaga <Ricardo.Labiaga@netapp.com>
Implement the NFSv4.1 backchannel service. Invokes the common callback
processing logic svc_process_common() to authenticate the call and
dispatch the appropriate NFSv4.1 XDR decoder and operation procedure.
It then invokes bc_send() to send the reply over the same connection.
bc_send() is implemented in a separate patch.
At this time there is no slot validation or reply cache handling.
Signed-off-by: Ricardo Labiaga <Ricardo.Labiaga@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
net/sunrpc/svc.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 49 insertions(+), 0 deletions(-)
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index e4efeeb..906b992 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -25,6 +25,7 @@
#include <linux/sunrpc/stats.h>
#include <linux/sunrpc/svcsock.h>
#include <linux/sunrpc/clnt.h>
+#include <linux/sunrpc/bc_xprt.h>
#define RPCDBG_FACILITY RPCDBG_SVCDSP
@@ -1253,6 +1254,54 @@ svc_process(struct svc_rqst *rqstp)
return svc_send(rqstp);
}
+#if defined(CONFIG_NFS_V4_1)
+/*
+ * Process a backchannel RPC request that arrived over an existing
+ * outbound connection
+ */
+int
+bc_svc_process(struct svc_serv *serv, struct rpc_rqst *req,
+ struct svc_rqst *rqstp)
+{
+ struct kvec *argv = &rqstp->rq_arg.head[0];
+ struct kvec *resv = &rqstp->rq_res.head[0];
+ int error;
+
+ /* Build the svc_rqst used by the common processing routine */
+ rqstp->rq_xid = req->rq_xid;
+ rqstp->rq_prot = req->rq_xprt->prot;
+ rqstp->rq_server = serv;
+
+ rqstp->rq_addrlen = sizeof(req->rq_xprt->addr);
+ memcpy(&rqstp->rq_addr, &req->rq_xprt->addr, rqstp->rq_addrlen);
+ memcpy(&rqstp->rq_arg, &req->rq_private_buf, sizeof(rqstp->rq_arg));
+ memcpy(&rqstp->rq_res, &req->rq_snd_buf, sizeof(rqstp->rq_res));
+
+ /* reset result send buffer "put" position */
+ resv->iov_len = 0;
+
+ if (rqstp->rq_prot != IPPROTO_TCP) {
+ printk(KERN_ERR "No support for Non-TCP transports!\n");
+ BUG();
+ }
+
+ /*
+ * Skip the next two words because they've already been
+ * processed in the trasport
+ */
+ svc_getu32(argv); /* XID */
+ svc_getnl(argv); /* CALLDIR */
+
+ error = svc_process_common(rqstp, argv, resv);
+ if (error <= 0)
+ return error;
+
+ memcpy(&req->rq_snd_buf, &rqstp->rq_res, sizeof(req->rq_snd_buf));
+ return bc_send(req);
+}
+EXPORT_SYMBOL(bc_svc_process);
+#endif /* CONFIG_NFS_V4_1 */
+
/*
* Return (transport-specific) limit on the rpc payload.
*/
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* Re: [pnfs] [RFC 65/85] nfs41: Backchannel bc_svc_process()
2008-11-10 20:29 ` [RFC 65/85] nfs41: Backchannel bc_svc_process() Benny Halevy
@ 2008-11-17 13:55 ` Benny Halevy
0 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-17 13:55 UTC (permalink / raw)
To: pnfs; +Cc: trond.myklebust, linux-nfs
On Nov. 10, 2008, 22:29 +0200, Benny Halevy <bhalevy@panasas.com> wrote:
> From: Ricardo Labiaga <Ricardo.Labiaga@netapp.com>
>
> Implement the NFSv4.1 backchannel service. Invokes the common callback
> processing logic svc_process_common() to authenticate the call and
> dispatch the appropriate NFSv4.1 XDR decoder and operation procedure.
> It then invokes bc_send() to send the reply over the same connection.
> bc_send() is implemented in a separate patch.
>
> At this time there is no slot validation or reply cache handling.
>
> Signed-off-by: Ricardo Labiaga <Ricardo.Labiaga@netapp.com>
> Signed-off-by: Benny Halevy <bhalevy@panasas.com>
> ---
> net/sunrpc/svc.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
> 1 files changed, 49 insertions(+), 0 deletions(-)
>
> diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
> index e4efeeb..906b992 100644
> --- a/net/sunrpc/svc.c
> +++ b/net/sunrpc/svc.c
> @@ -25,6 +25,7 @@
> #include <linux/sunrpc/stats.h>
> #include <linux/sunrpc/svcsock.h>
> #include <linux/sunrpc/clnt.h>
> +#include <linux/sunrpc/bc_xprt.h>
>
> #define RPCDBG_FACILITY RPCDBG_SVCDSP
>
> @@ -1253,6 +1254,54 @@ svc_process(struct svc_rqst *rqstp)
> return svc_send(rqstp);
> }
>
> +#if defined(CONFIG_NFS_V4_1)
> +/*
> + * Process a backchannel RPC request that arrived over an existing
> + * outbound connection
> + */
> +int
> +bc_svc_process(struct svc_serv *serv, struct rpc_rqst *req,
> + struct svc_rqst *rqstp)
> +{
> + struct kvec *argv = &rqstp->rq_arg.head[0];
> + struct kvec *resv = &rqstp->rq_res.head[0];
> + int error;
> +
> + /* Build the svc_rqst used by the common processing routine */
> + rqstp->rq_xid = req->rq_xid;
> + rqstp->rq_prot = req->rq_xprt->prot;
> + rqstp->rq_server = serv;
> +
> + rqstp->rq_addrlen = sizeof(req->rq_xprt->addr);
> + memcpy(&rqstp->rq_addr, &req->rq_xprt->addr, rqstp->rq_addrlen);
> + memcpy(&rqstp->rq_arg, &req->rq_private_buf, sizeof(rqstp->rq_arg));
> + memcpy(&rqstp->rq_res, &req->rq_snd_buf, sizeof(rqstp->rq_res));
> +
> + /* reset result send buffer "put" position */
> + resv->iov_len = 0;
> +
> + if (rqstp->rq_prot != IPPROTO_TCP) {
> + printk(KERN_ERR "No support for Non-TCP transports!\n");
> + BUG();
> + }
> +
> + /*
> + * Skip the next two words because they've already been
> + * processed in the trasport
> + */
> + svc_getu32(argv); /* XID */
> + svc_getnl(argv); /* CALLDIR */
> +
> + error = svc_process_common(rqstp, argv, resv);
> + if (error <= 0)
> + return error;
> +
> + memcpy(&req->rq_snd_buf, &rqstp->rq_res, sizeof(req->rq_snd_buf));
review 11-14: just copy the pointers, not data.
> + return bc_send(req);
> +}
> +EXPORT_SYMBOL(bc_svc_process);
> +#endif /* CONFIG_NFS_V4_1 */
> +
> /*
> * Return (transport-specific) limit on the rpc payload.
> */
^ permalink raw reply [flat|nested] 115+ messages in thread
* [RFC 66/85] nfs41: Implement NFSv4.1 callback service process.
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (63 preceding siblings ...)
2008-11-10 20:29 ` [RFC 65/85] nfs41: Backchannel bc_svc_process() Benny Halevy
@ 2008-11-10 20:30 ` Benny Halevy
2008-11-10 20:30 ` [RFC 67/85] nfs41: sunrpc: provide functions to create and destroy a svc_xprt for backchannel use Benny Halevy
` (20 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:30 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
From: Ricardo Labiaga <Ricardo.Labiaga@netapp.com>
nfs41_callback_up() initializes the necessary queues and creates the new
nfs41_callback_svc thread. This thread executes the callback service which
waits for requests to arrive on the svc_serv->sv_cb_list.
NFS41_BC_MIN_CALLBACKS is set to 1 because we expect callbacks to not
cause substantial latency.
The actual processing of the callback will be implemented as a separate patch.
Signed-off-by: Ricardo Labiaga <Ricardo.Labiaga@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/callback.c | 76 +++++++++++++++++++++++++++++++++++++++++++-
fs/nfs/callback.h | 8 +++++
include/linux/sunrpc/svc.h | 2 +
3 files changed, 85 insertions(+), 1 deletions(-)
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index 2f5acd3..86f4d88 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -16,6 +16,9 @@
#include <linux/mutex.h>
#include <linux/freezer.h>
#include <linux/kthread.h>
+#if defined(CONFIG_NFS_V4_1)
+#include <linux/sunrpc/bc_xprt.h>
+#endif
#include <net/inet_sock.h>
@@ -126,6 +129,69 @@ nfs4_callback_up(struct svc_serv *serv)
return svc_prepare_thread(serv, &serv->sv_pools[0]);
}
+#if defined(CONFIG_NFS_V4_1)
+/*
+ * The callback service for NFSv4.1 callbacks
+ */
+static int
+nfs41_callback_svc(void *vrqstp)
+{
+ struct svc_rqst *rqstp = vrqstp;
+ struct svc_serv *serv = rqstp->rq_server;
+ struct rpc_rqst *req;
+ int error;
+ DEFINE_WAIT(wq);
+
+ set_freezable();
+
+ /*
+ * FIXME: do we really need to run this under the BKL? If so, please
+ * add a comment about what it's intended to protect.
+ */
+ lock_kernel();
+ while (!kthread_should_stop()) {
+ prepare_to_wait(&serv->sv_cb_waitq, &wq, TASK_INTERRUPTIBLE);
+ spin_lock_bh(&serv->sv_cb_lock);
+ if (!list_empty(&serv->sv_cb_list)) {
+ req = list_first_entry(&serv->sv_cb_list,
+ struct rpc_rqst, rq_bc_list);
+ list_del(&req->rq_bc_list);
+ spin_unlock_bh(&serv->sv_cb_lock);
+ dprintk("Invoking bc_svc_process()\n");
+ error = bc_svc_process(serv, req, rqstp);
+ dprintk("bc_svc_process() returned w/ error code= %d\n",
+ error);
+ } else {
+ spin_unlock_bh(&serv->sv_cb_lock);
+ schedule();
+ }
+ finish_wait(&serv->sv_cb_waitq, &wq);
+ }
+ unlock_kernel();
+ nfs_callback_info.task = NULL;
+ svc_exit_thread(rqstp);
+ return 0;
+}
+
+/*
+ * Bring up the NFSv4.1 callback service
+ */
+struct svc_rqst *
+nfs41_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt)
+{
+ /*
+ * Save the svc_serv in the transport so that it can
+ * be referenced when the session backchannel is initialized
+ */
+ xprt->bc_serv = serv;
+
+ INIT_LIST_HEAD(&serv->sv_cb_list);
+ spin_lock_init(&serv->sv_cb_lock);
+ init_waitqueue_head(&serv->sv_cb_waitq);
+ return svc_prepare_thread(serv, &serv->sv_pools[0]);
+}
+#endif /* CONFIG_NFS_V4_1 */
+
/*
* Bring up the callback thread if it is not already up.
*/
@@ -136,6 +202,9 @@ int nfs_callback_up(u32 minorversion, void *args)
int (* callback_svc)(void *vrqstp);
char svc_name[12];
int ret = 0;
+#if defined(CONFIG_NFS_V4_1)
+ struct rpc_xprt *xprt = (struct rpc_xprt *)args;
+#endif /* CONFIG_NFS_V4_1 */
mutex_lock(&nfs_callback_mutex);
if (nfs_callback_info.users++ || nfs_callback_info.task != NULL)
@@ -153,7 +222,12 @@ int nfs_callback_up(u32 minorversion, void *args)
rqst = nfs4_callback_up(serv);
callback_svc = nfs4_callback_svc;
} else {
- BUG(); /* for now */
+#if defined(CONFIG_NFS_V4_1)
+ rqst = nfs41_callback_up(serv, xprt);
+ callback_svc = nfs41_callback_svc;
+#else /* CONFIG_NFS_V4_1 */
+ BUG();
+#endif /* CONFIG_NFS_V4_1 */
}
if (IS_ERR(rqst)) {
ret = PTR_ERR(rqst);
diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h
index a2b3ce4..49ea368 100644
--- a/fs/nfs/callback.h
+++ b/fs/nfs/callback.h
@@ -70,6 +70,14 @@ extern void nfs_callback_down(void);
#define nfs_callback_down() do {} while(0)
#endif
+#ifdef CONFIG_NFS_V4_1
+/*
+ * Callbacks are expected to not cause substantial latency,
+ * so we limit their concurrency to 1.
+ */
+#define NFS41_BC_MIN_CALLBACKS 1
+#endif /* CONFIG_NFS_V4_1 */
+
extern unsigned int nfs_callback_set_tcpport;
extern unsigned short nfs_callback_tcpport;
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index 1d3b971..1bb51dc 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -403,6 +403,8 @@ struct svc_serv * svc_create_pooled(struct svc_program *, unsigned int,
int svc_set_num_threads(struct svc_serv *, struct svc_pool *, int);
void svc_destroy(struct svc_serv *);
int svc_process(struct svc_rqst *);
+int bc_svc_process(struct svc_serv *, struct rpc_rqst *,
+ struct svc_rqst *);
int svc_register(const struct svc_serv *, const unsigned short,
const unsigned short);
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 67/85] nfs41: sunrpc: provide functions to create and destroy a svc_xprt for backchannel use
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (64 preceding siblings ...)
2008-11-10 20:30 ` [RFC 66/85] nfs41: Implement NFSv4.1 callback service process Benny Halevy
@ 2008-11-10 20:30 ` Benny Halevy
2008-11-10 20:30 ` [RFC 68/85] nfs41: sunrpc: add a struct svc_xprt pointer to struct svc_serv " Benny Halevy
` (19 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:30 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
For nfs41 callbacks we need an svc_xprt to process requests coming up the
backchannel socket as rpc_rqst's that are transformed into svc_rqst's that
need a rq_xprt to be processed.
The svc_{udp,tcp}_create methods are too heavy for this job as svc_create_socket
creates an actual socket to listen on while for nfs41 we're "reusing" the
fore channel's socket.
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
include/linux/sunrpc/svcsock.h | 2 ++
net/sunrpc/svcsock.c | 39 +++++++++++++++++++++++++++++++++++++++
2 files changed, 41 insertions(+), 0 deletions(-)
diff --git a/include/linux/sunrpc/svcsock.h b/include/linux/sunrpc/svcsock.h
index 483e103..6bb1ec4 100644
--- a/include/linux/sunrpc/svcsock.h
+++ b/include/linux/sunrpc/svcsock.h
@@ -42,6 +42,8 @@ int svc_sock_names(char *buf, struct svc_serv *serv, char *toclose);
int svc_addsock(struct svc_serv *serv, int fd, char *name_return);
void svc_init_xprt_sock(void);
void svc_cleanup_xprt_sock(void);
+struct svc_xprt *svc_sock_create(struct svc_serv *serv, int prot);
+void svc_sock_destroy(struct svc_xprt *);
/*
* svc_makesock socket characteristics
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 95293f5..c2b6fa4 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -1298,3 +1298,42 @@ static void svc_sock_free(struct svc_xprt *xprt)
sock_release(svsk->sk_sock);
kfree(svsk);
}
+
+/*
+ * Create a svc_xprt.
+ *
+ * For internal use only (e.g. nfsv4.1 backchannel).
+ * Callers should typically use the xpo_create() method.
+ */
+struct svc_xprt *svc_sock_create(struct svc_serv *serv, int prot)
+{
+ struct svc_sock *svsk;
+ struct svc_xprt *xprt = NULL;
+
+ dprintk("svc: %s\n", __func__);
+ svsk = kzalloc(sizeof(*svsk), GFP_KERNEL);
+ if (!svsk)
+ goto out;
+
+ xprt = &svsk->sk_xprt;
+ if (prot == IPPROTO_TCP)
+ svc_xprt_init(&svc_tcp_class, xprt, serv);
+ else if (prot == IPPROTO_UDP)
+ svc_xprt_init(&svc_udp_class, xprt, serv);
+ else
+ BUG();
+out:
+ dprintk("svc: %s return %p\n", __func__, xprt);
+ return xprt;
+}
+EXPORT_SYMBOL_GPL(svc_sock_create);
+
+/*
+ * Destroy a svc_sock.
+ */
+void svc_sock_destroy(struct svc_xprt *xprt)
+{
+ if (xprt)
+ kfree(container_of(xprt, struct svc_sock, sk_xprt));
+}
+EXPORT_SYMBOL_GPL(svc_sock_destroy);
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 68/85] nfs41: sunrpc: add a struct svc_xprt pointer to struct svc_serv for backchannel use
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (65 preceding siblings ...)
2008-11-10 20:30 ` [RFC 67/85] nfs41: sunrpc: provide functions to create and destroy a svc_xprt for backchannel use Benny Halevy
@ 2008-11-10 20:30 ` Benny Halevy
2008-11-10 20:30 ` [RFC 69/85] nfs41: create a svc_xprt for nfs41 callback thread and use for incoming callbacks Benny Halevy
` (18 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:30 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
This svc_xprt is passed on to the callback service thread to be later used
to processes incoming svc_rqst's
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
include/linux/sunrpc/svc.h | 1 +
net/sunrpc/svc.c | 4 ++++
2 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index 1bb51dc..7653dd3 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -90,6 +90,7 @@ struct svc_serv {
wait_queue_head_t sv_cb_waitq; /* sleep here if there are no
* entries in the svc_cb_list
*/
+ struct svc_xprt *bc_xprt;
#endif /* CONFIG_NFS_V4_1 */
};
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index 906b992..b84ae54 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -489,6 +489,10 @@ svc_destroy(struct svc_serv *serv)
if (svc_serv_is_pooled(serv))
svc_pool_map_put();
+#if defined(CONFIG_NFS_V4_1)
+ svc_sock_destroy(serv->bc_xprt);
+#endif /* CONFIG_NFS_V4_1 */
+
svc_unregister(serv);
kfree(serv->sv_pools);
kfree(serv);
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 69/85] nfs41: create a svc_xprt for nfs41 callback thread and use for incoming callbacks
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (66 preceding siblings ...)
2008-11-10 20:30 ` [RFC 68/85] nfs41: sunrpc: add a struct svc_xprt pointer to struct svc_serv " Benny Halevy
@ 2008-11-10 20:30 ` Benny Halevy
2008-11-10 20:30 ` [RFC 70/85] nfs41: save svc_serv in nfs_callback_info Benny Halevy
` (17 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:30 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/callback.c | 17 ++++++++++++++++-
net/sunrpc/svc.c | 1 +
2 files changed, 17 insertions(+), 1 deletions(-)
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index 86f4d88..fc30f87 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -179,16 +179,31 @@ nfs41_callback_svc(void *vrqstp)
struct svc_rqst *
nfs41_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt)
{
+ struct svc_xprt *bc_xprt;
+ struct svc_rqst *rqstp = ERR_PTR(-ENOMEM);
+
+ dprintk("--> %s\n", __func__);
+ /* Create a svc_sock for the service */
+ bc_xprt = svc_sock_create(serv, xprt->prot);
+ if (!bc_xprt)
+ goto out;
+
/*
* Save the svc_serv in the transport so that it can
* be referenced when the session backchannel is initialized
*/
+ serv->bc_xprt = bc_xprt;
xprt->bc_serv = serv;
INIT_LIST_HEAD(&serv->sv_cb_list);
spin_lock_init(&serv->sv_cb_lock);
init_waitqueue_head(&serv->sv_cb_waitq);
- return svc_prepare_thread(serv, &serv->sv_pools[0]);
+ rqstp = svc_prepare_thread(serv, &serv->sv_pools[0]);
+ if (IS_ERR(rqstp))
+ svc_sock_destroy(bc_xprt);
+out:
+ dprintk("--> %s return %p\n", __func__, rqstp);
+ return rqstp;
}
#endif /* CONFIG_NFS_V4_1 */
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index b84ae54..1b95de7 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -1272,6 +1272,7 @@ bc_svc_process(struct svc_serv *serv, struct rpc_rqst *req,
int error;
/* Build the svc_rqst used by the common processing routine */
+ rqstp->rq_xprt = serv->bc_xprt;
rqstp->rq_xid = req->rq_xid;
rqstp->rq_prot = req->rq_xprt->prot;
rqstp->rq_server = serv;
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 70/85] nfs41: save svc_serv in nfs_callback_info
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (67 preceding siblings ...)
2008-11-10 20:30 ` [RFC 69/85] nfs41: create a svc_xprt for nfs41 callback thread and use for incoming callbacks Benny Halevy
@ 2008-11-10 20:30 ` Benny Halevy
2008-11-10 20:30 ` [RFC 71/85] nfs41: Add a reference to svc_serv during callback service bring up Benny Halevy
` (16 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:30 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
We need to pass the svc_serv* to the xprt when nfs_callback_info.users > 0
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/callback.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index fc30f87..be8ac50 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -30,6 +30,7 @@
struct nfs_callback_data {
unsigned int users;
+ struct svc_serv *serv;
struct svc_rqst *rqst;
struct task_struct *task;
};
@@ -252,6 +253,7 @@ int nfs_callback_up(u32 minorversion, void *args)
svc_sock_update_bufs(serv);
sprintf(svc_name, "nfsv4.%u-svc", minorversion);
+ nfs_callback_info.serv = serv;
nfs_callback_info.rqst = rqst;
nfs_callback_info.task = kthread_run(callback_svc,
nfs_callback_info.rqst,
@@ -259,6 +261,7 @@ int nfs_callback_up(u32 minorversion, void *args)
if (IS_ERR(nfs_callback_info.task)) {
ret = PTR_ERR(nfs_callback_info.task);
svc_exit_thread(nfs_callback_info.rqst);
+ nfs_callback_info.serv = NULL;
nfs_callback_info.rqst = NULL;
nfs_callback_info.task = NULL;
goto out_err;
@@ -291,6 +294,7 @@ void nfs_callback_down(void)
if (nfs_callback_info.users == 0 && nfs_callback_info.task != NULL) {
kthread_stop(nfs_callback_info.task);
svc_exit_thread(nfs_callback_info.rqst);
+ nfs_callback_info.serv = NULL;
nfs_callback_info.rqst = NULL;
nfs_callback_info.task = NULL;
}
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 71/85] nfs41: Add a reference to svc_serv during callback service bring up
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (68 preceding siblings ...)
2008-11-10 20:30 ` [RFC 70/85] nfs41: save svc_serv in nfs_callback_info Benny Halevy
@ 2008-11-10 20:30 ` Benny Halevy
2008-11-10 20:31 ` [RFC 72/85] nfs41: Allow NFSv4 and NFSv4.1 callback services to coexist Benny Halevy
` (15 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:30 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
From: Ricardo Labiaga <Ricardo.Labiaga@netapp.com>
There is only one NFSv4.1 callback service. The first caller of
nfs4_callback_up() creates the service, subsequent callers increment a
reference count on the service. The service is destroyed when the last
caller invokes nfs_callback_down().
The transport needs to hold a reference to the callback service in order
to invoke it during callback processing. Currently this reference is only
obtained when the service is first created. This is incorrect, since
subsequent registrations for other transports will leave the xprt->serv
pointer uninitialized, leading to an oops when a callback arrives on
the "unreferenced" transport.
This patch fixes the problem by ensuring that a reference to the service
is saved in xprt->serv, either because the service is created by this
invocation to nfs4_callback_up() or by a prior invocation.
Signed-off-by: Ricardo Labiaga <Ricardo.Labiaga@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/callback.c | 7 ++++++-
1 files changed, 6 insertions(+), 1 deletions(-)
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index be8ac50..036d66a 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -223,8 +223,13 @@ int nfs_callback_up(u32 minorversion, void *args)
#endif /* CONFIG_NFS_V4_1 */
mutex_lock(&nfs_callback_mutex);
- if (nfs_callback_info.users++ || nfs_callback_info.task != NULL)
+ if (nfs_callback_info.users++ || nfs_callback_info.task != NULL) {
+#if defined(CONFIG_NFS_V4_1)
+ if (minorversion)
+ xprt->bc_serv = nfs_callback_info.serv;
+#endif /* CONFIG_NFS_V4_1 */
goto out;
+ }
serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE,
nfs_callback_family, NULL);
if (!serv) {
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 72/85] nfs41: Allow NFSv4 and NFSv4.1 callback services to coexist
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (69 preceding siblings ...)
2008-11-10 20:30 ` [RFC 71/85] nfs41: Add a reference to svc_serv during callback service bring up Benny Halevy
@ 2008-11-10 20:31 ` Benny Halevy
2008-11-10 20:31 ` [RFC 73/85] nfs41: Setup the backchannel Benny Halevy
` (14 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:31 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
From: Ricardo Labiaga <ricardo.labiaga@netapp.com>
Tracks the nfs_callback_info for both versions, enabling the callback
service for v4 and v4.1 to run concurrently and be stopped independently
of each other.
Signed-off-by: Ricardo Labiaga <ricardo.labiaga@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/callback.c | 50 ++++++++++++++++++++++++--------------------------
fs/nfs/callback.h | 7 ++-----
fs/nfs/client.c | 4 +++-
3 files changed, 29 insertions(+), 32 deletions(-)
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index 036d66a..ff9ce3e 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -35,7 +35,7 @@ struct nfs_callback_data {
struct task_struct *task;
};
-static struct nfs_callback_data nfs_callback_info;
+static struct nfs_callback_data nfs_callback_info[NFS4_MAX_MINOR_VERSION + 1];
static DEFINE_MUTEX(nfs_callback_mutex);
static struct svc_program nfs4_callback_program;
@@ -68,7 +68,7 @@ module_param_call(callback_tcpport, param_set_port, param_get_int,
&nfs_callback_set_tcpport, 0644);
/*
- * This is the callback kernel thread.
+ * This is the NFSv4 callback kernel thread.
*/
static int
nfs4_callback_svc(void *vrqstp)
@@ -169,8 +169,6 @@ nfs41_callback_svc(void *vrqstp)
finish_wait(&serv->sv_cb_waitq, &wq);
}
unlock_kernel();
- nfs_callback_info.task = NULL;
- svc_exit_thread(rqstp);
return 0;
}
@@ -216,6 +214,7 @@ int nfs_callback_up(u32 minorversion, void *args)
struct svc_serv *serv = NULL;
struct svc_rqst *rqst;
int (* callback_svc)(void *vrqstp);
+ struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion];
char svc_name[12];
int ret = 0;
#if defined(CONFIG_NFS_V4_1)
@@ -223,10 +222,10 @@ int nfs_callback_up(u32 minorversion, void *args)
#endif /* CONFIG_NFS_V4_1 */
mutex_lock(&nfs_callback_mutex);
- if (nfs_callback_info.users++ || nfs_callback_info.task != NULL) {
+ if (cb_info->users++ || cb_info->task != NULL) {
#if defined(CONFIG_NFS_V4_1)
if (minorversion)
- xprt->bc_serv = nfs_callback_info.serv;
+ xprt->bc_serv = cb_info->serv;
#endif /* CONFIG_NFS_V4_1 */
goto out;
}
@@ -258,17 +257,14 @@ int nfs_callback_up(u32 minorversion, void *args)
svc_sock_update_bufs(serv);
sprintf(svc_name, "nfsv4.%u-svc", minorversion);
- nfs_callback_info.serv = serv;
- nfs_callback_info.rqst = rqst;
- nfs_callback_info.task = kthread_run(callback_svc,
- nfs_callback_info.rqst,
- svc_name);
- if (IS_ERR(nfs_callback_info.task)) {
- ret = PTR_ERR(nfs_callback_info.task);
- svc_exit_thread(nfs_callback_info.rqst);
- nfs_callback_info.serv = NULL;
- nfs_callback_info.rqst = NULL;
- nfs_callback_info.task = NULL;
+ cb_info->serv = serv;
+ cb_info->rqst = rqst;
+ cb_info->task = kthread_run(callback_svc, cb_info->rqst, svc_name);
+ if (IS_ERR(cb_info->task)) {
+ ret = PTR_ERR(cb_info->task);
+ svc_exit_thread(cb_info->rqst);
+ cb_info->rqst = NULL;
+ cb_info->task = NULL;
goto out_err;
}
out:
@@ -285,23 +281,25 @@ out:
out_err:
dprintk("NFS: Couldn't create callback socket or server thread; "
"err = %d\n", ret);
- nfs_callback_info.users--;
+ cb_info->users--;
goto out;
}
/*
* Kill the callback thread if it's no longer being used.
*/
-void nfs_callback_down(void)
+void nfs_callback_down(int minorversion)
{
+ struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion];
+
mutex_lock(&nfs_callback_mutex);
- nfs_callback_info.users--;
- if (nfs_callback_info.users == 0 && nfs_callback_info.task != NULL) {
- kthread_stop(nfs_callback_info.task);
- svc_exit_thread(nfs_callback_info.rqst);
- nfs_callback_info.serv = NULL;
- nfs_callback_info.rqst = NULL;
- nfs_callback_info.task = NULL;
+ cb_info->users--;
+ if (cb_info->users == 0 && cb_info->task != NULL) {
+ kthread_stop(cb_info->task);
+ svc_exit_thread(cb_info->rqst);
+ cb_info->serv = NULL;
+ cb_info->rqst = NULL;
+ cb_info->task = NULL;
}
mutex_unlock(&nfs_callback_mutex);
}
diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h
index 49ea368..4c69b27 100644
--- a/fs/nfs/callback.h
+++ b/fs/nfs/callback.h
@@ -64,11 +64,8 @@ extern __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy);
#ifdef CONFIG_NFS_V4
extern int nfs_callback_up(u32 minorversion, void *args);
-extern void nfs_callback_down(void);
-#else
-#define nfs_callback_up() (0)
-#define nfs_callback_down() do {} while(0)
-#endif
+extern void nfs_callback_down(int minorversion);
+#endif /* CONFIG_NFS_V4 */
#ifdef CONFIG_NFS_V4_1
/*
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 1c0cae9..dc5b6e7 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -193,8 +193,10 @@ static void nfs_free_client(struct nfs_client *clp)
if (!IS_ERR(clp->cl_rpcclient))
rpc_shutdown_client(clp->cl_rpcclient);
+#ifdef CONFIG_NFS_V4
if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state))
- nfs_callback_down();
+ nfs_callback_down(clp->cl_minorversion);
+#endif /* CONFIG_NFS_V4 */
if (clp->cl_machine_cred != NULL)
put_rpccred(clp->cl_machine_cred);
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 73/85] nfs41: Setup the backchannel
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (70 preceding siblings ...)
2008-11-10 20:31 ` [RFC 72/85] nfs41: Allow NFSv4 and NFSv4.1 callback services to coexist Benny Halevy
@ 2008-11-10 20:31 ` Benny Halevy
2008-11-10 20:31 ` [RFC 74/85] nfs41: Client indicates presence of NFSv4.1 callback channel Benny Halevy
` (13 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:31 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
From: Ricardo Labiaga <ricardo.labiaga@netapp.com>
The NFS v4.1 callback service has already been setup, and
rpc_xprt->serv points to the svc_serv structure describing it.
Invoke the xprt_setup_backchannel() initialization to pre-
allocate the necessary backchannel structures.
Signed-off-by: Ricardo Labiaga <ricardo.labiaga@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/client.c | 9 ++++++++-
1 files changed, 8 insertions(+), 1 deletions(-)
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index dc5b6e7..2a24d43 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -39,6 +39,7 @@
#include <linux/nfs_xdr.h>
#if defined(CONFIG_NFS_V4_1)
#include <linux/nfs41_session_recovery.h>
+#include <linux/sunrpc/bc_xprt.h>
#endif /* CONFIG_NFS_V4_1 */
#include <asm/system.h>
@@ -1125,7 +1126,7 @@ error:
}
/*
- * Allocate and initialize a session if required
+ * Allocate and initialize a session if required, including its backchannel.
*/
int nfs4_init_session(struct nfs_client *clp, struct rpc_clnt *clnt)
{
@@ -1145,6 +1146,12 @@ int nfs4_init_session(struct nfs_client *clp, struct rpc_clnt *clnt)
else {
session->clnt = clnt;
session->clp = clp;
+
+ error = xprt_setup_backchannel(clnt->cl_xprt,
+ NFS41_BC_MIN_CALLBACKS);
+ if (error < 0)
+ /* nfs4_put session sets the session to NULL */
+ nfs4_put_session(&session);
}
clp->cl_session = session;
}
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 74/85] nfs41: Client indicates presence of NFSv4.1 callback channel.
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (71 preceding siblings ...)
2008-11-10 20:31 ` [RFC 73/85] nfs41: Setup the backchannel Benny Halevy
@ 2008-11-10 20:31 ` Benny Halevy
2008-11-10 20:31 ` [RFC 75/85] nfs41: Get the rpc_xprt * from the rpc_rqst instead of the rpc_clnt Benny Halevy
` (12 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:31 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
From: Ricardo Labiaga <ricardo.labiaga@netapp.com>
Set the SESSION4_BACK_CHAN flag to indicate the client supports a backchannel.
Signed-off-by: Ricardo Labiaga <ricardo.labiaga@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/nfs4proc.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 28c3cf8..f6a9894 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -4679,7 +4679,7 @@ static int _nfs4_proc_create_session(struct nfs4_session *session)
int status;
nfs4_init_channel_attrs(clp, &args.fc_attrs, &args.bc_attrs);
- args.flags = (SESSION4_PERSIST);
+ args.flags = (SESSION4_PERSIST | SESSION4_BACK_CHAN);
status = rpc_call_sync(session->clnt, &msg, 0);
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 75/85] nfs41: Get the rpc_xprt * from the rpc_rqst instead of the rpc_clnt.
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (72 preceding siblings ...)
2008-11-10 20:31 ` [RFC 74/85] nfs41: Client indicates presence of NFSv4.1 callback channel Benny Halevy
@ 2008-11-10 20:31 ` Benny Halevy
2008-11-10 20:31 ` [RFC 76/85] nfs41: Release backchannel resources associated with session Benny Halevy
` (11 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:31 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
From: Rahul Iyer <iyer@netapp.com>
Obtain the rpc_xprt from the rpc_rqst so that calls and callback replies
can both use the same code path. A client needs the rpc_xprt in order
to reply to a callback.
Signed-off-by: Rahul Iyer <iyer@netapp.com>
Signed-off-by: Ricardo Labiaga <ricardo.labiaga@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
net/sunrpc/xprt.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index cc1e5f2..e71f1be 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -164,8 +164,8 @@ EXPORT_SYMBOL_GPL(xprt_unregister_transport);
*/
int xprt_reserve_xprt(struct rpc_task *task)
{
- struct rpc_xprt *xprt = task->tk_xprt;
struct rpc_rqst *req = task->tk_rqstp;
+ struct rpc_xprt *xprt = req->rq_xprt;
if (test_and_set_bit(XPRT_LOCKED, &xprt->state)) {
if (task == xprt->snd_task)
@@ -837,7 +837,7 @@ out_unlock:
void xprt_end_transmit(struct rpc_task *task)
{
- xprt_release_write(task->tk_xprt, task);
+ xprt_release_write(task->tk_rqstp->rq_xprt, task);
}
/**
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 76/85] nfs41: Release backchannel resources associated with session
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (73 preceding siblings ...)
2008-11-10 20:31 ` [RFC 75/85] nfs41: Get the rpc_xprt * from the rpc_rqst instead of the rpc_clnt Benny Halevy
@ 2008-11-10 20:31 ` Benny Halevy
2008-11-10 20:31 ` [RFC 77/85] nfs41: store minorversion in cb_compound_hdr_arg Benny Halevy
` (10 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:31 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
From: Ricardo Labiaga <ricardo.labiaga@netapp.com>
Frees the preallocated backchannel resources that are associated with
this session when the session is destroyed.
A backchannel is currently created once per session. Destroy the backchannel
only when the session is destroyed.
Signed-off-by: Ricardo Labiaga <ricardo.labiaga@netapp.com>
Signed-off-by: Andy Adamson<andros@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/nfs4proc.c | 6 ++++++
fs/nfs/super.c | 1 -
2 files changed, 6 insertions(+), 1 deletions(-)
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index f6a9894..b57ff19 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -57,6 +57,7 @@
#if defined(CONFIG_NFS_V4_1)
#include "callback.h"
#include <linux/nfs41_session_recovery.h>
+#include <linux/sunrpc/bc_xprt.h>
#endif /* CONFIG_NFS_V4_1 */
#define NFSDBG_FACILITY NFSDBG_PROC
@@ -4588,6 +4589,11 @@ void nfs4_put_session(struct nfs4_session **session)
{
dprintk("--> nfs4_put_session()\n");
if (atomic_dec_and_test(&((*session)->ref_count))) {
+ nfs4_proc_destroy_session(*session);
+ dprintk("%s Destroy backchannel for xprt%p\n",
+ __func__, (*session)->clnt->cl_xprt);
+ xprt_destroy_backchannel((*session)->clnt->cl_xprt,
+ NFS41_BC_MIN_CALLBACKS);
nfs4_destroy_slot_table(&((*session)->fore_channel));
nfs4_free_session(*session);
*session = NULL;
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index d7f99f8..e005889 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -2434,7 +2434,6 @@ static void nfs4_kill_super(struct super_block *sb)
dprintk("--> %s\n", __func__);
nfs_return_all_delegations(sb);
kill_anon_super(sb);
-
nfs4_renewd_prepare_shutdown(server);
nfs_free_server(server);
dprintk("<-- %s\n", __func__);
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 77/85] nfs41: store minorversion in cb_compound_hdr_arg
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (74 preceding siblings ...)
2008-11-10 20:31 ` [RFC 76/85] nfs41: Release backchannel resources associated with session Benny Halevy
@ 2008-11-10 20:31 ` Benny Halevy
2008-11-10 20:32 ` [RFC 78/85] nfs41: decode minorversion 1 cb_compound header Benny Halevy
` (9 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:31 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/callback.h | 1 +
fs/nfs/callback_xdr.c | 12 +++++++-----
2 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h
index 4c69b27..e5ce040 100644
--- a/fs/nfs/callback.h
+++ b/fs/nfs/callback.h
@@ -26,6 +26,7 @@ enum nfs4_callback_opnum {
struct cb_compound_hdr_arg {
unsigned int taglen;
const char *tag;
+ unsigned int minorversion;
unsigned int callback_ident;
unsigned nops;
};
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
index dd0ef34..91f6f74 100644
--- a/fs/nfs/callback_xdr.c
+++ b/fs/nfs/callback_xdr.c
@@ -132,7 +132,6 @@ static __be32 decode_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid)
static __be32 decode_compound_hdr_arg(struct xdr_stream *xdr, struct cb_compound_hdr_arg *hdr)
{
__be32 *p;
- unsigned int minor_version;
__be32 status;
status = decode_string(xdr, &hdr->taglen, &hdr->tag);
@@ -147,15 +146,18 @@ static __be32 decode_compound_hdr_arg(struct xdr_stream *xdr, struct cb_compound
p = read_buf(xdr, 12);
if (unlikely(p == NULL))
return htonl(NFS4ERR_RESOURCE);
- minor_version = ntohl(*p++);
+ hdr->minorversion = ntohl(*p++);
/* Check minor version is zero. */
- if (minor_version != 0) {
- printk(KERN_WARNING "%s: NFSv4 server callback with illegal minor version %u!\n",
- __func__, minor_version);
+ if (hdr->minorversion != 0) {
+ printk(KERN_WARNING "%s: NFSv4 server callback with "
+ "illegal minor version %u!\n",
+ __func__, hdr->minorversion);
return htonl(NFS4ERR_MINOR_VERS_MISMATCH);
}
hdr->callback_ident = ntohl(*p++);
hdr->nops = ntohl(*p);
+ dprintk("%s: minorversion %d nops %d\n", __func__,
+ hdr->minorversion, hdr->nops);
return 0;
}
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 78/85] nfs41: decode minorversion 1 cb_compound header
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (75 preceding siblings ...)
2008-11-10 20:31 ` [RFC 77/85] nfs41: store minorversion in cb_compound_hdr_arg Benny Halevy
@ 2008-11-10 20:32 ` Benny Halevy
2008-11-10 20:32 ` [RFC 79/85] nfs41: callback numbers definitions Benny Halevy
` (8 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:32 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
decode cb_compound header conforming to
http://tools.ietf.org/html/draft-ietf-nfsv4-minorversion1-26
Get rid of cb_compound_hdr_arg.callback_ident
callback_ident is not used anywhere so we shouldn't waste any memory to
store it.
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/callback.h | 1 -
fs/nfs/callback_xdr.c | 12 ++++++++----
2 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h
index e5ce040..f8325da 100644
--- a/fs/nfs/callback.h
+++ b/fs/nfs/callback.h
@@ -27,7 +27,6 @@ struct cb_compound_hdr_arg {
unsigned int taglen;
const char *tag;
unsigned int minorversion;
- unsigned int callback_ident;
unsigned nops;
};
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
index 91f6f74..e141a7e 100644
--- a/fs/nfs/callback_xdr.c
+++ b/fs/nfs/callback_xdr.c
@@ -143,18 +143,22 @@ static __be32 decode_compound_hdr_arg(struct xdr_stream *xdr, struct cb_compound
__func__, hdr->taglen);
return htonl(NFS4ERR_RESOURCE);
}
- p = read_buf(xdr, 12);
+ p = read_buf(xdr, 4);
if (unlikely(p == NULL))
return htonl(NFS4ERR_RESOURCE);
hdr->minorversion = ntohl(*p++);
- /* Check minor version is zero. */
- if (hdr->minorversion != 0) {
+ /* Check minor version is zero or one. */
+ if (hdr->minorversion <= 1) {
+ p = read_buf(xdr, 8);
+ if (unlikely(p == NULL))
+ return htonl(NFS4ERR_RESOURCE);
+ p++; /* skip callback_ident */
+ } else {
printk(KERN_WARNING "%s: NFSv4 server callback with "
"illegal minor version %u!\n",
__func__, hdr->minorversion);
return htonl(NFS4ERR_MINOR_VERS_MISMATCH);
}
- hdr->callback_ident = ntohl(*p++);
hdr->nops = ntohl(*p);
dprintk("%s: minorversion %d nops %d\n", __func__,
hdr->minorversion, hdr->nops);
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 79/85] nfs41: callback numbers definitions
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (76 preceding siblings ...)
2008-11-10 20:32 ` [RFC 78/85] nfs41: decode minorversion 1 cb_compound header Benny Halevy
@ 2008-11-10 20:32 ` Benny Halevy
2008-11-10 20:32 ` [RFC 80/85] nfs41: consider minorversion in callback_xdr:process_op Benny Halevy
` (7 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:32 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/callback.h | 10 ++++++++++
1 files changed, 10 insertions(+), 0 deletions(-)
diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h
index f8325da..9cb0451 100644
--- a/fs/nfs/callback.h
+++ b/fs/nfs/callback.h
@@ -20,6 +20,16 @@ enum nfs4_callback_procnum {
enum nfs4_callback_opnum {
OP_CB_GETATTR = 3,
OP_CB_RECALL = 4,
+/* Callback operations new to NFSv4.1 */
+ OP_CB_LAYOUTRECALL = 5,
+ OP_CB_NOTIFY = 6,
+ OP_CB_PUSH_DELEG = 7,
+ OP_CB_RECALL_ANY = 8,
+ OP_CB_RECALLABLE_OBJ_AVAIL = 9,
+ OP_CB_RECALL_SLOT = 10,
+ OP_CB_SEQUENCE = 11,
+ OP_CB_WANTS_CANCELLED = 12,
+ OP_CB_NOTIFY_LOCK = 13,
OP_CB_ILLEGAL = 10044,
};
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 80/85] nfs41: consider minorversion in callback_xdr:process_op
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (77 preceding siblings ...)
2008-11-10 20:32 ` [RFC 79/85] nfs41: callback numbers definitions Benny Halevy
@ 2008-11-10 20:32 ` Benny Halevy
2008-11-10 20:32 ` [RFC 81/85] nfs41: define CB_NOTIFY_DEVICEID as not supported Benny Halevy
` (6 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:32 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/callback_xdr.c | 63 ++++++++++++++++++++++++++++++++++++++----------
1 files changed, 50 insertions(+), 13 deletions(-)
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
index e141a7e..dd25794 100644
--- a/fs/nfs/callback_xdr.c
+++ b/fs/nfs/callback_xdr.c
@@ -359,31 +359,61 @@ out:
return status;
}
-static __be32 process_op(struct svc_rqst *rqstp,
+static __be32 process_op(uint32_t minorversion, int nop,
+ struct svc_rqst *rqstp,
struct xdr_stream *xdr_in, void *argp,
struct xdr_stream *xdr_out, void *resp)
{
struct callback_op *op = &callback_ops[0];
unsigned int op_nr = OP_CB_ILLEGAL;
- __be32 status = 0;
+ __be32 status;
long maxlen;
__be32 res;
dprintk("%s: start\n", __func__);
status = decode_op_hdr(xdr_in, &op_nr);
- if (likely(status == 0)) {
+ if (unlikely(status))
+ goto out_illegal;
+
+ dprintk("%s: minorversion=%d nop=%d op_nr=%u\n",
+ __func__, minorversion, nop, op_nr);
+#if defined(CONFIG_NFS_V4_1)
+ if (minorversion == 1) {
switch (op_nr) {
- case OP_CB_GETATTR:
- case OP_CB_RECALL:
- op = &callback_ops[op_nr];
- break;
- default:
- op_nr = OP_CB_ILLEGAL;
- op = &callback_ops[0];
- status = htonl(NFS4ERR_OP_ILLEGAL);
+ case OP_CB_GETATTR:
+ case OP_CB_RECALL:
+ op = &callback_ops[op_nr];
+ break;
+
+ case OP_CB_LAYOUTRECALL:
+ case OP_CB_NOTIFY:
+ case OP_CB_PUSH_DELEG:
+ case OP_CB_RECALL_ANY:
+ case OP_CB_RECALLABLE_OBJ_AVAIL:
+ case OP_CB_RECALL_SLOT:
+ case OP_CB_SEQUENCE:
+ case OP_CB_WANTS_CANCELLED:
+ case OP_CB_NOTIFY_LOCK:
+ op = &callback_ops[0];
+ status = htonl(NFS4ERR_NOTSUPP);
+ break;
+ default:
+ goto out_illegal;
}
- }
+ goto out;
+ }
+#endif /* defined(CONFIG_NFS_V4_1) */
+
+ switch (op_nr) {
+ case OP_CB_GETATTR:
+ case OP_CB_RECALL:
+ op = &callback_ops[op_nr];
+ break;
+ default:
+ goto out_illegal;
+ }
+out:
maxlen = xdr_out->end - xdr_out->p;
if (maxlen > 0 && maxlen < PAGE_SIZE) {
if (likely(status == 0 && op->decode_args != NULL))
@@ -400,6 +430,12 @@ static __be32 process_op(struct svc_rqst *rqstp,
status = op->encode_res(rqstp, xdr_out, resp);
dprintk("%s: done, status = %d\n", __func__, ntohl(status));
return status;
+
+out_illegal:
+ op_nr = OP_CB_ILLEGAL;
+ op = &callback_ops[0];
+ status = htonl(NFS4ERR_OP_ILLEGAL);
+ goto out;
}
/*
@@ -431,7 +467,8 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r
return rpc_system_err;
while (status == 0 && nops != hdr_arg.nops) {
- status = process_op(rqstp, &xdr_in, argp, &xdr_out, resp);
+ status = process_op(hdr_arg.minorversion, nops,
+ rqstp, &xdr_in, argp, &xdr_out, resp);
nops++;
}
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 81/85] nfs41: define CB_NOTIFY_DEVICEID as not supported
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (78 preceding siblings ...)
2008-11-10 20:32 ` [RFC 80/85] nfs41: consider minorversion in callback_xdr:process_op Benny Halevy
@ 2008-11-10 20:32 ` Benny Halevy
2008-11-10 20:32 ` [RFC 82/85] nfs41: cb_sequence protocol level data structures Benny Halevy
` (5 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:32 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
From: Ricardo Labiaga <Ricardo.Labiaga@netapp.com>
Need to return NFS4ERR_NOTSUPP for CB_NOTIFY_DEVICEID rather
than NFS4ERR_OP_ILLEGAL.
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/callback.h | 1 +
fs/nfs/callback_xdr.c | 1 +
2 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h
index 9cb0451..b3ccfe8 100644
--- a/fs/nfs/callback.h
+++ b/fs/nfs/callback.h
@@ -30,6 +30,7 @@ enum nfs4_callback_opnum {
OP_CB_SEQUENCE = 11,
OP_CB_WANTS_CANCELLED = 12,
OP_CB_NOTIFY_LOCK = 13,
+ OP_CB_NOTIFY_DEVICEID = 14,
OP_CB_ILLEGAL = 10044,
};
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
index dd25794..9db88ce 100644
--- a/fs/nfs/callback_xdr.c
+++ b/fs/nfs/callback_xdr.c
@@ -394,6 +394,7 @@ static __be32 process_op(uint32_t minorversion, int nop,
case OP_CB_SEQUENCE:
case OP_CB_WANTS_CANCELLED:
case OP_CB_NOTIFY_LOCK:
+ case OP_CB_NOTIFY_DEVICEID:
op = &callback_ops[0];
status = htonl(NFS4ERR_NOTSUPP);
break;
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 82/85] nfs41: cb_sequence protocol level data structures
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (79 preceding siblings ...)
2008-11-10 20:32 ` [RFC 81/85] nfs41: define CB_NOTIFY_DEVICEID as not supported Benny Halevy
@ 2008-11-10 20:32 ` Benny Halevy
2008-11-10 20:33 ` [RFC 83/85] nfs41: cb_sequence proc implementation Benny Halevy
` (4 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:32 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/callback.h | 35 +++++++++++++++++++++++++++++++++++
1 files changed, 35 insertions(+), 0 deletions(-)
diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h
index b3ccfe8..5616257 100644
--- a/fs/nfs/callback.h
+++ b/fs/nfs/callback.h
@@ -70,6 +70,41 @@ struct cb_recallargs {
uint32_t truncate;
};
+#if defined(CONFIG_NFS_V4_1)
+
+struct referring_call {
+ uint32_t rc_sequenceid;
+ uint32_t rc_slotid;
+};
+
+struct referring_call_list {
+ nfs41_sessionid rcl_sessionid;
+ uint32_t rcl_nrefcalls;
+ struct referring_call *rcl_refcalls;
+};
+
+struct cb_sequenceargs {
+ struct sockaddr_in *csa_addr;
+ nfs41_sessionid csa_sessionid;
+ uint32_t csa_sequenceid;
+ uint32_t csa_slotid;
+ uint32_t csa_highestslotid;
+ uint32_t csa_cachethis;
+ uint32_t csa_nrclists;
+ struct referring_call_list *csa_rclists;
+};
+
+struct cb_sequenceres {
+ uint32_t csr_status;
+ nfs41_sessionid csr_sessionid;
+ uint32_t csr_sequenceid;
+ uint32_t csr_slotid;
+ uint32_t csr_highestslotid;
+ uint32_t csr_target_highestslotid;
+};
+
+#endif /* CONFIG_NFS_V4_1 */
+
extern __be32 nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres *res);
extern __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy);
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 83/85] nfs41: cb_sequence proc implementation
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (80 preceding siblings ...)
2008-11-10 20:32 ` [RFC 82/85] nfs41: cb_sequence protocol level data structures Benny Halevy
@ 2008-11-10 20:33 ` Benny Halevy
2008-11-10 20:33 ` [RFC 84/85] nfs41: cb_sequence xdr implementation Benny Halevy
` (3 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:33 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
Currently, just free up any referring calls information.
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/callback.h | 4 ++++
fs/nfs/callback_proc.c | 30 ++++++++++++++++++++++++++++++
2 files changed, 34 insertions(+), 0 deletions(-)
diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h
index 5616257..81a9df6 100644
--- a/fs/nfs/callback.h
+++ b/fs/nfs/callback.h
@@ -119,6 +119,10 @@ extern void nfs_callback_down(int minorversion);
* so we limit their concurrency to 1.
*/
#define NFS41_BC_MIN_CALLBACKS 1
+#define NFS41_BC_MAX_CALLBACKS 1
+
+extern unsigned nfs4_callback_sequence(struct cb_sequenceargs *args,
+ struct cb_sequenceres *res);
#endif /* CONFIG_NFS_V4_1 */
extern unsigned int nfs_callback_set_tcpport;
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
index f7e83e2..63b8662 100644
--- a/fs/nfs/callback_proc.c
+++ b/fs/nfs/callback_proc.c
@@ -101,3 +101,33 @@ out:
dprintk("%s: exit with status = %d\n", __func__, ntohl(res));
return res;
}
+
+#if defined(CONFIG_NFS_V4_1)
+
+/* FIXME: validate args->cbs_{sequence,slot}id */
+/* FIXME: referring calls should be processed */
+unsigned nfs4_callback_sequence(struct cb_sequenceargs *args,
+ struct cb_sequenceres *res)
+{
+ int i;
+ unsigned status = 0;
+
+ for (i = 0; i < args->csa_nrclists; i++)
+ kfree(args->csa_rclists[i].rcl_refcalls);
+ kfree(args->csa_rclists);
+
+ memcpy(&res->csr_sessionid, &args->csa_sessionid,
+ sizeof(res->csr_sessionid));
+ res->csr_sequenceid = args->csa_sequenceid;
+ res->csr_slotid = args->csa_slotid;
+ res->csr_highestslotid = NFS41_BC_MAX_CALLBACKS;
+ if (res->csr_highestslotid > args->csa_highestslotid)
+ res->csr_highestslotid = args->csa_highestslotid;
+ res->csr_target_highestslotid = NFS41_BC_MAX_CALLBACKS;
+
+ dprintk("%s: exit with status = %d\n", __func__, ntohl(status));
+ res->csr_status = status;
+ return status;
+}
+
+#endif /* CONFIG_NFS_V4_1 */
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 84/85] nfs41: cb_sequence xdr implementation
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (81 preceding siblings ...)
2008-11-10 20:33 ` [RFC 83/85] nfs41: cb_sequence proc implementation Benny Halevy
@ 2008-11-10 20:33 ` Benny Halevy
2008-11-10 20:33 ` [RFC 85/85] nfs41: verify CB_SEQUENCE position in callback compound Benny Halevy
` (2 subsequent siblings)
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:33 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/callback_xdr.c | 191 ++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 189 insertions(+), 2 deletions(-)
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
index 9db88ce..7b96b09 100644
--- a/fs/nfs/callback_xdr.c
+++ b/fs/nfs/callback_xdr.c
@@ -20,8 +20,28 @@
2 + 2 + 3 + 3)
#define CB_OP_RECALL_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ)
+#if defined(CONFIG_NFS_V4_1)
+#define CB_OP_SEQUENCE_RES_MAXSZ (CB_OP_HDR_RES_MAXSZ + \
+ 4 + 1 + 3)
+#endif /* CONFIG_NFS_V4_1 */
+
#define NFSDBG_FACILITY NFSDBG_CALLBACK
+#define READ64(x) do { \
+ (x) = (u64)ntohl(*p++) << 32; \
+ (x) |= ntohl(*p++); \
+} while (0)
+
+#define READMEM(x,nbytes) do { \
+ x = (char *)p; \
+ p += XDR_QUADLEN(nbytes); \
+} while (0)
+
+#define COPYMEM(x,nbytes) do { \
+ memcpy((x), p, nbytes); \
+ p += XDR_QUADLEN(nbytes); \
+} while (0)
+
typedef __be32 (*callback_process_op_t)(void *, void *);
typedef __be32 (*callback_decode_arg_t)(struct svc_rqst *, struct xdr_stream *, void *);
typedef __be32 (*callback_encode_res_t)(struct svc_rqst *, struct xdr_stream *, void *);
@@ -210,6 +230,122 @@ out:
return status;
}
+#if defined(CONFIG_NFS_V4_1)
+
+static unsigned decode_sessionid(struct xdr_stream *xdr,
+ nfs41_sessionid *sid)
+{
+ uint32_t *p;
+ int len = 16;
+
+ p = read_buf(xdr, len);
+ if (unlikely(p == NULL))
+ return htonl(NFS4ERR_RESOURCE);;
+
+ memcpy(sid, p, len);
+ return 0;
+}
+
+static unsigned decode_rc_list(struct xdr_stream *xdr,
+ struct referring_call_list *rc_list)
+{
+ uint32_t *p;
+ int i;
+ unsigned status;
+
+ status = decode_sessionid(xdr, &rc_list->rcl_sessionid);
+ if (status)
+ goto out;
+
+ status = htonl(NFS4ERR_RESOURCE);
+ p = read_buf(xdr, sizeof(uint32_t));
+ if (unlikely(p == NULL))
+ goto out;
+
+ rc_list->rcl_nrefcalls = ntohl(*p++);
+ if (rc_list->rcl_nrefcalls) {
+ p = read_buf(xdr,
+ rc_list->rcl_nrefcalls * 2 * sizeof(uint32_t));
+ if (unlikely(p == NULL))
+ goto out;
+ rc_list->rcl_refcalls = kmalloc(rc_list->rcl_nrefcalls *
+ sizeof(*rc_list->rcl_refcalls),
+ GFP_KERNEL);
+ if (unlikely(rc_list->rcl_refcalls == NULL))
+ goto out;
+ for (i = 0; i < rc_list->rcl_nrefcalls; i++) {
+ rc_list->rcl_refcalls[i].rc_sequenceid = ntohl(*p++);
+ rc_list->rcl_refcalls[i].rc_slotid = ntohl(*p++);
+ }
+ }
+ status = 0;
+
+out:
+ return status;
+}
+
+static unsigned decode_cb_sequence_args(struct svc_rqst *rqstp,
+ struct xdr_stream *xdr,
+ struct cb_sequenceargs *args)
+{
+ uint32_t *p;
+ int i;
+ unsigned status;
+
+ status = decode_sessionid(xdr, &args->csa_sessionid);
+ if (status)
+ goto out;
+
+ status = htonl(NFS4ERR_RESOURCE);
+ p = read_buf(xdr, 5 * sizeof(uint32_t));
+ if (unlikely(p == NULL))
+ goto out;
+
+ args->csa_addr = svc_addr_in(rqstp);
+ args->csa_sequenceid = ntohl(*p++);
+ args->csa_slotid = ntohl(*p++);
+ args->csa_highestslotid = ntohl(*p++);
+ args->csa_cachethis = ntohl(*p++);
+ args->csa_nrclists = ntohl(*p++);
+ args->csa_rclists = NULL;
+ if (args->csa_nrclists) {
+ args->csa_rclists = kmalloc(args->csa_nrclists *
+ sizeof(*args->csa_rclists),
+ GFP_KERNEL);
+ if (unlikely(args->csa_rclists == NULL))
+ goto out;
+
+ for (i = 0; i < args->csa_nrclists; i++) {
+ status = decode_rc_list(xdr, &args->csa_rclists[i]);
+ if (status)
+ goto out_free;
+ }
+ }
+ status = 0;
+
+ dprintk("%s: sessionid %x:%x:%x:%x sequenceid %u slotid %u "
+ "highestslotid %u cachethis %d nrclists %u\n",
+ __func__,
+ ((u32 *)&args->csa_sessionid)[0],
+ ((u32 *)&args->csa_sessionid)[1],
+ ((u32 *)&args->csa_sessionid)[2],
+ ((u32 *)&args->csa_sessionid)[3],
+ args->csa_sequenceid, args->csa_slotid,
+ args->csa_highestslotid, args->csa_cachethis,
+ args->csa_nrclists);
+out:
+ dprintk("%s: exit with status = %d\n", __func__, ntohl(status));
+ return status;
+
+out_free:
+ for (i = 0; i < args->csa_nrclists; i++)
+ kfree(args->csa_rclists[i].rcl_refcalls);
+ kfree(args->csa_rclists);
+ goto out;
+}
+
+#endif /* CONFIG_NFS_V4_1 */
+
static __be32 encode_string(struct xdr_stream *xdr, unsigned int len, const char *str)
{
__be32 *p;
@@ -359,6 +495,49 @@ out:
return status;
}
+#if defined(CONFIG_NFS_V4_1)
+
+static unsigned encode_sessionid(struct xdr_stream *xdr,
+ const nfs41_sessionid *sid)
+{
+ uint32_t *p;
+ int len = 4 * sizeof(uint32_t);
+
+ p = xdr_reserve_space(xdr, len);
+ if (unlikely(p == NULL))
+ return htonl(NFS4ERR_RESOURCE);
+
+ memcpy(p, sid, len);
+ return 0;
+}
+
+static unsigned encode_cb_sequence_res(struct svc_rqst *rqstp,
+ struct xdr_stream *xdr,
+ const struct cb_sequenceres *res)
+{
+ uint32_t *p;
+ unsigned status = res->csr_status;
+
+ if (unlikely(status != 0))
+ goto out;
+
+ encode_sessionid(xdr, &res->csr_sessionid);
+
+ p = xdr_reserve_space(xdr, 4 * sizeof(uint32_t));
+ if (unlikely(p == NULL))
+ return htonl(NFS4ERR_RESOURCE);
+
+ *p++ = htonl(res->csr_sequenceid);
+ *p++ = htonl(res->csr_slotid);
+ *p++ = htonl(res->csr_highestslotid);
+ *p++ = htonl(res->csr_target_highestslotid);
+out:
+ dprintk("%s: exit with status = %d\n", __func__, ntohl(status));
+ return status;
+}
+
+#endif /* CONFIG_NFS_V4_1 */
+
static __be32 process_op(uint32_t minorversion, int nop,
struct svc_rqst *rqstp,
struct xdr_stream *xdr_in, void *argp,
@@ -382,6 +561,7 @@ static __be32 process_op(uint32_t minorversion, int nop,
switch (op_nr) {
case OP_CB_GETATTR:
case OP_CB_RECALL:
+ case OP_CB_SEQUENCE:
op = &callback_ops[op_nr];
break;
@@ -391,7 +571,6 @@ static __be32 process_op(uint32_t minorversion, int nop,
case OP_CB_RECALL_ANY:
case OP_CB_RECALLABLE_OBJ_AVAIL:
case OP_CB_RECALL_SLOT:
- case OP_CB_SEQUENCE:
case OP_CB_WANTS_CANCELLED:
case OP_CB_NOTIFY_LOCK:
case OP_CB_NOTIFY_DEVICEID:
@@ -496,7 +675,15 @@ static struct callback_op callback_ops[] = {
.process_op = (callback_process_op_t)nfs4_callback_recall,
.decode_args = (callback_decode_arg_t)decode_recall_args,
.res_maxsize = CB_OP_RECALL_RES_MAXSZ,
- }
+ },
+#if defined(CONFIG_NFS_V4_1)
+ [OP_CB_SEQUENCE] = {
+ .process_op = (callback_process_op_t)nfs4_callback_sequence,
+ .decode_args = (callback_decode_arg_t)decode_cb_sequence_args,
+ .encode_res = (callback_encode_res_t)encode_cb_sequence_res,
+ .res_maxsize = CB_OP_SEQUENCE_RES_MAXSZ,
+ },
+#endif /* CONFIG_NFS_V4_1 */
};
/*
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* [RFC 85/85] nfs41: verify CB_SEQUENCE position in callback compound
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (82 preceding siblings ...)
2008-11-10 20:33 ` [RFC 84/85] nfs41: cb_sequence xdr implementation Benny Halevy
@ 2008-11-10 20:33 ` Benny Halevy
2008-11-10 20:37 ` [pnfs] [RFC 0/85] nfs41 client patches for review Benny Halevy
2008-11-10 20:42 ` J. Bruce Fields
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:33 UTC (permalink / raw)
To: trond.myklebust; +Cc: pnfs, linux-nfs
CB_SEQUENCE must appear first in the callback compound RPC.
If it is not the first operation NFS4ERR_SEQUENCE_POS must be returned.
If the first operation ni the CB_COMPOUND is not CB_SEQUENCE then
NFS4ERR_OP_NOT_IN_SESSION must be returned.
Signed-off-by: Ricardo Labiaga <ricardo.labiaga@netapp.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
---
fs/nfs/callback_xdr.c | 8 ++++++++
1 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
index 7b96b09..e0bd42b 100644
--- a/fs/nfs/callback_xdr.c
+++ b/fs/nfs/callback_xdr.c
@@ -558,6 +558,14 @@ static __be32 process_op(uint32_t minorversion, int nop,
__func__, minorversion, nop, op_nr);
#if defined(CONFIG_NFS_V4_1)
if (minorversion == 1) {
+ if (op_nr == OP_CB_SEQUENCE) {
+ if (nop != 0) {
+ status = htonl(NFS4ERR_SEQUENCE_POS);
+ goto out;
+ }
+ } else if (nop == 0)
+ status = htonl(NFS4ERR_OP_NOT_IN_SESSION);
+
switch (op_nr) {
case OP_CB_GETATTR:
case OP_CB_RECALL:
--
1.6.0.2
^ permalink raw reply related [flat|nested] 115+ messages in thread* Re: [pnfs] [RFC 0/85] nfs41 client patches for review
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (83 preceding siblings ...)
2008-11-10 20:33 ` [RFC 85/85] nfs41: verify CB_SEQUENCE position in callback compound Benny Halevy
@ 2008-11-10 20:37 ` Benny Halevy
2008-11-10 20:42 ` J. Bruce Fields
85 siblings, 0 replies; 115+ messages in thread
From: Benny Halevy @ 2008-11-10 20:37 UTC (permalink / raw)
To: Trond Myklebust; +Cc: NFS list, pNFS Mailing List
The patchset is also available on
git://linux-nfs.org/~bhalevy/linux-pnfs.git nfs41-2.6.28-review
Cumulated diff for the client side changes:
http://git.linux-nfs.org/?p=bhalevy/linux-pnfs.git;a=commitdiff_plain;h=nfs41-2.6.28-rc4-client-review-2008-11-10;hp=upstream-2.6.28
Benny
On Nov. 10, 2008, 21:57 +0200, Benny Halevy <bhalevy@panasas.com> wrote:
> Trond,
>
> Here's the patch series for nfs41 client side, rebased
> over 2.6.28 for review.
>
> I've cleaned up the patch as much as I could in the given
> time frame but surely there's more work to be done.
>
> I encourage others to comment on the patches as well.
>
> Thanks,
>
> Benny
>
> pre-nfs41 patches:
> [RFC 01/85] sunrpc: get rid of rpc_rqst.rq_bufsize
> [RFC 02/85] nfs: return compound hdr.status when there are no op replies
> [RFC 03/85] nfs: remove incorrect usage of nfs4 compound response hdr.status
> [RFC 04/85] FIXME: NFS: Increment operation number in each encode_* routine
>
>
> general defs:
> [RFC 05/85] nfs41: Add Kconfig symbols for NFSv4.1
> [RFC 06/85] nfs41: common protocol definitions
> [RFC 07/85] nfs41: define NFS4_MAX_MINOR_VERSION based on CONFIG_NFS_V4_1
> [RFC 08/85] nfs41: client xdr definitions
>
>
> basic support for minorversion != 0:
> [RFC 09/85] nfs41: add mount command option minorvers
> [RFC 10/85] nfs41: struct nfs_server minorversion
> [RFC 11/85] nfs41: nfs_client.cl_minorversion
> [RFC 12/85] nfs41: set nfs_client rpc_ops based on minorversion
> [RFC 13/85] nfs41: use ptr to rpc procedures via struct nfs_client
> [RFC 14/85] nfs41: sunrpc: support minorversion for rpc_clnt version table.
> [RFC 15/85] nfs41: Proper initialization of nfs_client_initdata.rpc_ops
> [RFC 16/85] nfs41: pass recovery status from reclaimer kthread up to nfs4_wait_clnt_recover
> [RFC 17/85] nfs41: fallback to lower minorversion if nfs4_create_server fails
>
>
> sessions basic functionality:
> [RFC 18/85] nfs41: sessions client infrastructure
> [RFC 19/85] nfs41: share client sessions across mounts
> [RFC 20/85] nfs41: slot table init and destroy
> [RFC 21/85] nfs41: find slot
> [RFC 22/85] nfs41: free slot
>
> support for sequence for legacy ops:
> [RFC 23/85] nfs41: minorversion support for xdr
> [RFC 24/85] nfs41: stubs for nfs41 procedures
> [RFC 25/85] nfs41: make nfs4_wait_bit_killable public
> [RFC 26/85] nfs41: introduce nfs4_call_sync
> [RFC 27/85] nfs41: nfs4_setup_sequence
> [RFC 28/85] nfs41: setup_sequence method
> [RFC 29/85] nfs41: nfs41_sequence_done
> [RFC 30/85] nfs41: nfs41_call_sync_done
> [RFC 31/85] nfs41: separate free slot from sequence done
> [RFC 32/85] nfs41: sequence setup/done support
> [RFC 33/85] nfs41: Support sessions with O_DIRECT.
>
> nfs41 ops:
> [RFC 34/85] nfs41: exchange_id operation
> [RFC 35/85] nfs41: get_lease_time
> [RFC 36/85] nfs41: create_session operation
> [RFC 37/85] nfs41: destroy_session operation
> [RFC 38/85] nfs41: sequence operation
>
> session setup and recovery:
> [RFC 39/85] nfs41: session recovery infrastructure
> [RFC 40/85] nfs41: schedule async session reset
> [RFC 41/85] nfs41: lease renewal
> [RFC 42/85] nfs41: sunrpc: Export the call prepare state for session reset
> [RFC 43/85] nfs41: use rpc prepare call state for session reset
> [RFC 44/85] nfs41: kick start nfs41 session recovery when handling errors
> [RFC 45/85] nfs41: start session recovery from nfs4_setup_sequence
> [RFC 46/85] nfs41: introduce get_state_renewal_cred
> [RFC 47/85] nfs41: get cred in exchange_id when cred arg is NULL
> [RFC 48/85] nfs41: establish sessions-based clientid
> [RFC 49/85] nfs41: recover lease in _nfs4_lookup_root
> [RFC 50/85] nfs41: schedule state recovery on BAD or DEAD session
> [RFC 51/85] nfs41: state reclaimer renew lease error handling
> [RFC 52/85] nfs41: increment_{open,lock}_seqid
>
> backchannel:
> [RFC 53/85] nfs41: Add ability to read RPC call direction on TCP stream.
> [RFC 54/85] nfs41: Skip past the RPC call direction
> [RFC 55/85] nfs41: Refactor NFSv4 callback service
> [RFC 56/85] nfs41: client callback structures
> [RFC 57/85] nfs41: Initialize new rpc_xprt callback related fields
> [RFC 58/85] nfs41: New backchannel helper routines
> [RFC 59/85] nfs41: New include/linux/sunrpc/bc_xprt.h
> [RFC 60/85] nfs41: New xs_tcp_read_data()
> [RFC 61/85] nfs41: Add backchannel processing support to RPC state machine
> [RFC 62/85] nfs41: Backchannel callback service helper routines
> [RFC 63/85] FIXME: nfs41: sunrpc: handle clnt==NULL in call_status
>
> callback service:
> [RFC 64/85] nfs41: Refactor svc_process()
> [RFC 65/85] nfs41: Backchannel bc_svc_process()
> [RFC 66/85] nfs41: Implement NFSv4.1 callback service process.
> [RFC 67/85] nfs41: sunrpc: provide functions to create and destroy a svc_xprt for backchannel use
> [RFC 68/85] nfs41: sunrpc: add a struct svc_xprt pointer to struct svc_serv for backchannel use
> [RFC 69/85] nfs41: create a svc_xprt for nfs41 callback thread and use for incoming callbacks
> [RFC 70/85] nfs41: save svc_serv in nfs_callback_info
> [RFC 71/85] nfs41: Add a reference to svc_serv during callback service bring up
> [RFC 72/85] nfs41: Allow NFSv4 and NFSv4.1 callback services to coexist
> [RFC 73/85] nfs41: Setup the backchannel
> [RFC 74/85] nfs41: Client indicates presence of NFSv4.1 callback channel.
> [RFC 75/85] nfs41: Get the rpc_xprt * from the rpc_rqst instead of the rpc_clnt.
> [RFC 76/85] nfs41: Release backchannel resources associated with session
>
> callback processing:
> [RFC 77/85] nfs41: store minorversion in cb_compound_hdr_arg
> [RFC 78/85] nfs41: decode minorversion 1 cb_compound header
> [RFC 79/85] nfs41: callback numbers definitions
> [RFC 80/85] nfs41: consider minorversion in callback_xdr:process_op
> [RFC 81/85] nfs41: define CB_NOTIFY_DEVICEID as not supported
> [RFC 82/85] nfs41: cb_sequence protocol level data structures
> [RFC 83/85] nfs41: cb_sequence proc implementation
> [RFC 84/85] nfs41: cb_sequence xdr implementation
> [RFC 85/85] nfs41: verify CB_SEQUENCE position in callback compound
> _______________________________________________
> pNFS mailing list
> pNFS@linux-nfs.org
> http://linux-nfs.org/cgi-bin/mailman/listinfo/pnfs
^ permalink raw reply [flat|nested] 115+ messages in thread* Re: [pnfs] [RFC 0/85] nfs41 client patches for review
2008-11-10 19:57 [RFC 0/85] nfs41 client patches for review Benny Halevy
` (84 preceding siblings ...)
2008-11-10 20:37 ` [pnfs] [RFC 0/85] nfs41 client patches for review Benny Halevy
@ 2008-11-10 20:42 ` J. Bruce Fields
85 siblings, 0 replies; 115+ messages in thread
From: J. Bruce Fields @ 2008-11-10 20:42 UTC (permalink / raw)
To: Benny Halevy; +Cc: Trond Myklebust, NFS list, pNFS Mailing List
On Mon, Nov 10, 2008 at 09:57:02PM +0200, Benny Halevy wrote:
> Trond,
>
> Here's the patch series for nfs41 client side, rebased
> over 2.6.28 for review.
>
> I've cleaned up the patch as much as I could in the given
> time frame but surely there's more work to be done.
>
> I encourage others to comment on the patches as well.
Yipes! Well, no shortage of reading material now....
--b.
>
> Thanks,
>
> Benny
>
> pre-nfs41 patches:
> [RFC 01/85] sunrpc: get rid of rpc_rqst.rq_bufsize
> [RFC 02/85] nfs: return compound hdr.status when there are no op replies
> [RFC 03/85] nfs: remove incorrect usage of nfs4 compound response hdr.status
> [RFC 04/85] FIXME: NFS: Increment operation number in each encode_* routine
>
>
> general defs:
> [RFC 05/85] nfs41: Add Kconfig symbols for NFSv4.1
> [RFC 06/85] nfs41: common protocol definitions
> [RFC 07/85] nfs41: define NFS4_MAX_MINOR_VERSION based on CONFIG_NFS_V4_1
> [RFC 08/85] nfs41: client xdr definitions
>
>
> basic support for minorversion != 0:
> [RFC 09/85] nfs41: add mount command option minorvers
> [RFC 10/85] nfs41: struct nfs_server minorversion
> [RFC 11/85] nfs41: nfs_client.cl_minorversion
> [RFC 12/85] nfs41: set nfs_client rpc_ops based on minorversion
> [RFC 13/85] nfs41: use ptr to rpc procedures via struct nfs_client
> [RFC 14/85] nfs41: sunrpc: support minorversion for rpc_clnt version table.
> [RFC 15/85] nfs41: Proper initialization of nfs_client_initdata.rpc_ops
> [RFC 16/85] nfs41: pass recovery status from reclaimer kthread up to nfs4_wait_clnt_recover
> [RFC 17/85] nfs41: fallback to lower minorversion if nfs4_create_server fails
>
>
> sessions basic functionality:
> [RFC 18/85] nfs41: sessions client infrastructure
> [RFC 19/85] nfs41: share client sessions across mounts
> [RFC 20/85] nfs41: slot table init and destroy
> [RFC 21/85] nfs41: find slot
> [RFC 22/85] nfs41: free slot
>
> support for sequence for legacy ops:
> [RFC 23/85] nfs41: minorversion support for xdr
> [RFC 24/85] nfs41: stubs for nfs41 procedures
> [RFC 25/85] nfs41: make nfs4_wait_bit_killable public
> [RFC 26/85] nfs41: introduce nfs4_call_sync
> [RFC 27/85] nfs41: nfs4_setup_sequence
> [RFC 28/85] nfs41: setup_sequence method
> [RFC 29/85] nfs41: nfs41_sequence_done
> [RFC 30/85] nfs41: nfs41_call_sync_done
> [RFC 31/85] nfs41: separate free slot from sequence done
> [RFC 32/85] nfs41: sequence setup/done support
> [RFC 33/85] nfs41: Support sessions with O_DIRECT.
>
> nfs41 ops:
> [RFC 34/85] nfs41: exchange_id operation
> [RFC 35/85] nfs41: get_lease_time
> [RFC 36/85] nfs41: create_session operation
> [RFC 37/85] nfs41: destroy_session operation
> [RFC 38/85] nfs41: sequence operation
>
> session setup and recovery:
> [RFC 39/85] nfs41: session recovery infrastructure
> [RFC 40/85] nfs41: schedule async session reset
> [RFC 41/85] nfs41: lease renewal
> [RFC 42/85] nfs41: sunrpc: Export the call prepare state for session reset
> [RFC 43/85] nfs41: use rpc prepare call state for session reset
> [RFC 44/85] nfs41: kick start nfs41 session recovery when handling errors
> [RFC 45/85] nfs41: start session recovery from nfs4_setup_sequence
> [RFC 46/85] nfs41: introduce get_state_renewal_cred
> [RFC 47/85] nfs41: get cred in exchange_id when cred arg is NULL
> [RFC 48/85] nfs41: establish sessions-based clientid
> [RFC 49/85] nfs41: recover lease in _nfs4_lookup_root
> [RFC 50/85] nfs41: schedule state recovery on BAD or DEAD session
> [RFC 51/85] nfs41: state reclaimer renew lease error handling
> [RFC 52/85] nfs41: increment_{open,lock}_seqid
>
> backchannel:
> [RFC 53/85] nfs41: Add ability to read RPC call direction on TCP stream.
> [RFC 54/85] nfs41: Skip past the RPC call direction
> [RFC 55/85] nfs41: Refactor NFSv4 callback service
> [RFC 56/85] nfs41: client callback structures
> [RFC 57/85] nfs41: Initialize new rpc_xprt callback related fields
> [RFC 58/85] nfs41: New backchannel helper routines
> [RFC 59/85] nfs41: New include/linux/sunrpc/bc_xprt.h
> [RFC 60/85] nfs41: New xs_tcp_read_data()
> [RFC 61/85] nfs41: Add backchannel processing support to RPC state machine
> [RFC 62/85] nfs41: Backchannel callback service helper routines
> [RFC 63/85] FIXME: nfs41: sunrpc: handle clnt==NULL in call_status
>
> callback service:
> [RFC 64/85] nfs41: Refactor svc_process()
> [RFC 65/85] nfs41: Backchannel bc_svc_process()
> [RFC 66/85] nfs41: Implement NFSv4.1 callback service process.
> [RFC 67/85] nfs41: sunrpc: provide functions to create and destroy a svc_xprt for backchannel use
> [RFC 68/85] nfs41: sunrpc: add a struct svc_xprt pointer to struct svc_serv for backchannel use
> [RFC 69/85] nfs41: create a svc_xprt for nfs41 callback thread and use for incoming callbacks
> [RFC 70/85] nfs41: save svc_serv in nfs_callback_info
> [RFC 71/85] nfs41: Add a reference to svc_serv during callback service bring up
> [RFC 72/85] nfs41: Allow NFSv4 and NFSv4.1 callback services to coexist
> [RFC 73/85] nfs41: Setup the backchannel
> [RFC 74/85] nfs41: Client indicates presence of NFSv4.1 callback channel.
> [RFC 75/85] nfs41: Get the rpc_xprt * from the rpc_rqst instead of the rpc_clnt.
> [RFC 76/85] nfs41: Release backchannel resources associated with session
>
> callback processing:
> [RFC 77/85] nfs41: store minorversion in cb_compound_hdr_arg
> [RFC 78/85] nfs41: decode minorversion 1 cb_compound header
> [RFC 79/85] nfs41: callback numbers definitions
> [RFC 80/85] nfs41: consider minorversion in callback_xdr:process_op
> [RFC 81/85] nfs41: define CB_NOTIFY_DEVICEID as not supported
> [RFC 82/85] nfs41: cb_sequence protocol level data structures
> [RFC 83/85] nfs41: cb_sequence proc implementation
> [RFC 84/85] nfs41: cb_sequence xdr implementation
> [RFC 85/85] nfs41: verify CB_SEQUENCE position in callback compound
> _______________________________________________
> pNFS mailing list
> pNFS@linux-nfs.org
> http://linux-nfs.org/cgi-bin/mailman/listinfo/pnfs
^ permalink raw reply [flat|nested] 115+ messages in thread