]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - fs/nfs/nfs4xdr.c
pnfs: layoutreturn
[karo-tx-linux.git] / fs / nfs / nfs4xdr.c
index c3ccd2c468344fab9076214fec8d99fc1eee9036..f2421206435697b0459caf328d4554204f5edfe1 100644 (file)
@@ -338,7 +338,11 @@ static int nfs4_stat_to_errno(int);
                                1 /* layoutupdate4 layout type */ + \
                                1 /* NULL filelayout layoutupdate4 payload */)
 #define decode_layoutcommit_maxsz (op_decode_hdr_maxsz + 3)
-
+#define encode_layoutreturn_maxsz (8 + op_encode_hdr_maxsz + \
+                               encode_stateid_maxsz + \
+                               1 /* FIXME: opaque lrf_body always empty at the moment */)
+#define decode_layoutreturn_maxsz (op_decode_hdr_maxsz + \
+                               1 + decode_stateid_maxsz)
 #else /* CONFIG_NFS_V4_1 */
 #define encode_sequence_maxsz  0
 #define decode_sequence_maxsz  0
@@ -760,7 +764,14 @@ static int nfs4_stat_to_errno(int);
                                decode_putfh_maxsz + \
                                decode_layoutcommit_maxsz + \
                                decode_getattr_maxsz)
-
+#define NFS4_enc_layoutreturn_sz (compound_encode_hdr_maxsz + \
+                               encode_sequence_maxsz + \
+                               encode_putfh_maxsz + \
+                               encode_layoutreturn_maxsz)
+#define NFS4_dec_layoutreturn_sz (compound_decode_hdr_maxsz + \
+                               decode_sequence_maxsz + \
+                               decode_putfh_maxsz + \
+                               decode_layoutreturn_maxsz)
 
 const u32 nfs41_maxwrite_overhead = ((RPC_MAX_HEADER_WITH_AUTH +
                                      compound_encode_hdr_maxsz +
@@ -1889,6 +1900,31 @@ encode_layoutcommit(struct xdr_stream *xdr,
        hdr->replen += decode_layoutcommit_maxsz;
        return 0;
 }
+
+static void
+encode_layoutreturn(struct xdr_stream *xdr,
+                   const struct nfs4_layoutreturn_args *args,
+                   struct compound_hdr *hdr)
+{
+       __be32 *p;
+
+       p = reserve_space(xdr, 20);
+       *p++ = cpu_to_be32(OP_LAYOUTRETURN);
+       *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(RETURN_FILE);
+       p = reserve_space(xdr, 16 + NFS4_STATEID_SIZE);
+       p = xdr_encode_hyper(p, 0);
+       p = xdr_encode_hyper(p, NFS4_MAX_UINT64);
+       spin_lock(&args->inode->i_lock);
+       xdr_encode_opaque_fixed(p, &args->stateid.data, NFS4_STATEID_SIZE);
+       spin_unlock(&args->inode->i_lock);
+       p = reserve_space(xdr, 4);
+       *p = cpu_to_be32(0);
+       hdr->nops++;
+       hdr->replen += decode_layoutreturn_maxsz;
+}
 #endif /* CONFIG_NFS_V4_1 */
 
 /*
@@ -2706,9 +2742,9 @@ static void nfs4_xdr_enc_layoutget(struct rpc_rqst *req,
 /*
  *  Encode LAYOUTCOMMIT request
  */
-static int nfs4_xdr_enc_layoutcommit(struct rpc_rqst *req,
-                                    struct xdr_stream *xdr,
-                                    struct nfs4_layoutcommit_args *args)
+static void nfs4_xdr_enc_layoutcommit(struct rpc_rqst *req,
+                                     struct xdr_stream *xdr,
+                                     struct nfs4_layoutcommit_args *args)
 {
        struct compound_hdr hdr = {
                .minorversion = nfs4_xdr_minorversion(&args->seq_args),
@@ -2720,7 +2756,24 @@ static int nfs4_xdr_enc_layoutcommit(struct rpc_rqst *req,
        encode_layoutcommit(xdr, args, &hdr);
        encode_getfattr(xdr, args->bitmask, &hdr);
        encode_nops(&hdr);
-       return 0;
+}
+
+/*
+ * Encode LAYOUTRETURN request
+ */
+static void nfs4_xdr_enc_layoutreturn(struct rpc_rqst *req,
+                                     struct xdr_stream *xdr,
+                                     struct nfs4_layoutreturn_args *args)
+{
+       struct compound_hdr hdr = {
+               .minorversion = nfs4_xdr_minorversion(&args->seq_args),
+       };
+
+       encode_compound_hdr(xdr, req, &hdr);
+       encode_sequence(xdr, &args->seq_args, &hdr);
+       encode_putfh(xdr, NFS_FH(args->inode), &hdr);
+       encode_layoutreturn(xdr, args, &hdr);
+       encode_nops(&hdr);
 }
 #endif /* CONFIG_NFS_V4_1 */
 
@@ -5203,6 +5256,27 @@ out_overflow:
        return -EIO;
 }
 
+static int decode_layoutreturn(struct xdr_stream *xdr,
+                              struct nfs4_layoutreturn_res *res)
+{
+       __be32 *p;
+       int status;
+
+       status = decode_op_hdr(xdr, OP_LAYOUTRETURN);
+       if (status)
+               return status;
+       p = xdr_inline_decode(xdr, 4);
+       if (unlikely(!p))
+               goto out_overflow;
+       res->lrs_present = be32_to_cpup(p);
+       if (res->lrs_present)
+               status = decode_stateid(xdr, &res->stateid);
+       return status;
+out_overflow:
+       print_overflow_msg(__func__, xdr);
+       return -EIO;
+}
+
 static int decode_layoutcommit(struct xdr_stream *xdr,
                               struct rpc_rqst *req,
                               struct nfs4_layoutcommit_res *res)
@@ -6319,6 +6393,30 @@ out:
        return status;
 }
 
+/*
+ * Decode LAYOUTRETURN response
+ */
+static int nfs4_xdr_dec_layoutreturn(struct rpc_rqst *rqstp,
+                                    struct xdr_stream *xdr,
+                                    struct nfs4_layoutreturn_res *res)
+{
+       struct compound_hdr hdr;
+       int status;
+
+       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_layoutreturn(xdr, res);
+out:
+       return status;
+}
+
 /*
  * Decode LAYOUTCOMMIT response
  */
@@ -6547,6 +6645,7 @@ struct rpc_procinfo       nfs4_procedures[] = {
        PROC(GETDEVICEINFO,     enc_getdeviceinfo,      dec_getdeviceinfo),
        PROC(LAYOUTGET,         enc_layoutget,          dec_layoutget),
        PROC(LAYOUTCOMMIT,      enc_layoutcommit,       dec_layoutcommit),
+       PROC(LAYOUTRETURN,      enc_layoutreturn,       dec_layoutreturn),
 #endif /* CONFIG_NFS_V4_1 */
 };