]> git.sesse.net Git - bcachefs-tools-debian/blob - libbcachefs/xattr.c
Update bcachefs sources to 14ce2a2031 bcachefs: fixes for building in userspace
[bcachefs-tools-debian] / libbcachefs / xattr.c
1
2 #include "bcachefs.h"
3 #include "bkey_methods.h"
4 #include "btree_update.h"
5 #include "compress.h"
6 #include "extents.h"
7 #include "fs.h"
8 #include "str_hash.h"
9 #include "xattr.h"
10
11 #include <linux/dcache.h>
12 #include <linux/posix_acl_xattr.h>
13 #include <linux/xattr.h>
14
15 static unsigned xattr_val_u64s(unsigned name_len, unsigned val_len)
16 {
17         return DIV_ROUND_UP(sizeof(struct bch_xattr) +
18                             name_len + val_len, sizeof(u64));
19 }
20
21 #define xattr_val(_xattr)       ((_xattr)->x_name + (_xattr)->x_name_len)
22
23 static const struct xattr_handler *bch2_xattr_type_to_handler(unsigned);
24
25 struct xattr_search_key {
26         u8              type;
27         struct qstr     name;
28 };
29
30 #define X_SEARCH(_type, _name, _len) ((struct xattr_search_key) \
31         { .type = _type, .name = QSTR_INIT(_name, _len) })
32
33 static u64 bch2_xattr_hash(const struct bch_hash_info *info,
34                           const struct xattr_search_key *key)
35 {
36         struct bch_str_hash_ctx ctx;
37
38         bch2_str_hash_init(&ctx, info);
39         bch2_str_hash_update(&ctx, info, &key->type, sizeof(key->type));
40         bch2_str_hash_update(&ctx, info, key->name.name, key->name.len);
41
42         return bch2_str_hash_end(&ctx, info);
43 }
44
45 static u64 xattr_hash_key(const struct bch_hash_info *info, const void *key)
46 {
47         return bch2_xattr_hash(info, key);
48 }
49
50 static u64 xattr_hash_bkey(const struct bch_hash_info *info, struct bkey_s_c k)
51 {
52         struct bkey_s_c_xattr x = bkey_s_c_to_xattr(k);
53
54         return bch2_xattr_hash(info,
55                  &X_SEARCH(x.v->x_type, x.v->x_name, x.v->x_name_len));
56 }
57
58 static bool xattr_cmp_key(struct bkey_s_c _l, const void *_r)
59 {
60         struct bkey_s_c_xattr l = bkey_s_c_to_xattr(_l);
61         const struct xattr_search_key *r = _r;
62
63         return l.v->x_type != r->type ||
64                 l.v->x_name_len != r->name.len ||
65                 memcmp(l.v->x_name, r->name.name, r->name.len);
66 }
67
68 static bool xattr_cmp_bkey(struct bkey_s_c _l, struct bkey_s_c _r)
69 {
70         struct bkey_s_c_xattr l = bkey_s_c_to_xattr(_l);
71         struct bkey_s_c_xattr r = bkey_s_c_to_xattr(_r);
72
73         return l.v->x_type != r.v->x_type ||
74                 l.v->x_name_len != r.v->x_name_len ||
75                 memcmp(l.v->x_name, r.v->x_name, r.v->x_name_len);
76 }
77
78 const struct bch_hash_desc bch2_xattr_hash_desc = {
79         .btree_id       = BTREE_ID_XATTRS,
80         .key_type       = BCH_XATTR,
81         .whiteout_type  = BCH_XATTR_WHITEOUT,
82         .hash_key       = xattr_hash_key,
83         .hash_bkey      = xattr_hash_bkey,
84         .cmp_key        = xattr_cmp_key,
85         .cmp_bkey       = xattr_cmp_bkey,
86 };
87
88 static const char *bch2_xattr_invalid(const struct bch_fs *c,
89                                      struct bkey_s_c k)
90 {
91         const struct xattr_handler *handler;
92         struct bkey_s_c_xattr xattr;
93         unsigned u64s;
94
95         switch (k.k->type) {
96         case BCH_XATTR:
97                 if (bkey_val_bytes(k.k) < sizeof(struct bch_xattr))
98                         return "value too small";
99
100                 xattr = bkey_s_c_to_xattr(k);
101                 u64s = xattr_val_u64s(xattr.v->x_name_len,
102                                       le16_to_cpu(xattr.v->x_val_len));
103
104                 if (bkey_val_u64s(k.k) < u64s)
105                         return "value too small";
106
107                 if (bkey_val_u64s(k.k) > u64s)
108                         return "value too big";
109
110                 handler = bch2_xattr_type_to_handler(xattr.v->x_type);
111                 if (!handler)
112                         return "invalid type";
113
114                 if (memchr(xattr.v->x_name, '\0', xattr.v->x_name_len))
115                         return "xattr name has invalid characters";
116
117                 return NULL;
118         case BCH_XATTR_WHITEOUT:
119                 return bkey_val_bytes(k.k) != 0
120                         ? "value size should be zero"
121                         : NULL;
122
123         default:
124                 return "invalid type";
125         }
126 }
127
128 static void bch2_xattr_to_text(struct bch_fs *c, char *buf,
129                               size_t size, struct bkey_s_c k)
130 {
131         const struct xattr_handler *handler;
132         struct bkey_s_c_xattr xattr;
133         size_t n = 0;
134
135         switch (k.k->type) {
136         case BCH_XATTR:
137                 xattr = bkey_s_c_to_xattr(k);
138
139                 handler = bch2_xattr_type_to_handler(xattr.v->x_type);
140                 if (handler && handler->prefix)
141                         n += scnprintf(buf + n, size - n, "%s", handler->prefix);
142                 else if (handler)
143                         n += scnprintf(buf + n, size - n, "(type %u)",
144                                        xattr.v->x_type);
145                 else
146                         n += scnprintf(buf + n, size - n, "(unknown type %u)",
147                                        xattr.v->x_type);
148
149                 n += bch_scnmemcpy(buf + n, size - n, xattr.v->x_name,
150                                    xattr.v->x_name_len);
151                 n += scnprintf(buf + n, size - n, ":");
152                 n += bch_scnmemcpy(buf + n, size - n, xattr_val(xattr.v),
153                                    le16_to_cpu(xattr.v->x_val_len));
154                 break;
155         case BCH_XATTR_WHITEOUT:
156                 scnprintf(buf, size, "whiteout");
157                 break;
158         }
159 }
160
161 const struct bkey_ops bch2_bkey_xattr_ops = {
162         .key_invalid    = bch2_xattr_invalid,
163         .val_to_text    = bch2_xattr_to_text,
164 };
165
166 int bch2_xattr_get(struct bch_fs *c, struct bch_inode_info *inode,
167                   const char *name, void *buffer, size_t size, int type)
168 {
169         struct btree_iter iter;
170         struct bkey_s_c k;
171         struct bkey_s_c_xattr xattr;
172         int ret;
173
174         k = bch2_hash_lookup(bch2_xattr_hash_desc, &inode->ei_str_hash, c,
175                              inode->v.i_ino, &iter,
176                              &X_SEARCH(type, name, strlen(name)));
177         if (IS_ERR(k.k))
178                 return bch2_btree_iter_unlock(&iter) ?: -ENODATA;
179
180         xattr = bkey_s_c_to_xattr(k);
181         ret = le16_to_cpu(xattr.v->x_val_len);
182         if (buffer) {
183                 if (ret > size)
184                         ret = -ERANGE;
185                 else
186                         memcpy(buffer, xattr_val(xattr.v), ret);
187         }
188
189         bch2_btree_iter_unlock(&iter);
190         return ret;
191 }
192
193 int __bch2_xattr_set(struct bch_fs *c, u64 inum,
194                     const struct bch_hash_info *hash_info,
195                     const char *name, const void *value, size_t size,
196                     int flags, int type, u64 *journal_seq)
197 {
198         struct xattr_search_key search = X_SEARCH(type, name, strlen(name));
199         int ret;
200
201         if (!value) {
202                 ret = bch2_hash_delete(bch2_xattr_hash_desc, hash_info,
203                                       c, inum,
204                                       journal_seq, &search);
205         } else {
206                 struct bkey_i_xattr *xattr;
207                 unsigned u64s = BKEY_U64s +
208                         xattr_val_u64s(search.name.len, size);
209
210                 if (u64s > U8_MAX)
211                         return -ERANGE;
212
213                 xattr = kmalloc(u64s * sizeof(u64), GFP_NOFS);
214                 if (!xattr)
215                         return -ENOMEM;
216
217                 bkey_xattr_init(&xattr->k_i);
218                 xattr->k.u64s           = u64s;
219                 xattr->v.x_type         = type;
220                 xattr->v.x_name_len     = search.name.len;
221                 xattr->v.x_val_len      = cpu_to_le16(size);
222                 memcpy(xattr->v.x_name, search.name.name, search.name.len);
223                 memcpy(xattr_val(&xattr->v), value, size);
224
225                 ret = bch2_hash_set(bch2_xattr_hash_desc, hash_info, c,
226                                 inum, journal_seq,
227                                 &xattr->k_i,
228                                 (flags & XATTR_CREATE ? BCH_HASH_SET_MUST_CREATE : 0)|
229                                 (flags & XATTR_REPLACE ? BCH_HASH_SET_MUST_REPLACE : 0));
230                 kfree(xattr);
231         }
232
233         if (ret == -ENOENT)
234                 ret = flags & XATTR_REPLACE ? -ENODATA : 0;
235
236         return ret;
237 }
238
239 int bch2_xattr_set(struct bch_fs *c, struct bch_inode_info *inode,
240                    const char *name, const void *value, size_t size,
241                    int flags, int type)
242 {
243         return __bch2_xattr_set(c, inode->v.i_ino, &inode->ei_str_hash,
244                                 name, value, size, flags, type,
245                                 &inode->ei_journal_seq);
246 }
247
248 static size_t bch2_xattr_emit(struct dentry *dentry,
249                              const struct bch_xattr *xattr,
250                              char *buffer, size_t buffer_size)
251 {
252         const struct xattr_handler *handler =
253                 bch2_xattr_type_to_handler(xattr->x_type);
254
255         if (handler && (!handler->list || handler->list(dentry))) {
256                 const char *prefix = handler->prefix ?: handler->name;
257                 const size_t prefix_len = strlen(prefix);
258                 const size_t total_len = prefix_len + xattr->x_name_len + 1;
259
260                 if (buffer && total_len <= buffer_size) {
261                         memcpy(buffer, prefix, prefix_len);
262                         memcpy(buffer + prefix_len,
263                                xattr->x_name, xattr->x_name_len);
264                         buffer[prefix_len + xattr->x_name_len] = '\0';
265                 }
266
267                 return total_len;
268         } else {
269                 return 0;
270         }
271 }
272
273 ssize_t bch2_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size)
274 {
275         struct bch_fs *c = dentry->d_sb->s_fs_info;
276         struct btree_iter iter;
277         struct bkey_s_c k;
278         const struct bch_xattr *xattr;
279         u64 inum = dentry->d_inode->i_ino;
280         ssize_t ret = 0;
281         size_t len;
282
283         for_each_btree_key(&iter, c, BTREE_ID_XATTRS, POS(inum, 0), 0, k) {
284                 BUG_ON(k.k->p.inode < inum);
285
286                 if (k.k->p.inode > inum)
287                         break;
288
289                 if (k.k->type != BCH_XATTR)
290                         continue;
291
292                 xattr = bkey_s_c_to_xattr(k).v;
293
294                 len = bch2_xattr_emit(dentry, xattr, buffer, buffer_size);
295                 if (buffer) {
296                         if (len > buffer_size) {
297                                 bch2_btree_iter_unlock(&iter);
298                                 return -ERANGE;
299                         }
300
301                         buffer += len;
302                         buffer_size -= len;
303                 }
304
305                 ret += len;
306
307         }
308         bch2_btree_iter_unlock(&iter);
309
310         return ret;
311 }
312
313 static int bch2_xattr_get_handler(const struct xattr_handler *handler,
314                                   struct dentry *dentry, struct inode *vinode,
315                                   const char *name, void *buffer, size_t size)
316 {
317         struct bch_inode_info *inode = to_bch_ei(vinode);
318         struct bch_fs *c = inode->v.i_sb->s_fs_info;
319
320         return bch2_xattr_get(c, inode, name, buffer, size, handler->flags);
321 }
322
323 static int bch2_xattr_set_handler(const struct xattr_handler *handler,
324                                   struct dentry *dentry, struct inode *vinode,
325                                   const char *name, const void *value,
326                                   size_t size, int flags)
327 {
328         struct bch_inode_info *inode = to_bch_ei(vinode);
329         struct bch_fs *c = inode->v.i_sb->s_fs_info;
330
331         return bch2_xattr_set(c, inode, name, value, size, flags,
332                               handler->flags);
333 }
334
335 static const struct xattr_handler bch_xattr_user_handler = {
336         .prefix = XATTR_USER_PREFIX,
337         .get    = bch2_xattr_get_handler,
338         .set    = bch2_xattr_set_handler,
339         .flags  = BCH_XATTR_INDEX_USER,
340 };
341
342 static bool bch2_xattr_trusted_list(struct dentry *dentry)
343 {
344         return capable(CAP_SYS_ADMIN);
345 }
346
347 static const struct xattr_handler bch_xattr_trusted_handler = {
348         .prefix = XATTR_TRUSTED_PREFIX,
349         .list   = bch2_xattr_trusted_list,
350         .get    = bch2_xattr_get_handler,
351         .set    = bch2_xattr_set_handler,
352         .flags  = BCH_XATTR_INDEX_TRUSTED,
353 };
354
355 static const struct xattr_handler bch_xattr_security_handler = {
356         .prefix = XATTR_SECURITY_PREFIX,
357         .get    = bch2_xattr_get_handler,
358         .set    = bch2_xattr_set_handler,
359         .flags  = BCH_XATTR_INDEX_SECURITY,
360 };
361
362 #ifndef NO_BCACHEFS_FS
363
364 static int bch2_xattr_bcachefs_get(const struct xattr_handler *handler,
365                                    struct dentry *dentry, struct inode *vinode,
366                                    const char *name, void *buffer, size_t size)
367 {
368         struct bch_inode_info *inode = to_bch_ei(vinode);
369         struct bch_opts opts =
370                 bch2_inode_opts_to_opts(bch2_inode_opts_get(&inode->ei_inode));
371         const struct bch_option *opt;
372         int ret, id;
373         u64 v;
374
375         id = bch2_opt_lookup(name);
376         if (id < 0 || !bch2_opt_is_inode_opt(id))
377                 return -EINVAL;
378
379         opt = bch2_opt_table + id;
380
381         if (!bch2_opt_defined_by_id(&opts, id))
382                 return -ENODATA;
383
384         v = bch2_opt_get_by_id(&opts, id);
385
386         if (opt->type == BCH_OPT_STR)
387                 ret = snprintf(buffer, size, "%s", opt->choices[v]);
388         else
389                 ret = snprintf(buffer, size, "%llu", v);
390
391         return ret <= size || !buffer ? ret : -ERANGE;
392 }
393
394 struct inode_opt_set {
395         int                     id;
396         u64                     v;
397         bool                    defined;
398 };
399
400 static int inode_opt_set_fn(struct bch_inode_info *inode,
401                             struct bch_inode_unpacked *bi,
402                             void *p)
403 {
404         struct inode_opt_set *s = p;
405
406         if (s->defined)
407                 bch2_inode_opt_set(bi, s->id, s->v);
408         else
409                 bch2_inode_opt_clear(bi, s->id);
410         return 0;
411 }
412
413 static int bch2_xattr_bcachefs_set(const struct xattr_handler *handler,
414                                    struct dentry *dentry, struct inode *vinode,
415                                    const char *name, const void *value,
416                                    size_t size, int flags)
417 {
418         struct bch_inode_info *inode = to_bch_ei(vinode);
419         struct bch_fs *c = inode->v.i_sb->s_fs_info;
420         const struct bch_option *opt;
421         char *buf;
422         struct inode_opt_set s;
423         int ret;
424
425         s.id = bch2_opt_lookup(name);
426         if (s.id < 0 || !bch2_opt_is_inode_opt(s.id))
427                 return -EINVAL;
428
429         opt = bch2_opt_table + s.id;
430
431         if (value) {
432                 buf = kmalloc(size + 1, GFP_KERNEL);
433                 if (!buf)
434                         return -ENOMEM;
435                 memcpy(buf, value, size);
436                 buf[size] = '\0';
437
438                 ret = bch2_opt_parse(opt, buf, &s.v);
439                 kfree(buf);
440
441                 if (ret < 0)
442                         return ret;
443
444                 if (s.id == Opt_compression) {
445                         mutex_lock(&c->sb_lock);
446                         ret = bch2_check_set_has_compressed_data(c, s.v);
447                         mutex_unlock(&c->sb_lock);
448
449                         if (ret)
450                                 return ret;
451                 }
452
453                 s.defined = true;
454         } else {
455                 s.defined = false;
456         }
457
458         mutex_lock(&inode->ei_update_lock);
459         ret = __bch2_write_inode(c, inode, inode_opt_set_fn, &s);
460         mutex_unlock(&inode->ei_update_lock);
461
462         return ret;
463 }
464
465 static const struct xattr_handler bch_xattr_bcachefs_handler = {
466         .prefix = "bcachefs.",
467         .get    = bch2_xattr_bcachefs_get,
468         .set    = bch2_xattr_bcachefs_set,
469 };
470
471 #endif /* NO_BCACHEFS_FS */
472
473 const struct xattr_handler *bch2_xattr_handlers[] = {
474         &bch_xattr_user_handler,
475         &posix_acl_access_xattr_handler,
476         &posix_acl_default_xattr_handler,
477         &bch_xattr_trusted_handler,
478         &bch_xattr_security_handler,
479 #ifndef NO_BCACHEFS_FS
480         &bch_xattr_bcachefs_handler,
481 #endif
482         NULL
483 };
484
485 static const struct xattr_handler *bch_xattr_handler_map[] = {
486         [BCH_XATTR_INDEX_USER]                  = &bch_xattr_user_handler,
487         [BCH_XATTR_INDEX_POSIX_ACL_ACCESS]      =
488                 &posix_acl_access_xattr_handler,
489         [BCH_XATTR_INDEX_POSIX_ACL_DEFAULT]     =
490                 &posix_acl_default_xattr_handler,
491         [BCH_XATTR_INDEX_TRUSTED]               = &bch_xattr_trusted_handler,
492         [BCH_XATTR_INDEX_SECURITY]              = &bch_xattr_security_handler,
493 };
494
495 static const struct xattr_handler *bch2_xattr_type_to_handler(unsigned type)
496 {
497         return type < ARRAY_SIZE(bch_xattr_handler_map)
498                 ? bch_xattr_handler_map[type]
499                 : NULL;
500 }