Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/fs/9p/xattr.c
26289 views
1
// SPDX-License-Identifier: LGPL-2.1
2
/*
3
* Copyright IBM Corporation, 2010
4
* Author Aneesh Kumar K.V <[email protected]>
5
*/
6
7
#include <linux/module.h>
8
#include <linux/fs.h>
9
#include <linux/sched.h>
10
#include <linux/uio.h>
11
#include <linux/posix_acl_xattr.h>
12
#include <net/9p/9p.h>
13
#include <net/9p/client.h>
14
15
#include "fid.h"
16
#include "xattr.h"
17
18
ssize_t v9fs_fid_xattr_get(struct p9_fid *fid, const char *name,
19
void *buffer, size_t buffer_size)
20
{
21
ssize_t retval;
22
u64 attr_size;
23
struct p9_fid *attr_fid;
24
struct kvec kvec = {.iov_base = buffer, .iov_len = buffer_size};
25
struct iov_iter to;
26
int err;
27
28
iov_iter_kvec(&to, ITER_DEST, &kvec, 1, buffer_size);
29
30
attr_fid = p9_client_xattrwalk(fid, name, &attr_size);
31
if (IS_ERR(attr_fid)) {
32
retval = PTR_ERR(attr_fid);
33
p9_debug(P9_DEBUG_VFS, "p9_client_attrwalk failed %zd\n",
34
retval);
35
return retval;
36
}
37
if (attr_size > buffer_size) {
38
if (buffer_size)
39
retval = -ERANGE;
40
else if (attr_size > SSIZE_MAX)
41
retval = -EOVERFLOW;
42
else /* request to get the attr_size */
43
retval = attr_size;
44
} else {
45
iov_iter_truncate(&to, attr_size);
46
retval = p9_client_read(attr_fid, 0, &to, &err);
47
if (err)
48
retval = err;
49
}
50
p9_fid_put(attr_fid);
51
return retval;
52
}
53
54
55
/*
56
* v9fs_xattr_get()
57
*
58
* Copy an extended attribute into the buffer
59
* provided, or compute the buffer size required.
60
* Buffer is NULL to compute the size of the buffer required.
61
*
62
* Returns a negative error number on failure, or the number of bytes
63
* used / required on success.
64
*/
65
ssize_t v9fs_xattr_get(struct dentry *dentry, const char *name,
66
void *buffer, size_t buffer_size)
67
{
68
struct p9_fid *fid;
69
int ret;
70
71
p9_debug(P9_DEBUG_VFS, "name = '%s' value_len = %zu\n",
72
name, buffer_size);
73
fid = v9fs_fid_lookup(dentry);
74
if (IS_ERR(fid))
75
return PTR_ERR(fid);
76
ret = v9fs_fid_xattr_get(fid, name, buffer, buffer_size);
77
p9_fid_put(fid);
78
79
return ret;
80
}
81
82
/*
83
* v9fs_xattr_set()
84
*
85
* Create, replace or remove an extended attribute for this inode. Buffer
86
* is NULL to remove an existing extended attribute, and non-NULL to
87
* either replace an existing extended attribute, or create a new extended
88
* attribute. The flags XATTR_REPLACE and XATTR_CREATE
89
* specify that an extended attribute must exist and must not exist
90
* previous to the call, respectively.
91
*
92
* Returns 0, or a negative error number on failure.
93
*/
94
int v9fs_xattr_set(struct dentry *dentry, const char *name,
95
const void *value, size_t value_len, int flags)
96
{
97
int ret;
98
struct p9_fid *fid;
99
100
fid = v9fs_fid_lookup(dentry);
101
if (IS_ERR(fid))
102
return PTR_ERR(fid);
103
ret = v9fs_fid_xattr_set(fid, name, value, value_len, flags);
104
p9_fid_put(fid);
105
return ret;
106
}
107
108
int v9fs_fid_xattr_set(struct p9_fid *fid, const char *name,
109
const void *value, size_t value_len, int flags)
110
{
111
struct kvec kvec = {.iov_base = (void *)value, .iov_len = value_len};
112
struct iov_iter from;
113
int retval, err;
114
115
iov_iter_kvec(&from, ITER_SOURCE, &kvec, 1, value_len);
116
117
p9_debug(P9_DEBUG_VFS, "name = %s value_len = %zu flags = %d\n",
118
name, value_len, flags);
119
120
/* Clone it */
121
fid = clone_fid(fid);
122
if (IS_ERR(fid))
123
return PTR_ERR(fid);
124
125
/*
126
* On success fid points to xattr
127
*/
128
retval = p9_client_xattrcreate(fid, name, value_len, flags);
129
if (retval < 0)
130
p9_debug(P9_DEBUG_VFS, "p9_client_xattrcreate failed %d\n",
131
retval);
132
else
133
p9_client_write(fid, 0, &from, &retval);
134
err = p9_fid_put(fid);
135
if (!retval && err)
136
retval = err;
137
return retval;
138
}
139
140
ssize_t v9fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
141
{
142
/* Txattrwalk with an empty string lists xattrs instead */
143
return v9fs_xattr_get(dentry, "", buffer, buffer_size);
144
}
145
146
static int v9fs_xattr_handler_get(const struct xattr_handler *handler,
147
struct dentry *dentry, struct inode *inode,
148
const char *name, void *buffer, size_t size)
149
{
150
const char *full_name = xattr_full_name(handler, name);
151
152
return v9fs_xattr_get(dentry, full_name, buffer, size);
153
}
154
155
static int v9fs_xattr_handler_set(const struct xattr_handler *handler,
156
struct mnt_idmap *idmap,
157
struct dentry *dentry, struct inode *inode,
158
const char *name, const void *value,
159
size_t size, int flags)
160
{
161
const char *full_name = xattr_full_name(handler, name);
162
163
return v9fs_xattr_set(dentry, full_name, value, size, flags);
164
}
165
166
static const struct xattr_handler v9fs_xattr_user_handler = {
167
.prefix = XATTR_USER_PREFIX,
168
.get = v9fs_xattr_handler_get,
169
.set = v9fs_xattr_handler_set,
170
};
171
172
static const struct xattr_handler v9fs_xattr_trusted_handler = {
173
.prefix = XATTR_TRUSTED_PREFIX,
174
.get = v9fs_xattr_handler_get,
175
.set = v9fs_xattr_handler_set,
176
};
177
178
#ifdef CONFIG_9P_FS_SECURITY
179
static const struct xattr_handler v9fs_xattr_security_handler = {
180
.prefix = XATTR_SECURITY_PREFIX,
181
.get = v9fs_xattr_handler_get,
182
.set = v9fs_xattr_handler_set,
183
};
184
#endif
185
186
const struct xattr_handler * const v9fs_xattr_handlers[] = {
187
&v9fs_xattr_user_handler,
188
&v9fs_xattr_trusted_handler,
189
#ifdef CONFIG_9P_FS_SECURITY
190
&v9fs_xattr_security_handler,
191
#endif
192
NULL
193
};
194
195