NFSv4: Specify the type of ACL to cache
When caching a NFSv4 ACL, we want to specify whether we are caching an NFSv4.0 type acl, the NFSv4.1 dacl or the NFSv4.1 sacl. Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
This commit is contained in:
parent
6949493884
commit
7b8b44eb77
|
@ -5772,9 +5772,17 @@ static int nfs4_proc_renew(struct nfs_client *clp, const struct cred *cred)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline int nfs4_server_supports_acls(struct nfs_server *server)
|
||||
static bool nfs4_server_supports_acls(const struct nfs_server *server,
|
||||
enum nfs4_acl_type type)
|
||||
{
|
||||
return server->caps & NFS_CAP_ACLS;
|
||||
switch (type) {
|
||||
default:
|
||||
return server->attr_bitmask[0] & FATTR4_WORD0_ACL;
|
||||
case NFS4ACL_DACL:
|
||||
return server->attr_bitmask[1] & FATTR4_WORD1_DACL;
|
||||
case NFS4ACL_SACL:
|
||||
return server->attr_bitmask[1] & FATTR4_WORD1_SACL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Assuming that XATTR_SIZE_MAX is a multiple of PAGE_SIZE, and that
|
||||
|
@ -5813,6 +5821,7 @@ unwind:
|
|||
}
|
||||
|
||||
struct nfs4_cached_acl {
|
||||
enum nfs4_acl_type type;
|
||||
int cached;
|
||||
size_t len;
|
||||
char data[];
|
||||
|
@ -5833,7 +5842,8 @@ static void nfs4_zap_acl_attr(struct inode *inode)
|
|||
nfs4_set_cached_acl(inode, NULL);
|
||||
}
|
||||
|
||||
static inline ssize_t nfs4_read_cached_acl(struct inode *inode, char *buf, size_t buflen)
|
||||
static ssize_t nfs4_read_cached_acl(struct inode *inode, char *buf,
|
||||
size_t buflen, enum nfs4_acl_type type)
|
||||
{
|
||||
struct nfs_inode *nfsi = NFS_I(inode);
|
||||
struct nfs4_cached_acl *acl;
|
||||
|
@ -5843,6 +5853,8 @@ static inline ssize_t nfs4_read_cached_acl(struct inode *inode, char *buf, size_
|
|||
acl = nfsi->nfs4_acl;
|
||||
if (acl == NULL)
|
||||
goto out;
|
||||
if (acl->type != type)
|
||||
goto out;
|
||||
if (buf == NULL) /* user is just asking for length */
|
||||
goto out_len;
|
||||
if (acl->cached == 0)
|
||||
|
@ -5858,7 +5870,9 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void nfs4_write_cached_acl(struct inode *inode, struct page **pages, size_t pgbase, size_t acl_len)
|
||||
static void nfs4_write_cached_acl(struct inode *inode, struct page **pages,
|
||||
size_t pgbase, size_t acl_len,
|
||||
enum nfs4_acl_type type)
|
||||
{
|
||||
struct nfs4_cached_acl *acl;
|
||||
size_t buflen = sizeof(*acl) + acl_len;
|
||||
|
@ -5875,6 +5889,7 @@ static void nfs4_write_cached_acl(struct inode *inode, struct page **pages, size
|
|||
goto out;
|
||||
acl->cached = 0;
|
||||
}
|
||||
acl->type = type;
|
||||
acl->len = acl_len;
|
||||
out:
|
||||
nfs4_set_cached_acl(inode, acl);
|
||||
|
@ -5890,7 +5905,8 @@ out:
|
|||
* length. The next getxattr call will then produce another round trip to
|
||||
* the server, this time with the input buf of the required size.
|
||||
*/
|
||||
static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t buflen)
|
||||
static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf,
|
||||
size_t buflen, enum nfs4_acl_type type)
|
||||
{
|
||||
struct page **pages;
|
||||
struct nfs_getaclargs args = {
|
||||
|
@ -5947,7 +5963,8 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu
|
|||
ret = -ERANGE;
|
||||
goto out_free;
|
||||
}
|
||||
nfs4_write_cached_acl(inode, pages, res.acl_data_offset, res.acl_len);
|
||||
nfs4_write_cached_acl(inode, pages, res.acl_data_offset, res.acl_len,
|
||||
type);
|
||||
if (buf) {
|
||||
if (res.acl_len > buflen) {
|
||||
ret = -ERANGE;
|
||||
|
@ -5967,14 +5984,15 @@ out_free:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t buflen)
|
||||
static ssize_t nfs4_get_acl_uncached(struct inode *inode, void *buf,
|
||||
size_t buflen, enum nfs4_acl_type type)
|
||||
{
|
||||
struct nfs4_exception exception = {
|
||||
.interruptible = true,
|
||||
};
|
||||
ssize_t ret;
|
||||
do {
|
||||
ret = __nfs4_get_acl_uncached(inode, buf, buflen);
|
||||
ret = __nfs4_get_acl_uncached(inode, buf, buflen, type);
|
||||
trace_nfs4_get_acl(inode, ret);
|
||||
if (ret >= 0)
|
||||
break;
|
||||
|
@ -5983,27 +6001,29 @@ static ssize_t nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bufl
|
|||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t nfs4_proc_get_acl(struct inode *inode, void *buf, size_t buflen)
|
||||
static ssize_t nfs4_proc_get_acl(struct inode *inode, void *buf, size_t buflen,
|
||||
enum nfs4_acl_type type)
|
||||
{
|
||||
struct nfs_server *server = NFS_SERVER(inode);
|
||||
int ret;
|
||||
|
||||
if (!nfs4_server_supports_acls(server))
|
||||
if (!nfs4_server_supports_acls(server, type))
|
||||
return -EOPNOTSUPP;
|
||||
ret = nfs_revalidate_inode(inode, NFS_INO_INVALID_CHANGE);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (NFS_I(inode)->cache_validity & NFS_INO_INVALID_ACL)
|
||||
nfs_zap_acl_cache(inode);
|
||||
ret = nfs4_read_cached_acl(inode, buf, buflen);
|
||||
ret = nfs4_read_cached_acl(inode, buf, buflen, type);
|
||||
if (ret != -ENOENT)
|
||||
/* -ENOENT is returned if there is no ACL or if there is an ACL
|
||||
* but no cached acl data, just the acl length */
|
||||
return ret;
|
||||
return nfs4_get_acl_uncached(inode, buf, buflen);
|
||||
return nfs4_get_acl_uncached(inode, buf, buflen, type);
|
||||
}
|
||||
|
||||
static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen)
|
||||
static int __nfs4_proc_set_acl(struct inode *inode, const void *buf,
|
||||
size_t buflen, enum nfs4_acl_type type)
|
||||
{
|
||||
struct nfs_server *server = NFS_SERVER(inode);
|
||||
struct page *pages[NFS4ACL_MAXPAGES];
|
||||
|
@ -6024,7 +6044,7 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl
|
|||
/* You can't remove system.nfs4_acl: */
|
||||
if (buflen == 0)
|
||||
return -EINVAL;
|
||||
if (!nfs4_server_supports_acls(server))
|
||||
if (!nfs4_server_supports_acls(server, type))
|
||||
return -EOPNOTSUPP;
|
||||
if (npages > ARRAY_SIZE(pages))
|
||||
return -ERANGE;
|
||||
|
@ -6055,12 +6075,13 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen)
|
||||
static int nfs4_proc_set_acl(struct inode *inode, const void *buf,
|
||||
size_t buflen, enum nfs4_acl_type type)
|
||||
{
|
||||
struct nfs4_exception exception = { };
|
||||
int err;
|
||||
do {
|
||||
err = __nfs4_proc_set_acl(inode, buf, buflen);
|
||||
err = __nfs4_proc_set_acl(inode, buf, buflen, type);
|
||||
trace_nfs4_set_acl(inode, err);
|
||||
if (err == -NFS4ERR_BADOWNER || err == -NFS4ERR_BADNAME) {
|
||||
/*
|
||||
|
@ -7659,19 +7680,19 @@ static int nfs4_xattr_set_nfs4_acl(const struct xattr_handler *handler,
|
|||
const char *key, const void *buf,
|
||||
size_t buflen, int flags)
|
||||
{
|
||||
return nfs4_proc_set_acl(inode, buf, buflen);
|
||||
return nfs4_proc_set_acl(inode, buf, buflen, NFS4ACL_ACL);
|
||||
}
|
||||
|
||||
static int nfs4_xattr_get_nfs4_acl(const struct xattr_handler *handler,
|
||||
struct dentry *unused, struct inode *inode,
|
||||
const char *key, void *buf, size_t buflen)
|
||||
{
|
||||
return nfs4_proc_get_acl(inode, buf, buflen);
|
||||
return nfs4_proc_get_acl(inode, buf, buflen, NFS4ACL_ACL);
|
||||
}
|
||||
|
||||
static bool nfs4_xattr_list_nfs4_acl(struct dentry *dentry)
|
||||
{
|
||||
return nfs4_server_supports_acls(NFS_SERVER(d_inode(dentry)));
|
||||
return nfs4_server_supports_acls(NFS_SB(dentry->d_sb), NFS4ACL_ACL);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NFS_V4_SECURITY_LABEL
|
||||
|
|
|
@ -451,6 +451,8 @@ enum lock_type4 {
|
|||
#define FATTR4_WORD1_TIME_MODIFY (1UL << 21)
|
||||
#define FATTR4_WORD1_TIME_MODIFY_SET (1UL << 22)
|
||||
#define FATTR4_WORD1_MOUNTED_ON_FILEID (1UL << 23)
|
||||
#define FATTR4_WORD1_DACL (1UL << 26)
|
||||
#define FATTR4_WORD1_SACL (1UL << 27)
|
||||
#define FATTR4_WORD1_FS_LAYOUT_TYPES (1UL << 30)
|
||||
#define FATTR4_WORD2_LAYOUT_TYPES (1UL << 0)
|
||||
#define FATTR4_WORD2_LAYOUT_BLKSIZE (1UL << 1)
|
||||
|
|
|
@ -800,6 +800,13 @@ struct nfs_setattrargs {
|
|||
const struct nfs4_label *label;
|
||||
};
|
||||
|
||||
enum nfs4_acl_type {
|
||||
NFS4ACL_NONE = 0,
|
||||
NFS4ACL_ACL,
|
||||
NFS4ACL_DACL,
|
||||
NFS4ACL_SACL,
|
||||
};
|
||||
|
||||
struct nfs_setaclargs {
|
||||
struct nfs4_sequence_args seq_args;
|
||||
struct nfs_fh * fh;
|
||||
|
|
Loading…
Reference in New Issue