gpio: rcar: Fix runtime PM imbalance on error
[linux/fpc-iii.git] / fs / afs / xattr.c
blob7af41fd5f3ee4f396aba46849192b1adb3bf51b1
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* Extended attribute handling for AFS. We use xattrs to get and set metadata
3 * instead of providing pioctl().
5 * Copyright (C) 2017 Red Hat, Inc. All Rights Reserved.
6 * Written by David Howells (dhowells@redhat.com)
7 */
9 #include <linux/slab.h>
10 #include <linux/fs.h>
11 #include <linux/xattr.h>
12 #include "internal.h"
14 static const char afs_xattr_list[] =
15 "afs.acl\0"
16 "afs.cell\0"
17 "afs.fid\0"
18 "afs.volume\0"
19 "afs.yfs.acl\0"
20 "afs.yfs.acl_inherited\0"
21 "afs.yfs.acl_num_cleaned\0"
22 "afs.yfs.vol_acl";
25 * Retrieve a list of the supported xattrs.
27 ssize_t afs_listxattr(struct dentry *dentry, char *buffer, size_t size)
29 if (size == 0)
30 return sizeof(afs_xattr_list);
31 if (size < sizeof(afs_xattr_list))
32 return -ERANGE;
33 memcpy(buffer, afs_xattr_list, sizeof(afs_xattr_list));
34 return sizeof(afs_xattr_list);
38 * Get a file's ACL.
40 static int afs_xattr_get_acl(const struct xattr_handler *handler,
41 struct dentry *dentry,
42 struct inode *inode, const char *name,
43 void *buffer, size_t size)
45 struct afs_fs_cursor fc;
46 struct afs_status_cb *scb;
47 struct afs_vnode *vnode = AFS_FS_I(inode);
48 struct afs_acl *acl = NULL;
49 struct key *key;
50 int ret = -ENOMEM;
52 scb = kzalloc(sizeof(struct afs_status_cb), GFP_NOFS);
53 if (!scb)
54 goto error;
56 key = afs_request_key(vnode->volume->cell);
57 if (IS_ERR(key)) {
58 ret = PTR_ERR(key);
59 goto error_scb;
62 ret = -ERESTARTSYS;
63 if (afs_begin_vnode_operation(&fc, vnode, key, true)) {
64 afs_dataversion_t data_version = vnode->status.data_version;
66 while (afs_select_fileserver(&fc)) {
67 fc.cb_break = afs_calc_vnode_cb_break(vnode);
68 acl = afs_fs_fetch_acl(&fc, scb);
71 afs_check_for_remote_deletion(&fc, fc.vnode);
72 afs_vnode_commit_status(&fc, vnode, fc.cb_break,
73 &data_version, scb);
74 ret = afs_end_vnode_operation(&fc);
77 if (ret == 0) {
78 ret = acl->size;
79 if (size > 0) {
80 if (acl->size <= size)
81 memcpy(buffer, acl->data, acl->size);
82 else
83 ret = -ERANGE;
85 kfree(acl);
88 key_put(key);
89 error_scb:
90 kfree(scb);
91 error:
92 return ret;
96 * Set a file's AFS3 ACL.
98 static int afs_xattr_set_acl(const struct xattr_handler *handler,
99 struct dentry *dentry,
100 struct inode *inode, const char *name,
101 const void *buffer, size_t size, int flags)
103 struct afs_fs_cursor fc;
104 struct afs_status_cb *scb;
105 struct afs_vnode *vnode = AFS_FS_I(inode);
106 struct afs_acl *acl = NULL;
107 struct key *key;
108 int ret = -ENOMEM;
110 if (flags == XATTR_CREATE)
111 return -EINVAL;
113 scb = kzalloc(sizeof(struct afs_status_cb), GFP_NOFS);
114 if (!scb)
115 goto error;
117 acl = kmalloc(sizeof(*acl) + size, GFP_KERNEL);
118 if (!acl)
119 goto error_scb;
121 key = afs_request_key(vnode->volume->cell);
122 if (IS_ERR(key)) {
123 ret = PTR_ERR(key);
124 goto error_acl;
127 acl->size = size;
128 memcpy(acl->data, buffer, size);
130 ret = -ERESTARTSYS;
131 if (afs_begin_vnode_operation(&fc, vnode, key, true)) {
132 afs_dataversion_t data_version = vnode->status.data_version;
134 while (afs_select_fileserver(&fc)) {
135 fc.cb_break = afs_calc_vnode_cb_break(vnode);
136 afs_fs_store_acl(&fc, acl, scb);
139 afs_check_for_remote_deletion(&fc, fc.vnode);
140 afs_vnode_commit_status(&fc, vnode, fc.cb_break,
141 &data_version, scb);
142 ret = afs_end_vnode_operation(&fc);
145 key_put(key);
146 error_acl:
147 kfree(acl);
148 error_scb:
149 kfree(scb);
150 error:
151 return ret;
154 static const struct xattr_handler afs_xattr_afs_acl_handler = {
155 .name = "afs.acl",
156 .get = afs_xattr_get_acl,
157 .set = afs_xattr_set_acl,
161 * Get a file's YFS ACL.
163 static int afs_xattr_get_yfs(const struct xattr_handler *handler,
164 struct dentry *dentry,
165 struct inode *inode, const char *name,
166 void *buffer, size_t size)
168 struct afs_fs_cursor fc;
169 struct afs_status_cb *scb;
170 struct afs_vnode *vnode = AFS_FS_I(inode);
171 struct yfs_acl *yacl = NULL;
172 struct key *key;
173 char buf[16], *data;
174 int which = 0, dsize, ret = -ENOMEM;
176 if (strcmp(name, "acl") == 0)
177 which = 0;
178 else if (strcmp(name, "acl_inherited") == 0)
179 which = 1;
180 else if (strcmp(name, "acl_num_cleaned") == 0)
181 which = 2;
182 else if (strcmp(name, "vol_acl") == 0)
183 which = 3;
184 else
185 return -EOPNOTSUPP;
187 yacl = kzalloc(sizeof(struct yfs_acl), GFP_KERNEL);
188 if (!yacl)
189 goto error;
191 if (which == 0)
192 yacl->flags |= YFS_ACL_WANT_ACL;
193 else if (which == 3)
194 yacl->flags |= YFS_ACL_WANT_VOL_ACL;
196 scb = kzalloc(sizeof(struct afs_status_cb), GFP_NOFS);
197 if (!scb)
198 goto error_yacl;
200 key = afs_request_key(vnode->volume->cell);
201 if (IS_ERR(key)) {
202 ret = PTR_ERR(key);
203 goto error_scb;
206 ret = -ERESTARTSYS;
207 if (afs_begin_vnode_operation(&fc, vnode, key, true)) {
208 afs_dataversion_t data_version = vnode->status.data_version;
210 while (afs_select_fileserver(&fc)) {
211 fc.cb_break = afs_calc_vnode_cb_break(vnode);
212 yfs_fs_fetch_opaque_acl(&fc, yacl, scb);
215 afs_check_for_remote_deletion(&fc, fc.vnode);
216 afs_vnode_commit_status(&fc, vnode, fc.cb_break,
217 &data_version, scb);
218 ret = afs_end_vnode_operation(&fc);
221 if (ret < 0)
222 goto error_key;
224 switch (which) {
225 case 0:
226 data = yacl->acl->data;
227 dsize = yacl->acl->size;
228 break;
229 case 1:
230 data = buf;
231 dsize = scnprintf(buf, sizeof(buf), "%u", yacl->inherit_flag);
232 break;
233 case 2:
234 data = buf;
235 dsize = scnprintf(buf, sizeof(buf), "%u", yacl->num_cleaned);
236 break;
237 case 3:
238 data = yacl->vol_acl->data;
239 dsize = yacl->vol_acl->size;
240 break;
241 default:
242 ret = -EOPNOTSUPP;
243 goto error_key;
246 ret = dsize;
247 if (size > 0) {
248 if (dsize > size) {
249 ret = -ERANGE;
250 goto error_key;
252 memcpy(buffer, data, dsize);
255 error_key:
256 key_put(key);
257 error_scb:
258 kfree(scb);
259 error_yacl:
260 yfs_free_opaque_acl(yacl);
261 error:
262 return ret;
266 * Set a file's YFS ACL.
268 static int afs_xattr_set_yfs(const struct xattr_handler *handler,
269 struct dentry *dentry,
270 struct inode *inode, const char *name,
271 const void *buffer, size_t size, int flags)
273 struct afs_fs_cursor fc;
274 struct afs_status_cb *scb;
275 struct afs_vnode *vnode = AFS_FS_I(inode);
276 struct afs_acl *acl = NULL;
277 struct key *key;
278 int ret = -ENOMEM;
280 if (flags == XATTR_CREATE ||
281 strcmp(name, "acl") != 0)
282 return -EINVAL;
284 scb = kzalloc(sizeof(struct afs_status_cb), GFP_NOFS);
285 if (!scb)
286 goto error;
288 acl = kmalloc(sizeof(*acl) + size, GFP_KERNEL);
289 if (!acl)
290 goto error_scb;
292 acl->size = size;
293 memcpy(acl->data, buffer, size);
295 key = afs_request_key(vnode->volume->cell);
296 if (IS_ERR(key)) {
297 ret = PTR_ERR(key);
298 goto error_acl;
301 ret = -ERESTARTSYS;
302 if (afs_begin_vnode_operation(&fc, vnode, key, true)) {
303 afs_dataversion_t data_version = vnode->status.data_version;
305 while (afs_select_fileserver(&fc)) {
306 fc.cb_break = afs_calc_vnode_cb_break(vnode);
307 yfs_fs_store_opaque_acl2(&fc, acl, scb);
310 afs_check_for_remote_deletion(&fc, fc.vnode);
311 afs_vnode_commit_status(&fc, vnode, fc.cb_break,
312 &data_version, scb);
313 ret = afs_end_vnode_operation(&fc);
316 error_acl:
317 kfree(acl);
318 key_put(key);
319 error_scb:
320 kfree(scb);
321 error:
322 return ret;
325 static const struct xattr_handler afs_xattr_yfs_handler = {
326 .prefix = "afs.yfs.",
327 .get = afs_xattr_get_yfs,
328 .set = afs_xattr_set_yfs,
332 * Get the name of the cell on which a file resides.
334 static int afs_xattr_get_cell(const struct xattr_handler *handler,
335 struct dentry *dentry,
336 struct inode *inode, const char *name,
337 void *buffer, size_t size)
339 struct afs_vnode *vnode = AFS_FS_I(inode);
340 struct afs_cell *cell = vnode->volume->cell;
341 size_t namelen;
343 namelen = cell->name_len;
344 if (size == 0)
345 return namelen;
346 if (namelen > size)
347 return -ERANGE;
348 memcpy(buffer, cell->name, namelen);
349 return namelen;
352 static const struct xattr_handler afs_xattr_afs_cell_handler = {
353 .name = "afs.cell",
354 .get = afs_xattr_get_cell,
358 * Get the volume ID, vnode ID and vnode uniquifier of a file as a sequence of
359 * hex numbers separated by colons.
361 static int afs_xattr_get_fid(const struct xattr_handler *handler,
362 struct dentry *dentry,
363 struct inode *inode, const char *name,
364 void *buffer, size_t size)
366 struct afs_vnode *vnode = AFS_FS_I(inode);
367 char text[16 + 1 + 24 + 1 + 8 + 1];
368 size_t len;
370 /* The volume ID is 64-bit, the vnode ID is 96-bit and the
371 * uniquifier is 32-bit.
373 len = scnprintf(text, sizeof(text), "%llx:", vnode->fid.vid);
374 if (vnode->fid.vnode_hi)
375 len += scnprintf(text + len, sizeof(text) - len, "%x%016llx",
376 vnode->fid.vnode_hi, vnode->fid.vnode);
377 else
378 len += scnprintf(text + len, sizeof(text) - len, "%llx",
379 vnode->fid.vnode);
380 len += scnprintf(text + len, sizeof(text) - len, ":%x",
381 vnode->fid.unique);
383 if (size == 0)
384 return len;
385 if (len > size)
386 return -ERANGE;
387 memcpy(buffer, text, len);
388 return len;
391 static const struct xattr_handler afs_xattr_afs_fid_handler = {
392 .name = "afs.fid",
393 .get = afs_xattr_get_fid,
397 * Get the name of the volume on which a file resides.
399 static int afs_xattr_get_volume(const struct xattr_handler *handler,
400 struct dentry *dentry,
401 struct inode *inode, const char *name,
402 void *buffer, size_t size)
404 struct afs_vnode *vnode = AFS_FS_I(inode);
405 const char *volname = vnode->volume->name;
406 size_t namelen;
408 namelen = strlen(volname);
409 if (size == 0)
410 return namelen;
411 if (namelen > size)
412 return -ERANGE;
413 memcpy(buffer, volname, namelen);
414 return namelen;
417 static const struct xattr_handler afs_xattr_afs_volume_handler = {
418 .name = "afs.volume",
419 .get = afs_xattr_get_volume,
422 const struct xattr_handler *afs_xattr_handlers[] = {
423 &afs_xattr_afs_acl_handler,
424 &afs_xattr_afs_cell_handler,
425 &afs_xattr_afs_fid_handler,
426 &afs_xattr_afs_volume_handler,
427 &afs_xattr_yfs_handler, /* afs.yfs. prefix */
428 NULL