p = read_buf(xdr, NFS4_STATEID_SIZE);
        if (unlikely(p == NULL))
                return htonl(NFS4ERR_RESOURCE);
-       memcpy(stateid, p, NFS4_STATEID_SIZE);
+       memcpy(stateid->data, p, NFS4_STATEID_SIZE);
        return 0;
 }
 
+static __be32 decode_delegation_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid)
+{
+       stateid->type = NFS4_DELEGATION_STATEID_TYPE;
+       return decode_stateid(xdr, stateid);
+}
+
 static __be32 decode_compound_hdr_arg(struct xdr_stream *xdr, struct cb_compound_hdr_arg *hdr)
 {
        __be32 *p;
        __be32 *p;
        __be32 status;
 
-       status = decode_stateid(xdr, &args->stateid);
+       status = decode_delegation_stateid(xdr, &args->stateid);
        if (unlikely(status != 0))
                goto out;
        p = read_buf(xdr, 4);
 }
 
 #if defined(CONFIG_NFS_V4_1)
+static __be32 decode_layout_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid)
+{
+       stateid->type = NFS4_LAYOUT_STATEID_TYPE;
+       return decode_stateid(xdr, stateid);
+}
 
 static __be32 decode_layoutrecall_args(struct svc_rqst *rqstp,
                                       struct xdr_stream *xdr,
                }
                p = xdr_decode_hyper(p, &args->cbl_range.offset);
                p = xdr_decode_hyper(p, &args->cbl_range.length);
-               status = decode_stateid(xdr, &args->cbl_stateid);
+               status = decode_layout_stateid(xdr, &args->cbl_stateid);
                if (unlikely(status != 0))
                        goto out;
        } else if (args->cbl_recall_type == RETURN_FSID) {
 
        kfree(FF_LAYOUT_FROM_HDR(lo));
 }
 
-static int decode_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid)
+static int decode_pnfs_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid)
 {
        __be32 *p;
 
        p = xdr_inline_decode(xdr, NFS4_STATEID_SIZE);
        if (unlikely(p == NULL))
                return -ENOBUFS;
-       memcpy(stateid, p, NFS4_STATEID_SIZE);
+       stateid->type = NFS4_PNFS_DS_STATEID_TYPE;
+       memcpy(stateid->data, p, NFS4_STATEID_SIZE);
        dprintk("%s: stateid id= [%x%x%x%x]\n", __func__,
                p[0], p[1], p[2], p[3]);
        return 0;
                fls->mirror_array[i]->efficiency = be32_to_cpup(p);
 
                /* stateid */
-               rc = decode_stateid(&stream, &fls->mirror_array[i]->stateid);
+               rc = decode_pnfs_stateid(&stream, &fls->mirror_array[i]->stateid);
                if (rc)
                        goto out_err_free;
 
 
                return e1->opnum < e2->opnum ? -1 : 1;
        if (e1->status != e2->status)
                return e1->status < e2->status ? -1 : 1;
-       ret = memcmp(&e1->stateid, &e2->stateid, sizeof(e1->stateid));
+       ret = memcmp(e1->stateid.data, e2->stateid.data,
+                       sizeof(e1->stateid.data));
        if (ret != 0)
                return ret;
        ret = memcmp(&e1->deviceid, &e2->deviceid, sizeof(e1->deviceid));
 
 
 static inline void nfs4_stateid_copy(nfs4_stateid *dst, const nfs4_stateid *src)
 {
-       memcpy(dst, src, sizeof(*dst));
+       memcpy(dst->data, src->data, sizeof(dst->data));
+       dst->type = src->type;
 }
 
 static inline bool nfs4_stateid_match(const nfs4_stateid *dst, const nfs4_stateid *src)
 {
-       return memcmp(dst, src, sizeof(*dst)) == 0;
+       if (dst->type != src->type)
+               return false;
+       return memcmp(dst->data, src->data, sizeof(dst->data)) == 0;
 }
 
 static inline bool nfs4_stateid_match_other(const nfs4_stateid *dst, const nfs4_stateid *src)
 
 static bool nfs41_match_stateid(const nfs4_stateid *s1,
                const nfs4_stateid *s2)
 {
+       if (s1->type != s2->type)
+               return false;
+
        if (memcmp(s1->other, s2->other, sizeof(s1->other)) != 0)
                return false;
 
 
 
 #define OPENOWNER_POOL_SIZE    8
 
-const nfs4_stateid zero_stateid;
+const nfs4_stateid zero_stateid = {
+       .data = { 0 },
+       .type = NFS4_SPECIAL_STATEID_TYPE,
+};
 static DEFINE_MUTEX(nfs_clid_init_mutex);
 
 int nfs4_init_clientid(struct nfs_client *clp, struct rpc_cred *cred)
 
        return decode_opaque_fixed(xdr, stateid, NFS4_STATEID_SIZE);
 }
 
+static int decode_open_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid)
+{
+       stateid->type = NFS4_OPEN_STATEID_TYPE;
+       return decode_stateid(xdr, stateid);
+}
+
+static int decode_lock_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid)
+{
+       stateid->type = NFS4_LOCK_STATEID_TYPE;
+       return decode_stateid(xdr, stateid);
+}
+
+static int decode_delegation_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid)
+{
+       stateid->type = NFS4_DELEGATION_STATEID_TYPE;
+       return decode_stateid(xdr, stateid);
+}
+
 static int decode_close(struct xdr_stream *xdr, struct nfs_closeres *res)
 {
        int status;
        if (status != -EIO)
                nfs_increment_open_seqid(status, res->seqid);
        if (!status)
-               status = decode_stateid(xdr, &res->stateid);
+               status = decode_open_stateid(xdr, &res->stateid);
        return status;
 }
 
        if (status == -EIO)
                goto out;
        if (status == 0) {
-               status = decode_stateid(xdr, &res->stateid);
+               status = decode_lock_stateid(xdr, &res->stateid);
                if (unlikely(status))
                        goto out;
        } else if (status == -NFS4ERR_DENIED)
        if (status != -EIO)
                nfs_increment_lock_seqid(status, res->seqid);
        if (status == 0)
