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)
9 #include <linux/slab.h>
11 #include <linux/xattr.h>
15 * Deal with the result of a successful fetch ACL operation.
17 static void afs_acl_success(struct afs_operation
*op
)
19 afs_vnode_commit_status(op
, &op
->file
[0]);
22 static void afs_acl_put(struct afs_operation
*op
)
27 static const struct afs_operation_ops afs_fetch_acl_operation
= {
28 .issue_afs_rpc
= afs_fs_fetch_acl
,
29 .success
= afs_acl_success
,
36 static int afs_xattr_get_acl(const struct xattr_handler
*handler
,
37 struct dentry
*dentry
,
38 struct inode
*inode
, const char *name
,
39 void *buffer
, size_t size
)
41 struct afs_operation
*op
;
42 struct afs_vnode
*vnode
= AFS_FS_I(inode
);
43 struct afs_acl
*acl
= NULL
;
46 op
= afs_alloc_operation(NULL
, vnode
->volume
);
50 afs_op_set_vnode(op
, 0, vnode
);
51 op
->ops
= &afs_fetch_acl_operation
;
53 afs_begin_vnode_operation(op
);
54 afs_wait_for_operation(op
);
57 ret
= afs_put_operation(op
);
62 if (acl
->size
<= size
)
63 memcpy(buffer
, acl
->data
, acl
->size
);
73 static bool afs_make_acl(struct afs_operation
*op
,
74 const void *buffer
, size_t size
)
78 acl
= kmalloc(struct_size(acl
, data
, size
), GFP_KERNEL
);
85 memcpy(acl
->data
, buffer
, size
);
90 static const struct afs_operation_ops afs_store_acl_operation
= {
91 .issue_afs_rpc
= afs_fs_store_acl
,
92 .success
= afs_acl_success
,
97 * Set a file's AFS3 ACL.
99 static int afs_xattr_set_acl(const struct xattr_handler
*handler
,
100 struct mnt_idmap
*idmap
,
101 struct dentry
*dentry
,
102 struct inode
*inode
, const char *name
,
103 const void *buffer
, size_t size
, int flags
)
105 struct afs_operation
*op
;
106 struct afs_vnode
*vnode
= AFS_FS_I(inode
);
108 if (flags
== XATTR_CREATE
)
111 op
= afs_alloc_operation(NULL
, vnode
->volume
);
115 afs_op_set_vnode(op
, 0, vnode
);
116 if (!afs_make_acl(op
, buffer
, size
))
117 return afs_put_operation(op
);
119 op
->ops
= &afs_store_acl_operation
;
120 return afs_do_sync_operation(op
);
123 static const struct xattr_handler afs_xattr_afs_acl_handler
= {
125 .get
= afs_xattr_get_acl
,
126 .set
= afs_xattr_set_acl
,
129 static const struct afs_operation_ops yfs_fetch_opaque_acl_operation
= {
130 .issue_yfs_rpc
= yfs_fs_fetch_opaque_acl
,
131 .success
= afs_acl_success
,
132 /* Don't free op->yacl in .put here */
136 * Get a file's YFS ACL.
138 static int afs_xattr_get_yfs(const struct xattr_handler
*handler
,
139 struct dentry
*dentry
,
140 struct inode
*inode
, const char *name
,
141 void *buffer
, size_t size
)
143 struct afs_operation
*op
;
144 struct afs_vnode
*vnode
= AFS_FS_I(inode
);
145 struct yfs_acl
*yacl
= NULL
;
147 int which
= 0, dsize
, ret
= -ENOMEM
;
149 if (strcmp(name
, "acl") == 0)
151 else if (strcmp(name
, "acl_inherited") == 0)
153 else if (strcmp(name
, "acl_num_cleaned") == 0)
155 else if (strcmp(name
, "vol_acl") == 0)
160 yacl
= kzalloc(sizeof(struct yfs_acl
), GFP_KERNEL
);
165 yacl
->flags
|= YFS_ACL_WANT_ACL
;
167 yacl
->flags
|= YFS_ACL_WANT_VOL_ACL
;
169 op
= afs_alloc_operation(NULL
, vnode
->volume
);
173 afs_op_set_vnode(op
, 0, vnode
);
175 op
->ops
= &yfs_fetch_opaque_acl_operation
;
177 afs_begin_vnode_operation(op
);
178 afs_wait_for_operation(op
);
179 ret
= afs_put_operation(op
);
184 data
= yacl
->acl
->data
;
185 dsize
= yacl
->acl
->size
;
189 dsize
= scnprintf(buf
, sizeof(buf
), "%u", yacl
->inherit_flag
);
193 dsize
= scnprintf(buf
, sizeof(buf
), "%u", yacl
->num_cleaned
);
196 data
= yacl
->vol_acl
->data
;
197 dsize
= yacl
->vol_acl
->size
;
207 memcpy(buffer
, data
, dsize
);
211 } else if (ret
== -ENOTSUPP
) {
216 yfs_free_opaque_acl(yacl
);
221 static const struct afs_operation_ops yfs_store_opaque_acl2_operation
= {
222 .issue_yfs_rpc
= yfs_fs_store_opaque_acl2
,
223 .success
= afs_acl_success
,
228 * Set a file's YFS ACL.
230 static int afs_xattr_set_yfs(const struct xattr_handler
*handler
,
231 struct mnt_idmap
*idmap
,
232 struct dentry
*dentry
,
233 struct inode
*inode
, const char *name
,
234 const void *buffer
, size_t size
, int flags
)
236 struct afs_operation
*op
;
237 struct afs_vnode
*vnode
= AFS_FS_I(inode
);
240 if (flags
== XATTR_CREATE
||
241 strcmp(name
, "acl") != 0)
244 op
= afs_alloc_operation(NULL
, vnode
->volume
);
248 afs_op_set_vnode(op
, 0, vnode
);
249 if (!afs_make_acl(op
, buffer
, size
))
250 return afs_put_operation(op
);
252 op
->ops
= &yfs_store_opaque_acl2_operation
;
253 ret
= afs_do_sync_operation(op
);
254 if (ret
== -ENOTSUPP
)
259 static const struct xattr_handler afs_xattr_yfs_handler
= {
260 .prefix
= "afs.yfs.",
261 .get
= afs_xattr_get_yfs
,
262 .set
= afs_xattr_set_yfs
,
266 * Get the name of the cell on which a file resides.
268 static int afs_xattr_get_cell(const struct xattr_handler
*handler
,
269 struct dentry
*dentry
,
270 struct inode
*inode
, const char *name
,
271 void *buffer
, size_t size
)
273 struct afs_vnode
*vnode
= AFS_FS_I(inode
);
274 struct afs_cell
*cell
= vnode
->volume
->cell
;
277 namelen
= cell
->name_len
;
282 memcpy(buffer
, cell
->name
, namelen
);
286 static const struct xattr_handler afs_xattr_afs_cell_handler
= {
288 .get
= afs_xattr_get_cell
,
292 * Get the volume ID, vnode ID and vnode uniquifier of a file as a sequence of
293 * hex numbers separated by colons.
295 static int afs_xattr_get_fid(const struct xattr_handler
*handler
,
296 struct dentry
*dentry
,
297 struct inode
*inode
, const char *name
,
298 void *buffer
, size_t size
)
300 struct afs_vnode
*vnode
= AFS_FS_I(inode
);
301 char text
[16 + 1 + 24 + 1 + 8 + 1];
304 /* The volume ID is 64-bit, the vnode ID is 96-bit and the
305 * uniquifier is 32-bit.
307 len
= scnprintf(text
, sizeof(text
), "%llx:", vnode
->fid
.vid
);
308 if (vnode
->fid
.vnode_hi
)
309 len
+= scnprintf(text
+ len
, sizeof(text
) - len
, "%x%016llx",
310 vnode
->fid
.vnode_hi
, vnode
->fid
.vnode
);
312 len
+= scnprintf(text
+ len
, sizeof(text
) - len
, "%llx",
314 len
+= scnprintf(text
+ len
, sizeof(text
) - len
, ":%x",
321 memcpy(buffer
, text
, len
);
325 static const struct xattr_handler afs_xattr_afs_fid_handler
= {
327 .get
= afs_xattr_get_fid
,
331 * Get the name of the volume on which a file resides.
333 static int afs_xattr_get_volume(const struct xattr_handler
*handler
,
334 struct dentry
*dentry
,
335 struct inode
*inode
, const char *name
,
336 void *buffer
, size_t size
)
338 struct afs_vnode
*vnode
= AFS_FS_I(inode
);
339 const char *volname
= vnode
->volume
->name
;
342 namelen
= strlen(volname
);
347 memcpy(buffer
, volname
, namelen
);
351 static const struct xattr_handler afs_xattr_afs_volume_handler
= {
352 .name
= "afs.volume",
353 .get
= afs_xattr_get_volume
,
356 const struct xattr_handler
* const afs_xattr_handlers
[] = {
357 &afs_xattr_afs_acl_handler
,
358 &afs_xattr_afs_cell_handler
,
359 &afs_xattr_afs_fid_handler
,
360 &afs_xattr_afs_volume_handler
,
361 &afs_xattr_yfs_handler
, /* afs.yfs. prefix */