Commit 720869eb authored by Trond Myklebust's avatar Trond Myklebust

NFS: Separate tracking of file mode cache validity from the uid/gid

chown()/chgrp() and chmod() are separate operations, and in addition,
there are mode operations that are performed automatically by the
server. So let's track mode validity separately from the file ownership
validity.
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
parent fabf2b34
...@@ -2948,7 +2948,7 @@ static int nfs_execute_ok(struct inode *inode, int mask) ...@@ -2948,7 +2948,7 @@ static int nfs_execute_ok(struct inode *inode, int mask)
if (S_ISDIR(inode->i_mode)) if (S_ISDIR(inode->i_mode))
return 0; return 0;
if (nfs_check_cache_invalid(inode, NFS_INO_INVALID_OTHER)) { if (nfs_check_cache_invalid(inode, NFS_INO_INVALID_MODE)) {
if (mask & MAY_NOT_BLOCK) if (mask & MAY_NOT_BLOCK)
return -ECHILD; return -ECHILD;
ret = __nfs_revalidate_inode(server, inode); ret = __nfs_revalidate_inode(server, inode);
...@@ -3006,7 +3006,8 @@ int nfs_permission(struct user_namespace *mnt_userns, ...@@ -3006,7 +3006,8 @@ int nfs_permission(struct user_namespace *mnt_userns,
if (mask & MAY_NOT_BLOCK) if (mask & MAY_NOT_BLOCK)
return -ECHILD; return -ECHILD;
res = nfs_revalidate_inode(inode, NFS_INO_INVALID_OTHER); res = nfs_revalidate_inode(inode, NFS_INO_INVALID_MODE |
NFS_INO_INVALID_OTHER);
if (res == 0) if (res == 0)
res = generic_permission(&init_user_ns, inode, mask); res = generic_permission(&init_user_ns, inode, mask);
goto out; goto out;
......
...@@ -199,7 +199,8 @@ void nfs_set_cache_invalid(struct inode *inode, unsigned long flags) ...@@ -199,7 +199,8 @@ void nfs_set_cache_invalid(struct inode *inode, unsigned long flags)
if (have_delegation) { if (have_delegation) {
if (!(flags & NFS_INO_REVAL_FORCED)) if (!(flags & NFS_INO_REVAL_FORCED))
flags &= ~NFS_INO_INVALID_OTHER; flags &= ~(NFS_INO_INVALID_MODE |
NFS_INO_INVALID_OTHER);
flags &= ~(NFS_INO_INVALID_CHANGE flags &= ~(NFS_INO_INVALID_CHANGE
| NFS_INO_INVALID_SIZE | NFS_INO_INVALID_SIZE
| NFS_INO_INVALID_XATTR); | NFS_INO_INVALID_XATTR);
...@@ -472,7 +473,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr, st ...@@ -472,7 +473,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr, st
nfsi->cache_validity = 0; nfsi->cache_validity = 0;
if ((fattr->valid & NFS_ATTR_FATTR_MODE) == 0 if ((fattr->valid & NFS_ATTR_FATTR_MODE) == 0
&& nfs_server_capable(inode, NFS_CAP_MODE)) && nfs_server_capable(inode, NFS_CAP_MODE))
nfs_set_cache_invalid(inode, NFS_INO_INVALID_OTHER); nfs_set_cache_invalid(inode, NFS_INO_INVALID_MODE);
/* Why so? Because we want revalidate for devices/FIFOs, and /* Why so? Because we want revalidate for devices/FIFOs, and
* that's precisely what we have in nfs_file_inode_operations. * that's precisely what we have in nfs_file_inode_operations.
*/ */
...@@ -803,8 +804,10 @@ static u32 nfs_get_valid_attrmask(struct inode *inode) ...@@ -803,8 +804,10 @@ static u32 nfs_get_valid_attrmask(struct inode *inode)
reply_mask |= STATX_SIZE; reply_mask |= STATX_SIZE;
if (!(cache_validity & NFS_INO_INVALID_NLINK)) if (!(cache_validity & NFS_INO_INVALID_NLINK))
reply_mask |= STATX_NLINK; reply_mask |= STATX_NLINK;
if (!(cache_validity & NFS_INO_INVALID_MODE))
reply_mask |= STATX_MODE;
if (!(cache_validity & NFS_INO_INVALID_OTHER)) if (!(cache_validity & NFS_INO_INVALID_OTHER))
reply_mask |= STATX_UID | STATX_GID | STATX_MODE; reply_mask |= STATX_UID | STATX_GID;
if (!(cache_validity & NFS_INO_INVALID_BLOCKS)) if (!(cache_validity & NFS_INO_INVALID_BLOCKS))
reply_mask |= STATX_BLOCKS; reply_mask |= STATX_BLOCKS;
return reply_mask; return reply_mask;
...@@ -872,7 +875,9 @@ int nfs_getattr(struct user_namespace *mnt_userns, const struct path *path, ...@@ -872,7 +875,9 @@ int nfs_getattr(struct user_namespace *mnt_userns, const struct path *path,
do_update |= cache_validity & NFS_INO_INVALID_SIZE; do_update |= cache_validity & NFS_INO_INVALID_SIZE;
if (request_mask & STATX_NLINK) if (request_mask & STATX_NLINK)
do_update |= cache_validity & NFS_INO_INVALID_NLINK; do_update |= cache_validity & NFS_INO_INVALID_NLINK;
if (request_mask & (STATX_UID | STATX_GID | STATX_MODE)) if (request_mask & STATX_MODE)
do_update |= cache_validity & NFS_INO_INVALID_MODE;
if (request_mask & (STATX_UID | STATX_GID))
do_update |= cache_validity & NFS_INO_INVALID_OTHER; do_update |= cache_validity & NFS_INO_INVALID_OTHER;
if (request_mask & STATX_BLOCKS) if (request_mask & STATX_BLOCKS)
do_update |= cache_validity & NFS_INO_INVALID_BLOCKS; do_update |= cache_validity & NFS_INO_INVALID_BLOCKS;
...@@ -1510,7 +1515,7 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat ...@@ -1510,7 +1515,7 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat
if ((fattr->valid & NFS_ATTR_FATTR_MODE) && (inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO)) if ((fattr->valid & NFS_ATTR_FATTR_MODE) && (inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO))
invalid |= NFS_INO_INVALID_ACCESS invalid |= NFS_INO_INVALID_ACCESS
| NFS_INO_INVALID_ACL | NFS_INO_INVALID_ACL
| NFS_INO_INVALID_OTHER; | NFS_INO_INVALID_MODE;
if ((fattr->valid & NFS_ATTR_FATTR_OWNER) && !uid_eq(inode->i_uid, fattr->uid)) if ((fattr->valid & NFS_ATTR_FATTR_OWNER) && !uid_eq(inode->i_uid, fattr->uid))
invalid |= NFS_INO_INVALID_ACCESS invalid |= NFS_INO_INVALID_ACCESS
| NFS_INO_INVALID_ACL | NFS_INO_INVALID_ACL
...@@ -1947,6 +1952,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) ...@@ -1947,6 +1952,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
| NFS_INO_INVALID_SIZE | NFS_INO_INVALID_SIZE
| NFS_INO_INVALID_BLOCKS | NFS_INO_INVALID_BLOCKS
| NFS_INO_INVALID_NLINK | NFS_INO_INVALID_NLINK
| NFS_INO_INVALID_MODE
| NFS_INO_INVALID_OTHER; | NFS_INO_INVALID_OTHER;
if (S_ISDIR(inode->i_mode)) if (S_ISDIR(inode->i_mode))
nfs_force_lookup_revalidate(inode); nfs_force_lookup_revalidate(inode);
...@@ -2037,7 +2043,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) ...@@ -2037,7 +2043,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
} }
} else if (server->caps & NFS_CAP_MODE) { } else if (server->caps & NFS_CAP_MODE) {
nfsi->cache_validity |= save_cache_validity & nfsi->cache_validity |= save_cache_validity &
(NFS_INO_INVALID_OTHER (NFS_INO_INVALID_MODE
| NFS_INO_REVAL_FORCED); | NFS_INO_REVAL_FORCED);
cache_revalidated = false; cache_revalidated = false;
} }
......
...@@ -302,9 +302,10 @@ static void nfs4_bitmap_copy_adjust(__u32 *dst, const __u32 *src, ...@@ -302,9 +302,10 @@ static void nfs4_bitmap_copy_adjust(__u32 *dst, const __u32 *src,
if (!(cache_validity & NFS_INO_INVALID_CHANGE)) if (!(cache_validity & NFS_INO_INVALID_CHANGE))
dst[0] &= ~FATTR4_WORD0_CHANGE; dst[0] &= ~FATTR4_WORD0_CHANGE;
if (!(cache_validity & NFS_INO_INVALID_MODE))
dst[1] &= ~FATTR4_WORD1_MODE;
if (!(cache_validity & NFS_INO_INVALID_OTHER)) if (!(cache_validity & NFS_INO_INVALID_OTHER))
dst[1] &= ~(FATTR4_WORD1_MODE | FATTR4_WORD1_OWNER | dst[1] &= ~(FATTR4_WORD1_OWNER | FATTR4_WORD1_OWNER_GROUP);
FATTR4_WORD1_OWNER_GROUP);
} }
static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dentry, static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dentry,
...@@ -3344,7 +3345,9 @@ static int nfs4_do_setattr(struct inode *inode, const struct cred *cred, ...@@ -3344,7 +3345,9 @@ static int nfs4_do_setattr(struct inode *inode, const struct cred *cred,
unsigned long adjust_flags = NFS_INO_INVALID_CHANGE; unsigned long adjust_flags = NFS_INO_INVALID_CHANGE;
int err; int err;
if (sattr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) if (sattr->ia_valid & (ATTR_MODE | ATTR_KILL_SUID | ATTR_KILL_SGID))
adjust_flags |= NFS_INO_INVALID_MODE;
if (sattr->ia_valid & (ATTR_UID | ATTR_GID))
adjust_flags |= NFS_INO_INVALID_OTHER; adjust_flags |= NFS_INO_INVALID_OTHER;
do { do {
...@@ -5431,9 +5434,10 @@ static void nfs4_bitmask_set(__u32 bitmask[NFS4_BITMASK_SZ], const __u32 *src, ...@@ -5431,9 +5434,10 @@ static void nfs4_bitmask_set(__u32 bitmask[NFS4_BITMASK_SZ], const __u32 *src,
bitmask[0] |= FATTR4_WORD0_CHANGE; bitmask[0] |= FATTR4_WORD0_CHANGE;
if (cache_validity & NFS_INO_INVALID_ATIME) if (cache_validity & NFS_INO_INVALID_ATIME)
bitmask[1] |= FATTR4_WORD1_TIME_ACCESS; bitmask[1] |= FATTR4_WORD1_TIME_ACCESS;
if (cache_validity & NFS_INO_INVALID_MODE)
bitmask[1] |= FATTR4_WORD1_MODE;
if (cache_validity & NFS_INO_INVALID_OTHER) if (cache_validity & NFS_INO_INVALID_OTHER)
bitmask[1] |= FATTR4_WORD1_MODE | FATTR4_WORD1_OWNER | bitmask[1] |= FATTR4_WORD1_OWNER | FATTR4_WORD1_OWNER_GROUP;
FATTR4_WORD1_OWNER_GROUP;
if (cache_validity & NFS_INO_INVALID_NLINK) if (cache_validity & NFS_INO_INVALID_NLINK)
bitmask[1] |= FATTR4_WORD1_NUMLINKS; bitmask[1] |= FATTR4_WORD1_NUMLINKS;
if (label && label->len && cache_validity & NFS_INO_INVALID_LABEL) if (label && label->len && cache_validity & NFS_INO_INVALID_LABEL)
......
...@@ -49,6 +49,7 @@ TRACE_DEFINE_ENUM(NFS_INO_DATA_INVAL_DEFER); ...@@ -49,6 +49,7 @@ TRACE_DEFINE_ENUM(NFS_INO_DATA_INVAL_DEFER);
TRACE_DEFINE_ENUM(NFS_INO_INVALID_BLOCKS); TRACE_DEFINE_ENUM(NFS_INO_INVALID_BLOCKS);
TRACE_DEFINE_ENUM(NFS_INO_INVALID_XATTR); TRACE_DEFINE_ENUM(NFS_INO_INVALID_XATTR);
TRACE_DEFINE_ENUM(NFS_INO_INVALID_NLINK); TRACE_DEFINE_ENUM(NFS_INO_INVALID_NLINK);
TRACE_DEFINE_ENUM(NFS_INO_INVALID_MODE);
#define nfs_show_cache_validity(v) \ #define nfs_show_cache_validity(v) \
__print_flags(v, "|", \ __print_flags(v, "|", \
...@@ -67,7 +68,8 @@ TRACE_DEFINE_ENUM(NFS_INO_INVALID_NLINK); ...@@ -67,7 +68,8 @@ TRACE_DEFINE_ENUM(NFS_INO_INVALID_NLINK);
{ NFS_INO_DATA_INVAL_DEFER, "DATA_INVAL_DEFER" }, \ { NFS_INO_DATA_INVAL_DEFER, "DATA_INVAL_DEFER" }, \
{ NFS_INO_INVALID_BLOCKS, "INVALID_BLOCKS" }, \ { NFS_INO_INVALID_BLOCKS, "INVALID_BLOCKS" }, \
{ NFS_INO_INVALID_XATTR, "INVALID_XATTR" }, \ { NFS_INO_INVALID_XATTR, "INVALID_XATTR" }, \
{ NFS_INO_INVALID_NLINK, "INVALID_NLINK" }) { NFS_INO_INVALID_NLINK, "INVALID_NLINK" }, \
{ NFS_INO_INVALID_MODE, "INVALID_MODE" })
TRACE_DEFINE_ENUM(NFS_INO_ADVISE_RDPLUS); TRACE_DEFINE_ENUM(NFS_INO_ADVISE_RDPLUS);
TRACE_DEFINE_ENUM(NFS_INO_STALE); TRACE_DEFINE_ENUM(NFS_INO_STALE);
......
...@@ -1604,7 +1604,7 @@ static int nfs_writeback_done(struct rpc_task *task, ...@@ -1604,7 +1604,7 @@ static int nfs_writeback_done(struct rpc_task *task,
/* Deal with the suid/sgid bit corner case */ /* Deal with the suid/sgid bit corner case */
if (nfs_should_remove_suid(inode)) { if (nfs_should_remove_suid(inode)) {
spin_lock(&inode->i_lock); spin_lock(&inode->i_lock);
nfs_set_cache_invalid(inode, NFS_INO_INVALID_OTHER); nfs_set_cache_invalid(inode, NFS_INO_INVALID_MODE);
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
} }
return 0; return 0;
......
...@@ -247,12 +247,14 @@ struct nfs4_copy_state { ...@@ -247,12 +247,14 @@ struct nfs4_copy_state {
#define NFS_INO_INVALID_BLOCKS BIT(14) /* cached blocks are invalid */ #define NFS_INO_INVALID_BLOCKS BIT(14) /* cached blocks are invalid */
#define NFS_INO_INVALID_XATTR BIT(15) /* xattrs are invalid */ #define NFS_INO_INVALID_XATTR BIT(15) /* xattrs are invalid */
#define NFS_INO_INVALID_NLINK BIT(16) /* cached nlinks is invalid */ #define NFS_INO_INVALID_NLINK BIT(16) /* cached nlinks is invalid */
#define NFS_INO_INVALID_MODE BIT(17) /* cached mode is invalid */
#define NFS_INO_INVALID_ATTR (NFS_INO_INVALID_CHANGE \ #define NFS_INO_INVALID_ATTR (NFS_INO_INVALID_CHANGE \
| NFS_INO_INVALID_CTIME \ | NFS_INO_INVALID_CTIME \
| NFS_INO_INVALID_MTIME \ | NFS_INO_INVALID_MTIME \
| NFS_INO_INVALID_SIZE \ | NFS_INO_INVALID_SIZE \
| NFS_INO_INVALID_NLINK \ | NFS_INO_INVALID_NLINK \
| NFS_INO_INVALID_MODE \
| NFS_INO_INVALID_OTHER) /* inode metadata is invalid */ | NFS_INO_INVALID_OTHER) /* inode metadata is invalid */
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment