Skip to content

Commit 95ad37f

Browse files
fllindenTrond Myklebust
authored andcommitted
NFSv4.2: add client side xattr caching.
Implement client side caching for NFSv4.2 extended attributes. The cache is a per-inode hashtable, with name/value entries. There is one special entry for the listxattr cache. NFS inodes have a pointer to a cache structure. The cache structure is allocated on demand, freed when the cache is invalidated. Memory shrinkers keep the size in check. Large entries (> PAGE_SIZE) are collected by a separate shrinker, and freed more aggressively than others. Signed-off-by: Frank van der Linden <[email protected]> Signed-off-by: Trond Myklebust <[email protected]>
1 parent 012a211 commit 95ad37f

File tree

9 files changed

+1179
-8
lines changed

9 files changed

+1179
-8
lines changed

fs/nfs/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ nfsv4-y := nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o nfs4super.o nfs4file.o
3030
nfsv4-$(CONFIG_NFS_USE_LEGACY_DNS) += cache_lib.o
3131
nfsv4-$(CONFIG_SYSCTL) += nfs4sysctl.o
3232
nfsv4-$(CONFIG_NFS_V4_1) += pnfs.o pnfs_dev.o pnfs_nfs.o
33-
nfsv4-$(CONFIG_NFS_V4_2) += nfs42proc.o
33+
nfsv4-$(CONFIG_NFS_V4_2) += nfs42proc.o nfs42xattr.o
3434

3535
obj-$(CONFIG_PNFS_FILE_LAYOUT) += filelayout/
3636
obj-$(CONFIG_PNFS_BLOCK) += blocklayout/

fs/nfs/inode.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ bool nfs_check_cache_invalid(struct inode *inode, unsigned long flags)
193193

194194
return nfs_check_cache_invalid_not_delegated(inode, flags);
195195
}
196+
EXPORT_SYMBOL_GPL(nfs_check_cache_invalid);
196197

197198
static void nfs_set_cache_invalid(struct inode *inode, unsigned long flags)
198199
{
@@ -234,11 +235,13 @@ static void nfs_zap_caches_locked(struct inode *inode)
234235
| NFS_INO_INVALID_DATA
235236
| NFS_INO_INVALID_ACCESS
236237
| NFS_INO_INVALID_ACL
238+
| NFS_INO_INVALID_XATTR
237239
| NFS_INO_REVAL_PAGECACHE);
238240
} else
239241
nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATTR
240242
| NFS_INO_INVALID_ACCESS
241243
| NFS_INO_INVALID_ACL
244+
| NFS_INO_INVALID_XATTR
242245
| NFS_INO_REVAL_PAGECACHE);
243246
nfs_zap_label_cache_locked(nfsi);
244247
}
@@ -1897,7 +1900,8 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
18971900
if (!(have_writers || have_delegation)) {
18981901
invalid |= NFS_INO_INVALID_DATA
18991902
| NFS_INO_INVALID_ACCESS
1900-
| NFS_INO_INVALID_ACL;
1903+
| NFS_INO_INVALID_ACL
1904+
| NFS_INO_INVALID_XATTR;
19011905
/* Force revalidate of all attributes */
19021906
save_cache_validity |= NFS_INO_INVALID_CTIME
19031907
| NFS_INO_INVALID_MTIME
@@ -2100,6 +2104,9 @@ struct inode *nfs_alloc_inode(struct super_block *sb)
21002104
#if IS_ENABLED(CONFIG_NFS_V4)
21012105
nfsi->nfs4_acl = NULL;
21022106
#endif /* CONFIG_NFS_V4 */
2107+
#ifdef CONFIG_NFS_V4_2
2108+
nfsi->xattr_cache = NULL;
2109+
#endif
21032110
return &nfsi->vfs_inode;
21042111
}
21052112
EXPORT_SYMBOL_GPL(nfs_alloc_inode);

fs/nfs/nfs42proc.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1182,6 +1182,18 @@ static ssize_t _nfs42_proc_getxattr(struct inode *inode, const char *name,
11821182
if (ret < 0)
11831183
return ret;
11841184

1185+
/*
1186+
* Normally, the caching is done one layer up, but for successful
1187+
* RPCS, always cache the result here, even if the caller was
1188+
* just querying the length, or if the reply was too big for
1189+
* the caller. This avoids a second RPC in the case of the
1190+
* common query-alloc-retrieve cycle for xattrs.
1191+
*
1192+
* Note that xattr_len is always capped to XATTR_SIZE_MAX.
1193+
*/
1194+
1195+
nfs4_xattr_cache_add(inode, name, NULL, pages, res.xattr_len);
1196+
11851197
if (buflen) {
11861198
if (res.xattr_len > buflen)
11871199
return -ERANGE;

0 commit comments

Comments
 (0)