-               status = decode_stateid(xdr, &res->stateid);
+               status = decode_lock_stateid(xdr, &res->stateid);
        return status;
 }
 
        __be32 *p;
        int status;
 
-       status = decode_stateid(xdr, &res->delegation);
+       status = decode_delegation_stateid(xdr, &res->delegation);
        if (unlikely(status))
                return status;
        p = xdr_inline_decode(xdr, 4);
        nfs_increment_open_seqid(status, res->seqid);
        if (status)
                return status;
-       status = decode_stateid(xdr, &res->stateid);
+       status = decode_open_stateid(xdr, &res->stateid);
        if (unlikely(status))
                return status;
 
        if (status != -EIO)
                nfs_increment_open_seqid(status, res->seqid);
        if (!status)
-               status = decode_stateid(xdr, &res->stateid);
+               status = decode_open_stateid(xdr, &res->stateid);
        return status;
 }
 
        if (status != -EIO)
                nfs_increment_open_seqid(status, res->seqid);
        if (!status)
-               status = decode_stateid(xdr, &res->stateid);
+               status = decode_open_stateid(xdr, &res->stateid);
        return status;
 }
 
 }
 
 #if defined(CONFIG_NFS_V4_1)
+static int decode_layout_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid)
+{
+       stateid->type = NFS4_LAYOUT_STATEID_TYPE;
+       return decode_stateid(xdr, stateid);
+}
+
 static int decode_getdeviceinfo(struct xdr_stream *xdr,
                                struct nfs4_getdeviceinfo_res *res)
 {
        if (unlikely(!p))
                goto out_overflow;
        res->return_on_close = be32_to_cpup(p);
-       decode_stateid(xdr, &res->stateid);
+       decode_layout_stateid(xdr, &res->stateid);
        p = xdr_inline_decode(xdr, 4);
        if (unlikely(!p))
                goto out_overflow;
                goto out_overflow;
        res->lrs_present = be32_to_cpup(p);
        if (res->lrs_present)
-               status = decode_stateid(xdr, &res->stateid);
+               status = decode_layout_stateid(xdr, &res->stateid);
        return status;
 out_overflow:
        print_overflow_msg(__func__, xdr);
 
 
 typedef struct { char data[NFS4_VERIFIER_SIZE]; } nfs4_verifier;
 
-struct nfs_stateid4 {
-       __be32 seqid;
-       char other[NFS4_STATEID_OTHER_SIZE];
-} __attribute__ ((packed));
+struct nfs4_stateid_struct {
+       union {
+               char data[NFS4_STATEID_SIZE];
+               struct {
+                       __be32 seqid;
+                       char other[NFS4_STATEID_OTHER_SIZE];
+               } __attribute__ ((packed));
+       };
+
+       enum {
+               NFS4_INVALID_STATEID_TYPE = 0,
+               NFS4_SPECIAL_STATEID_TYPE,
+               NFS4_OPEN_STATEID_TYPE,
+               NFS4_LOCK_STATEID_TYPE,
+               NFS4_DELEGATION_STATEID_TYPE,
+               NFS4_LAYOUT_STATEID_TYPE,
+               NFS4_PNFS_DS_STATEID_TYPE,
+       } type;
+};
 
-typedef struct nfs_stateid4 nfs4_stateid;
+typedef struct nfs4_stateid_struct nfs4_stateid;
 
 enum nfs_opnum4 {
        OP_ACCESS = 3,