Skip to content

Commit

Permalink
Merge branch 'xattr-devel'
Browse files Browse the repository at this point in the history
  • Loading branch information
Trond Myklebust committed Jul 17, 2020
2 parents 18eb87f + 95ad37f commit 57f80c0
Show file tree
Hide file tree
Showing 20 changed files with 2,269 additions and 42 deletions.
2 changes: 1 addition & 1 deletion fs/nfs/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ nfsv4-y := nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o nfs4super.o nfs4file.o
nfsv4-$(CONFIG_NFS_USE_LEGACY_DNS) += cache_lib.o
nfsv4-$(CONFIG_SYSCTL) += nfs4sysctl.o
nfsv4-$(CONFIG_NFS_V4_1) += pnfs.o pnfs_dev.o pnfs_nfs.o
nfsv4-$(CONFIG_NFS_V4_2) += nfs42proc.o
nfsv4-$(CONFIG_NFS_V4_2) += nfs42proc.o nfs42xattr.o

obj-$(CONFIG_PNFS_FILE_LAYOUT) += filelayout/
obj-$(CONFIG_PNFS_BLOCK) += blocklayout/
Expand Down
22 changes: 20 additions & 2 deletions fs/nfs/client.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
#include "nfs.h"
#include "netns.h"
#include "sysfs.h"
#include "nfs42.h"

#define NFSDBG_FACILITY NFSDBG_CLIENT

