NFS: Split attribute support out from the server capabilities
authorTrond Myklebust <trond.myklebust@primarydata.com>
Mon, 5 Mar 2018 20:01:18 +0000 (15:01 -0500)
committerTrond Myklebust <trond.myklebust@hammerspace.com>
Wed, 14 Apr 2021 13:36:29 +0000 (09:36 -0400)
There are lots of attributes, and they are crowding out the bit space.

Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
fs/nfs/client.c
fs/nfs/inode.c
fs/nfs/nfs4proc.c
include/linux/nfs_fs_sb.h

index 2aeb4e52a4f1ca6a199fa14fadd1acebf5583ab8..cfeaadf56bf0622b54559a228659b16ebd8e1e18 100644 (file)
@@ -696,9 +696,18 @@ static int nfs_init_server(struct nfs_server *server,
        /* Initialise the client representation from the mount data */
        server->flags = ctx->flags;
        server->options = ctx->options;
-       server->caps |= NFS_CAP_HARDLINKS|NFS_CAP_SYMLINKS|NFS_CAP_FILEID|
-               NFS_CAP_MODE|NFS_CAP_NLINK|NFS_CAP_OWNER|NFS_CAP_OWNER_GROUP|
-               NFS_CAP_ATIME|NFS_CAP_CTIME|NFS_CAP_MTIME;
+       server->caps |= NFS_CAP_HARDLINKS | NFS_CAP_SYMLINKS;
+
+       switch (clp->rpc_ops->version) {
+       case 2:
+               server->fattr_valid = NFS_ATTR_FATTR_V2;
+               break;
+       case 3:
+               server->fattr_valid = NFS_ATTR_FATTR_V3;
+               break;
+       default:
+               server->fattr_valid = NFS_ATTR_FATTR_V4;
+       }
 
        if (ctx->rsize)
                server->rsize = nfs_block_size(ctx->rsize, NULL);
index 7fa914e24fc4cd1d3999684aa1fa35abf0e45b87..6d04ebb4f08404e28284ed3b8a1ec3b2b6b7b09f 100644 (file)
@@ -438,6 +438,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr, st
                .fattr  = fattr
        };
        struct inode *inode = ERR_PTR(-ENOENT);
+       u64 fattr_supported = NFS_SB(sb)->fattr_valid;
        unsigned long hash;
 
        nfs_attr_check_mountpoint(sb, fattr);
@@ -470,7 +471,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr, st
                inode->i_mode = fattr->mode;
                nfsi->cache_validity = 0;
                if ((fattr->valid & NFS_ATTR_FATTR_MODE) == 0
-                               && nfs_server_capable(inode, NFS_CAP_MODE))
+                               && (fattr_supported & NFS_ATTR_FATTR_MODE))
                        nfs_set_cache_invalid(inode, NFS_INO_INVALID_MODE);
                /* Why so? Because we want revalidate for devices/FIFOs, and
                 * that's precisely what we have in nfs_file_inode_operations.
@@ -516,15 +517,15 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr, st
                nfsi->attr_gencount = fattr->gencount;
                if (fattr->valid & NFS_ATTR_FATTR_ATIME)
                        inode->i_atime = fattr->atime;
-               else if (nfs_server_capable(inode, NFS_CAP_ATIME))
+               else if (fattr_supported & NFS_ATTR_FATTR_ATIME)
                        nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATIME);
                if (fattr->valid & NFS_ATTR_FATTR_MTIME)
                        inode->i_mtime = fattr->mtime;
-               else if (nfs_server_capable(inode, NFS_CAP_MTIME))
+               else if (fattr_supported & NFS_ATTR_FATTR_MTIME)
                        nfs_set_cache_invalid(inode, NFS_INO_INVALID_MTIME);
                if (fattr->valid & NFS_ATTR_FATTR_CTIME)
                        inode->i_ctime = fattr->ctime;
-               else if (nfs_server_capable(inode, NFS_CAP_CTIME))
+               else if (fattr_supported & NFS_ATTR_FATTR_CTIME)
                        nfs_set_cache_invalid(inode, NFS_INO_INVALID_CTIME);
                if (fattr->valid & NFS_ATTR_FATTR_CHANGE)
                        inode_set_iversion_raw(inode, fattr->change_attr);
@@ -536,26 +537,30 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr, st
                        nfs_set_cache_invalid(inode, NFS_INO_INVALID_SIZE);
                if (fattr->valid & NFS_ATTR_FATTR_NLINK)
                        set_nlink(inode, fattr->nlink);
-               else if (nfs_server_capable(inode, NFS_CAP_NLINK))
+               else if (fattr_supported & NFS_ATTR_FATTR_NLINK)
                        nfs_set_cache_invalid(inode, NFS_INO_INVALID_NLINK);
                if (fattr->valid & NFS_ATTR_FATTR_OWNER)
                        inode->i_uid = fattr->uid;
-               else if (nfs_server_capable(inode, NFS_CAP_OWNER))
+               else if (fattr_supported & NFS_ATTR_FATTR_OWNER)
                        nfs_set_cache_invalid(inode, NFS_INO_INVALID_OTHER);
                if (fattr->valid & NFS_ATTR_FATTR_GROUP)
                        inode->i_gid = fattr->gid;
-               else if (nfs_server_capable(inode, NFS_CAP_OWNER_GROUP))
+               else if (fattr_supported & NFS_ATTR_FATTR_GROUP)
                        nfs_set_cache_invalid(inode, NFS_INO_INVALID_OTHER);
                if (nfs_server_capable(inode, NFS_CAP_XATTR))
                        nfs_set_cache_invalid(inode, NFS_INO_INVALID_XATTR);
                if (fattr->valid & NFS_ATTR_FATTR_BLOCKS_USED)
                        inode->i_blocks = fattr->du.nfs2.blocks;
-               else if (fattr->valid & NFS_ATTR_FATTR_SPACE_USED) {
+               else if (fattr_supported & NFS_ATTR_FATTR_BLOCKS_USED &&
+                        fattr->size != 0)
+                       nfs_set_cache_invalid(inode, NFS_INO_INVALID_BLOCKS);
+               if (fattr->valid & NFS_ATTR_FATTR_SPACE_USED) {
                        /*
                         * report the blocks in 512byte units
                         */
                        inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used);
