]> asedeno.scripts.mit.edu Git - linux.git/blob - fs/afs/xattr.c
b7d3d714d8ff0a1a11c527df9d6218ed5c7305eb
[linux.git] / fs / afs / xattr.c
1 /* Extended attribute handling for AFS.  We use xattrs to get and set metadata
2  * instead of providing pioctl().
3  *
4  * Copyright (C) 2017 Red Hat, Inc. All Rights Reserved.
5  * Written by David Howells (dhowells@redhat.com)
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public Licence
9  * as published by the Free Software Foundation; either version
10  * 2 of the Licence, or (at your option) any later version.
11  */
12
13 #include <linux/slab.h>
14 #include <linux/fs.h>
15 #include <linux/xattr.h>
16 #include "internal.h"
17
18 static const char afs_xattr_list[] =
19         "afs.acl\0"
20         "afs.cell\0"
21         "afs.fid\0"
22         "afs.volume";
23
24 /*
25  * Retrieve a list of the supported xattrs.
26  */
27 ssize_t afs_listxattr(struct dentry *dentry, char *buffer, size_t size)
28 {
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);
35 }
36
37 /*
38  * Get a file's ACL.
39  */
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)
44 {
45         struct afs_fs_cursor fc;
46         struct afs_vnode *vnode = AFS_FS_I(inode);
47         struct afs_acl *acl = NULL;
48         struct key *key;
49         int ret;
50
51         key = afs_request_key(vnode->volume->cell);
52         if (IS_ERR(key))
53                 return PTR_ERR(key);
54
55         ret = -ERESTARTSYS;
56         if (afs_begin_vnode_operation(&fc, vnode, key)) {
57                 while (afs_select_fileserver(&fc)) {
58                         fc.cb_break = afs_calc_vnode_cb_break(vnode);
59                         acl = afs_fs_fetch_acl(&fc);
60                 }
61
62                 afs_check_for_remote_deletion(&fc, fc.vnode);
63                 afs_vnode_commit_status(&fc, vnode, fc.cb_break);
64                 ret = afs_end_vnode_operation(&fc);
65         }
66
67         if (ret == 0) {
68                 ret = acl->size;
69                 if (size > 0) {
70                         ret = -ERANGE;
71                         if (acl->size > size)
72                                 return -ERANGE;
73                         memcpy(buffer, acl->data, acl->size);
74                         ret = acl->size;
75                 }
76                 kfree(acl);
77         }
78
79         key_put(key);
80         return ret;
81 }
82
83 static const struct xattr_handler afs_xattr_afs_acl_handler = {
84         .name   = "afs.acl",
85         .get    = afs_xattr_get_acl,
86 };
87
88 /*
89  * Get the name of the cell on which a file resides.
90  */
91 static int afs_xattr_get_cell(const struct xattr_handler *handler,
92                               struct dentry *dentry,
93                               struct inode *inode, const char *name,
94                               void *buffer, size_t size)
95 {
96         struct afs_vnode *vnode = AFS_FS_I(inode);
97         struct afs_cell *cell = vnode->volume->cell;
98         size_t namelen;
99
100         namelen = cell->name_len;
101         if (size == 0)
102                 return namelen;
103         if (namelen > size)
104                 return -ERANGE;
105         memcpy(buffer, cell->name, namelen);
106         return namelen;
107 }
108
109 static const struct xattr_handler afs_xattr_afs_cell_handler = {
110         .name   = "afs.cell",
111         .get    = afs_xattr_get_cell,
112 };
113
114 /*
115  * Get the volume ID, vnode ID and vnode uniquifier of a file as a sequence of
116  * hex numbers separated by colons.
117  */
118 static int afs_xattr_get_fid(const struct xattr_handler *handler,
119                              struct dentry *dentry,
120                              struct inode *inode, const char *name,
121                              void *buffer, size_t size)
122 {
123         struct afs_vnode *vnode = AFS_FS_I(inode);
124         char text[16 + 1 + 24 + 1 + 8 + 1];
125         size_t len;
126
127         /* The volume ID is 64-bit, the vnode ID is 96-bit and the
128          * uniquifier is 32-bit.
129          */
130         len = sprintf(text, "%llx:", vnode->fid.vid);
131         if (vnode->fid.vnode_hi)
132                 len += sprintf(text + len, "%x%016llx",
133                                vnode->fid.vnode_hi, vnode->fid.vnode);
134         else
135                 len += sprintf(text + len, "%llx", vnode->fid.vnode);
136         len += sprintf(text + len, ":%x", vnode->fid.unique);
137
138         if (size == 0)
139                 return len;
140         if (len > size)
141                 return -ERANGE;
142         memcpy(buffer, text, len);
143         return len;
144 }
145
146 static const struct xattr_handler afs_xattr_afs_fid_handler = {
147         .name   = "afs.fid",
148         .get    = afs_xattr_get_fid,
149 };
150
151 /*
152  * Get the name of the volume on which a file resides.
153  */
154 static int afs_xattr_get_volume(const struct xattr_handler *handler,
155                               struct dentry *dentry,
156                               struct inode *inode, const char *name,
157                               void *buffer, size_t size)
158 {
159         struct afs_vnode *vnode = AFS_FS_I(inode);
160         const char *volname = vnode->volume->name;
161         size_t namelen;
162
163         namelen = strlen(volname);
164         if (size == 0)
165                 return namelen;
166         if (namelen > size)
167                 return -ERANGE;
168         memcpy(buffer, volname, namelen);
169         return namelen;
170 }
171
172 static const struct xattr_handler afs_xattr_afs_volume_handler = {
173         .name   = "afs.volume",
174         .get    = afs_xattr_get_volume,
175 };
176
177 const struct xattr_handler *afs_xattr_handlers[] = {
178         &afs_xattr_afs_acl_handler,
179         &afs_xattr_afs_cell_handler,
180         &afs_xattr_afs_fid_handler,
181         &afs_xattr_afs_volume_handler,
182         NULL
183 };