forked from Minki/linux
NFSD: Update XDR decoders in NFSv4 callback client
Clean up. Remove old-style NFSv4 XDR macros in favor of the style now used in fs/nfs/nfs4xdr.c. These were forgotten during the recent nfs4xdr.c rewrite. Additional whitespace cleanup adds to the size of this patch. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Tested-by: J. Bruce Fields <bfields@redhat.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
parent
a033db487e
commit
85a5648019
@ -74,37 +74,6 @@ enum {
|
|||||||
cb_sequence_dec_sz + \
|
cb_sequence_dec_sz + \
|
||||||
op_dec_sz)
|
op_dec_sz)
|
||||||
|
|
||||||
/*
|
|
||||||
* Generic decode routines from fs/nfs/nfs4xdr.c
|
|
||||||
*/
|
|
||||||
#define DECODE_TAIL \
|
|
||||||
status = 0; \
|
|
||||||
out: \
|
|
||||||
return status; \
|
|
||||||
xdr_error: \
|
|
||||||
dprintk("NFSD: xdr error! (%s:%d)\n", __FILE__, __LINE__); \
|
|
||||||
status = -EIO; \
|
|
||||||
goto out
|
|
||||||
|
|
||||||
#define READ32(x) (x) = ntohl(*p++)
|
|
||||||
#define READ64(x) do { \
|
|
||||||
(x) = (u64)ntohl(*p++) << 32; \
|
|
||||||
(x) |= ntohl(*p++); \
|
|
||||||
} while (0)
|
|
||||||
#define READTIME(x) do { \
|
|
||||||
p++; \
|
|
||||||
(x.tv_sec) = ntohl(*p++); \
|
|
||||||
(x.tv_nsec) = ntohl(*p++); \
|
|
||||||
} while (0)
|
|
||||||
#define READ_BUF(nbytes) do { \
|
|
||||||
p = xdr_inline_decode(xdr, nbytes); \
|
|
||||||
if (!p) { \
|
|
||||||
dprintk("NFSD: %s: reply buffer overflowed in line %d.\n", \
|
|
||||||
__func__, __LINE__); \
|
|
||||||
return -EIO; \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
struct nfs4_cb_compound_hdr {
|
struct nfs4_cb_compound_hdr {
|
||||||
/* args */
|
/* args */
|
||||||
u32 ident; /* minorversion 0 only */
|
u32 ident; /* minorversion 0 only */
|
||||||
@ -115,57 +84,14 @@ struct nfs4_cb_compound_hdr {
|
|||||||
int status;
|
int status;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct {
|
/*
|
||||||
int stat;
|
* Handle decode buffer overflows out-of-line.
|
||||||
int errno;
|
*/
|
||||||
} nfs_cb_errtbl[] = {
|
static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
|
||||||
{ NFS4_OK, 0 },
|
|
||||||
{ NFS4ERR_PERM, EPERM },
|
|
||||||
{ NFS4ERR_NOENT, ENOENT },
|
|
||||||
{ NFS4ERR_IO, EIO },
|
|
||||||
{ NFS4ERR_NXIO, ENXIO },
|
|
||||||
{ NFS4ERR_ACCESS, EACCES },
|
|
||||||
{ NFS4ERR_EXIST, EEXIST },
|
|
||||||
{ NFS4ERR_XDEV, EXDEV },
|
|
||||||
{ NFS4ERR_NOTDIR, ENOTDIR },
|
|
||||||
{ NFS4ERR_ISDIR, EISDIR },
|
|
||||||
{ NFS4ERR_INVAL, EINVAL },
|
|
||||||
{ NFS4ERR_FBIG, EFBIG },
|
|
||||||
{ NFS4ERR_NOSPC, ENOSPC },
|
|
||||||
{ NFS4ERR_ROFS, EROFS },
|
|
||||||
{ NFS4ERR_MLINK, EMLINK },
|
|
||||||
{ NFS4ERR_NAMETOOLONG, ENAMETOOLONG },
|
|
||||||
{ NFS4ERR_NOTEMPTY, ENOTEMPTY },
|
|
||||||
{ NFS4ERR_DQUOT, EDQUOT },
|
|
||||||
{ NFS4ERR_STALE, ESTALE },
|
|
||||||
{ NFS4ERR_BADHANDLE, EBADHANDLE },
|
|
||||||
{ NFS4ERR_BAD_COOKIE, EBADCOOKIE },
|
|
||||||
{ NFS4ERR_NOTSUPP, ENOTSUPP },
|
|
||||||
{ NFS4ERR_TOOSMALL, ETOOSMALL },
|
|
||||||
{ NFS4ERR_SERVERFAULT, ESERVERFAULT },
|
|
||||||
{ NFS4ERR_BADTYPE, EBADTYPE },
|
|
||||||
{ NFS4ERR_LOCKED, EAGAIN },
|
|
||||||
{ NFS4ERR_RESOURCE, EREMOTEIO },
|
|
||||||
{ NFS4ERR_SYMLINK, ELOOP },
|
|
||||||
{ NFS4ERR_OP_ILLEGAL, EOPNOTSUPP },
|
|
||||||
{ NFS4ERR_DEADLOCK, EDEADLK },
|
|
||||||
{ -1, EIO }
|
|
||||||
};
|
|
||||||
|
|
||||||
static int
|
|
||||||
nfs_cb_stat_to_errno(int stat)
|
|
||||||
{
|
{
|
||||||
int i;
|
dprintk("NFS: %s prematurely hit the end of our receive buffer. "
|
||||||
for (i = 0; nfs_cb_errtbl[i].stat != -1; i++) {
|
"Remaining buffer length is %tu words.\n",
|
||||||
if (nfs_cb_errtbl[i].stat == stat)
|
func, xdr->end - xdr->p);
|
||||||
return nfs_cb_errtbl[i].errno;
|
|
||||||
}
|
|
||||||
/* If we cannot translate the error, the recovery routines should
|
|
||||||
* handle it.
|
|
||||||
* Note: remaining NFSv4 error codes have values > 10000, so should
|
|
||||||
* not conflict with native Linux error codes.
|
|
||||||
*/
|
|
||||||
return stat;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static __be32 *xdr_encode_empty_array(__be32 *p)
|
static __be32 *xdr_encode_empty_array(__be32 *p)
|
||||||
@ -262,6 +188,89 @@ static void encode_sessionid4(struct xdr_stream *xdr,
|
|||||||
NFS4_MAX_SESSIONID_LEN);
|
NFS4_MAX_SESSIONID_LEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* nfsstat4
|
||||||
|
*/
|
||||||
|
static const struct {
|
||||||
|
int stat;
|
||||||
|
int errno;
|
||||||
|
} nfs_cb_errtbl[] = {
|
||||||
|
{ NFS4_OK, 0 },
|
||||||
|
{ NFS4ERR_PERM, -EPERM },
|
||||||
|
{ NFS4ERR_NOENT, -ENOENT },
|
||||||
|
{ NFS4ERR_IO, -EIO },
|
||||||
|
{ NFS4ERR_NXIO, -ENXIO },
|
||||||
|
{ NFS4ERR_ACCESS, -EACCES },
|
||||||
|
{ NFS4ERR_EXIST, -EEXIST },
|
||||||
|
{ NFS4ERR_XDEV, -EXDEV },
|
||||||
|
{ NFS4ERR_NOTDIR, -ENOTDIR },
|
||||||
|
{ NFS4ERR_ISDIR, -EISDIR },
|
||||||
|
{ NFS4ERR_INVAL, -EINVAL },
|
||||||
|
{ NFS4ERR_FBIG, -EFBIG },
|
||||||
|
{ NFS4ERR_NOSPC, -ENOSPC },
|
||||||
|
{ NFS4ERR_ROFS, -EROFS },
|
||||||
|
{ NFS4ERR_MLINK, -EMLINK },
|
||||||
|
{ NFS4ERR_NAMETOOLONG, -ENAMETOOLONG },
|
||||||
|
{ NFS4ERR_NOTEMPTY, -ENOTEMPTY },
|
||||||
|
{ NFS4ERR_DQUOT, -EDQUOT },
|
||||||
|
{ NFS4ERR_STALE, -ESTALE },
|
||||||
|
{ NFS4ERR_BADHANDLE, -EBADHANDLE },
|
||||||
|
{ NFS4ERR_BAD_COOKIE, -EBADCOOKIE },
|
||||||
|
{ NFS4ERR_NOTSUPP, -ENOTSUPP },
|
||||||
|
{ NFS4ERR_TOOSMALL, -ETOOSMALL },
|
||||||
|
{ NFS4ERR_SERVERFAULT, -ESERVERFAULT },
|
||||||
|
{ NFS4ERR_BADTYPE, -EBADTYPE },
|
||||||
|
{ NFS4ERR_LOCKED, -EAGAIN },
|
||||||
|
{ NFS4ERR_RESOURCE, -EREMOTEIO },
|
||||||
|
{ NFS4ERR_SYMLINK, -ELOOP },
|
||||||
|
{ NFS4ERR_OP_ILLEGAL, -EOPNOTSUPP },
|
||||||
|
{ NFS4ERR_DEADLOCK, -EDEADLK },
|
||||||
|
{ -1, -EIO }
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we cannot translate the error, the recovery routines should
|
||||||
|
* handle it.
|
||||||
|
*
|
||||||
|
* Note: remaining NFSv4 error codes have values > 10000, so should
|
||||||
|
* not conflict with native Linux error codes.
|
||||||
|
*/
|
||||||
|
static int nfs_cb_stat_to_errno(int status)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; nfs_cb_errtbl[i].stat != -1; i++) {
|
||||||
|
if (nfs_cb_errtbl[i].stat == status)
|
||||||
|
return nfs_cb_errtbl[i].errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
dprintk("NFSD: Unrecognized NFS CB status value: %u\n", status);
|
||||||
|
return -status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int decode_cb_op_status(struct xdr_stream *xdr, enum nfs_opnum4 expected,
|
||||||
|
enum nfsstat4 *status)
|
||||||
|
{
|
||||||
|
__be32 *p;
|
||||||
|
u32 op;
|
||||||
|
|
||||||
|
p = xdr_inline_decode(xdr, 4 + 4);
|
||||||
|
if (unlikely(p == NULL))
|
||||||
|
goto out_overflow;
|
||||||
|
op = be32_to_cpup(p++);
|
||||||
|
if (unlikely(op != expected))
|
||||||
|
goto out_unexpected;
|
||||||
|
*status = be32_to_cpup(p);
|
||||||
|
return 0;
|
||||||
|
out_overflow:
|
||||||
|
print_overflow_msg(__func__, xdr);
|
||||||
|
return -EIO;
|
||||||
|
out_unexpected:
|
||||||
|
dprintk("NFSD: Callback server returned operation %d but "
|
||||||
|
"we issued a request for %d\n", op, expected);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CB_COMPOUND4args
|
* CB_COMPOUND4args
|
||||||
*
|
*
|
||||||
@ -295,6 +304,37 @@ static void encode_cb_nops(struct nfs4_cb_compound_hdr *hdr)
|
|||||||
*hdr->nops_p = cpu_to_be32(hdr->nops);
|
*hdr->nops_p = cpu_to_be32(hdr->nops);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CB_COMPOUND4res
|
||||||
|
*
|
||||||
|
* struct CB_COMPOUND4res {
|
||||||
|
* nfsstat4 status;
|
||||||
|
* utf8str_cs tag;
|
||||||
|
* nfs_cb_resop4 resarray<>;
|
||||||
|
* };
|
||||||
|
*/
|
||||||
|
static int decode_cb_compound4res(struct xdr_stream *xdr,
|
||||||
|
struct nfs4_cb_compound_hdr *hdr)
|
||||||
|
{
|
||||||
|
u32 length;
|
||||||
|
__be32 *p;
|
||||||
|
|
||||||
|
p = xdr_inline_decode(xdr, 4 + 4);
|
||||||
|
if (unlikely(p == NULL))
|
||||||
|
goto out_overflow;
|
||||||
|
hdr->status = be32_to_cpup(p++);
|
||||||
|
/* Ignore the tag */
|
||||||
|
length = be32_to_cpup(p++);
|
||||||
|
p = xdr_inline_decode(xdr, length + 4);
|
||||||
|
if (unlikely(p == NULL))
|
||||||
|
goto out_overflow;
|
||||||
|
hdr->nops = be32_to_cpup(p);
|
||||||
|
return 0;
|
||||||
|
out_overflow:
|
||||||
|
print_overflow_msg(__func__, xdr);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CB_RECALL4args
|
* CB_RECALL4args
|
||||||
*
|
*
|
||||||
@ -356,6 +396,97 @@ static void encode_cb_sequence4args(struct xdr_stream *xdr,
|
|||||||
hdr->nops++;
|
hdr->nops++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CB_SEQUENCE4resok
|
||||||
|
*
|
||||||
|
* struct CB_SEQUENCE4resok {
|
||||||
|
* sessionid4 csr_sessionid;
|
||||||
|
* sequenceid4 csr_sequenceid;
|
||||||
|
* slotid4 csr_slotid;
|
||||||
|
* slotid4 csr_highest_slotid;
|
||||||
|
* slotid4 csr_target_highest_slotid;
|
||||||
|
* };
|
||||||
|
*
|
||||||
|
* union CB_SEQUENCE4res switch (nfsstat4 csr_status) {
|
||||||
|
* case NFS4_OK:
|
||||||
|
* CB_SEQUENCE4resok csr_resok4;
|
||||||
|
* default:
|
||||||
|
* void;
|
||||||
|
* };
|
||||||
|
*
|
||||||
|
* Our current back channel implmentation supports a single backchannel
|
||||||
|
* with a single slot.
|
||||||
|
*/
|
||||||
|
static int decode_cb_sequence4resok(struct xdr_stream *xdr,
|
||||||
|
struct nfsd4_callback *cb)
|
||||||
|
{
|
||||||
|
struct nfsd4_session *session = cb->cb_clp->cl_cb_session;
|
||||||
|
struct nfs4_sessionid id;
|
||||||
|
int status;
|
||||||
|
__be32 *p;
|
||||||
|
u32 dummy;
|
||||||
|
|
||||||
|
status = -ESERVERFAULT;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the server returns different values for sessionID, slotID or
|
||||||
|
* sequence number, the server is looney tunes.
|
||||||
|
*/
|
||||||
|
p = xdr_inline_decode(xdr, NFS4_MAX_SESSIONID_LEN + 4 + 4);
|
||||||
|
if (unlikely(p == NULL))
|
||||||
|
goto out_overflow;
|
||||||
|
memcpy(id.data, p, NFS4_MAX_SESSIONID_LEN);
|
||||||
|
if (memcmp(id.data, session->se_sessionid.data,
|
||||||
|
NFS4_MAX_SESSIONID_LEN) != 0) {
|
||||||
|
dprintk("NFS: %s Invalid session id\n", __func__);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
p += XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN);
|
||||||
|
|
||||||
|
dummy = be32_to_cpup(p++);
|
||||||
|
if (dummy != session->se_cb_seq_nr) {
|
||||||
|
dprintk("NFS: %s Invalid sequence number\n", __func__);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
dummy = be32_to_cpup(p++);
|
||||||
|
if (dummy != 0) {
|
||||||
|
dprintk("NFS: %s Invalid slotid\n", __func__);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FIXME: process highest slotid and target highest slotid
|
||||||
|
*/
|
||||||
|
status = 0;
|
||||||
|
out:
|
||||||
|
return status;
|
||||||
|
out_overflow:
|
||||||
|
print_overflow_msg(__func__, xdr);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int decode_cb_sequence4res(struct xdr_stream *xdr,
|
||||||
|
struct nfsd4_callback *cb)
|
||||||
|
{
|
||||||
|
enum nfsstat4 nfserr;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
if (cb->cb_minorversion == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
status = decode_cb_op_status(xdr, OP_CB_SEQUENCE, &nfserr);
|
||||||
|
if (unlikely(status))
|
||||||
|
goto out;
|
||||||
|
if (unlikely(nfserr != NFS4_OK))
|
||||||
|
goto out_default;
|
||||||
|
status = decode_cb_sequence4resok(xdr, cb);
|
||||||
|
out:
|
||||||
|
return status;
|
||||||
|
out_default:
|
||||||
|
return nfs_cb_stat_to_errno(status);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NFSv4.0 and NFSv4.1 XDR encode functions
|
* NFSv4.0 and NFSv4.1 XDR encode functions
|
||||||
*
|
*
|
||||||
@ -399,119 +530,51 @@ static int nfs4_xdr_enc_cb_recall(struct rpc_rqst *req, __be32 *p,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
/*
|
||||||
decode_cb_compound_hdr(struct xdr_stream *xdr, struct nfs4_cb_compound_hdr *hdr){
|
* NFSv4.0 and NFSv4.1 XDR decode functions
|
||||||
__be32 *p;
|
*
|
||||||
u32 taglen;
|
* NFSv4.0 callback result types are defined in section 15 of RFC
|
||||||
|
* 3530: "Network File System (NFS) version 4 Protocol" and section 20
|
||||||
|
* of RFC 5661: "Network File System (NFS) Version 4 Minor Version 1
|
||||||
|
* Protocol".
|
||||||
|
*/
|
||||||
|
|
||||||
READ_BUF(8);
|
static int nfs4_xdr_dec_cb_null(struct rpc_rqst *req, __be32 *p, void *__unused)
|
||||||
READ32(hdr->status);
|
|
||||||
/* We've got no use for the tag; ignore it: */
|
|
||||||
READ32(taglen);
|
|
||||||
READ_BUF(taglen + 4);
|
|
||||||
p += XDR_QUADLEN(taglen);
|
|
||||||
READ32(hdr->nops);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
decode_cb_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected)
|
|
||||||
{
|
{
|
||||||
__be32 *p;
|
|
||||||
u32 op;
|
|
||||||
int32_t nfserr;
|
|
||||||
|
|
||||||
READ_BUF(8);
|
|
||||||
READ32(op);
|
|
||||||
if (op != expected) {
|
|
||||||
dprintk("NFSD: decode_cb_op_hdr: Callback server returned "
|
|
||||||
" operation %d but we issued a request for %d\n",
|
|
||||||
op, expected);
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
READ32(nfserr);
|
|
||||||
if (nfserr != NFS_OK)
|
|
||||||
return -nfs_cb_stat_to_errno(nfserr);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Our current back channel implmentation supports a single backchannel
|
* 20.2. Operation 4: CB_RECALL - Recall a Delegation
|
||||||
* with a single slot.
|
|
||||||
*/
|
*/
|
||||||
static int
|
static int nfs4_xdr_dec_cb_recall(struct rpc_rqst *rqstp, __be32 *p,
|
||||||
decode_cb_sequence(struct xdr_stream *xdr, struct nfsd4_callback *cb,
|
struct nfsd4_callback *cb)
|
||||||
struct rpc_rqst *rqstp)
|
|
||||||
{
|
|
||||||
struct nfsd4_session *ses = cb->cb_clp->cl_cb_session;
|
|
||||||
struct nfs4_sessionid id;
|
|
||||||
int status;
|
|
||||||
u32 dummy;
|
|
||||||
__be32 *p;
|
|
||||||
|
|
||||||
if (cb->cb_minorversion == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
status = decode_cb_op_hdr(xdr, OP_CB_SEQUENCE);
|
|
||||||
if (status)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the server returns different values for sessionID, slotID or
|
|
||||||
* sequence number, the server is looney tunes.
|
|
||||||
*/
|
|
||||||
status = -ESERVERFAULT;
|
|
||||||
|
|
||||||
READ_BUF(NFS4_MAX_SESSIONID_LEN + 16);
|
|
||||||
memcpy(id.data, p, NFS4_MAX_SESSIONID_LEN);
|
|
||||||
p += XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN);
|
|
||||||
if (memcmp(id.data, ses->se_sessionid.data, NFS4_MAX_SESSIONID_LEN)) {
|
|
||||||
dprintk("%s Invalid session id\n", __func__);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
READ32(dummy);
|
|
||||||
if (dummy != ses->se_cb_seq_nr) {
|
|
||||||
dprintk("%s Invalid sequence number\n", __func__);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
READ32(dummy); /* slotid must be 0 */
|
|
||||||
if (dummy != 0) {
|
|
||||||
dprintk("%s Invalid slotid\n", __func__);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
/* FIXME: process highest slotid and target highest slotid */
|
|
||||||
status = 0;
|
|
||||||
out:
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
nfs4_xdr_dec_cb_null(struct rpc_rqst *req, __be32 *p)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
nfs4_xdr_dec_cb_recall(struct rpc_rqst *rqstp, __be32 *p,
|
|
||||||
struct nfsd4_callback *cb)
|
|
||||||
{
|
{
|
||||||
struct xdr_stream xdr;
|
struct xdr_stream xdr;
|
||||||
struct nfs4_cb_compound_hdr hdr;
|
struct nfs4_cb_compound_hdr hdr;
|
||||||
|
enum nfsstat4 nfserr;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
|
xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
|
||||||
status = decode_cb_compound_hdr(&xdr, &hdr);
|
status = decode_cb_compound4res(&xdr, &hdr);
|
||||||
if (status)
|
if (unlikely(status))
|
||||||
goto out;
|
goto out;
|
||||||
if (cb) {
|
|
||||||
status = decode_cb_sequence(&xdr, cb, rqstp);
|
if (cb != NULL) {
|
||||||
if (status)
|
status = decode_cb_sequence4res(&xdr, cb);
|
||||||
|
if (unlikely(status))
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
status = decode_cb_op_hdr(&xdr, OP_CB_RECALL);
|
|
||||||
|
status = decode_cb_op_status(&xdr, OP_CB_RECALL, &nfserr);
|
||||||
|
if (unlikely(status))
|
||||||
|
goto out;
|
||||||
|
if (unlikely(nfserr != NFS4_OK))
|
||||||
|
goto out_default;
|
||||||
out:
|
out:
|
||||||
return status;
|
return status;
|
||||||
|
out_default:
|
||||||
|
return nfs_cb_stat_to_errno(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user