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