]> git.sesse.net Git - bcachefs-tools-debian/blob - libbcache/xattr.c
Delete more unused shim code, update bcache code
[bcachefs-tools-debian] / libbcache / xattr.c
1
2 #include "bcache.h"
3 #include "bkey_methods.h"
4 #include "btree_update.h"
5 #include "extents.h"
6 #include "fs.h"
7 #include "str_hash.h"
8 #include "xattr.h"
9
10 #include <linux/posix_acl_xattr.h>
11 #include <linux/xattr.h>
12
13 struct xattr_search_key {
14         u8              type;
15         struct qstr     name;
16 };
17
18 #define X_SEARCH(_type, _name, _len) ((struct xattr_search_key) \
19         { .type = _type, .name = QSTR_INIT(_name, _len) })
20
21 static u64 bch_xattr_hash(const struct bch_hash_info *info,
22                           const struct xattr_search_key *key)
23 {
24         struct bch_str_hash_ctx ctx;
25
26         bch_str_hash_init(&ctx, info);
27         bch_str_hash_update(&ctx, info, &key->type, sizeof(key->type));
28         bch_str_hash_update(&ctx, info, key->name.name, key->name.len);
29
30         return bch_str_hash_end(&ctx, info);
31 }
32
33 #define xattr_val(_xattr)       ((_xattr)->x_name + (_xattr)->x_name_len)
34
35 static u64 xattr_hash_key(const struct bch_hash_info *info, const void *key)
36 {
37         return bch_xattr_hash(info, key);
38 }
39
40 static u64 xattr_hash_bkey(const struct bch_hash_info *info, struct bkey_s_c k)
41 {
42         struct bkey_s_c_xattr x = bkey_s_c_to_xattr(k);
43
44         return bch_xattr_hash(info,
45                  &X_SEARCH(x.v->x_type, x.v->x_name, x.v->x_name_len));
46 }
47
48 static bool xattr_cmp_key(struct bkey_s_c _l, const void *_r)
49 {
50         struct bkey_s_c_xattr l = bkey_s_c_to_xattr(_l);
51         const struct xattr_search_key *r = _r;
52
53         return l.v->x_type != r->type ||
54                 l.v->x_name_len != r->name.len ||
55                 memcmp(l.v->x_name, r->name.name, r->name.len);
56 }
57
58 static bool xattr_cmp_bkey(struct bkey_s_c _l, struct bkey_s_c _r)
59 {
60         struct bkey_s_c_xattr l = bkey_s_c_to_xattr(_l);
61         struct bkey_s_c_xattr r = bkey_s_c_to_xattr(_r);
62
63         return l.v->x_type != r.v->x_type ||
64                 l.v->x_name_len != r.v->x_name_len ||
65                 memcmp(l.v->x_name, r.v->x_name, r.v->x_name_len);
66 }
67
68 static const struct bch_hash_desc xattr_hash_desc = {
69         .btree_id       = BTREE_ID_XATTRS,
70         .key_type       = BCH_XATTR,
71         .whiteout_type  = BCH_XATTR_WHITEOUT,
72         .hash_key       = xattr_hash_key,
73         .hash_bkey      = xattr_hash_bkey,
74         .cmp_key        = xattr_cmp_key,
75         .cmp_bkey       = xattr_cmp_bkey,
76 };
77
78 static const char *bch_xattr_invalid(const struct cache_set *c,
79                                      struct bkey_s_c k)
80 {
81         switch (k.k->type) {
82         case BCH_XATTR:
83                 return bkey_val_bytes(k.k) < sizeof(struct bch_xattr)
84                         ? "value too small"
85                         : NULL;
86
87         case BCH_XATTR_WHITEOUT:
88                 return bkey_val_bytes(k.k) != 0
89                         ? "value size should be zero"
90                         : NULL;
91
92         default:
93                 return "invalid type";
94         }
95 }
96
97 static void bch_xattr_to_text(struct cache_set *c, char *buf,
98                               size_t size, struct bkey_s_c k)
99 {
100         struct bkey_s_c_xattr xattr;
101         int n;
102
103         switch (k.k->type) {
104         case BCH_XATTR:
105                 xattr = bkey_s_c_to_xattr(k);
106
107                 if (size) {
108                         n = min_t(unsigned, size, xattr.v->x_name_len);
109                         memcpy(buf, xattr.v->x_name, n);
110                         buf[size - 1] = '\0';
111                         buf += n;
112                         size -= n;
113                 }
114
115                 n = scnprintf(buf, size, " -> ");
116                 buf += n;
117                 size -= n;
118
119                 if (size) {
120                         n = min_t(unsigned, size,
121                                   le16_to_cpu(xattr.v->x_val_len));
122                         memcpy(buf, xattr_val(xattr.v), n);
123                         buf[size - 1] = '\0';
124                         buf += n;
125                         size -= n;
126                 }
127
128                 break;
129         case BCH_XATTR_WHITEOUT:
130                 scnprintf(buf, size, "whiteout");
131                 break;
132         }
133 }
134
135 const struct bkey_ops bch_bkey_xattr_ops = {
136         .key_invalid    = bch_xattr_invalid,
137         .val_to_text    = bch_xattr_to_text,
138 };
139
140 int bch_xattr_get(struct cache_set *c, struct inode *inode,
141                   const char *name, void *buffer, size_t size, int type)
142 {
143         struct bch_inode_info *ei = to_bch_ei(inode);
144         struct btree_iter iter;
145         struct bkey_s_c k;
146         struct bkey_s_c_xattr xattr;
147         int ret;
148
149         k = bch_hash_lookup(xattr_hash_desc, &ei->str_hash, c,
150                             ei->vfs_inode.i_ino, &iter,
151                             &X_SEARCH(type, name, strlen(name)));
152         if (IS_ERR(k.k))
153                 return bch_btree_iter_unlock(&iter) ?: -ENODATA;
154
155         xattr = bkey_s_c_to_xattr(k);
156         ret = le16_to_cpu(xattr.v->x_val_len);
157         if (buffer) {
158                 if (ret > size)
159                         ret = -ERANGE;
160                 else
161                         memcpy(buffer, xattr_val(xattr.v), ret);
162         }
163
164         bch_btree_iter_unlock(&iter);
165         return ret;
166 }
167
168 int __bch_xattr_set(struct cache_set *c, u64 inum,
169                   const struct bch_hash_info *hash_info,
170                   const char *name, const void *value, size_t size,
171                   int flags, int type, u64 *journal_seq)
172 {
173         struct xattr_search_key search = X_SEARCH(type, name, strlen(name));
174         int ret;
175
176         if (!value) {
177                 ret = bch_hash_delete(xattr_hash_desc, hash_info,
178                                       c, inum,
179                                       journal_seq, &search);
180         } else {
181                 struct bkey_i_xattr *xattr;
182                 unsigned u64s = BKEY_U64s +
183                         DIV_ROUND_UP(sizeof(struct bch_xattr) +
184                                      search.name.len + size,
185                                      sizeof(u64));
186
187                 if (u64s > U8_MAX)
188                         return -ERANGE;
189
190                 xattr = kmalloc(u64s * sizeof(u64), GFP_NOFS);
191                 if (!xattr)
192                         return -ENOMEM;
193
194                 bkey_xattr_init(&xattr->k_i);
195                 xattr->k.u64s           = u64s;
196                 xattr->v.x_type         = type;
197                 xattr->v.x_name_len     = search.name.len;
198                 xattr->v.x_val_len      = cpu_to_le16(size);
199                 memcpy(xattr->v.x_name, search.name.name, search.name.len);
200                 memcpy(xattr_val(&xattr->v), value, size);
201
202                 ret = bch_hash_set(xattr_hash_desc, hash_info, c,
203                                 inum, journal_seq,
204                                 &xattr->k_i,
205                                 (flags & XATTR_CREATE ? BCH_HASH_SET_MUST_CREATE : 0)|
206                                 (flags & XATTR_REPLACE ? BCH_HASH_SET_MUST_REPLACE : 0));
207                 kfree(xattr);
208         }
209
210         if (ret == -ENOENT)
211                 ret = flags & XATTR_REPLACE ? -ENODATA : 0;
212
213         return ret;
214 }
215
216 int bch_xattr_set(struct cache_set *c, struct inode *inode,
217                   const char *name, const void *value, size_t size,
218                   int flags, int type)
219 {
220         struct bch_inode_info *ei = to_bch_ei(inode);
221
222         return __bch_xattr_set(c, inode->i_ino, &ei->str_hash,
223                                name, value, size, flags, type,
224                                &ei->journal_seq);
225 }
226
227 static const struct xattr_handler *bch_xattr_type_to_handler(unsigned);
228
229 static size_t bch_xattr_emit(struct dentry *dentry,
230                              const struct bch_xattr *xattr,
231                              char *buffer, size_t buffer_size)
232 {
233         const struct xattr_handler *handler =
234                 bch_xattr_type_to_handler(xattr->x_type);
235
236         if (handler && (!handler->list || handler->list(dentry))) {
237                 const char *prefix = handler->prefix ?: handler->name;
238                 const size_t prefix_len = strlen(prefix);
239                 const size_t total_len = prefix_len + xattr->x_name_len + 1;
240
241                 if (buffer && total_len <= buffer_size) {
242                         memcpy(buffer, prefix, prefix_len);
243                         memcpy(buffer + prefix_len,
244                                xattr->x_name, xattr->x_name_len);
245                         buffer[prefix_len + xattr->x_name_len] = '\0';
246                 }
247
248                 return total_len;
249         } else {
250                 return 0;
251         }
252 }
253
254 ssize_t bch_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size)
255 {
256         struct cache_set *c = dentry->d_sb->s_fs_info;
257         struct btree_iter iter;
258         struct bkey_s_c k;
259         const struct bch_xattr *xattr;
260         u64 inum = dentry->d_inode->i_ino;
261         ssize_t ret = 0;
262         size_t len;
263
264         for_each_btree_key(&iter, c, BTREE_ID_XATTRS, POS(inum, 0), k) {
265                 BUG_ON(k.k->p.inode < inum);
266
267                 if (k.k->p.inode > inum)
268                         break;
269
270                 if (k.k->type != BCH_XATTR)
271                         continue;
272
273                 xattr = bkey_s_c_to_xattr(k).v;
274
275                 len = bch_xattr_emit(dentry, xattr, buffer, buffer_size);
276                 if (buffer) {
277                         if (len > buffer_size) {
278                                 bch_btree_iter_unlock(&iter);
279                                 return -ERANGE;
280                         }
281
282                         buffer += len;
283                         buffer_size -= len;
284                 }
285
286                 ret += len;
287
288         }
289         bch_btree_iter_unlock(&iter);
290
291         return ret;
292 }
293
294 static int bch_xattr_get_handler(const struct xattr_handler *handler,
295                                  struct dentry *dentry, struct inode *inode,
296                                  const char *name, void *buffer, size_t size)
297 {
298         struct cache_set *c = inode->i_sb->s_fs_info;
299
300         return bch_xattr_get(c, inode, name, buffer, size, handler->flags);
301 }
302
303 static int bch_xattr_set_handler(const struct xattr_handler *handler,
304                                  struct dentry *dentry, struct inode *inode,
305                                  const char *name, const void *value,
306                                  size_t size, int flags)
307 {
308         struct cache_set *c = inode->i_sb->s_fs_info;
309
310         return bch_xattr_set(c, inode, name, value, size, flags,
311                              handler->flags);
312 }
313
314 static const struct xattr_handler bch_xattr_user_handler = {
315         .prefix = XATTR_USER_PREFIX,
316         .get    = bch_xattr_get_handler,
317         .set    = bch_xattr_set_handler,
318         .flags  = BCH_XATTR_INDEX_USER,
319 };
320
321 static bool bch_xattr_trusted_list(struct dentry *dentry)
322 {
323         return capable(CAP_SYS_ADMIN);
324 }
325
326 static const struct xattr_handler bch_xattr_trusted_handler = {
327         .prefix = XATTR_TRUSTED_PREFIX,
328         .list   = bch_xattr_trusted_list,
329         .get    = bch_xattr_get_handler,
330         .set    = bch_xattr_set_handler,
331         .flags  = BCH_XATTR_INDEX_TRUSTED,
332 };
333
334 static const struct xattr_handler bch_xattr_security_handler = {
335         .prefix = XATTR_SECURITY_PREFIX,
336         .get    = bch_xattr_get_handler,
337         .set    = bch_xattr_set_handler,
338         .flags  = BCH_XATTR_INDEX_SECURITY,
339 };
340
341 static const struct xattr_handler *bch_xattr_handler_map[] = {
342         [BCH_XATTR_INDEX_USER]                  = &bch_xattr_user_handler,
343         [BCH_XATTR_INDEX_POSIX_ACL_ACCESS]      =
344                 &posix_acl_access_xattr_handler,
345         [BCH_XATTR_INDEX_POSIX_ACL_DEFAULT]     =
346                 &posix_acl_default_xattr_handler,
347         [BCH_XATTR_INDEX_TRUSTED]               = &bch_xattr_trusted_handler,
348         [BCH_XATTR_INDEX_SECURITY]              = &bch_xattr_security_handler,
349 };
350
351 const struct xattr_handler *bch_xattr_handlers[] = {
352         &bch_xattr_user_handler,
353         &posix_acl_access_xattr_handler,
354         &posix_acl_default_xattr_handler,
355         &bch_xattr_trusted_handler,
356         &bch_xattr_security_handler,
357         NULL
358 };
359
360 static const struct xattr_handler *bch_xattr_type_to_handler(unsigned type)
361 {
362         return type < ARRAY_SIZE(bch_xattr_handler_map)
363                 ? bch_xattr_handler_map[type]
364                 : NULL;
365 }