Merge tag 'md/3.20-fixes' of git://neil.brown.name/md
[firefly-linux-kernel-4.4.55.git] / fs / nfs / nfs4xdr.c
index cb4376b78ed91771b98bf03695eea1c67a5b5889..e23a0a664e12d5130162bc320e80a57a5264bc9b 100644 (file)
@@ -946,7 +946,10 @@ static void encode_uint64(struct xdr_stream *xdr, u64 n)
 static void encode_nfs4_seqid(struct xdr_stream *xdr,
                const struct nfs_seqid *seqid)
 {
-       encode_uint32(xdr, seqid->sequence->counter);
+       if (seqid != NULL)
+               encode_uint32(xdr, seqid->sequence->counter);
+       else
+               encode_uint32(xdr, 0);
 }
 
 static void encode_compound_hdr(struct xdr_stream *xdr,
@@ -1125,7 +1128,7 @@ static void encode_close(struct xdr_stream *xdr, const struct nfs_closeargs *arg
 {
        encode_op_hdr(xdr, OP_CLOSE, decode_close_maxsz, hdr);
        encode_nfs4_seqid(xdr, arg->seqid);
-       encode_nfs4_stateid(xdr, arg->stateid);
+       encode_nfs4_stateid(xdr, &arg->stateid);
 }
 
 static void encode_commit(struct xdr_stream *xdr, const struct nfs_commitargs *args, struct compound_hdr *hdr)
@@ -1301,12 +1304,12 @@ static void encode_lock(struct xdr_stream *xdr, const struct nfs_lock_args *args
        *p = cpu_to_be32(args->new_lock_owner);
        if (args->new_lock_owner){
                encode_nfs4_seqid(xdr, args->open_seqid);
-               encode_nfs4_stateid(xdr, args->open_stateid);
+               encode_nfs4_stateid(xdr, &args->open_stateid);
                encode_nfs4_seqid(xdr, args->lock_seqid);
                encode_lockowner(xdr, &args->lock_owner);
        }
        else {
-               encode_nfs4_stateid(xdr, args->lock_stateid);
+               encode_nfs4_stateid(xdr, &args->lock_stateid);
                encode_nfs4_seqid(xdr, args->lock_seqid);
        }
 }
@@ -1330,7 +1333,7 @@ static void encode_locku(struct xdr_stream *xdr, const struct nfs_locku_args *ar
        encode_op_hdr(xdr, OP_LOCKU, decode_locku_maxsz, hdr);
        encode_uint32(xdr, nfs4_lock_type(args->fl, 0));
        encode_nfs4_seqid(xdr, args->seqid);
-       encode_nfs4_stateid(xdr, args->stateid);
+       encode_nfs4_stateid(xdr, &args->stateid);
        p = reserve_space(xdr, 16);
        p = xdr_encode_hyper(p, args->fl->fl_start);
        xdr_encode_hyper(p, nfs4_lock_length(args->fl));
@@ -1348,24 +1351,12 @@ static void encode_lookup(struct xdr_stream *xdr, const struct qstr *name, struc
        encode_string(xdr, name->len, name->name);
 }
 
-static void encode_share_access(struct xdr_stream *xdr, fmode_t fmode)
+static void encode_share_access(struct xdr_stream *xdr, u32 share_access)
 {
        __be32 *p;
 
        p = reserve_space(xdr, 8);
-       switch (fmode & (FMODE_READ|FMODE_WRITE)) {
-       case FMODE_READ:
-               *p++ = cpu_to_be32(NFS4_SHARE_ACCESS_READ);
-               break;
-       case FMODE_WRITE:
-               *p++ = cpu_to_be32(NFS4_SHARE_ACCESS_WRITE);
-               break;
-       case FMODE_READ|FMODE_WRITE:
-               *p++ = cpu_to_be32(NFS4_SHARE_ACCESS_BOTH);
-               break;
-       default:
-               *p++ = cpu_to_be32(0);
-       }
+       *p++ = cpu_to_be32(share_access);
        *p = cpu_to_be32(0);            /* for linux, share_deny = 0 always */
 }
 
@@ -1377,7 +1368,7 @@ static inline void encode_openhdr(struct xdr_stream *xdr, const struct nfs_opena
  * owner 4 = 32
  */
        encode_nfs4_seqid(xdr, arg->seqid);
-       encode_share_access(xdr, arg->fmode);
+       encode_share_access(xdr, arg->share_access);
        p = reserve_space(xdr, 36);
        p = xdr_encode_hyper(p, arg->clientid);
        *p++ = cpu_to_be32(24);
@@ -1530,9 +1521,9 @@ static void encode_open_confirm(struct xdr_stream *xdr, const struct nfs_open_co
 static void encode_open_downgrade(struct xdr_stream *xdr, const struct nfs_closeargs *arg, struct compound_hdr *hdr)
 {
        encode_op_hdr(xdr, OP_OPEN_DOWNGRADE, decode_open_downgrade_maxsz, hdr);
-       encode_nfs4_stateid(xdr, arg->stateid);
+       encode_nfs4_stateid(xdr, &arg->stateid);
        encode_nfs4_seqid(xdr, arg->seqid);
-       encode_share_access(xdr, arg->fmode);
+       encode_share_access(xdr, arg->share_access);
 }
 
 static void
@@ -1801,9 +1792,8 @@ static void encode_create_session(struct xdr_stream *xdr,
                                  struct compound_hdr *hdr)
 {
        __be32 *p;
-       char machine_name[NFS4_MAX_MACHINE_NAME_LEN];
-       uint32_t len;
        struct nfs_client *clp = args->client;
+       struct rpc_clnt *clnt = clp->cl_rpcclient;
        struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id);
        u32 max_resp_sz_cached;
 
@@ -1814,11 +1804,8 @@ static void encode_create_session(struct xdr_stream *xdr,
        max_resp_sz_cached = (NFS4_dec_open_sz + RPC_REPHDRSIZE +
                              RPC_MAX_AUTH_SIZE + 2) * XDR_UNIT;
 
-       len = scnprintf(machine_name, sizeof(machine_name), "%s",
-                       clp->cl_ipaddr);
-
        encode_op_hdr(xdr, OP_CREATE_SESSION, decode_create_session_maxsz, hdr);
-       p = reserve_space(xdr, 16 + 2*28 + 20 + len + 12);
+       p = reserve_space(xdr, 16 + 2*28 + 20 + clnt->cl_nodelen + 12);
        p = xdr_encode_hyper(p, clp->cl_clientid);
        *p++ = cpu_to_be32(clp->cl_seqid);                      /*Sequence id */
        *p++ = cpu_to_be32(args->flags);                        /*flags */
@@ -1847,7 +1834,7 @@ static void encode_create_session(struct xdr_stream *xdr,
 
        /* authsys_parms rfc1831 */
        *p++ = cpu_to_be32(nn->boot_time.tv_nsec);      /* stamp */
-       p = xdr_encode_opaque(p, machine_name, len);
+       p = xdr_encode_array(p, clnt->cl_nodename, clnt->cl_nodelen);
        *p++ = cpu_to_be32(0);                          /* UID */
        *p++ = cpu_to_be32(0);                          /* GID */
        *p = cpu_to_be32(0);                            /* No more gids */
@@ -2012,11 +1999,11 @@ encode_layoutreturn(struct xdr_stream *xdr,
        p = reserve_space(xdr, 16);
        *p++ = cpu_to_be32(0);          /* reclaim. always 0 for now */
        *p++ = cpu_to_be32(args->layout_type);
-       *p++ = cpu_to_be32(IOMODE_ANY);
+       *p++ = cpu_to_be32(args->range.iomode);
        *p = cpu_to_be32(RETURN_FILE);
        p = reserve_space(xdr, 16);
-       p = xdr_encode_hyper(p, 0);
-       p = xdr_encode_hyper(p, NFS4_MAX_UINT64);
+       p = xdr_encode_hyper(p, args->range.offset);
+       p = xdr_encode_hyper(p, args->range.length);
        spin_lock(&args->inode->i_lock);
        encode_nfs4_stateid(xdr, &args->stateid);
        spin_unlock(&args->inode->i_lock);
@@ -4936,20 +4923,13 @@ out_overflow:
        return -EIO;
 }
 
-static int decode_delegation(struct xdr_stream *xdr, struct nfs_openres *res)
+static int decode_rw_delegation(struct xdr_stream *xdr,
+               uint32_t delegation_type,
+               struct nfs_openres *res)
 {
        __be32 *p;
-       uint32_t delegation_type;
        int status;
 
-       p = xdr_inline_decode(xdr, 4);
-       if (unlikely(!p))
-               goto out_overflow;
-       delegation_type = be32_to_cpup(p);
-       if (delegation_type == NFS4_OPEN_DELEGATE_NONE) {
-               res->delegation_type = 0;
-               return 0;
-       }
        status = decode_stateid(xdr, &res->delegation);
        if (unlikely(status))
                return status;
@@ -4973,6 +4953,52 @@ out_overflow:
        return -EIO;
 }
 
+static int decode_no_delegation(struct xdr_stream *xdr, struct nfs_openres *res)
+{
+       __be32 *p;
+       uint32_t why_no_delegation;
+
+       p = xdr_inline_decode(xdr, 4);
+       if (unlikely(!p))
+               goto out_overflow;
+       why_no_delegation = be32_to_cpup(p);
+       switch (why_no_delegation) {
+               case WND4_CONTENTION:
+               case WND4_RESOURCE:
+                       xdr_inline_decode(xdr, 4);
+                       /* Ignore for now */
+       }
+       return 0;
+out_overflow:
+       print_overflow_msg(__func__, xdr);
+       return -EIO;
+}
+
+static int decode_delegation(struct xdr_stream *xdr, struct nfs_openres *res)
+{
+       __be32 *p;
+       uint32_t delegation_type;
+
+       p = xdr_inline_decode(xdr, 4);
+       if (unlikely(!p))
+               goto out_overflow;
+       delegation_type = be32_to_cpup(p);
+       res->delegation_type = 0;
+       switch (delegation_type) {
+       case NFS4_OPEN_DELEGATE_NONE:
+               return 0;
+       case NFS4_OPEN_DELEGATE_READ:
+       case NFS4_OPEN_DELEGATE_WRITE:
+               return decode_rw_delegation(xdr, delegation_type, res);
+       case NFS4_OPEN_DELEGATE_NONE_EXT:
+               return decode_no_delegation(xdr, res);
+       }
+       return -EIO;
+out_overflow:
+       print_overflow_msg(__func__, xdr);
+       return -EIO;
+}
+
 static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res)
 {
        __be32 *p;
@@ -6567,6 +6593,7 @@ static int nfs4_xdr_dec_read(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
        int status;
 
        status = decode_compound_hdr(xdr, &hdr);
+       res->op_status = hdr.status;
        if (status)
                goto out;
        status = decode_sequence(xdr, &res->seq_res, rqstp);
@@ -6592,6 +6619,7 @@ static int nfs4_xdr_dec_write(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
        int status;
 
        status = decode_compound_hdr(xdr, &hdr);
+       res->op_status = hdr.status;
        if (status)
                goto out;
        status = decode_sequence(xdr, &res->seq_res, rqstp);
@@ -6621,6 +6649,7 @@ static int nfs4_xdr_dec_commit(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
        int status;
 
        status = decode_compound_hdr(xdr, &hdr);
+       res->op_status = hdr.status;
        if (status)
                goto out;
        status = decode_sequence(xdr, &res->seq_res, rqstp);