-               } else if (fattr->size != 0)
+               } else if (fattr_supported & NFS_ATTR_FATTR_SPACE_USED &&
+                          fattr->size != 0)
                        nfs_set_cache_invalid(inode, NFS_INO_INVALID_BLOCKS);
 
                nfs_setsecurity(inode, fattr, label);
@@ -1952,9 +1957,10 @@ EXPORT_SYMBOL_GPL(nfs_post_op_update_inode_force_wcc);
  */
 static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
 {
-       struct nfs_server *server;
+       struct nfs_server *server = NFS_SERVER(inode);
        struct nfs_inode *nfsi = NFS_I(inode);
        loff_t cur_isize, new_isize;
+       u64 fattr_supported = server->fattr_valid;
        unsigned long invalid = 0;
        unsigned long now = jiffies;
        unsigned long save_cache_validity;
@@ -1998,7 +2004,6 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
                goto out_err;
        }
 
-       server = NFS_SERVER(inode);
        /* Update the fsid? */
        if (S_ISDIR(inode->i_mode) && (fattr->valid & NFS_ATTR_FATTR_FSID) &&
                        !nfs_fsid_equal(&server->fsid, &fattr->fsid) &&
@@ -2066,7 +2071,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
 
        if (fattr->valid & NFS_ATTR_FATTR_MTIME) {
                inode->i_mtime = fattr->mtime;
-       } else if (server->caps & NFS_CAP_MTIME) {
+       } else if (fattr_supported & NFS_ATTR_FATTR_MTIME) {
                nfsi->cache_validity |=
                        save_cache_validity & NFS_INO_INVALID_MTIME;
                cache_revalidated = false;
@@ -2074,7 +2079,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
 
        if (fattr->valid & NFS_ATTR_FATTR_CTIME) {
                inode->i_ctime = fattr->ctime;
-       } else if (server->caps & NFS_CAP_CTIME) {
+       } else if (fattr_supported & NFS_ATTR_FATTR_CTIME) {
                nfsi->cache_validity |=
                        save_cache_validity & NFS_INO_INVALID_CTIME;
                cache_revalidated = false;
@@ -2114,7 +2119,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
 
        if (fattr->valid & NFS_ATTR_FATTR_ATIME)
                inode->i_atime = fattr->atime;
-       else if (server->caps & NFS_CAP_ATIME) {
+       else if (fattr_supported & NFS_ATTR_FATTR_ATIME) {
                nfsi->cache_validity |=
                        save_cache_validity & NFS_INO_INVALID_ATIME;
                cache_revalidated = false;
@@ -2129,7 +2134,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
                                | NFS_INO_INVALID_ACL;
                        attr_changed = true;
                }
-       } else if (server->caps & NFS_CAP_MODE) {
+       } else if (fattr_supported & NFS_ATTR_FATTR_MODE) {
                nfsi->cache_validity |=
                        save_cache_validity & NFS_INO_INVALID_MODE;
                cache_revalidated = false;
@@ -2142,7 +2147,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
                        inode->i_uid = fattr->uid;
                        attr_changed = true;
                }
-       } else if (server->caps & NFS_CAP_OWNER) {
+       } else if (fattr_supported & NFS_ATTR_FATTR_OWNER) {
                nfsi->cache_validity |=
                        save_cache_validity & NFS_INO_INVALID_OTHER;
                cache_revalidated = false;
@@ -2155,7 +2160,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
                        inode->i_gid = fattr->gid;
                        attr_changed = true;
                }
-       } else if (server->caps & NFS_CAP_OWNER_GROUP) {
+       } else if (fattr_supported & NFS_ATTR_FATTR_GROUP) {
                nfsi->cache_validity |=
                        save_cache_validity & NFS_INO_INVALID_OTHER;
                cache_revalidated = false;
@@ -2168,7 +2173,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
                        set_nlink(inode, fattr->nlink);
                        attr_changed = true;
                }
-       } else if (server->caps & NFS_CAP_NLINK) {
+       } else if (fattr_supported & NFS_ATTR_FATTR_NLINK) {
                nfsi->cache_validity |=
                        save_cache_validity & NFS_INO_INVALID_NLINK;
                cache_revalidated = false;
@@ -2179,9 +2184,15 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
                 * report the blocks in 512byte units
                 */
                inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used);
