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