Expand Down Expand Up @@ -749,7 +750,7 @@ static int nfs_init_server(struct nfs_server *server,
static void nfs_server_set_fsinfo(struct nfs_server *server,
struct nfs_fsinfo *fsinfo)
{
unsigned long max_rpc_payload;
unsigned long max_rpc_payload, raw_max_rpc_payload;

/* Work out a lot of parameters */
if (server->rsize == 0)
Expand All @@ -762,7 +763,9 @@ static void nfs_server_set_fsinfo(struct nfs_server *server,
if (fsinfo->wtmax >= 512 && server->wsize > fsinfo->wtmax)
server->wsize = nfs_block_size(fsinfo->wtmax, NULL);

max_rpc_payload = nfs_block_size(rpc_max_payload(server->client), NULL);
raw_max_rpc_payload = rpc_max_payload(server->client);
max_rpc_payload = nfs_block_size(raw_max_rpc_payload, NULL);

if (server->rsize > max_rpc_payload)
server->rsize = max_rpc_payload;
if (server->rsize > NFS_MAX_FILE_IO_SIZE)
Expand Down Expand Up @@ -795,6 +798,21 @@ static void nfs_server_set_fsinfo(struct nfs_server *server,
server->clone_blksize = fsinfo->clone_blksize;
/* We're airborne Set socket buffersize */
rpc_setbufsize(server->client, server->wsize + 100, server->rsize + 100);

#ifdef CONFIG_NFS_V4_2
/*
* Defaults until limited by the session parameters.
*/
server->gxasize = min_t(unsigned int, raw_max_rpc_payload,
XATTR_SIZE_MAX);
server->sxasize = min_t(unsigned int, raw_max_rpc_payload,
XATTR_SIZE_MAX);
server->lxasize = min_t(unsigned int, raw_max_rpc_payload,
nfs42_listxattr_xdrsize(XATTR_LIST_MAX));

if (fsinfo->xattr_support)
server->caps |= NFS_CAP_XATTR;
#endif
}

/*
Expand Down
24 changes: 20 additions & 4 deletions fs/nfs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -2460,7 +2460,7 @@ static struct nfs_access_entry *nfs_access_search_rbtree(struct inode *inode, co
return NULL;
}

static int nfs_access_get_cached(struct inode *inode, const struct cred *cred, struct nfs_access_entry *res, bool may_block)
static int nfs_access_get_cached_locked(struct inode *inode, const struct cred *cred, struct nfs_access_entry *res, bool may_block)
{
struct nfs_inode *nfsi = NFS_I(inode);
struct nfs_access_entry *cache;
Expand Down Expand Up @@ -2533,6 +2533,20 @@ static int nfs_access_get_cached_rcu(struct inode *inode, const struct cred *cre
return err;
}

int nfs_access_get_cached(struct inode *inode, const struct cred *cred, struct
nfs_access_entry *res, bool may_block)
{
int status;

status = nfs_access_get_cached_rcu(inode, cred, res);
if (status != 0)
status = nfs_access_get_cached_locked(inode, cred, res,
may_block);

return status;
}
EXPORT_SYMBOL_GPL(nfs_access_get_cached);

static void nfs_access_add_rbtree(struct inode *inode, struct nfs_access_entry *set)
{
struct nfs_inode *nfsi = NFS_I(inode);
Expand Down Expand Up @@ -2647,9 +2661,7 @@ static int nfs_do_access(struct inode *inode, const struct cred *cred, int mask)

trace_nfs_access_enter(inode);

status = nfs_access_get_cached_rcu(inode, cred, &cache);
if (status != 0)
status = nfs_access_get_cached(inode, cred, &cache, may_block);
status = nfs_access_get_cached(inode, cred, &cache, may_block);
if (status == 0)
goto out_cached;

Expand All @@ -2661,6 +2673,10 @@ static int nfs_do_access(struct inode *inode, const struct cred *cred, int mask)
* Determine which access bits we want to ask for...
*/
cache.mask = NFS_ACCESS_READ | NFS_ACCESS_MODIFY | NFS_ACCESS_EXTEND;
if (nfs_server_capable(inode, NFS_CAP_XATTR)) {
cache.mask |= NFS_ACCESS_XAREAD | NFS_ACCESS_XAWRITE |
NFS_ACCESS_XALIST;
}
if (S_ISDIR(inode->i_mode))
cache.mask |= NFS_ACCESS_DELETE | NFS_ACCESS_LOOKUP;
else
Expand Down
16 changes: 14 additions & 2 deletions fs/nfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ bool nfs_check_cache_invalid(struct inode *inode, unsigned long flags)

return nfs_check_cache_invalid_not_delegated(inode, flags);
}
EXPORT_SYMBOL_GPL(nfs_check_cache_invalid);

static void nfs_set_cache_invalid(struct inode *inode, unsigned long flags)
{
Expand All @@ -204,7 +205,8 @@ static void nfs_set_cache_invalid(struct inode *inode, unsigned long flags)
flags &= ~NFS_INO_INVALID_OTHER;
flags &= ~(NFS_INO_INVALID_CHANGE
| NFS_INO_INVALID_SIZE
| NFS_INO_REVAL_PAGECACHE);
| NFS_INO_REVAL_PAGECACHE
| NFS_INO_INVALID_XATTR);
}

if (inode->i_mapping->nrpages == 0)
Expand Down Expand Up @@ -233,11 +235,13 @@ static void nfs_zap_caches_locked(struct inode *inode)
| NFS_INO_INVALID_DATA
| NFS_INO_INVALID_ACCESS
| NFS_INO_INVALID_ACL
| NFS_INO_INVALID_XATTR
| NFS_INO_REVAL_PAGECACHE);
} else
nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATTR
| NFS_INO_INVALID_ACCESS
| NFS_INO_INVALID_ACL
| NFS_INO_INVALID_XATTR
| NFS_INO_REVAL_PAGECACHE);
nfs_zap_label_cache_locked(nfsi);
}
Expand Down Expand Up @@ -542,6 +546,8 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr, st
inode->i_gid = fattr->gid;
else if (nfs_server_capable(inode, NFS_CAP_OWNER_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;
if (fattr->valid & NFS_ATTR_FATTR_SPACE_USED) {
Expand Down Expand Up @@ -1377,6 +1383,8 @@ static void nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr)
inode_set_iversion_raw(inode, fattr->change_attr);
if (S_ISDIR(inode->i_mode))
nfs_set_cache_invalid(inode, NFS_INO_INVALID_DATA);
else if (nfs_server_capable(inode, NFS_CAP_XATTR))
nfs_set_cache_invalid(inode, NFS_INO_INVALID_XATTR);
}
/* If we have atomic WCC data, we may update some attributes */
ts = inode->i_ctime;
Expand Down Expand Up @@ -1894,7 +1902,8 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
if (!(have_writers || have_delegation)) {
invalid |= NFS_INO_INVALID_DATA
| NFS_INO_INVALID_ACCESS
| NFS_INO_INVALID_ACL;
| NFS_INO_INVALID_ACL
| NFS_INO_INVALID_XATTR;
/* Force revalidate of all attributes */
save_cache_validity |= NFS_INO_INVALID_CTIME
| NFS_INO_INVALID_MTIME
Expand Down Expand Up @@ -2097,6 +2106,9 @@ struct inode *nfs_alloc_inode(struct super_block *sb)
#if IS_ENABLED(CONFIG_NFS_V4)
nfsi->nfs4_acl = NULL;
#endif /* CONFIG_NFS_V4 */
#ifdef CONFIG_NFS_V4_2
nfsi->xattr_cache = NULL;
#endif
return &nfsi->vfs_inode;
}
EXPORT_SYMBOL_GPL(nfs_alloc_inode);
Expand Down
24 changes: 24 additions & 0 deletions fs/nfs/nfs42.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#ifndef __LINUX_FS_NFS_NFS4_2_H
#define __LINUX_FS_NFS_NFS4_2_H

#include <linux/xattr.h>

/*
* FIXME: four LAYOUTSTATS calls per compound at most! Do we need to support
* more? Need to consider not to pre-alloc too much for a compound.
Expand Down Expand Up @@ -36,5 +38,27 @@ static inline bool nfs42_files_from_same_server(struct file *in,
return nfs4_check_serverowner_major_id(c_in->cl_serverowner,
c_out->cl_serverowner);
}

ssize_t nfs42_proc_getxattr(struct inode *inode, const char *name,
void *buf, size_t buflen);
int nfs42_proc_setxattr(struct inode *inode, const char *name,
const void *buf, size_t buflen, int flags);
ssize_t nfs42_proc_listxattrs(struct inode *inode, void *buf,
size_t buflen, u64 *cookiep, bool *eofp);
int nfs42_proc_removexattr(struct inode *inode, const char *name);

/*
* Maximum XDR buffer size needed for a listxattr buffer of buflen size.
*
* The upper boundary is a buffer with all 1-byte sized attribute names.
* They would be 7 bytes long in the eventual buffer ("user.x\0"), and
* 8 bytes long XDR-encoded.
*
* Include the trailing eof word as well.
*/
static inline u32 nfs42_listxattr_xdrsize(u32 buflen)
{
return ((buflen / (XATTR_USER_PREFIX_LEN + 2)) * 8) + 4;
}
#endif /* CONFIG_NFS_V4_2 */
#endif /* __LINUX_FS_NFS_NFS4_2_H */
Loading

0 comments on commit 57f80c0

Please sign in to comment.