-       } else if (fattr->valid & NFS_ATTR_FATTR_BLOCKS_USED)
+       } else if (fattr_supported & NFS_ATTR_FATTR_SPACE_USED) {
+               nfsi->cache_validity |=
+                       save_cache_validity & NFS_INO_INVALID_BLOCKS;
+               cache_revalidated = false;
+       }
+
+       if (fattr->valid & NFS_ATTR_FATTR_BLOCKS_USED) {
                inode->i_blocks = fattr->du.nfs2.blocks;
-       else {
+       } else if (fattr_supported & NFS_ATTR_FATTR_BLOCKS_USED) {
                nfsi->cache_validity |=
                        save_cache_validity & NFS_INO_INVALID_BLOCKS;
                cache_revalidated = false;
index bcbb057d5529158eb509d22c9fccbed3c71f3ad5..21c31aebb1168462ce81b682c6434f03bc4d9c04 100644 (file)
@@ -3868,12 +3868,9 @@ static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f
                        res.attr_bitmask[2] &= FATTR4_WORD2_NFS42_MASK;
                }
                memcpy(server->attr_bitmask, res.attr_bitmask, sizeof(server->attr_bitmask));
-               server->caps &= ~(NFS_CAP_ACLS|NFS_CAP_HARDLINKS|
-                               NFS_CAP_SYMLINKS|NFS_CAP_FILEID|
-                               NFS_CAP_MODE|NFS_CAP_NLINK|NFS_CAP_OWNER|
-                               NFS_CAP_OWNER_GROUP|NFS_CAP_ATIME|
-                               NFS_CAP_CTIME|NFS_CAP_MTIME|
-                               NFS_CAP_SECURITY_LABEL);
+               server->caps &= ~(NFS_CAP_ACLS | NFS_CAP_HARDLINKS |
+                                 NFS_CAP_SYMLINKS| NFS_CAP_SECURITY_LABEL);
+               server->fattr_valid = NFS_ATTR_FATTR_V4;
                if (res.attr_bitmask[0] & FATTR4_WORD0_ACL &&
                                res.acl_bitmask & ACL4_SUPPORT_ALLOW_ACL)
                        server->caps |= NFS_CAP_ACLS;
@@ -3881,25 +3878,29 @@ static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f
                        server->caps |= NFS_CAP_HARDLINKS;
                if (res.has_symlinks != 0)
                        server->caps |= NFS_CAP_SYMLINKS;
-               if (res.attr_bitmask[0] & FATTR4_WORD0_FILEID)
-                       server->caps |= NFS_CAP_FILEID;
-               if (res.attr_bitmask[1] & FATTR4_WORD1_MODE)
-                       server->caps |= NFS_CAP_MODE;
-               if (res.attr_bitmask[1] & FATTR4_WORD1_NUMLINKS)
-                       server->caps |= NFS_CAP_NLINK;
-               if (res.attr_bitmask[1] & FATTR4_WORD1_OWNER)
-                       server->caps |= NFS_CAP_OWNER;
-               if (res.attr_bitmask[1] & FATTR4_WORD1_OWNER_GROUP)
-                       server->caps |= NFS_CAP_OWNER_GROUP;
-               if (res.attr_bitmask[1] & FATTR4_WORD1_TIME_ACCESS)
-                       server->caps |= NFS_CAP_ATIME;
-               if (res.attr_bitmask[1] & FATTR4_WORD1_TIME_METADATA)
-                       server->caps |= NFS_CAP_CTIME;
-               if (res.attr_bitmask[1] & FATTR4_WORD1_TIME_MODIFY)
-                       server->caps |= NFS_CAP_MTIME;
+               if (!(res.attr_bitmask[0] & FATTR4_WORD0_FILEID))
+                       server->fattr_valid &= ~NFS_ATTR_FATTR_FILEID;
+               if (!(res.attr_bitmask[1] & FATTR4_WORD1_MODE))
+                       server->fattr_valid &= ~NFS_ATTR_FATTR_MODE;
+               if (!(res.attr_bitmask[1] & FATTR4_WORD1_NUMLINKS))
+                       server->fattr_valid &= ~NFS_ATTR_FATTR_NLINK;
+               if (!(res.attr_bitmask[1] & FATTR4_WORD1_OWNER))
+                       server->fattr_valid &= ~(NFS_ATTR_FATTR_OWNER |
+                               NFS_ATTR_FATTR_OWNER_NAME);
+               if (!(res.attr_bitmask[1] & FATTR4_WORD1_OWNER_GROUP))
+                       server->fattr_valid &= ~(NFS_ATTR_FATTR_GROUP |
+                               NFS_ATTR_FATTR_GROUP_NAME);
+               if (!(res.attr_bitmask[1] & FATTR4_WORD1_SPACE_USED))
+                       server->fattr_valid &= ~NFS_ATTR_FATTR_SPACE_USED;
+               if (!(res.attr_bitmask[1] & FATTR4_WORD1_TIME_ACCESS))
+                       server->fattr_valid &= ~NFS_ATTR_FATTR_ATIME;
+               if (!(res.attr_bitmask[1] & FATTR4_WORD1_TIME_METADATA))
+                       server->fattr_valid &= ~NFS_ATTR_FATTR_CTIME;
+               if (!(res.attr_bitmask[1] & FATTR4_WORD1_TIME_MODIFY))
+                       server->fattr_valid &= ~NFS_ATTR_FATTR_MTIME;
 #ifdef CONFIG_NFS_V4_SECURITY_LABEL
-               if (res.attr_bitmask[2] & FATTR4_WORD2_SECURITY_LABEL)
-                       server->caps |= NFS_CAP_SECURITY_LABEL;
+               if (!(res.attr_bitmask[2] & FATTR4_WORD2_SECURITY_LABEL))
+                       server->fattr_valid &= ~NFS_ATTR_FATTR_V4_SECURITY_LABEL;
 #endif
                memcpy(server->attr_bitmask_nl, res.attr_bitmask,
                                sizeof(server->attr_bitmask));
index fbcdfd9f7a7f865ffeb6fafb8865b67a2e4304cb..d28d7a62864f76175e3dfb07bde0d669dcbaaa49 100644 (file)
@@ -191,6 +191,8 @@ struct nfs_server {
        dev_t                   s_dev;          /* superblock dev numbers */
        struct nfs_auth_info    auth_info;      /* parsed auth flavors */
 
+       __u64                   fattr_valid;    /* Valid attributes */
+
 #ifdef CONFIG_NFS_FSCACHE
        struct nfs_fscache_key  *fscache_key;   /* unique key for superblock */
        struct fscache_cookie   *fscache;       /* superblock cookie */
@@ -267,16 +269,7 @@ struct nfs_server {
 #define NFS_CAP_SYMLINKS       (1U << 2)
 #define NFS_CAP_ACLS           (1U << 3)
 #define NFS_CAP_ATOMIC_OPEN    (1U << 4)
-/* #define NFS_CAP_CHANGE_ATTR (1U << 5) */
 #define NFS_CAP_LGOPEN         (1U << 5)
-#define NFS_CAP_FILEID         (1U << 6)
-#define NFS_CAP_MODE           (1U << 7)
-#define NFS_CAP_NLINK          (1U << 8)
-#define NFS_CAP_OWNER          (1U << 9)
-#define NFS_CAP_OWNER_GROUP    (1U << 10)
-#define NFS_CAP_ATIME          (1U << 11)
-#define NFS_CAP_CTIME          (1U << 12)
-#define NFS_CAP_MTIME          (1U << 13)
 #define NFS_CAP_POSIX_LOCK     (1U << 14)
 #define NFS_CAP_UIDGID_NOMAP   (1U << 15)
 #define NFS_CAP_STATEID_NFSV41 (1U << 16)