NFS: Get suppattr_exclcreat when getting server capabilities
authorKinglong Mee <kinglongmee@gmail.com>
Wed, 26 Aug 2015 13:12:58 +0000 (21:12 +0800)
committerTrond Myklebust <trond.myklebust@primarydata.com>
Thu, 27 Aug 2015 23:45:27 +0000 (19:45 -0400)
Create file with attributs as NFS4_CREATE_EXCLUSIVE4_1 mode
depends on suppattr_exclcreat attribut.

v3, same as v2.

Signed-off-by: Kinglong Mee <kinglongmee@gmail.com>
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
fs/nfs/nfs4proc.c
fs/nfs/nfs4xdr.c
include/linux/nfs_fs_sb.h
include/linux/nfs_xdr.h

index 4687661bfbdcd0d61cf45c7186b48a84daebb02c..a6a28d45cca4a70ef9d3cc47c5d8609f844dff73 100644 (file)
@@ -2893,8 +2893,10 @@ static void nfs4_close_context(struct nfs_open_context *ctx, int is_sync)
 
 static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle)
 {
+       u32 bitmask[3] = {}, minorversion = server->nfs_client->cl_minorversion;
        struct nfs4_server_caps_arg args = {
                .fhandle = fhandle,
+               .bitmask = bitmask,
        };
        struct nfs4_server_caps_res res = {};
        struct rpc_message msg = {
@@ -2904,10 +2906,18 @@ static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f
        };
        int status;
 
+       bitmask[0] = FATTR4_WORD0_SUPPORTED_ATTRS |
+                    FATTR4_WORD0_FH_EXPIRE_TYPE |
+                    FATTR4_WORD0_LINK_SUPPORT |
+                    FATTR4_WORD0_SYMLINK_SUPPORT |
+                    FATTR4_WORD0_ACLSUPPORT;
+       if (minorversion)
+               bitmask[2] = FATTR4_WORD2_SUPPATTR_EXCLCREAT;
+
        status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
        if (status == 0) {
                /* Sanity check the server answers */
-               switch (server->nfs_client->cl_minorversion) {
+               switch (minorversion) {
                case 0:
                        res.attr_bitmask[1] &= FATTR4_WORD1_NFS40_MASK;
                        res.attr_bitmask[2] = 0;
@@ -2960,6 +2970,8 @@ static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f
                server->cache_consistency_bitmask[0] &= FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE;
                server->cache_consistency_bitmask[1] &= FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY;
                server->cache_consistency_bitmask[2] = 0;
+               memcpy(server->exclcreat_bitmask, res.exclcreat_bitmask,
+                       sizeof(server->exclcreat_bitmask));
                server->acl_bitmask = res.acl_bitmask;
                server->fh_expire_type = res.fh_expire_type;
        }
index c42459e45f622c8b13a1dcf7c77d00bdf99d2da6..ad8dde12f23bc85aeff71b272b9743ff538b52bc 100644 (file)
@@ -2582,6 +2582,7 @@ static void nfs4_xdr_enc_server_caps(struct rpc_rqst *req,
                                     struct xdr_stream *xdr,
                                     struct nfs4_server_caps_arg *args)
 {
+       const u32 *bitmask = args->bitmask;
        struct compound_hdr hdr = {
                .minorversion = nfs4_xdr_minorversion(&args->seq_args),
        };
@@ -2589,11 +2590,7 @@ static void nfs4_xdr_enc_server_caps(struct rpc_rqst *req,
        encode_compound_hdr(xdr, req, &hdr);
        encode_sequence(xdr, &args->seq_args, &hdr);
        encode_putfh(xdr, args->fhandle, &hdr);
-       encode_getattr_one(xdr, FATTR4_WORD0_SUPPORTED_ATTRS|
-                          FATTR4_WORD0_FH_EXPIRE_TYPE|
-                          FATTR4_WORD0_LINK_SUPPORT|
-                          FATTR4_WORD0_SYMLINK_SUPPORT|
-                          FATTR4_WORD0_ACLSUPPORT, &hdr);
+       encode_getattr_three(xdr, bitmask[0], bitmask[1], bitmask[2], &hdr);
        encode_nops(&hdr);
 }
 
@@ -3370,6 +3367,22 @@ out_overflow:
        return -EIO;
 }
 
+static int decode_attr_exclcreat_supported(struct xdr_stream *xdr,
+                                uint32_t *bitmap, uint32_t *bitmask)
+{
+       if (likely(bitmap[2] & FATTR4_WORD2_SUPPATTR_EXCLCREAT)) {
+               int ret;
+               ret = decode_attr_bitmap(xdr, bitmask);
+               if (unlikely(ret < 0))
+                       return ret;
+               bitmap[2] &= ~FATTR4_WORD2_SUPPATTR_EXCLCREAT;
+       } else
+               bitmask[0] = bitmask[1] = bitmask[2] = 0;
+       dprintk("%s: bitmask=%08x:%08x:%08x\n", __func__,
+               bitmask[0], bitmask[1], bitmask[2]);
+       return 0;
+}
+
 static int decode_attr_filehandle(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_fh *fh)
 {
        __be32 *p;
@@ -4323,6 +4336,9 @@ static int decode_server_caps(struct xdr_stream *xdr, struct nfs4_server_caps_re
                goto xdr_error;
        if ((status = decode_attr_aclsupport(xdr, bitmap, &res->acl_bitmask)) != 0)
                goto xdr_error;
+       if ((status = decode_attr_exclcreat_supported(xdr, bitmap,
+                               res->exclcreat_bitmask)) != 0)
+               goto xdr_error;
        status = verify_attr_len(xdr, savep, attrlen);
 xdr_error:
        dprintk("%s: xdr returned %d!\n", __func__, -status);
index 20bc8e51b16124496326274e84fc12d61996a4fd..570a7df2775b599eab0d59ad9e92b888f60dec87 100644 (file)
@@ -173,6 +173,11 @@ struct nfs_server {
                                                   set of attributes supported
                                                   on this filesystem excluding
                                                   the label support bit. */
+       u32                     exclcreat_bitmask[3];
+                                               /* V4 bitmask representing the
+                                                  set of attributes supported
+                                                  on this filesystem for the
+                                                  exclusive create. */
        u32                     cache_consistency_bitmask[3];
                                                /* V4 bitmask representing the subset
                                                   of change attribute, size, ctime
index b9b530409ff7c7b95618df3b754bff121e7bfc26..0d7c832ec41527a8da86384d36ddf9351d411189 100644 (file)
@@ -1057,11 +1057,13 @@ struct nfs4_statfs_res {
 struct nfs4_server_caps_arg {
        struct nfs4_sequence_args       seq_args;
        struct nfs_fh                  *fhandle;
+       const u32 *                     bitmask;
 };
 
 struct nfs4_server_caps_res {
        struct nfs4_sequence_res        seq_res;
        u32                             attr_bitmask[3];
+       u32                             exclcreat_bitmask[3];
        u32                             acl_bitmask;
        u32                             has_links;
        u32                             has_symlinks;