]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/btrfs-util.c
pkgconfig: define variables relative to ${prefix}/${rootprefix}/${sysconfdir}
[thirdparty/systemd.git] / src / basic / btrfs-util.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #include <errno.h>
4 #include <fcntl.h>
5 #include <inttypes.h>
6 #include <linux/fs.h>
7 #include <linux/loop.h>
8 #include <stddef.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <sys/ioctl.h>
13 #include <sys/stat.h>
14 #include <sys/statfs.h>
15 #include <sys/sysmacros.h>
16 #include <unistd.h>
17
18 #if HAVE_LINUX_BTRFS_H
19 #include <linux/btrfs.h>
20 #endif
21
22 #include "alloc-util.h"
23 #include "blockdev-util.h"
24 #include "btrfs-ctree.h"
25 #include "btrfs-util.h"
26 #include "chattr-util.h"
27 #include "copy.h"
28 #include "device-nodes.h"
29 #include "fd-util.h"
30 #include "fileio.h"
31 #include "fs-util.h"
32 #include "io-util.h"
33 #include "macro.h"
34 #include "missing.h"
35 #include "path-util.h"
36 #include "rm-rf.h"
37 #include "smack-util.h"
38 #include "sparse-endian.h"
39 #include "stat-util.h"
40 #include "string-util.h"
41 #include "time-util.h"
42 #include "util.h"
43
44 /* WARNING: Be careful with file system ioctls! When we get an fd, we
45 * need to make sure it either refers to only a regular file or
46 * directory, or that it is located on btrfs, before invoking any
47 * btrfs ioctls. The ioctl numbers are reused by some device drivers
48 * (such as DRM), and hence might have bad effects when invoked on
49 * device nodes (that reference drivers) rather than fds to normal
50 * files or directories. */
51
52 static int validate_subvolume_name(const char *name) {
53
54 if (!filename_is_valid(name))
55 return -EINVAL;
56
57 if (strlen(name) > BTRFS_SUBVOL_NAME_MAX)
58 return -E2BIG;
59
60 return 0;
61 }
62
63 static int extract_subvolume_name(const char *path, const char **subvolume) {
64 const char *fn;
65 int r;
66
67 assert(path);
68 assert(subvolume);
69
70 fn = basename(path);
71
72 r = validate_subvolume_name(fn);
73 if (r < 0)
74 return r;
75
76 *subvolume = fn;
77 return 0;
78 }
79
80 int btrfs_is_filesystem(int fd) {
81 struct statfs sfs;
82
83 assert(fd >= 0);
84
85 if (fstatfs(fd, &sfs) < 0)
86 return -errno;
87
88 return F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC);
89 }
90
91 int btrfs_is_subvol_fd(int fd) {
92 struct stat st;
93
94 assert(fd >= 0);
95
96 /* On btrfs subvolumes always have the inode 256 */
97
98 if (fstat(fd, &st) < 0)
99 return -errno;
100
101 if (!S_ISDIR(st.st_mode) || st.st_ino != 256)
102 return 0;
103
104 return btrfs_is_filesystem(fd);
105 }
106
107 int btrfs_is_subvol(const char *path) {
108 _cleanup_close_ int fd = -1;
109
110 assert(path);
111
112 fd = open(path, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
113 if (fd < 0)
114 return -errno;
115
116 return btrfs_is_subvol_fd(fd);
117 }
118
119 int btrfs_subvol_make_fd(int fd, const char *subvolume) {
120 struct btrfs_ioctl_vol_args args = {};
121 _cleanup_close_ int real_fd = -1;
122 int r;
123
124 assert(subvolume);
125
126 r = validate_subvolume_name(subvolume);
127 if (r < 0)
128 return r;
129
130 r = fcntl(fd, F_GETFL);
131 if (r < 0)
132 return -errno;
133 if (FLAGS_SET(r, O_PATH)) {
134 /* An O_PATH fd was specified, let's convert here to a proper one, as btrfs ioctl's can't deal with
135 * O_PATH. */
136
137 real_fd = fd_reopen(fd, O_RDONLY|O_CLOEXEC|O_DIRECTORY);
138 if (real_fd < 0)
139 return real_fd;
140
141 fd = real_fd;
142 }
143
144 strncpy(args.name, subvolume, sizeof(args.name)-1);
145
146 if (ioctl(fd, BTRFS_IOC_SUBVOL_CREATE, &args) < 0)
147 return -errno;
148
149 return 0;
150 }
151
152 int btrfs_subvol_make(const char *path) {
153 _cleanup_close_ int fd = -1;
154 const char *subvolume;
155 int r;
156
157 assert(path);
158
159 r = extract_subvolume_name(path, &subvolume);
160 if (r < 0)
161 return r;
162
163 fd = open_parent(path, O_CLOEXEC, 0);
164 if (fd < 0)
165 return fd;
166
167 return btrfs_subvol_make_fd(fd, subvolume);
168 }
169
170 int btrfs_subvol_set_read_only_fd(int fd, bool b) {
171 uint64_t flags, nflags;
172 struct stat st;
173
174 assert(fd >= 0);
175
176 if (fstat(fd, &st) < 0)
177 return -errno;
178
179 if (!S_ISDIR(st.st_mode) || st.st_ino != 256)
180 return -EINVAL;
181
182 if (ioctl(fd, BTRFS_IOC_SUBVOL_GETFLAGS, &flags) < 0)
183 return -errno;
184
185 if (b)
186 nflags = flags | BTRFS_SUBVOL_RDONLY;
187 else
188 nflags = flags & ~BTRFS_SUBVOL_RDONLY;
189
190 if (flags == nflags)
191 return 0;
192
193 if (ioctl(fd, BTRFS_IOC_SUBVOL_SETFLAGS, &nflags) < 0)
194 return -errno;
195
196 return 0;
197 }
198
199 int btrfs_subvol_set_read_only(const char *path, bool b) {
200 _cleanup_close_ int fd = -1;
201
202 fd = open(path, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
203 if (fd < 0)
204 return -errno;
205
206 return btrfs_subvol_set_read_only_fd(fd, b);
207 }
208
209 int btrfs_subvol_get_read_only_fd(int fd) {
210 uint64_t flags;
211 struct stat st;
212
213 assert(fd >= 0);
214
215 if (fstat(fd, &st) < 0)
216 return -errno;
217
218 if (!S_ISDIR(st.st_mode) || st.st_ino != 256)
219 return -EINVAL;
220
221 if (ioctl(fd, BTRFS_IOC_SUBVOL_GETFLAGS, &flags) < 0)
222 return -errno;
223
224 return !!(flags & BTRFS_SUBVOL_RDONLY);
225 }
226
227 int btrfs_reflink(int infd, int outfd) {
228 int r;
229
230 assert(infd >= 0);
231 assert(outfd >= 0);
232
233 /* Make sure we invoke the ioctl on a regular file, so that no device driver accidentally gets it. */
234
235 r = fd_verify_regular(outfd);
236 if (r < 0)
237 return r;
238
239 if (ioctl(outfd, BTRFS_IOC_CLONE, infd) < 0)
240 return -errno;
241
242 return 0;
243 }
244
245 int btrfs_clone_range(int infd, uint64_t in_offset, int outfd, uint64_t out_offset, uint64_t sz) {
246 struct btrfs_ioctl_clone_range_args args = {
247 .src_fd = infd,
248 .src_offset = in_offset,
249 .src_length = sz,
250 .dest_offset = out_offset,
251 };
252 int r;
253
254 assert(infd >= 0);
255 assert(outfd >= 0);
256 assert(sz > 0);
257
258 r = fd_verify_regular(outfd);
259 if (r < 0)
260 return r;
261
262 if (ioctl(outfd, BTRFS_IOC_CLONE_RANGE, &args) < 0)
263 return -errno;
264
265 return 0;
266 }
267
268 int btrfs_get_block_device_fd(int fd, dev_t *dev) {
269 struct btrfs_ioctl_fs_info_args fsi = {};
270 uint64_t id;
271 int r;
272
273 assert(fd >= 0);
274 assert(dev);
275
276 r = btrfs_is_filesystem(fd);
277 if (r < 0)
278 return r;
279 if (!r)
280 return -ENOTTY;
281
282 if (ioctl(fd, BTRFS_IOC_FS_INFO, &fsi) < 0)
283 return -errno;
284
285 /* We won't do this for btrfs RAID */
286 if (fsi.num_devices != 1) {
287 *dev = 0;
288 return 0;
289 }
290
291 for (id = 1; id <= fsi.max_id; id++) {
292 struct btrfs_ioctl_dev_info_args di = {
293 .devid = id,
294 };
295 struct stat st;
296
297 if (ioctl(fd, BTRFS_IOC_DEV_INFO, &di) < 0) {
298 if (errno == ENODEV)
299 continue;
300
301 return -errno;
302 }
303
304 if (stat((char*) di.path, &st) < 0)
305 return -errno;
306
307 if (!S_ISBLK(st.st_mode))
308 return -ENODEV;
309
310 if (major(st.st_rdev) == 0)
311 return -ENODEV;
312
313 *dev = st.st_rdev;
314 return 1;
315 }
316
317 return -ENODEV;
318 }
319
320 int btrfs_get_block_device(const char *path, dev_t *dev) {
321 _cleanup_close_ int fd = -1;
322
323 assert(path);
324 assert(dev);
325
326 fd = open(path, O_RDONLY|O_NOCTTY|O_CLOEXEC);
327 if (fd < 0)
328 return -errno;
329
330 return btrfs_get_block_device_fd(fd, dev);
331 }
332
333 int btrfs_subvol_get_id_fd(int fd, uint64_t *ret) {
334 struct btrfs_ioctl_ino_lookup_args args = {
335 .objectid = BTRFS_FIRST_FREE_OBJECTID
336 };
337 int r;
338
339 assert(fd >= 0);
340 assert(ret);
341
342 r = btrfs_is_filesystem(fd);
343 if (r < 0)
344 return r;
345 if (!r)
346 return -ENOTTY;
347
348 if (ioctl(fd, BTRFS_IOC_INO_LOOKUP, &args) < 0)
349 return -errno;
350
351 *ret = args.treeid;
352 return 0;
353 }
354
355 int btrfs_subvol_get_id(int fd, const char *subvol, uint64_t *ret) {
356 _cleanup_close_ int subvol_fd = -1;
357
358 assert(fd >= 0);
359 assert(ret);
360
361 subvol_fd = openat(fd, subvol, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
362 if (subvol_fd < 0)
363 return -errno;
364
365 return btrfs_subvol_get_id_fd(subvol_fd, ret);
366 }
367
368 static bool btrfs_ioctl_search_args_inc(struct btrfs_ioctl_search_args *args) {
369 assert(args);
370
371 /* the objectid, type, offset together make up the btrfs key,
372 * which is considered a single 136byte integer when
373 * comparing. This call increases the counter by one, dealing
374 * with the overflow between the overflows */
375
376 if (args->key.min_offset < (uint64_t) -1) {
377 args->key.min_offset++;
378 return true;
379 }
380
381 if (args->key.min_type < (uint8_t) -1) {
382 args->key.min_type++;
383 args->key.min_offset = 0;
384 return true;
385 }
386
387 if (args->key.min_objectid < (uint64_t) -1) {
388 args->key.min_objectid++;
389 args->key.min_offset = 0;
390 args->key.min_type = 0;
391 return true;
392 }
393
394 return 0;
395 }
396
397 static void btrfs_ioctl_search_args_set(struct btrfs_ioctl_search_args *args, const struct btrfs_ioctl_search_header *h) {
398 assert(args);
399 assert(h);
400
401 args->key.min_objectid = h->objectid;
402 args->key.min_type = h->type;
403 args->key.min_offset = h->offset;
404 }
405
406 static int btrfs_ioctl_search_args_compare(const struct btrfs_ioctl_search_args *args) {
407 int r;
408
409 assert(args);
410
411 /* Compare min and max */
412
413 r = CMP(args->key.min_objectid, args->key.max_objectid);
414 if (r != 0)
415 return r;
416
417 r = CMP(args->key.min_type, args->key.max_type);
418 if (r != 0)
419 return r;
420
421 return CMP(args->key.min_offset, args->key.max_offset);
422 }
423
424 #define FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i, sh, args) \
425 for ((i) = 0, \
426 (sh) = (const struct btrfs_ioctl_search_header*) (args).buf; \
427 (i) < (args).key.nr_items; \
428 (i)++, \
429 (sh) = (const struct btrfs_ioctl_search_header*) ((uint8_t*) (sh) + sizeof(struct btrfs_ioctl_search_header) + (sh)->len))
430
431 #define BTRFS_IOCTL_SEARCH_HEADER_BODY(sh) \
432 ((void*) ((uint8_t*) sh + sizeof(struct btrfs_ioctl_search_header)))
433
434 int btrfs_subvol_get_info_fd(int fd, uint64_t subvol_id, BtrfsSubvolInfo *ret) {
435 struct btrfs_ioctl_search_args args = {
436 /* Tree of tree roots */
437 .key.tree_id = BTRFS_ROOT_TREE_OBJECTID,
438
439 /* Look precisely for the subvolume items */
440 .key.min_type = BTRFS_ROOT_ITEM_KEY,
441 .key.max_type = BTRFS_ROOT_ITEM_KEY,
442
443 .key.min_offset = 0,
444 .key.max_offset = (uint64_t) -1,
445
446 /* No restrictions on the other components */
447 .key.min_transid = 0,
448 .key.max_transid = (uint64_t) -1,
449 };
450
451 bool found = false;
452 int r;
453
454 assert(fd >= 0);
455 assert(ret);
456
457 if (subvol_id == 0) {
458 r = btrfs_subvol_get_id_fd(fd, &subvol_id);
459 if (r < 0)
460 return r;
461 } else {
462 r = btrfs_is_filesystem(fd);
463 if (r < 0)
464 return r;
465 if (!r)
466 return -ENOTTY;
467 }
468
469 args.key.min_objectid = args.key.max_objectid = subvol_id;
470
471 while (btrfs_ioctl_search_args_compare(&args) <= 0) {
472 const struct btrfs_ioctl_search_header *sh;
473 unsigned i;
474
475 args.key.nr_items = 256;
476 if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) < 0)
477 return -errno;
478
479 if (args.key.nr_items <= 0)
480 break;
481
482 FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i, sh, args) {
483
484 const struct btrfs_root_item *ri;
485
486 /* Make sure we start the next search at least from this entry */
487 btrfs_ioctl_search_args_set(&args, sh);
488
489 if (sh->objectid != subvol_id)
490 continue;
491 if (sh->type != BTRFS_ROOT_ITEM_KEY)
492 continue;
493
494 /* Older versions of the struct lacked the otime setting */
495 if (sh->len < offsetof(struct btrfs_root_item, otime) + sizeof(struct btrfs_timespec))
496 continue;
497
498 ri = BTRFS_IOCTL_SEARCH_HEADER_BODY(sh);
499
500 ret->otime = (usec_t) le64toh(ri->otime.sec) * USEC_PER_SEC +
501 (usec_t) le32toh(ri->otime.nsec) / NSEC_PER_USEC;
502
503 ret->subvol_id = subvol_id;
504 ret->read_only = le64toh(ri->flags) & BTRFS_ROOT_SUBVOL_RDONLY;
505
506 assert_cc(sizeof(ri->uuid) == sizeof(ret->uuid));
507 memcpy(&ret->uuid, ri->uuid, sizeof(ret->uuid));
508 memcpy(&ret->parent_uuid, ri->parent_uuid, sizeof(ret->parent_uuid));
509
510 found = true;
511 goto finish;
512 }
513
514 /* Increase search key by one, to read the next item, if we can. */
515 if (!btrfs_ioctl_search_args_inc(&args))
516 break;
517 }
518
519 finish:
520 if (!found)
521 return -ENODATA;
522
523 return 0;
524 }
525
526 int btrfs_qgroup_get_quota_fd(int fd, uint64_t qgroupid, BtrfsQuotaInfo *ret) {
527
528 struct btrfs_ioctl_search_args args = {
529 /* Tree of quota items */
530 .key.tree_id = BTRFS_QUOTA_TREE_OBJECTID,
531
532 /* The object ID is always 0 */
533 .key.min_objectid = 0,
534 .key.max_objectid = 0,
535
536 /* Look precisely for the quota items */
537 .key.min_type = BTRFS_QGROUP_STATUS_KEY,
538 .key.max_type = BTRFS_QGROUP_LIMIT_KEY,
539
540 /* No restrictions on the other components */
541 .key.min_transid = 0,
542 .key.max_transid = (uint64_t) -1,
543 };
544
545 bool found_info = false, found_limit = false;
546 int r;
547
548 assert(fd >= 0);
549 assert(ret);
550
551 if (qgroupid == 0) {
552 r = btrfs_subvol_get_id_fd(fd, &qgroupid);
553 if (r < 0)
554 return r;
555 } else {
556 r = btrfs_is_filesystem(fd);
557 if (r < 0)
558 return r;
559 if (!r)
560 return -ENOTTY;
561 }
562
563 args.key.min_offset = args.key.max_offset = qgroupid;
564
565 while (btrfs_ioctl_search_args_compare(&args) <= 0) {
566 const struct btrfs_ioctl_search_header *sh;
567 unsigned i;
568
569 args.key.nr_items = 256;
570 if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) < 0) {
571 if (errno == ENOENT) /* quota tree is missing: quota disabled */
572 break;
573
574 return -errno;
575 }
576
577 if (args.key.nr_items <= 0)
578 break;
579
580 FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i, sh, args) {
581
582 /* Make sure we start the next search at least from this entry */
583 btrfs_ioctl_search_args_set(&args, sh);
584
585 if (sh->objectid != 0)
586 continue;
587 if (sh->offset != qgroupid)
588 continue;
589
590 if (sh->type == BTRFS_QGROUP_INFO_KEY) {
591 const struct btrfs_qgroup_info_item *qii = BTRFS_IOCTL_SEARCH_HEADER_BODY(sh);
592
593 ret->referenced = le64toh(qii->rfer);
594 ret->exclusive = le64toh(qii->excl);
595
596 found_info = true;
597
598 } else if (sh->type == BTRFS_QGROUP_LIMIT_KEY) {
599 const struct btrfs_qgroup_limit_item *qli = BTRFS_IOCTL_SEARCH_HEADER_BODY(sh);
600
601 if (le64toh(qli->flags) & BTRFS_QGROUP_LIMIT_MAX_RFER)
602 ret->referenced_max = le64toh(qli->max_rfer);
603 else
604 ret->referenced_max = (uint64_t) -1;
605
606 if (le64toh(qli->flags) & BTRFS_QGROUP_LIMIT_MAX_EXCL)
607 ret->exclusive_max = le64toh(qli->max_excl);
608 else
609 ret->exclusive_max = (uint64_t) -1;
610
611 found_limit = true;
612 }
613
614 if (found_info && found_limit)
615 goto finish;
616 }
617
618 /* Increase search key by one, to read the next item, if we can. */
619 if (!btrfs_ioctl_search_args_inc(&args))
620 break;
621 }
622
623 finish:
624 if (!found_limit && !found_info)
625 return -ENODATA;
626
627 if (!found_info) {
628 ret->referenced = (uint64_t) -1;
629 ret->exclusive = (uint64_t) -1;
630 }
631
632 if (!found_limit) {
633 ret->referenced_max = (uint64_t) -1;
634 ret->exclusive_max = (uint64_t) -1;
635 }
636
637 return 0;
638 }
639
640 int btrfs_qgroup_get_quota(const char *path, uint64_t qgroupid, BtrfsQuotaInfo *ret) {
641 _cleanup_close_ int fd = -1;
642
643 fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
644 if (fd < 0)
645 return -errno;
646
647 return btrfs_qgroup_get_quota_fd(fd, qgroupid, ret);
648 }
649
650 int btrfs_subvol_find_subtree_qgroup(int fd, uint64_t subvol_id, uint64_t *ret) {
651 uint64_t level, lowest = (uint64_t) -1, lowest_qgroupid = 0;
652 _cleanup_free_ uint64_t *qgroups = NULL;
653 int r, n, i;
654
655 assert(fd >= 0);
656 assert(ret);
657
658 /* This finds the "subtree" qgroup for a specific
659 * subvolume. This only works for subvolumes that have been
660 * prepared with btrfs_subvol_auto_qgroup_fd() with
661 * insert_intermediary_qgroup=true (or equivalent). For others
662 * it will return the leaf qgroup instead. The two cases may
663 * be distuingished via the return value, which is 1 in case
664 * an appropriate "subtree" qgroup was found, and 0
665 * otherwise. */
666
667 if (subvol_id == 0) {
668 r = btrfs_subvol_get_id_fd(fd, &subvol_id);
669 if (r < 0)
670 return r;
671 }
672
673 r = btrfs_qgroupid_split(subvol_id, &level, NULL);
674 if (r < 0)
675 return r;
676 if (level != 0) /* Input must be a leaf qgroup */
677 return -EINVAL;
678
679 n = btrfs_qgroup_find_parents(fd, subvol_id, &qgroups);
680 if (n < 0)
681 return n;
682
683 for (i = 0; i < n; i++) {
684 uint64_t id;
685
686 r = btrfs_qgroupid_split(qgroups[i], &level, &id);
687 if (r < 0)
688 return r;
689
690 if (id != subvol_id)
691 continue;
692
693 if (lowest == (uint64_t) -1 || level < lowest) {
694 lowest_qgroupid = qgroups[i];
695 lowest = level;
696 }
697 }
698
699 if (lowest == (uint64_t) -1) {
700 /* No suitable higher-level qgroup found, let's return
701 * the leaf qgroup instead, and indicate that with the
702 * return value. */
703
704 *ret = subvol_id;
705 return 0;
706 }
707
708 *ret = lowest_qgroupid;
709 return 1;
710 }
711
712 int btrfs_subvol_get_subtree_quota_fd(int fd, uint64_t subvol_id, BtrfsQuotaInfo *ret) {
713 uint64_t qgroupid;
714 int r;
715
716 assert(fd >= 0);
717 assert(ret);
718
719 /* This determines the quota data of the qgroup with the
720 * lowest level, that shares the id part with the specified
721 * subvolume. This is useful for determining the quota data
722 * for entire subvolume subtrees, as long as the subtrees have
723 * been set up with btrfs_qgroup_subvol_auto_fd() or in a
724 * compatible way */
725
726 r = btrfs_subvol_find_subtree_qgroup(fd, subvol_id, &qgroupid);
727 if (r < 0)
728 return r;
729
730 return btrfs_qgroup_get_quota_fd(fd, qgroupid, ret);
731 }
732
733 int btrfs_subvol_get_subtree_quota(const char *path, uint64_t subvol_id, BtrfsQuotaInfo *ret) {
734 _cleanup_close_ int fd = -1;
735
736 fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
737 if (fd < 0)
738 return -errno;
739
740 return btrfs_subvol_get_subtree_quota_fd(fd, subvol_id, ret);
741 }
742
743 int btrfs_defrag_fd(int fd) {
744 int r;
745
746 assert(fd >= 0);
747
748 r = fd_verify_regular(fd);
749 if (r < 0)
750 return r;
751
752 if (ioctl(fd, BTRFS_IOC_DEFRAG, NULL) < 0)
753 return -errno;
754
755 return 0;
756 }
757
758 int btrfs_defrag(const char *p) {
759 _cleanup_close_ int fd = -1;
760
761 fd = open(p, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
762 if (fd < 0)
763 return -errno;
764
765 return btrfs_defrag_fd(fd);
766 }
767
768 int btrfs_quota_enable_fd(int fd, bool b) {
769 struct btrfs_ioctl_quota_ctl_args args = {
770 .cmd = b ? BTRFS_QUOTA_CTL_ENABLE : BTRFS_QUOTA_CTL_DISABLE,
771 };
772 int r;
773
774 assert(fd >= 0);
775
776 r = btrfs_is_filesystem(fd);
777 if (r < 0)
778 return r;
779 if (!r)
780 return -ENOTTY;
781
782 if (ioctl(fd, BTRFS_IOC_QUOTA_CTL, &args) < 0)
783 return -errno;
784
785 return 0;
786 }
787
788 int btrfs_quota_enable(const char *path, bool b) {
789 _cleanup_close_ int fd = -1;
790
791 fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
792 if (fd < 0)
793 return -errno;
794
795 return btrfs_quota_enable_fd(fd, b);
796 }
797
798 int btrfs_qgroup_set_limit_fd(int fd, uint64_t qgroupid, uint64_t referenced_max) {
799
800 struct btrfs_ioctl_qgroup_limit_args args = {
801 .lim.max_rfer = referenced_max,
802 .lim.flags = BTRFS_QGROUP_LIMIT_MAX_RFER,
803 };
804 unsigned c;
805 int r;
806
807 assert(fd >= 0);
808
809 if (qgroupid == 0) {
810 r = btrfs_subvol_get_id_fd(fd, &qgroupid);
811 if (r < 0)
812 return r;
813 } else {
814 r = btrfs_is_filesystem(fd);
815 if (r < 0)
816 return r;
817 if (!r)
818 return -ENOTTY;
819 }
820
821 args.qgroupid = qgroupid;
822
823 for (c = 0;; c++) {
824 if (ioctl(fd, BTRFS_IOC_QGROUP_LIMIT, &args) < 0) {
825
826 if (errno == EBUSY && c < 10) {
827 (void) btrfs_quota_scan_wait(fd);
828 continue;
829 }
830
831 return -errno;
832 }
833
834 break;
835 }
836
837 return 0;
838 }
839
840 int btrfs_qgroup_set_limit(const char *path, uint64_t qgroupid, uint64_t referenced_max) {
841 _cleanup_close_ int fd = -1;
842
843 fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
844 if (fd < 0)
845 return -errno;
846
847 return btrfs_qgroup_set_limit_fd(fd, qgroupid, referenced_max);
848 }
849
850 int btrfs_subvol_set_subtree_quota_limit_fd(int fd, uint64_t subvol_id, uint64_t referenced_max) {
851 uint64_t qgroupid;
852 int r;
853
854 assert(fd >= 0);
855
856 r = btrfs_subvol_find_subtree_qgroup(fd, subvol_id, &qgroupid);
857 if (r < 0)
858 return r;
859
860 return btrfs_qgroup_set_limit_fd(fd, qgroupid, referenced_max);
861 }
862
863 int btrfs_subvol_set_subtree_quota_limit(const char *path, uint64_t subvol_id, uint64_t referenced_max) {
864 _cleanup_close_ int fd = -1;
865
866 fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
867 if (fd < 0)
868 return -errno;
869
870 return btrfs_subvol_set_subtree_quota_limit_fd(fd, subvol_id, referenced_max);
871 }
872
873 int btrfs_resize_loopback_fd(int fd, uint64_t new_size, bool grow_only) {
874 struct btrfs_ioctl_vol_args args = {};
875 char p[SYS_BLOCK_PATH_MAX("/loop/backing_file")], q[DEV_NUM_PATH_MAX];
876 _cleanup_free_ char *backing = NULL;
877 _cleanup_close_ int loop_fd = -1, backing_fd = -1;
878 struct stat st;
879 dev_t dev = 0;
880 int r;
881
882 /* In contrast to btrfs quota ioctls ftruncate() cannot make sense of "infinity" or file sizes > 2^31 */
883 if (!FILE_SIZE_VALID(new_size))
884 return -EINVAL;
885
886 /* btrfs cannot handle file systems < 16M, hence use this as minimum */
887 if (new_size < 16*1024*1024)
888 new_size = 16*1024*1024;
889
890 r = btrfs_get_block_device_fd(fd, &dev);
891 if (r < 0)
892 return r;
893 if (r == 0)
894 return -ENODEV;
895
896 xsprintf_sys_block_path(p, "/loop/backing_file", dev);
897 r = read_one_line_file(p, &backing);
898 if (r == -ENOENT)
899 return -ENODEV;
900 if (r < 0)
901 return r;
902 if (isempty(backing) || !path_is_absolute(backing))
903 return -ENODEV;
904
905 backing_fd = open(backing, O_RDWR|O_CLOEXEC|O_NOCTTY);
906 if (backing_fd < 0)
907 return -errno;
908
909 if (fstat(backing_fd, &st) < 0)
910 return -errno;
911 if (!S_ISREG(st.st_mode))
912 return -ENODEV;
913
914 if (new_size == (uint64_t) st.st_size)
915 return 0;
916
917 if (grow_only && new_size < (uint64_t) st.st_size)
918 return -EINVAL;
919
920 xsprintf_dev_num_path(q, "block", dev);
921 loop_fd = open(q, O_RDWR|O_CLOEXEC|O_NOCTTY);
922 if (loop_fd < 0)
923 return -errno;
924
925 if (snprintf(args.name, sizeof(args.name), "%" PRIu64, new_size) >= (int) sizeof(args.name))
926 return -EINVAL;
927
928 if (new_size < (uint64_t) st.st_size) {
929 /* Decrease size: first decrease btrfs size, then shorten loopback */
930 if (ioctl(fd, BTRFS_IOC_RESIZE, &args) < 0)
931 return -errno;
932 }
933
934 if (ftruncate(backing_fd, new_size) < 0)
935 return -errno;
936
937 if (ioctl(loop_fd, LOOP_SET_CAPACITY, 0) < 0)
938 return -errno;
939
940 if (new_size > (uint64_t) st.st_size) {
941 /* Increase size: first enlarge loopback, then increase btrfs size */
942 if (ioctl(fd, BTRFS_IOC_RESIZE, &args) < 0)
943 return -errno;
944 }
945
946 /* Make sure the free disk space is correctly updated for both file systems */
947 (void) fsync(fd);
948 (void) fsync(backing_fd);
949
950 return 1;
951 }
952
953 int btrfs_resize_loopback(const char *p, uint64_t new_size, bool grow_only) {
954 _cleanup_close_ int fd = -1;
955
956 fd = open(p, O_RDONLY|O_NOCTTY|O_CLOEXEC);
957 if (fd < 0)
958 return -errno;
959
960 return btrfs_resize_loopback_fd(fd, new_size, grow_only);
961 }
962
963 int btrfs_qgroupid_make(uint64_t level, uint64_t id, uint64_t *ret) {
964 assert(ret);
965
966 if (level >= (UINT64_C(1) << (64 - BTRFS_QGROUP_LEVEL_SHIFT)))
967 return -EINVAL;
968
969 if (id >= (UINT64_C(1) << BTRFS_QGROUP_LEVEL_SHIFT))
970 return -EINVAL;
971
972 *ret = (level << BTRFS_QGROUP_LEVEL_SHIFT) | id;
973 return 0;
974 }
975
976 int btrfs_qgroupid_split(uint64_t qgroupid, uint64_t *level, uint64_t *id) {
977 assert(level || id);
978
979 if (level)
980 *level = qgroupid >> BTRFS_QGROUP_LEVEL_SHIFT;
981
982 if (id)
983 *id = qgroupid & ((UINT64_C(1) << BTRFS_QGROUP_LEVEL_SHIFT) - 1);
984
985 return 0;
986 }
987
988 static int qgroup_create_or_destroy(int fd, bool b, uint64_t qgroupid) {
989
990 struct btrfs_ioctl_qgroup_create_args args = {
991 .create = b,
992 .qgroupid = qgroupid,
993 };
994 unsigned c;
995 int r;
996
997 r = btrfs_is_filesystem(fd);
998 if (r < 0)
999 return r;
1000 if (r == 0)
1001 return -ENOTTY;
1002
1003 for (c = 0;; c++) {
1004 if (ioctl(fd, BTRFS_IOC_QGROUP_CREATE, &args) < 0) {
1005
1006 /* If quota is not enabled, we get EINVAL. Turn this into a recognizable error */
1007 if (errno == EINVAL)
1008 return -ENOPROTOOPT;
1009
1010 if (errno == EBUSY && c < 10) {
1011 (void) btrfs_quota_scan_wait(fd);
1012 continue;
1013 }
1014
1015 return -errno;
1016 }
1017
1018 break;
1019 }
1020
1021 return 0;
1022 }
1023
1024 int btrfs_qgroup_create(int fd, uint64_t qgroupid) {
1025 return qgroup_create_or_destroy(fd, true, qgroupid);
1026 }
1027
1028 int btrfs_qgroup_destroy(int fd, uint64_t qgroupid) {
1029 return qgroup_create_or_destroy(fd, false, qgroupid);
1030 }
1031
1032 int btrfs_qgroup_destroy_recursive(int fd, uint64_t qgroupid) {
1033 _cleanup_free_ uint64_t *qgroups = NULL;
1034 uint64_t subvol_id;
1035 int i, n, r;
1036
1037 /* Destroys the specified qgroup, but unassigns it from all
1038 * its parents first. Also, it recursively destroys all
1039 * qgroups it is assgined to that have the same id part of the
1040 * qgroupid as the specified group. */
1041
1042 r = btrfs_qgroupid_split(qgroupid, NULL, &subvol_id);
1043 if (r < 0)
1044 return r;
1045
1046 n = btrfs_qgroup_find_parents(fd, qgroupid, &qgroups);
1047 if (n < 0)
1048 return n;
1049
1050 for (i = 0; i < n; i++) {
1051 uint64_t id;
1052
1053 r = btrfs_qgroupid_split(qgroups[i], NULL, &id);
1054 if (r < 0)
1055 return r;
1056
1057 r = btrfs_qgroup_unassign(fd, qgroupid, qgroups[i]);
1058 if (r < 0)
1059 return r;
1060
1061 if (id != subvol_id)
1062 continue;
1063
1064 /* The parent qgroupid shares the same id part with
1065 * us? If so, destroy it too. */
1066
1067 (void) btrfs_qgroup_destroy_recursive(fd, qgroups[i]);
1068 }
1069
1070 return btrfs_qgroup_destroy(fd, qgroupid);
1071 }
1072
1073 int btrfs_quota_scan_start(int fd) {
1074 struct btrfs_ioctl_quota_rescan_args args = {};
1075
1076 assert(fd >= 0);
1077
1078 if (ioctl(fd, BTRFS_IOC_QUOTA_RESCAN, &args) < 0)
1079 return -errno;
1080
1081 return 0;
1082 }
1083
1084 int btrfs_quota_scan_wait(int fd) {
1085 assert(fd >= 0);
1086
1087 if (ioctl(fd, BTRFS_IOC_QUOTA_RESCAN_WAIT) < 0)
1088 return -errno;
1089
1090 return 0;
1091 }
1092
1093 int btrfs_quota_scan_ongoing(int fd) {
1094 struct btrfs_ioctl_quota_rescan_args args = {};
1095
1096 assert(fd >= 0);
1097
1098 if (ioctl(fd, BTRFS_IOC_QUOTA_RESCAN_STATUS, &args) < 0)
1099 return -errno;
1100
1101 return !!args.flags;
1102 }
1103
1104 static int qgroup_assign_or_unassign(int fd, bool b, uint64_t child, uint64_t parent) {
1105 struct btrfs_ioctl_qgroup_assign_args args = {
1106 .assign = b,
1107 .src = child,
1108 .dst = parent,
1109 };
1110 unsigned c;
1111 int r;
1112
1113 r = btrfs_is_filesystem(fd);
1114 if (r < 0)
1115 return r;
1116 if (r == 0)
1117 return -ENOTTY;
1118
1119 for (c = 0;; c++) {
1120 r = ioctl(fd, BTRFS_IOC_QGROUP_ASSIGN, &args);
1121 if (r < 0) {
1122 if (errno == EBUSY && c < 10) {
1123 (void) btrfs_quota_scan_wait(fd);
1124 continue;
1125 }
1126
1127 return -errno;
1128 }
1129
1130 if (r == 0)
1131 return 0;
1132
1133 /* If the return value is > 0, we need to request a rescan */
1134
1135 (void) btrfs_quota_scan_start(fd);
1136 return 1;
1137 }
1138 }
1139
1140 int btrfs_qgroup_assign(int fd, uint64_t child, uint64_t parent) {
1141 return qgroup_assign_or_unassign(fd, true, child, parent);
1142 }
1143
1144 int btrfs_qgroup_unassign(int fd, uint64_t child, uint64_t parent) {
1145 return qgroup_assign_or_unassign(fd, false, child, parent);
1146 }
1147
1148 static int subvol_remove_children(int fd, const char *subvolume, uint64_t subvol_id, BtrfsRemoveFlags flags) {
1149 struct btrfs_ioctl_search_args args = {
1150 .key.tree_id = BTRFS_ROOT_TREE_OBJECTID,
1151
1152 .key.min_objectid = BTRFS_FIRST_FREE_OBJECTID,
1153 .key.max_objectid = BTRFS_LAST_FREE_OBJECTID,
1154
1155 .key.min_type = BTRFS_ROOT_BACKREF_KEY,
1156 .key.max_type = BTRFS_ROOT_BACKREF_KEY,
1157
1158 .key.min_transid = 0,
1159 .key.max_transid = (uint64_t) -1,
1160 };
1161
1162 struct btrfs_ioctl_vol_args vol_args = {};
1163 _cleanup_close_ int subvol_fd = -1;
1164 struct stat st;
1165 bool made_writable = false;
1166 int r;
1167
1168 assert(fd >= 0);
1169 assert(subvolume);
1170
1171 if (fstat(fd, &st) < 0)
1172 return -errno;
1173
1174 if (!S_ISDIR(st.st_mode))
1175 return -EINVAL;
1176
1177 subvol_fd = openat(fd, subvolume, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY|O_NOFOLLOW);
1178 if (subvol_fd < 0)
1179 return -errno;
1180
1181 if (subvol_id == 0) {
1182 r = btrfs_subvol_get_id_fd(subvol_fd, &subvol_id);
1183 if (r < 0)
1184 return r;
1185 }
1186
1187 /* First, try to remove the subvolume. If it happens to be
1188 * already empty, this will just work. */
1189 strncpy(vol_args.name, subvolume, sizeof(vol_args.name)-1);
1190 if (ioctl(fd, BTRFS_IOC_SNAP_DESTROY, &vol_args) >= 0) {
1191 (void) btrfs_qgroup_destroy_recursive(fd, subvol_id); /* for the leaf subvolumes, the qgroup id is identical to the subvol id */
1192 return 0;
1193 }
1194 if (!(flags & BTRFS_REMOVE_RECURSIVE) || errno != ENOTEMPTY)
1195 return -errno;
1196
1197 /* OK, the subvolume is not empty, let's look for child
1198 * subvolumes, and remove them, first */
1199
1200 args.key.min_offset = args.key.max_offset = subvol_id;
1201
1202 while (btrfs_ioctl_search_args_compare(&args) <= 0) {
1203 const struct btrfs_ioctl_search_header *sh;
1204 unsigned i;
1205
1206 args.key.nr_items = 256;
1207 if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) < 0)
1208 return -errno;
1209
1210 if (args.key.nr_items <= 0)
1211 break;
1212
1213 FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i, sh, args) {
1214 _cleanup_free_ char *p = NULL;
1215 const struct btrfs_root_ref *ref;
1216 struct btrfs_ioctl_ino_lookup_args ino_args;
1217
1218 btrfs_ioctl_search_args_set(&args, sh);
1219
1220 if (sh->type != BTRFS_ROOT_BACKREF_KEY)
1221 continue;
1222 if (sh->offset != subvol_id)
1223 continue;
1224
1225 ref = BTRFS_IOCTL_SEARCH_HEADER_BODY(sh);
1226
1227 p = strndup((char*) ref + sizeof(struct btrfs_root_ref), le64toh(ref->name_len));
1228 if (!p)
1229 return -ENOMEM;
1230
1231 zero(ino_args);
1232 ino_args.treeid = subvol_id;
1233 ino_args.objectid = htole64(ref->dirid);
1234
1235 if (ioctl(fd, BTRFS_IOC_INO_LOOKUP, &ino_args) < 0)
1236 return -errno;
1237
1238 if (!made_writable) {
1239 r = btrfs_subvol_set_read_only_fd(subvol_fd, false);
1240 if (r < 0)
1241 return r;
1242
1243 made_writable = true;
1244 }
1245
1246 if (isempty(ino_args.name))
1247 /* Subvolume is in the top-level
1248 * directory of the subvolume. */
1249 r = subvol_remove_children(subvol_fd, p, sh->objectid, flags);
1250 else {
1251 _cleanup_close_ int child_fd = -1;
1252
1253 /* Subvolume is somewhere further down,
1254 * hence we need to open the
1255 * containing directory first */
1256
1257 child_fd = openat(subvol_fd, ino_args.name, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY|O_NOFOLLOW);
1258 if (child_fd < 0)
1259 return -errno;
1260
1261 r = subvol_remove_children(child_fd, p, sh->objectid, flags);
1262 }
1263 if (r < 0)
1264 return r;
1265 }
1266
1267 /* Increase search key by one, to read the next item, if we can. */
1268 if (!btrfs_ioctl_search_args_inc(&args))
1269 break;
1270 }
1271
1272 /* OK, the child subvolumes should all be gone now, let's try
1273 * again to remove the subvolume */
1274 if (ioctl(fd, BTRFS_IOC_SNAP_DESTROY, &vol_args) < 0)
1275 return -errno;
1276
1277 (void) btrfs_qgroup_destroy_recursive(fd, subvol_id);
1278 return 0;
1279 }
1280
1281 int btrfs_subvol_remove(const char *path, BtrfsRemoveFlags flags) {
1282 _cleanup_close_ int fd = -1;
1283 const char *subvolume;
1284 int r;
1285
1286 assert(path);
1287
1288 r = extract_subvolume_name(path, &subvolume);
1289 if (r < 0)
1290 return r;
1291
1292 fd = open_parent(path, O_CLOEXEC, 0);
1293 if (fd < 0)
1294 return fd;
1295
1296 return subvol_remove_children(fd, subvolume, 0, flags);
1297 }
1298
1299 int btrfs_subvol_remove_fd(int fd, const char *subvolume, BtrfsRemoveFlags flags) {
1300 return subvol_remove_children(fd, subvolume, 0, flags);
1301 }
1302
1303 int btrfs_qgroup_copy_limits(int fd, uint64_t old_qgroupid, uint64_t new_qgroupid) {
1304
1305 struct btrfs_ioctl_search_args args = {
1306 /* Tree of quota items */
1307 .key.tree_id = BTRFS_QUOTA_TREE_OBJECTID,
1308
1309 /* The object ID is always 0 */
1310 .key.min_objectid = 0,
1311 .key.max_objectid = 0,
1312
1313 /* Look precisely for the quota items */
1314 .key.min_type = BTRFS_QGROUP_LIMIT_KEY,
1315 .key.max_type = BTRFS_QGROUP_LIMIT_KEY,
1316
1317 /* For our qgroup */
1318 .key.min_offset = old_qgroupid,
1319 .key.max_offset = old_qgroupid,
1320
1321 /* No restrictions on the other components */
1322 .key.min_transid = 0,
1323 .key.max_transid = (uint64_t) -1,
1324 };
1325
1326 int r;
1327
1328 r = btrfs_is_filesystem(fd);
1329 if (r < 0)
1330 return r;
1331 if (!r)
1332 return -ENOTTY;
1333
1334 while (btrfs_ioctl_search_args_compare(&args) <= 0) {
1335 const struct btrfs_ioctl_search_header *sh;
1336 unsigned i;
1337
1338 args.key.nr_items = 256;
1339 if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) < 0) {
1340 if (errno == ENOENT) /* quota tree missing: quota is not enabled, hence nothing to copy */
1341 break;
1342
1343 return -errno;
1344 }
1345
1346 if (args.key.nr_items <= 0)
1347 break;
1348
1349 FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i, sh, args) {
1350 const struct btrfs_qgroup_limit_item *qli = BTRFS_IOCTL_SEARCH_HEADER_BODY(sh);
1351 struct btrfs_ioctl_qgroup_limit_args qargs;
1352 unsigned c;
1353
1354 /* Make sure we start the next search at least from this entry */
1355 btrfs_ioctl_search_args_set(&args, sh);
1356
1357 if (sh->objectid != 0)
1358 continue;
1359 if (sh->type != BTRFS_QGROUP_LIMIT_KEY)
1360 continue;
1361 if (sh->offset != old_qgroupid)
1362 continue;
1363
1364 /* We found the entry, now copy things over. */
1365
1366 qargs = (struct btrfs_ioctl_qgroup_limit_args) {
1367 .qgroupid = new_qgroupid,
1368
1369 .lim.max_rfer = le64toh(qli->max_rfer),
1370 .lim.max_excl = le64toh(qli->max_excl),
1371 .lim.rsv_rfer = le64toh(qli->rsv_rfer),
1372 .lim.rsv_excl = le64toh(qli->rsv_excl),
1373
1374 .lim.flags = le64toh(qli->flags) & (BTRFS_QGROUP_LIMIT_MAX_RFER|
1375 BTRFS_QGROUP_LIMIT_MAX_EXCL|
1376 BTRFS_QGROUP_LIMIT_RSV_RFER|
1377 BTRFS_QGROUP_LIMIT_RSV_EXCL),
1378 };
1379
1380 for (c = 0;; c++) {
1381 if (ioctl(fd, BTRFS_IOC_QGROUP_LIMIT, &qargs) < 0) {
1382 if (errno == EBUSY && c < 10) {
1383 (void) btrfs_quota_scan_wait(fd);
1384 continue;
1385 }
1386 return -errno;
1387 }
1388
1389 break;
1390 }
1391
1392 return 1;
1393 }
1394
1395 /* Increase search key by one, to read the next item, if we can. */
1396 if (!btrfs_ioctl_search_args_inc(&args))
1397 break;
1398 }
1399
1400 return 0;
1401 }
1402
1403 static int copy_quota_hierarchy(int fd, uint64_t old_subvol_id, uint64_t new_subvol_id) {
1404 _cleanup_free_ uint64_t *old_qgroups = NULL, *old_parent_qgroups = NULL;
1405 bool copy_from_parent = false, insert_intermediary_qgroup = false;
1406 int n_old_qgroups, n_old_parent_qgroups, r, i;
1407 uint64_t old_parent_id;
1408
1409 assert(fd >= 0);
1410
1411 /* Copies a reduced form of quota information from the old to
1412 * the new subvolume. */
1413
1414 n_old_qgroups = btrfs_qgroup_find_parents(fd, old_subvol_id, &old_qgroups);
1415 if (n_old_qgroups <= 0) /* Nothing to copy */
1416 return n_old_qgroups;
1417
1418 r = btrfs_subvol_get_parent(fd, old_subvol_id, &old_parent_id);
1419 if (r == -ENXIO)
1420 /* We have no parent, hence nothing to copy. */
1421 n_old_parent_qgroups = 0;
1422 else if (r < 0)
1423 return r;
1424 else {
1425 n_old_parent_qgroups = btrfs_qgroup_find_parents(fd, old_parent_id, &old_parent_qgroups);
1426 if (n_old_parent_qgroups < 0)
1427 return n_old_parent_qgroups;
1428 }
1429
1430 for (i = 0; i < n_old_qgroups; i++) {
1431 uint64_t id;
1432 int j;
1433
1434 r = btrfs_qgroupid_split(old_qgroups[i], NULL, &id);
1435 if (r < 0)
1436 return r;
1437
1438 if (id == old_subvol_id) {
1439 /* The old subvolume was member of a qgroup
1440 * that had the same id, but a different level
1441 * as it self. Let's set up something similar
1442 * in the destination. */
1443 insert_intermediary_qgroup = true;
1444 break;
1445 }
1446
1447 for (j = 0; j < n_old_parent_qgroups; j++)
1448 if (old_parent_qgroups[j] == old_qgroups[i]) {
1449 /* The old subvolume shared a common
1450 * parent qgroup with its parent
1451 * subvolume. Let's set up something
1452 * similar in the destination. */
1453 copy_from_parent = true;
1454 }
1455 }
1456
1457 if (!insert_intermediary_qgroup && !copy_from_parent)
1458 return 0;
1459
1460 return btrfs_subvol_auto_qgroup_fd(fd, new_subvol_id, insert_intermediary_qgroup);
1461 }
1462
1463 static int copy_subtree_quota_limits(int fd, uint64_t old_subvol, uint64_t new_subvol) {
1464 uint64_t old_subtree_qgroup, new_subtree_qgroup;
1465 bool changed;
1466 int r;
1467
1468 /* First copy the leaf limits */
1469 r = btrfs_qgroup_copy_limits(fd, old_subvol, new_subvol);
1470 if (r < 0)
1471 return r;
1472 changed = r > 0;
1473
1474 /* Then, try to copy the subtree limits, if there are any. */
1475 r = btrfs_subvol_find_subtree_qgroup(fd, old_subvol, &old_subtree_qgroup);
1476 if (r < 0)
1477 return r;
1478 if (r == 0)
1479 return changed;
1480
1481 r = btrfs_subvol_find_subtree_qgroup(fd, new_subvol, &new_subtree_qgroup);
1482 if (r < 0)
1483 return r;
1484 if (r == 0)
1485 return changed;
1486
1487 r = btrfs_qgroup_copy_limits(fd, old_subtree_qgroup, new_subtree_qgroup);
1488 if (r != 0)
1489 return r;
1490
1491 return changed;
1492 }
1493
1494 static int subvol_snapshot_children(int old_fd, int new_fd, const char *subvolume, uint64_t old_subvol_id, BtrfsSnapshotFlags flags) {
1495
1496 struct btrfs_ioctl_search_args args = {
1497 .key.tree_id = BTRFS_ROOT_TREE_OBJECTID,
1498
1499 .key.min_objectid = BTRFS_FIRST_FREE_OBJECTID,
1500 .key.max_objectid = BTRFS_LAST_FREE_OBJECTID,
1501
1502 .key.min_type = BTRFS_ROOT_BACKREF_KEY,
1503 .key.max_type = BTRFS_ROOT_BACKREF_KEY,
1504
1505 .key.min_transid = 0,
1506 .key.max_transid = (uint64_t) -1,
1507 };
1508
1509 struct btrfs_ioctl_vol_args_v2 vol_args = {
1510 .flags = flags & BTRFS_SNAPSHOT_READ_ONLY ? BTRFS_SUBVOL_RDONLY : 0,
1511 .fd = old_fd,
1512 };
1513 _cleanup_close_ int subvolume_fd = -1;
1514 uint64_t new_subvol_id;
1515 int r;
1516
1517 assert(old_fd >= 0);
1518 assert(new_fd >= 0);
1519 assert(subvolume);
1520
1521 strncpy(vol_args.name, subvolume, sizeof(vol_args.name)-1);
1522
1523 if (ioctl(new_fd, BTRFS_IOC_SNAP_CREATE_V2, &vol_args) < 0)
1524 return -errno;
1525
1526 if (!(flags & BTRFS_SNAPSHOT_RECURSIVE) &&
1527 !(flags & BTRFS_SNAPSHOT_QUOTA))
1528 return 0;
1529
1530 if (old_subvol_id == 0) {
1531 r = btrfs_subvol_get_id_fd(old_fd, &old_subvol_id);
1532 if (r < 0)
1533 return r;
1534 }
1535
1536 r = btrfs_subvol_get_id(new_fd, vol_args.name, &new_subvol_id);
1537 if (r < 0)
1538 return r;
1539
1540 if (flags & BTRFS_SNAPSHOT_QUOTA)
1541 (void) copy_quota_hierarchy(new_fd, old_subvol_id, new_subvol_id);
1542
1543 if (!(flags & BTRFS_SNAPSHOT_RECURSIVE)) {
1544
1545 if (flags & BTRFS_SNAPSHOT_QUOTA)
1546 (void) copy_subtree_quota_limits(new_fd, old_subvol_id, new_subvol_id);
1547
1548 return 0;
1549 }
1550
1551 args.key.min_offset = args.key.max_offset = old_subvol_id;
1552
1553 while (btrfs_ioctl_search_args_compare(&args) <= 0) {
1554 const struct btrfs_ioctl_search_header *sh;
1555 unsigned i;
1556
1557 args.key.nr_items = 256;
1558 if (ioctl(old_fd, BTRFS_IOC_TREE_SEARCH, &args) < 0)
1559 return -errno;
1560
1561 if (args.key.nr_items <= 0)
1562 break;
1563
1564 FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i, sh, args) {
1565 _cleanup_free_ char *p = NULL, *c = NULL, *np = NULL;
1566 struct btrfs_ioctl_ino_lookup_args ino_args;
1567 const struct btrfs_root_ref *ref;
1568 _cleanup_close_ int old_child_fd = -1, new_child_fd = -1;
1569
1570 btrfs_ioctl_search_args_set(&args, sh);
1571
1572 if (sh->type != BTRFS_ROOT_BACKREF_KEY)
1573 continue;
1574
1575 /* Avoid finding the source subvolume a second
1576 * time */
1577 if (sh->offset != old_subvol_id)
1578 continue;
1579
1580 /* Avoid running into loops if the new
1581 * subvolume is below the old one. */
1582 if (sh->objectid == new_subvol_id)
1583 continue;
1584
1585 ref = BTRFS_IOCTL_SEARCH_HEADER_BODY(sh);
1586 p = strndup((char*) ref + sizeof(struct btrfs_root_ref), le64toh(ref->name_len));
1587 if (!p)
1588 return -ENOMEM;
1589
1590 zero(ino_args);
1591 ino_args.treeid = old_subvol_id;
1592 ino_args.objectid = htole64(ref->dirid);
1593
1594 if (ioctl(old_fd, BTRFS_IOC_INO_LOOKUP, &ino_args) < 0)
1595 return -errno;
1596
1597 /* The kernel returns an empty name if the
1598 * subvolume is in the top-level directory,
1599 * and otherwise appends a slash, so that we
1600 * can just concatenate easily here, without
1601 * adding a slash. */
1602 c = strappend(ino_args.name, p);
1603 if (!c)
1604 return -ENOMEM;
1605
1606 old_child_fd = openat(old_fd, c, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY|O_NOFOLLOW);
1607 if (old_child_fd < 0)
1608 return -errno;
1609
1610 np = strjoin(subvolume, "/", ino_args.name);
1611 if (!np)
1612 return -ENOMEM;
1613
1614 new_child_fd = openat(new_fd, np, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY|O_NOFOLLOW);
1615 if (new_child_fd < 0)
1616 return -errno;
1617
1618 if (flags & BTRFS_SNAPSHOT_READ_ONLY) {
1619 /* If the snapshot is read-only we
1620 * need to mark it writable
1621 * temporarily, to put the subsnapshot
1622 * into place. */
1623
1624 if (subvolume_fd < 0) {
1625 subvolume_fd = openat(new_fd, subvolume, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY|O_NOFOLLOW);
1626 if (subvolume_fd < 0)
1627 return -errno;
1628 }
1629
1630 r = btrfs_subvol_set_read_only_fd(subvolume_fd, false);
1631 if (r < 0)
1632 return r;
1633 }
1634
1635 /* When btrfs clones the subvolumes, child
1636 * subvolumes appear as empty directories. Remove
1637 * them, so that we can create a new snapshot
1638 * in their place */
1639 if (unlinkat(new_child_fd, p, AT_REMOVEDIR) < 0) {
1640 int k = -errno;
1641
1642 if (flags & BTRFS_SNAPSHOT_READ_ONLY)
1643 (void) btrfs_subvol_set_read_only_fd(subvolume_fd, true);
1644
1645 return k;
1646 }
1647
1648 r = subvol_snapshot_children(old_child_fd, new_child_fd, p, sh->objectid, flags & ~BTRFS_SNAPSHOT_FALLBACK_COPY);
1649
1650 /* Restore the readonly flag */
1651 if (flags & BTRFS_SNAPSHOT_READ_ONLY) {
1652 int k;
1653
1654 k = btrfs_subvol_set_read_only_fd(subvolume_fd, true);
1655 if (r >= 0 && k < 0)
1656 return k;
1657 }
1658
1659 if (r < 0)
1660 return r;
1661 }
1662
1663 /* Increase search key by one, to read the next item, if we can. */
1664 if (!btrfs_ioctl_search_args_inc(&args))
1665 break;
1666 }
1667
1668 if (flags & BTRFS_SNAPSHOT_QUOTA)
1669 (void) copy_subtree_quota_limits(new_fd, old_subvol_id, new_subvol_id);
1670
1671 return 0;
1672 }
1673
1674 int btrfs_subvol_snapshot_fd(int old_fd, const char *new_path, BtrfsSnapshotFlags flags) {
1675 _cleanup_close_ int new_fd = -1;
1676 const char *subvolume;
1677 int r;
1678
1679 assert(old_fd >= 0);
1680 assert(new_path);
1681
1682 r = btrfs_is_subvol_fd(old_fd);
1683 if (r < 0)
1684 return r;
1685 if (r == 0) {
1686 bool plain_directory = false;
1687
1688 /* If the source isn't a proper subvolume, fail unless fallback is requested */
1689 if (!(flags & BTRFS_SNAPSHOT_FALLBACK_COPY))
1690 return -EISDIR;
1691
1692 r = btrfs_subvol_make(new_path);
1693 if (r == -ENOTTY && (flags & BTRFS_SNAPSHOT_FALLBACK_DIRECTORY)) {
1694 /* If the destination doesn't support subvolumes, then use a plain directory, if that's requested. */
1695 if (mkdir(new_path, 0755) < 0)
1696 return -errno;
1697
1698 plain_directory = true;
1699 } else if (r < 0)
1700 return r;
1701
1702 r = copy_directory_fd(old_fd, new_path, COPY_MERGE|COPY_REFLINK);
1703 if (r < 0)
1704 goto fallback_fail;
1705
1706 if (flags & BTRFS_SNAPSHOT_READ_ONLY) {
1707
1708 if (plain_directory) {
1709 /* Plain directories have no recursive read-only flag, but something pretty close to
1710 * it: the IMMUTABLE bit. Let's use this here, if this is requested. */
1711
1712 if (flags & BTRFS_SNAPSHOT_FALLBACK_IMMUTABLE)
1713 (void) chattr_path(new_path, FS_IMMUTABLE_FL, FS_IMMUTABLE_FL, NULL);
1714 } else {
1715 r = btrfs_subvol_set_read_only(new_path, true);
1716 if (r < 0)
1717 goto fallback_fail;
1718 }
1719 }
1720
1721 return 0;
1722
1723 fallback_fail:
1724 (void) rm_rf(new_path, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME);
1725 return r;
1726 }
1727
1728 r = extract_subvolume_name(new_path, &subvolume);
1729 if (r < 0)
1730 return r;
1731
1732 new_fd = open_parent(new_path, O_CLOEXEC, 0);
1733 if (new_fd < 0)
1734 return new_fd;
1735
1736 return subvol_snapshot_children(old_fd, new_fd, subvolume, 0, flags);
1737 }
1738
1739 int btrfs_subvol_snapshot(const char *old_path, const char *new_path, BtrfsSnapshotFlags flags) {
1740 _cleanup_close_ int old_fd = -1;
1741
1742 assert(old_path);
1743 assert(new_path);
1744
1745 old_fd = open(old_path, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
1746 if (old_fd < 0)
1747 return -errno;
1748
1749 return btrfs_subvol_snapshot_fd(old_fd, new_path, flags);
1750 }
1751
1752 int btrfs_qgroup_find_parents(int fd, uint64_t qgroupid, uint64_t **ret) {
1753
1754 struct btrfs_ioctl_search_args args = {
1755 /* Tree of quota items */
1756 .key.tree_id = BTRFS_QUOTA_TREE_OBJECTID,
1757
1758 /* Look precisely for the quota relation items */
1759 .key.min_type = BTRFS_QGROUP_RELATION_KEY,
1760 .key.max_type = BTRFS_QGROUP_RELATION_KEY,
1761
1762 /* No restrictions on the other components */
1763 .key.min_offset = 0,
1764 .key.max_offset = (uint64_t) -1,
1765
1766 .key.min_transid = 0,
1767 .key.max_transid = (uint64_t) -1,
1768 };
1769
1770 _cleanup_free_ uint64_t *items = NULL;
1771 size_t n_items = 0, n_allocated = 0;
1772 int r;
1773
1774 assert(fd >= 0);
1775 assert(ret);
1776
1777 if (qgroupid == 0) {
1778 r = btrfs_subvol_get_id_fd(fd, &qgroupid);
1779 if (r < 0)
1780 return r;
1781 } else {
1782 r = btrfs_is_filesystem(fd);
1783 if (r < 0)
1784 return r;
1785 if (!r)
1786 return -ENOTTY;
1787 }
1788
1789 args.key.min_objectid = args.key.max_objectid = qgroupid;
1790
1791 while (btrfs_ioctl_search_args_compare(&args) <= 0) {
1792 const struct btrfs_ioctl_search_header *sh;
1793 unsigned i;
1794
1795 args.key.nr_items = 256;
1796 if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) < 0) {
1797 if (errno == ENOENT) /* quota tree missing: quota is disabled */
1798 break;
1799
1800 return -errno;
1801 }
1802
1803 if (args.key.nr_items <= 0)
1804 break;
1805
1806 FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i, sh, args) {
1807
1808 /* Make sure we start the next search at least from this entry */
1809 btrfs_ioctl_search_args_set(&args, sh);
1810
1811 if (sh->type != BTRFS_QGROUP_RELATION_KEY)
1812 continue;
1813 if (sh->offset < sh->objectid)
1814 continue;
1815 if (sh->objectid != qgroupid)
1816 continue;
1817
1818 if (!GREEDY_REALLOC(items, n_allocated, n_items+1))
1819 return -ENOMEM;
1820
1821 items[n_items++] = sh->offset;
1822 }
1823
1824 /* Increase search key by one, to read the next item, if we can. */
1825 if (!btrfs_ioctl_search_args_inc(&args))
1826 break;
1827 }
1828
1829 if (n_items <= 0) {
1830 *ret = NULL;
1831 return 0;
1832 }
1833
1834 *ret = TAKE_PTR(items);
1835
1836 return (int) n_items;
1837 }
1838
1839 int btrfs_subvol_auto_qgroup_fd(int fd, uint64_t subvol_id, bool insert_intermediary_qgroup) {
1840 _cleanup_free_ uint64_t *qgroups = NULL;
1841 uint64_t parent_subvol;
1842 bool changed = false;
1843 int n = 0, r;
1844
1845 assert(fd >= 0);
1846
1847 /*
1848 * Sets up the specified subvolume's qgroup automatically in
1849 * one of two ways:
1850 *
1851 * If insert_intermediary_qgroup is false, the subvolume's
1852 * leaf qgroup will be assigned to the same parent qgroups as
1853 * the subvolume's parent subvolume.
1854 *
1855 * If insert_intermediary_qgroup is true a new intermediary
1856 * higher-level qgroup is created, with a higher level number,
1857 * but reusing the id of the subvolume. The level number is
1858 * picked as one smaller than the lowest level qgroup the
1859 * parent subvolume is a member of. If the parent subvolume's
1860 * leaf qgroup is assigned to no higher-level qgroup a new
1861 * qgroup of level 255 is created instead. Either way, the new
1862 * qgroup is then assigned to the parent's higher-level
1863 * qgroup, and the subvolume itself is assigned to it.
1864 *
1865 * If the subvolume is already assigned to a higher level
1866 * qgroup, no operation is executed.
1867 *
1868 * Effectively this means: regardless if
1869 * insert_intermediary_qgroup is true or not, after this
1870 * function is invoked the subvolume will be accounted within
1871 * the same qgroups as the parent. However, if it is true, it
1872 * will also get its own higher-level qgroup, which may in
1873 * turn be used by subvolumes created beneath this subvolume
1874 * later on.
1875 *
1876 * This hence defines a simple default qgroup setup for
1877 * subvolumes, as long as this function is invoked on each
1878 * created subvolume: each subvolume is always accounting
1879 * together with its immediate parents. Optionally, if
1880 * insert_intermediary_qgroup is true, it will also get a
1881 * qgroup that then includes all its own child subvolumes.
1882 */
1883
1884 if (subvol_id == 0) {
1885 r = btrfs_is_subvol_fd(fd);
1886 if (r < 0)
1887 return r;
1888 if (!r)
1889 return -ENOTTY;
1890
1891 r = btrfs_subvol_get_id_fd(fd, &subvol_id);
1892 if (r < 0)
1893 return r;
1894 }
1895
1896 n = btrfs_qgroup_find_parents(fd, subvol_id, &qgroups);
1897 if (n < 0)
1898 return n;
1899 if (n > 0) /* already parent qgroups set up, let's bail */
1900 return 0;
1901
1902 qgroups = mfree(qgroups);
1903
1904 r = btrfs_subvol_get_parent(fd, subvol_id, &parent_subvol);
1905 if (r == -ENXIO)
1906 /* No parent, hence no qgroup memberships */
1907 n = 0;
1908 else if (r < 0)
1909 return r;
1910 else {
1911 n = btrfs_qgroup_find_parents(fd, parent_subvol, &qgroups);
1912 if (n < 0)
1913 return n;
1914 }
1915
1916 if (insert_intermediary_qgroup) {
1917 uint64_t lowest = 256, new_qgroupid;
1918 bool created = false;
1919 int i;
1920
1921 /* Determine the lowest qgroup that the parent
1922 * subvolume is assigned to. */
1923
1924 for (i = 0; i < n; i++) {
1925 uint64_t level;
1926
1927 r = btrfs_qgroupid_split(qgroups[i], &level, NULL);
1928 if (r < 0)
1929 return r;
1930
1931 if (level < lowest)
1932 lowest = level;
1933 }
1934
1935 if (lowest <= 1) /* There are no levels left we could use insert an intermediary qgroup at */
1936 return -EBUSY;
1937
1938 r = btrfs_qgroupid_make(lowest - 1, subvol_id, &new_qgroupid);
1939 if (r < 0)
1940 return r;
1941
1942 /* Create the new intermediary group, unless it already exists */
1943 r = btrfs_qgroup_create(fd, new_qgroupid);
1944 if (r < 0 && r != -EEXIST)
1945 return r;
1946 if (r >= 0)
1947 changed = created = true;
1948
1949 for (i = 0; i < n; i++) {
1950 r = btrfs_qgroup_assign(fd, new_qgroupid, qgroups[i]);
1951 if (r < 0 && r != -EEXIST) {
1952 if (created)
1953 (void) btrfs_qgroup_destroy_recursive(fd, new_qgroupid);
1954
1955 return r;
1956 }
1957 if (r >= 0)
1958 changed = true;
1959 }
1960
1961 r = btrfs_qgroup_assign(fd, subvol_id, new_qgroupid);
1962 if (r < 0 && r != -EEXIST) {
1963 if (created)
1964 (void) btrfs_qgroup_destroy_recursive(fd, new_qgroupid);
1965 return r;
1966 }
1967 if (r >= 0)
1968 changed = true;
1969
1970 } else {
1971 int i;
1972
1973 /* Assign our subvolume to all the same qgroups as the parent */
1974
1975 for (i = 0; i < n; i++) {
1976 r = btrfs_qgroup_assign(fd, subvol_id, qgroups[i]);
1977 if (r < 0 && r != -EEXIST)
1978 return r;
1979 if (r >= 0)
1980 changed = true;
1981 }
1982 }
1983
1984 return changed;
1985 }
1986
1987 int btrfs_subvol_auto_qgroup(const char *path, uint64_t subvol_id, bool create_intermediary_qgroup) {
1988 _cleanup_close_ int fd = -1;
1989
1990 fd = open(path, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
1991 if (fd < 0)
1992 return -errno;
1993
1994 return btrfs_subvol_auto_qgroup_fd(fd, subvol_id, create_intermediary_qgroup);
1995 }
1996
1997 int btrfs_subvol_get_parent(int fd, uint64_t subvol_id, uint64_t *ret) {
1998
1999 struct btrfs_ioctl_search_args args = {
2000 /* Tree of tree roots */
2001 .key.tree_id = BTRFS_ROOT_TREE_OBJECTID,
2002
2003 /* Look precisely for the subvolume items */
2004 .key.min_type = BTRFS_ROOT_BACKREF_KEY,
2005 .key.max_type = BTRFS_ROOT_BACKREF_KEY,
2006
2007 /* No restrictions on the other components */
2008 .key.min_offset = 0,
2009 .key.max_offset = (uint64_t) -1,
2010
2011 .key.min_transid = 0,
2012 .key.max_transid = (uint64_t) -1,
2013 };
2014 int r;
2015
2016 assert(fd >= 0);
2017 assert(ret);
2018
2019 if (subvol_id == 0) {
2020 r = btrfs_subvol_get_id_fd(fd, &subvol_id);
2021 if (r < 0)
2022 return r;
2023 } else {
2024 r = btrfs_is_filesystem(fd);
2025 if (r < 0)
2026 return r;
2027 if (!r)
2028 return -ENOTTY;
2029 }
2030
2031 args.key.min_objectid = args.key.max_objectid = subvol_id;
2032
2033 while (btrfs_ioctl_search_args_compare(&args) <= 0) {
2034 const struct btrfs_ioctl_search_header *sh;
2035 unsigned i;
2036
2037 args.key.nr_items = 256;
2038 if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args) < 0)
2039 return negative_errno();
2040
2041 if (args.key.nr_items <= 0)
2042 break;
2043
2044 FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i, sh, args) {
2045
2046 if (sh->type != BTRFS_ROOT_BACKREF_KEY)
2047 continue;
2048 if (sh->objectid != subvol_id)
2049 continue;
2050
2051 *ret = sh->offset;
2052 return 0;
2053 }
2054 }
2055
2056 return -ENXIO;
2057 }