Skip to content

Commit 012a211

Browse files
fllindenTrond Myklebust
authored and
Trond Myklebust
committed
NFSv4.2: hook in the user extended attribute handlers
Now that all the lower level code is there to make the RPC calls, hook it in to the xattr handlers and the listxattr entry point, to make them available. Signed-off-by: Frank van der Linden <[email protected]> Signed-off-by: Trond Myklebust <[email protected]>
1 parent c10a751 commit 012a211

File tree

1 file changed

+121
-2
lines changed

1 file changed

+121
-2
lines changed

fs/nfs/nfs4proc.c

Lines changed: 121 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
#include "nfs4idmap.h"
6767
#include "nfs4session.h"
6868
#include "fscache.h"
69+
#include "nfs42.h"
6970

7071
#include "nfs4trace.h"
7172

@@ -7440,6 +7441,103 @@ nfs4_listxattr_nfs4_label(struct inode *inode, char *list, size_t list_len)
74407441

74417442
#endif
74427443

7444+
#ifdef CONFIG_NFS_V4_2
7445+
static int nfs4_xattr_set_nfs4_user(const struct xattr_handler *handler,
7446+
struct dentry *unused, struct inode *inode,
7447+
const char *key, const void *buf,
7448+
size_t buflen, int flags)
7449+
{
7450+
struct nfs_access_entry cache;
7451+
7452+
if (!nfs_server_capable(inode, NFS_CAP_XATTR))
7453+
return -EOPNOTSUPP;
7454+
7455+
/*
7456+
* There is no mapping from the MAY_* flags to the NFS_ACCESS_XA*
7457+
* flags right now. Handling of xattr operations use the normal
7458+
* file read/write permissions.
7459+
*
7460+
* Just in case the server has other ideas (which RFC 8276 allows),
7461+
* do a cached access check for the XA* flags to possibly avoid
7462+
* doing an RPC and getting EACCES back.
7463+
*/
7464+
if (!nfs_access_get_cached(inode, current_cred(), &cache, true)) {
7465+
if (!(cache.mask & NFS_ACCESS_XAWRITE))
7466+
return -EACCES;
7467+
}
7468+
7469+
if (buf == NULL)
7470+
return nfs42_proc_removexattr(inode, key);
7471+
else
7472+
return nfs42_proc_setxattr(inode, key, buf, buflen, flags);
7473+
}
7474+
7475+
static int nfs4_xattr_get_nfs4_user(const struct xattr_handler *handler,
7476+
struct dentry *unused, struct inode *inode,
7477+
const char *key, void *buf, size_t buflen)
7478+
{
7479+
struct nfs_access_entry cache;
7480+
7481+
if (!nfs_server_capable(inode, NFS_CAP_XATTR))
7482+
return -EOPNOTSUPP;
7483+
7484+
if (!nfs_access_get_cached(inode, current_cred(), &cache, true)) {
7485+
if (!(cache.mask & NFS_ACCESS_XAREAD))
7486+
return -EACCES;
7487+
}
7488+
7489+
return nfs42_proc_getxattr(inode, key, buf, buflen);
7490+
}
7491+
7492+
static ssize_t
7493+
nfs4_listxattr_nfs4_user(struct inode *inode, char *list, size_t list_len)
7494+
{
7495+
u64 cookie;
7496+
bool eof;
7497+
int ret, size;
7498+
char *buf;
7499+
size_t buflen;
7500+
struct nfs_access_entry cache;
7501+
7502+
if (!nfs_server_capable(inode, NFS_CAP_XATTR))
7503+
return 0;
7504+
7505+
if (!nfs_access_get_cached(inode, current_cred(), &cache, true)) {
7506+
if (!(cache.mask & NFS_ACCESS_XALIST))
7507+
return 0;
7508+
}
7509+
7510+
cookie = 0;
7511+
eof = false;
7512+
buflen = list_len ? list_len : XATTR_LIST_MAX;
7513+
buf = list_len ? list : NULL;
7514+
size = 0;
7515+
7516+
while (!eof) {
7517+
ret = nfs42_proc_listxattrs(inode, buf, buflen,
7518+
&cookie, &eof);
7519+
if (ret < 0)
7520+
return ret;
7521+
7522+
if (list_len) {
7523+
buf += ret;
7524+
buflen -= ret;
7525+
}
7526+
size += ret;
7527+
}
7528+
7529+
return size;
7530+
}
7531+
7532+
#else
7533+
7534+
static ssize_t
7535+
nfs4_listxattr_nfs4_user(struct inode *inode, char *list, size_t list_len)
7536+
{
7537+
return 0;
7538+
}
7539+
#endif /* CONFIG_NFS_V4_2 */
7540+
74437541
/*
74447542
* nfs_fhget will use either the mounted_on_fileid or the fileid
74457543
*/
@@ -10045,7 +10143,7 @@ const struct nfs4_minor_version_ops *nfs_v4_minor_ops[] = {
1004510143

1004610144
static ssize_t nfs4_listxattr(struct dentry *dentry, char *list, size_t size)
1004710145
{
10048-
ssize_t error, error2;
10146+
ssize_t error, error2, error3;
1004910147

1005010148
error = generic_listxattr(dentry, list, size);
1005110149
if (error < 0)
@@ -10058,7 +10156,17 @@ static ssize_t nfs4_listxattr(struct dentry *dentry, char *list, size_t size)
1005810156
error2 = nfs4_listxattr_nfs4_label(d_inode(dentry), list, size);
1005910157
if (error2 < 0)
1006010158
return error2;
10061-
return error + error2;
10159+
10160+
if (list) {
10161+
list += error2;
10162+
size -= error2;
10163+
}
10164+
10165+
error3 = nfs4_listxattr_nfs4_user(d_inode(dentry), list, size);
10166+
if (error3 < 0)
10167+
return error3;
10168+
10169+
return error + error2 + error3;
1006210170
}
1006310171

1006410172
static const struct inode_operations nfs4_dir_inode_operations = {
@@ -10146,10 +10254,21 @@ static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = {
1014610254
.set = nfs4_xattr_set_nfs4_acl,
1014710255
};
1014810256

10257+
#ifdef CONFIG_NFS_V4_2
10258+
static const struct xattr_handler nfs4_xattr_nfs4_user_handler = {
10259+
.prefix = XATTR_USER_PREFIX,
10260+
.get = nfs4_xattr_get_nfs4_user,
10261+
.set = nfs4_xattr_set_nfs4_user,
10262+
};
10263+
#endif
10264+
1014910265
const struct xattr_handler *nfs4_xattr_handlers[] = {
1015010266
&nfs4_xattr_nfs4_acl_handler,
1015110267
#ifdef CONFIG_NFS_V4_SECURITY_LABEL
1015210268
&nfs4_xattr_nfs4_label_handler,
10269+
#endif
10270+
#ifdef CONFIG_NFS_V4_2
10271+
&nfs4_xattr_nfs4_user_handler,
1015310272
#endif
1015410273
NULL
1015510274
};

0 commit comments

Comments
 (0)