2 This file is part of systemd.
4 Copyright 2014 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
24 #include <linux/loop.h>
29 #include <sys/ioctl.h>
31 #include <sys/statfs.h>
32 #include <sys/sysmacros.h>
35 #ifdef HAVE_LINUX_BTRFS_H
36 #include <linux/btrfs.h>
39 #include "alloc-util.h"
40 #include "btrfs-ctree.h"
41 #include "btrfs-util.h"
42 #include "chattr-util.h"
49 #include "path-util.h"
51 #include "selinux-util.h"
52 #include "smack-util.h"
53 #include "sparse-endian.h"
54 #include "stat-util.h"
55 #include "string-util.h"
56 #include "time-util.h"
59 /* WARNING: Be careful with file system ioctls! When we get an fd, we
60 * need to make sure it either refers to only a regular file or
61 * directory, or that it is located on btrfs, before invoking any
62 * btrfs ioctls. The ioctl numbers are reused by some device drivers
63 * (such as DRM), and hence might have bad effects when invoked on
64 * device nodes (that reference drivers) rather than fds to normal
65 * files or directories. */
67 static int validate_subvolume_name(const char *name
) {
69 if (!filename_is_valid(name
))
72 if (strlen(name
) > BTRFS_SUBVOL_NAME_MAX
)
78 static int open_parent(const char *path
, int flags
) {
79 _cleanup_free_
char *parent
= NULL
;
84 parent
= dirname_malloc(path
);
88 fd
= open(parent
, flags
);
95 static int extract_subvolume_name(const char *path
, const char **subvolume
) {
104 r
= validate_subvolume_name(fn
);
112 int btrfs_is_filesystem(int fd
) {
117 if (fstatfs(fd
, &sfs
) < 0)
120 return F_TYPE_EQUAL(sfs
.f_type
, BTRFS_SUPER_MAGIC
);
123 int btrfs_is_subvol_fd(int fd
) {
128 /* On btrfs subvolumes always have the inode 256 */
130 if (fstat(fd
, &st
) < 0)
133 if (!S_ISDIR(st
.st_mode
) || st
.st_ino
!= 256)
136 return btrfs_is_filesystem(fd
);
139 int btrfs_is_subvol(const char *path
) {
140 _cleanup_close_
int fd
= -1;
144 fd
= open(path
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
|O_DIRECTORY
);
148 return btrfs_is_subvol_fd(fd
);
151 int btrfs_subvol_make(const char *path
) {
152 struct btrfs_ioctl_vol_args args
= {};
153 _cleanup_close_
int fd
= -1;
154 const char *subvolume
;
159 r
= extract_subvolume_name(path
, &subvolume
);
163 fd
= open_parent(path
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
|O_DIRECTORY
);
167 strncpy(args
.name
, subvolume
, sizeof(args
.name
)-1);
169 if (ioctl(fd
, BTRFS_IOC_SUBVOL_CREATE
, &args
) < 0)
175 int btrfs_subvol_make_label(const char *path
) {
180 r
= mac_selinux_create_file_prepare(path
, S_IFDIR
);
184 r
= btrfs_subvol_make(path
);
185 mac_selinux_create_file_clear();
190 return mac_smack_fix(path
, false, false);
193 int btrfs_subvol_set_read_only_fd(int fd
, bool b
) {
194 uint64_t flags
, nflags
;
199 if (fstat(fd
, &st
) < 0)
202 if (!S_ISDIR(st
.st_mode
) || st
.st_ino
!= 256)
205 if (ioctl(fd
, BTRFS_IOC_SUBVOL_GETFLAGS
, &flags
) < 0)
209 nflags
= flags
| BTRFS_SUBVOL_RDONLY
;
211 nflags
= flags
& ~BTRFS_SUBVOL_RDONLY
;
216 if (ioctl(fd
, BTRFS_IOC_SUBVOL_SETFLAGS
, &nflags
) < 0)
222 int btrfs_subvol_set_read_only(const char *path
, bool b
) {
223 _cleanup_close_
int fd
= -1;
225 fd
= open(path
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
|O_DIRECTORY
);
229 return btrfs_subvol_set_read_only_fd(fd
, b
);
232 int btrfs_subvol_get_read_only_fd(int fd
) {
238 if (fstat(fd
, &st
) < 0)
241 if (!S_ISDIR(st
.st_mode
) || st
.st_ino
!= 256)
244 if (ioctl(fd
, BTRFS_IOC_SUBVOL_GETFLAGS
, &flags
) < 0)
247 return !!(flags
& BTRFS_SUBVOL_RDONLY
);
250 int btrfs_reflink(int infd
, int outfd
) {
257 /* Make sure we invoke the ioctl on a regular file, so that no
258 * device driver accidentally gets it. */
260 if (fstat(outfd
, &st
) < 0)
263 if (!S_ISREG(st
.st_mode
))
266 r
= ioctl(outfd
, BTRFS_IOC_CLONE
, infd
);
273 int btrfs_clone_range(int infd
, uint64_t in_offset
, int outfd
, uint64_t out_offset
, uint64_t sz
) {
274 struct btrfs_ioctl_clone_range_args args
= {
276 .src_offset
= in_offset
,
278 .dest_offset
= out_offset
,
287 if (fstat(outfd
, &st
) < 0)
290 if (!S_ISREG(st
.st_mode
))
293 r
= ioctl(outfd
, BTRFS_IOC_CLONE_RANGE
, &args
);
300 int btrfs_get_block_device_fd(int fd
, dev_t
*dev
) {
301 struct btrfs_ioctl_fs_info_args fsi
= {};
308 r
= btrfs_is_filesystem(fd
);
314 if (ioctl(fd
, BTRFS_IOC_FS_INFO
, &fsi
) < 0)
317 /* We won't do this for btrfs RAID */
318 if (fsi
.num_devices
!= 1)
321 for (id
= 1; id
<= fsi
.max_id
; id
++) {
322 struct btrfs_ioctl_dev_info_args di
= {
327 if (ioctl(fd
, BTRFS_IOC_DEV_INFO
, &di
) < 0) {
334 if (stat((char*) di
.path
, &st
) < 0)
337 if (!S_ISBLK(st
.st_mode
))
340 if (major(st
.st_rdev
) == 0)
350 int btrfs_get_block_device(const char *path
, dev_t
*dev
) {
351 _cleanup_close_
int fd
= -1;
356 fd
= open(path
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
);
360 return btrfs_get_block_device_fd(fd
, dev
);
363 int btrfs_subvol_get_id_fd(int fd
, uint64_t *ret
) {
364 struct btrfs_ioctl_ino_lookup_args args
= {
365 .objectid
= BTRFS_FIRST_FREE_OBJECTID
372 r
= btrfs_is_filesystem(fd
);
378 if (ioctl(fd
, BTRFS_IOC_INO_LOOKUP
, &args
) < 0)
385 int btrfs_subvol_get_id(int fd
, const char *subvol
, uint64_t *ret
) {
386 _cleanup_close_
int subvol_fd
= -1;
391 subvol_fd
= openat(fd
, subvol
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
|O_NOFOLLOW
);
395 return btrfs_subvol_get_id_fd(subvol_fd
, ret
);
398 static bool btrfs_ioctl_search_args_inc(struct btrfs_ioctl_search_args
*args
) {
401 /* the objectid, type, offset together make up the btrfs key,
402 * which is considered a single 136byte integer when
403 * comparing. This call increases the counter by one, dealing
404 * with the overflow between the overflows */
406 if (args
->key
.min_offset
< (uint64_t) -1) {
407 args
->key
.min_offset
++;
411 if (args
->key
.min_type
< (uint8_t) -1) {
412 args
->key
.min_type
++;
413 args
->key
.min_offset
= 0;
417 if (args
->key
.min_objectid
< (uint64_t) -1) {
418 args
->key
.min_objectid
++;
419 args
->key
.min_offset
= 0;
420 args
->key
.min_type
= 0;
427 static void btrfs_ioctl_search_args_set(struct btrfs_ioctl_search_args
*args
, const struct btrfs_ioctl_search_header
*h
) {
431 args
->key
.min_objectid
= h
->objectid
;
432 args
->key
.min_type
= h
->type
;
433 args
->key
.min_offset
= h
->offset
;
436 static int btrfs_ioctl_search_args_compare(const struct btrfs_ioctl_search_args
*args
) {
439 /* Compare min and max */
441 if (args
->key
.min_objectid
< args
->key
.max_objectid
)
443 if (args
->key
.min_objectid
> args
->key
.max_objectid
)
446 if (args
->key
.min_type
< args
->key
.max_type
)
448 if (args
->key
.min_type
> args
->key
.max_type
)
451 if (args
->key
.min_offset
< args
->key
.max_offset
)
453 if (args
->key
.min_offset
> args
->key
.max_offset
)
459 #define FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i, sh, args) \
461 (sh) = (const struct btrfs_ioctl_search_header*) (args).buf; \
462 (i) < (args).key.nr_items; \
464 (sh) = (const struct btrfs_ioctl_search_header*) ((uint8_t*) (sh) + sizeof(struct btrfs_ioctl_search_header) + (sh)->len))
466 #define BTRFS_IOCTL_SEARCH_HEADER_BODY(sh) \
467 ((void*) ((uint8_t*) sh + sizeof(struct btrfs_ioctl_search_header)))
469 int btrfs_subvol_get_info_fd(int fd
, uint64_t subvol_id
, BtrfsSubvolInfo
*ret
) {
470 struct btrfs_ioctl_search_args args
= {
471 /* Tree of tree roots */
472 .key
.tree_id
= BTRFS_ROOT_TREE_OBJECTID
,
474 /* Look precisely for the subvolume items */
475 .key
.min_type
= BTRFS_ROOT_ITEM_KEY
,
476 .key
.max_type
= BTRFS_ROOT_ITEM_KEY
,
479 .key
.max_offset
= (uint64_t) -1,
481 /* No restrictions on the other components */
482 .key
.min_transid
= 0,
483 .key
.max_transid
= (uint64_t) -1,
492 if (subvol_id
== 0) {
493 r
= btrfs_subvol_get_id_fd(fd
, &subvol_id
);
497 r
= btrfs_is_filesystem(fd
);
504 args
.key
.min_objectid
= args
.key
.max_objectid
= subvol_id
;
506 while (btrfs_ioctl_search_args_compare(&args
) <= 0) {
507 const struct btrfs_ioctl_search_header
*sh
;
510 args
.key
.nr_items
= 256;
511 if (ioctl(fd
, BTRFS_IOC_TREE_SEARCH
, &args
) < 0)
514 if (args
.key
.nr_items
<= 0)
517 FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i
, sh
, args
) {
519 const struct btrfs_root_item
*ri
;
521 /* Make sure we start the next search at least from this entry */
522 btrfs_ioctl_search_args_set(&args
, sh
);
524 if (sh
->objectid
!= subvol_id
)
526 if (sh
->type
!= BTRFS_ROOT_ITEM_KEY
)
529 /* Older versions of the struct lacked the otime setting */
530 if (sh
->len
< offsetof(struct btrfs_root_item
, otime
) + sizeof(struct btrfs_timespec
))
533 ri
= BTRFS_IOCTL_SEARCH_HEADER_BODY(sh
);
535 ret
->otime
= (usec_t
) le64toh(ri
->otime
.sec
) * USEC_PER_SEC
+
536 (usec_t
) le32toh(ri
->otime
.nsec
) / NSEC_PER_USEC
;
538 ret
->subvol_id
= subvol_id
;
539 ret
->read_only
= !!(le64toh(ri
->flags
) & BTRFS_ROOT_SUBVOL_RDONLY
);
541 assert_cc(sizeof(ri
->uuid
) == sizeof(ret
->uuid
));
542 memcpy(&ret
->uuid
, ri
->uuid
, sizeof(ret
->uuid
));
543 memcpy(&ret
->parent_uuid
, ri
->parent_uuid
, sizeof(ret
->parent_uuid
));
549 /* Increase search key by one, to read the next item, if we can. */
550 if (!btrfs_ioctl_search_args_inc(&args
))
561 int btrfs_qgroup_get_quota_fd(int fd
, uint64_t qgroupid
, BtrfsQuotaInfo
*ret
) {
563 struct btrfs_ioctl_search_args args
= {
564 /* Tree of quota items */
565 .key
.tree_id
= BTRFS_QUOTA_TREE_OBJECTID
,
567 /* The object ID is always 0 */
568 .key
.min_objectid
= 0,
569 .key
.max_objectid
= 0,
571 /* Look precisely for the quota items */
572 .key
.min_type
= BTRFS_QGROUP_STATUS_KEY
,
573 .key
.max_type
= BTRFS_QGROUP_LIMIT_KEY
,
575 /* No restrictions on the other components */
576 .key
.min_transid
= 0,
577 .key
.max_transid
= (uint64_t) -1,
580 bool found_info
= false, found_limit
= false;
587 r
= btrfs_subvol_get_id_fd(fd
, &qgroupid
);
591 r
= btrfs_is_filesystem(fd
);
598 args
.key
.min_offset
= args
.key
.max_offset
= qgroupid
;
600 while (btrfs_ioctl_search_args_compare(&args
) <= 0) {
601 const struct btrfs_ioctl_search_header
*sh
;
604 args
.key
.nr_items
= 256;
605 if (ioctl(fd
, BTRFS_IOC_TREE_SEARCH
, &args
) < 0) {
606 if (errno
== ENOENT
) /* quota tree is missing: quota disabled */
612 if (args
.key
.nr_items
<= 0)
615 FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i
, sh
, args
) {
617 /* Make sure we start the next search at least from this entry */
618 btrfs_ioctl_search_args_set(&args
, sh
);
620 if (sh
->objectid
!= 0)
622 if (sh
->offset
!= qgroupid
)
625 if (sh
->type
== BTRFS_QGROUP_INFO_KEY
) {
626 const struct btrfs_qgroup_info_item
*qii
= BTRFS_IOCTL_SEARCH_HEADER_BODY(sh
);
628 ret
->referenced
= le64toh(qii
->rfer
);
629 ret
->exclusive
= le64toh(qii
->excl
);
633 } else if (sh
->type
== BTRFS_QGROUP_LIMIT_KEY
) {
634 const struct btrfs_qgroup_limit_item
*qli
= BTRFS_IOCTL_SEARCH_HEADER_BODY(sh
);
636 if (le64toh(qli
->flags
) & BTRFS_QGROUP_LIMIT_MAX_RFER
)
637 ret
->referenced_max
= le64toh(qli
->max_rfer
);
639 ret
->referenced_max
= (uint64_t) -1;
641 if (le64toh(qli
->flags
) & BTRFS_QGROUP_LIMIT_MAX_EXCL
)
642 ret
->exclusive_max
= le64toh(qli
->max_excl
);
644 ret
->exclusive_max
= (uint64_t) -1;
649 if (found_info
&& found_limit
)
653 /* Increase search key by one, to read the next item, if we can. */
654 if (!btrfs_ioctl_search_args_inc(&args
))
659 if (!found_limit
&& !found_info
)
663 ret
->referenced
= (uint64_t) -1;
664 ret
->exclusive
= (uint64_t) -1;
668 ret
->referenced_max
= (uint64_t) -1;
669 ret
->exclusive_max
= (uint64_t) -1;
675 int btrfs_qgroup_get_quota(const char *path
, uint64_t qgroupid
, BtrfsQuotaInfo
*ret
) {
676 _cleanup_close_
int fd
= -1;
678 fd
= open(path
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
|O_NOFOLLOW
);
682 return btrfs_qgroup_get_quota_fd(fd
, qgroupid
, ret
);
685 int btrfs_subvol_find_subtree_qgroup(int fd
, uint64_t subvol_id
, uint64_t *ret
) {
686 uint64_t level
, lowest
= (uint64_t) -1, lowest_qgroupid
= 0;
687 _cleanup_free_
uint64_t *qgroups
= NULL
;
693 /* This finds the "subtree" qgroup for a specific
694 * subvolume. This only works for subvolumes that have been
695 * prepared with btrfs_subvol_auto_qgroup_fd() with
696 * insert_intermediary_qgroup=true (or equivalent). For others
697 * it will return the leaf qgroup instead. The two cases may
698 * be distuingished via the return value, which is 1 in case
699 * an appropriate "subtree" qgroup was found, and 0
702 if (subvol_id
== 0) {
703 r
= btrfs_subvol_get_id_fd(fd
, &subvol_id
);
708 r
= btrfs_qgroupid_split(subvol_id
, &level
, NULL
);
711 if (level
!= 0) /* Input must be a leaf qgroup */
714 n
= btrfs_qgroup_find_parents(fd
, subvol_id
, &qgroups
);
718 for (i
= 0; i
< n
; i
++) {
721 r
= btrfs_qgroupid_split(qgroups
[i
], &level
, &id
);
728 if (lowest
== (uint64_t) -1 || level
< lowest
) {
729 lowest_qgroupid
= qgroups
[i
];
734 if (lowest
== (uint64_t) -1) {
735 /* No suitable higher-level qgroup found, let's return
736 * the leaf qgroup instead, and indicate that with the
743 *ret
= lowest_qgroupid
;
747 int btrfs_subvol_get_subtree_quota_fd(int fd
, uint64_t subvol_id
, BtrfsQuotaInfo
*ret
) {
754 /* This determines the quota data of the qgroup with the
755 * lowest level, that shares the id part with the specified
756 * subvolume. This is useful for determining the quota data
757 * for entire subvolume subtrees, as long as the subtrees have
758 * been set up with btrfs_qgroup_subvol_auto_fd() or in a
761 r
= btrfs_subvol_find_subtree_qgroup(fd
, subvol_id
, &qgroupid
);
765 return btrfs_qgroup_get_quota_fd(fd
, qgroupid
, ret
);
768 int btrfs_subvol_get_subtree_quota(const char *path
, uint64_t subvol_id
, BtrfsQuotaInfo
*ret
) {
769 _cleanup_close_
int fd
= -1;
771 fd
= open(path
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
|O_NOFOLLOW
);
775 return btrfs_subvol_get_subtree_quota_fd(fd
, subvol_id
, ret
);
778 int btrfs_defrag_fd(int fd
) {
783 if (fstat(fd
, &st
) < 0)
786 if (!S_ISREG(st
.st_mode
))
789 if (ioctl(fd
, BTRFS_IOC_DEFRAG
, NULL
) < 0)
795 int btrfs_defrag(const char *p
) {
796 _cleanup_close_
int fd
= -1;
798 fd
= open(p
, O_RDWR
|O_CLOEXEC
|O_NOCTTY
|O_NOFOLLOW
);
802 return btrfs_defrag_fd(fd
);
805 int btrfs_quota_enable_fd(int fd
, bool b
) {
806 struct btrfs_ioctl_quota_ctl_args args
= {
807 .cmd
= b
? BTRFS_QUOTA_CTL_ENABLE
: BTRFS_QUOTA_CTL_DISABLE
,
813 r
= btrfs_is_filesystem(fd
);
819 if (ioctl(fd
, BTRFS_IOC_QUOTA_CTL
, &args
) < 0)
825 int btrfs_quota_enable(const char *path
, bool b
) {
826 _cleanup_close_
int fd
= -1;
828 fd
= open(path
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
|O_NOFOLLOW
);
832 return btrfs_quota_enable_fd(fd
, b
);
835 int btrfs_qgroup_set_limit_fd(int fd
, uint64_t qgroupid
, uint64_t referenced_max
) {
837 struct btrfs_ioctl_qgroup_limit_args args
= {
838 .lim
.max_rfer
= referenced_max
,
839 .lim
.flags
= BTRFS_QGROUP_LIMIT_MAX_RFER
,
847 r
= btrfs_subvol_get_id_fd(fd
, &qgroupid
);
851 r
= btrfs_is_filesystem(fd
);
858 args
.qgroupid
= qgroupid
;
861 if (ioctl(fd
, BTRFS_IOC_QGROUP_LIMIT
, &args
) < 0) {
863 if (errno
== EBUSY
&& c
< 10) {
864 (void) btrfs_quota_scan_wait(fd
);
877 int btrfs_qgroup_set_limit(const char *path
, uint64_t qgroupid
, uint64_t referenced_max
) {
878 _cleanup_close_
int fd
= -1;
880 fd
= open(path
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
|O_NOFOLLOW
);
884 return btrfs_qgroup_set_limit_fd(fd
, qgroupid
, referenced_max
);
887 int btrfs_subvol_set_subtree_quota_limit_fd(int fd
, uint64_t subvol_id
, uint64_t referenced_max
) {
893 r
= btrfs_subvol_find_subtree_qgroup(fd
, subvol_id
, &qgroupid
);
897 return btrfs_qgroup_set_limit_fd(fd
, qgroupid
, referenced_max
);
900 int btrfs_subvol_set_subtree_quota_limit(const char *path
, uint64_t subvol_id
, uint64_t referenced_max
) {
901 _cleanup_close_
int fd
= -1;
903 fd
= open(path
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
|O_NOFOLLOW
);
907 return btrfs_subvol_set_subtree_quota_limit_fd(fd
, subvol_id
, referenced_max
);
910 int btrfs_resize_loopback_fd(int fd
, uint64_t new_size
, bool grow_only
) {
911 struct btrfs_ioctl_vol_args args
= {};
912 _cleanup_free_
char *p
= NULL
, *loop
= NULL
, *backing
= NULL
;
913 _cleanup_close_
int loop_fd
= -1, backing_fd
= -1;
918 /* In contrast to btrfs quota ioctls ftruncate() cannot make sense of "infinity" or file sizes > 2^31 */
919 if (!FILE_SIZE_VALID(new_size
))
922 /* btrfs cannot handle file systems < 16M, hence use this as minimum */
923 if (new_size
< 16*1024*1024)
924 new_size
= 16*1024*1024;
926 r
= btrfs_get_block_device_fd(fd
, &dev
);
932 if (asprintf(&p
, "/sys/dev/block/%u:%u/loop/backing_file", major(dev
), minor(dev
)) < 0)
934 r
= read_one_line_file(p
, &backing
);
939 if (isempty(backing
) || !path_is_absolute(backing
))
942 backing_fd
= open(backing
, O_RDWR
|O_CLOEXEC
|O_NOCTTY
);
946 if (fstat(backing_fd
, &st
) < 0)
948 if (!S_ISREG(st
.st_mode
))
951 if (new_size
== (uint64_t) st
.st_size
)
954 if (grow_only
&& new_size
< (uint64_t) st
.st_size
)
957 if (asprintf(&loop
, "/dev/block/%u:%u", major(dev
), minor(dev
)) < 0)
959 loop_fd
= open(loop
, O_RDWR
|O_CLOEXEC
|O_NOCTTY
);
963 if (snprintf(args
.name
, sizeof(args
.name
), "%" PRIu64
, new_size
) >= (int) sizeof(args
.name
))
966 if (new_size
< (uint64_t) st
.st_size
) {
967 /* Decrease size: first decrease btrfs size, then shorten loopback */
968 if (ioctl(fd
, BTRFS_IOC_RESIZE
, &args
) < 0)
972 if (ftruncate(backing_fd
, new_size
) < 0)
975 if (ioctl(loop_fd
, LOOP_SET_CAPACITY
, 0) < 0)
978 if (new_size
> (uint64_t) st
.st_size
) {
979 /* Increase size: first enlarge loopback, then increase btrfs size */
980 if (ioctl(fd
, BTRFS_IOC_RESIZE
, &args
) < 0)
984 /* Make sure the free disk space is correctly updated for both file systems */
986 (void) fsync(backing_fd
);
991 int btrfs_resize_loopback(const char *p
, uint64_t new_size
, bool grow_only
) {
992 _cleanup_close_
int fd
= -1;
994 fd
= open(p
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
);
998 return btrfs_resize_loopback_fd(fd
, new_size
, grow_only
);
1001 int btrfs_qgroupid_make(uint64_t level
, uint64_t id
, uint64_t *ret
) {
1004 if (level
>= (UINT64_C(1) << (64 - BTRFS_QGROUP_LEVEL_SHIFT
)))
1007 if (id
>= (UINT64_C(1) << BTRFS_QGROUP_LEVEL_SHIFT
))
1010 *ret
= (level
<< BTRFS_QGROUP_LEVEL_SHIFT
) | id
;
1014 int btrfs_qgroupid_split(uint64_t qgroupid
, uint64_t *level
, uint64_t *id
) {
1015 assert(level
|| id
);
1018 *level
= qgroupid
>> BTRFS_QGROUP_LEVEL_SHIFT
;
1021 *id
= qgroupid
& ((UINT64_C(1) << BTRFS_QGROUP_LEVEL_SHIFT
) - 1);
1026 static int qgroup_create_or_destroy(int fd
, bool b
, uint64_t qgroupid
) {
1028 struct btrfs_ioctl_qgroup_create_args args
= {
1030 .qgroupid
= qgroupid
,
1035 r
= btrfs_is_filesystem(fd
);
1042 if (ioctl(fd
, BTRFS_IOC_QGROUP_CREATE
, &args
) < 0) {
1044 /* If quota is not enabled, we get EINVAL. Turn this into a recognizable error */
1045 if (errno
== EINVAL
)
1046 return -ENOPROTOOPT
;
1048 if (errno
== EBUSY
&& c
< 10) {
1049 (void) btrfs_quota_scan_wait(fd
);
1062 int btrfs_qgroup_create(int fd
, uint64_t qgroupid
) {
1063 return qgroup_create_or_destroy(fd
, true, qgroupid
);
1066 int btrfs_qgroup_destroy(int fd
, uint64_t qgroupid
) {
1067 return qgroup_create_or_destroy(fd
, false, qgroupid
);
1070 int btrfs_qgroup_destroy_recursive(int fd
, uint64_t qgroupid
) {
1071 _cleanup_free_
uint64_t *qgroups
= NULL
;
1075 /* Destroys the specified qgroup, but unassigns it from all
1076 * its parents first. Also, it recursively destroys all
1077 * qgroups it is assgined to that have the same id part of the
1078 * qgroupid as the specified group. */
1080 r
= btrfs_qgroupid_split(qgroupid
, NULL
, &subvol_id
);
1084 n
= btrfs_qgroup_find_parents(fd
, qgroupid
, &qgroups
);
1088 for (i
= 0; i
< n
; i
++) {
1091 r
= btrfs_qgroupid_split(qgroups
[i
], NULL
, &id
);
1095 r
= btrfs_qgroup_unassign(fd
, qgroupid
, qgroups
[i
]);
1099 if (id
!= subvol_id
)
1102 /* The parent qgroupid shares the same id part with
1103 * us? If so, destroy it too. */
1105 (void) btrfs_qgroup_destroy_recursive(fd
, qgroups
[i
]);
1108 return btrfs_qgroup_destroy(fd
, qgroupid
);
1111 int btrfs_quota_scan_start(int fd
) {
1112 struct btrfs_ioctl_quota_rescan_args args
= {};
1116 if (ioctl(fd
, BTRFS_IOC_QUOTA_RESCAN
, &args
) < 0)
1122 int btrfs_quota_scan_wait(int fd
) {
1125 if (ioctl(fd
, BTRFS_IOC_QUOTA_RESCAN_WAIT
) < 0)
1131 int btrfs_quota_scan_ongoing(int fd
) {
1132 struct btrfs_ioctl_quota_rescan_args args
= {};
1136 if (ioctl(fd
, BTRFS_IOC_QUOTA_RESCAN_STATUS
, &args
) < 0)
1139 return !!args
.flags
;
1142 static int qgroup_assign_or_unassign(int fd
, bool b
, uint64_t child
, uint64_t parent
) {
1143 struct btrfs_ioctl_qgroup_assign_args args
= {
1151 r
= btrfs_is_filesystem(fd
);
1158 r
= ioctl(fd
, BTRFS_IOC_QGROUP_ASSIGN
, &args
);
1160 if (errno
== EBUSY
&& c
< 10) {
1161 (void) btrfs_quota_scan_wait(fd
);
1171 /* If the return value is > 0, we need to request a rescan */
1173 (void) btrfs_quota_scan_start(fd
);
1178 int btrfs_qgroup_assign(int fd
, uint64_t child
, uint64_t parent
) {
1179 return qgroup_assign_or_unassign(fd
, true, child
, parent
);
1182 int btrfs_qgroup_unassign(int fd
, uint64_t child
, uint64_t parent
) {
1183 return qgroup_assign_or_unassign(fd
, false, child
, parent
);
1186 static int subvol_remove_children(int fd
, const char *subvolume
, uint64_t subvol_id
, BtrfsRemoveFlags flags
) {
1187 struct btrfs_ioctl_search_args args
= {
1188 .key
.tree_id
= BTRFS_ROOT_TREE_OBJECTID
,
1190 .key
.min_objectid
= BTRFS_FIRST_FREE_OBJECTID
,
1191 .key
.max_objectid
= BTRFS_LAST_FREE_OBJECTID
,
1193 .key
.min_type
= BTRFS_ROOT_BACKREF_KEY
,
1194 .key
.max_type
= BTRFS_ROOT_BACKREF_KEY
,
1196 .key
.min_transid
= 0,
1197 .key
.max_transid
= (uint64_t) -1,
1200 struct btrfs_ioctl_vol_args vol_args
= {};
1201 _cleanup_close_
int subvol_fd
= -1;
1203 bool made_writable
= false;
1209 if (fstat(fd
, &st
) < 0)
1212 if (!S_ISDIR(st
.st_mode
))
1215 subvol_fd
= openat(fd
, subvolume
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
|O_DIRECTORY
);
1219 if (subvol_id
== 0) {
1220 r
= btrfs_subvol_get_id_fd(subvol_fd
, &subvol_id
);
1225 /* First, try to remove the subvolume. If it happens to be
1226 * already empty, this will just work. */
1227 strncpy(vol_args
.name
, subvolume
, sizeof(vol_args
.name
)-1);
1228 if (ioctl(fd
, BTRFS_IOC_SNAP_DESTROY
, &vol_args
) >= 0) {
1229 (void) btrfs_qgroup_destroy_recursive(fd
, subvol_id
); /* for the leaf subvolumes, the qgroup id is identical to the subvol id */
1232 if (!(flags
& BTRFS_REMOVE_RECURSIVE
) || errno
!= ENOTEMPTY
)
1235 /* OK, the subvolume is not empty, let's look for child
1236 * subvolumes, and remove them, first */
1238 args
.key
.min_offset
= args
.key
.max_offset
= subvol_id
;
1240 while (btrfs_ioctl_search_args_compare(&args
) <= 0) {
1241 const struct btrfs_ioctl_search_header
*sh
;
1244 args
.key
.nr_items
= 256;
1245 if (ioctl(fd
, BTRFS_IOC_TREE_SEARCH
, &args
) < 0)
1248 if (args
.key
.nr_items
<= 0)
1251 FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i
, sh
, args
) {
1252 _cleanup_free_
char *p
= NULL
;
1253 const struct btrfs_root_ref
*ref
;
1254 struct btrfs_ioctl_ino_lookup_args ino_args
;
1256 btrfs_ioctl_search_args_set(&args
, sh
);
1258 if (sh
->type
!= BTRFS_ROOT_BACKREF_KEY
)
1260 if (sh
->offset
!= subvol_id
)
1263 ref
= BTRFS_IOCTL_SEARCH_HEADER_BODY(sh
);
1265 p
= strndup((char*) ref
+ sizeof(struct btrfs_root_ref
), le64toh(ref
->name_len
));
1270 ino_args
.treeid
= subvol_id
;
1271 ino_args
.objectid
= htole64(ref
->dirid
);
1273 if (ioctl(fd
, BTRFS_IOC_INO_LOOKUP
, &ino_args
) < 0)
1276 if (!made_writable
) {
1277 r
= btrfs_subvol_set_read_only_fd(subvol_fd
, false);
1281 made_writable
= true;
1284 if (isempty(ino_args
.name
))
1285 /* Subvolume is in the top-level
1286 * directory of the subvolume. */
1287 r
= subvol_remove_children(subvol_fd
, p
, sh
->objectid
, flags
);
1289 _cleanup_close_
int child_fd
= -1;
1291 /* Subvolume is somewhere further down,
1292 * hence we need to open the
1293 * containing directory first */
1295 child_fd
= openat(subvol_fd
, ino_args
.name
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
|O_DIRECTORY
);
1299 r
= subvol_remove_children(child_fd
, p
, sh
->objectid
, flags
);
1305 /* Increase search key by one, to read the next item, if we can. */
1306 if (!btrfs_ioctl_search_args_inc(&args
))
1310 /* OK, the child subvolumes should all be gone now, let's try
1311 * again to remove the subvolume */
1312 if (ioctl(fd
, BTRFS_IOC_SNAP_DESTROY
, &vol_args
) < 0)
1315 (void) btrfs_qgroup_destroy_recursive(fd
, subvol_id
);
1319 int btrfs_subvol_remove(const char *path
, BtrfsRemoveFlags flags
) {
1320 _cleanup_close_
int fd
= -1;
1321 const char *subvolume
;
1326 r
= extract_subvolume_name(path
, &subvolume
);
1330 fd
= open_parent(path
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
|O_DIRECTORY
);
1334 return subvol_remove_children(fd
, subvolume
, 0, flags
);
1337 int btrfs_subvol_remove_fd(int fd
, const char *subvolume
, BtrfsRemoveFlags flags
) {
1338 return subvol_remove_children(fd
, subvolume
, 0, flags
);
1341 int btrfs_qgroup_copy_limits(int fd
, uint64_t old_qgroupid
, uint64_t new_qgroupid
) {
1343 struct btrfs_ioctl_search_args args
= {
1344 /* Tree of quota items */
1345 .key
.tree_id
= BTRFS_QUOTA_TREE_OBJECTID
,
1347 /* The object ID is always 0 */
1348 .key
.min_objectid
= 0,
1349 .key
.max_objectid
= 0,
1351 /* Look precisely for the quota items */
1352 .key
.min_type
= BTRFS_QGROUP_LIMIT_KEY
,
1353 .key
.max_type
= BTRFS_QGROUP_LIMIT_KEY
,
1355 /* For our qgroup */
1356 .key
.min_offset
= old_qgroupid
,
1357 .key
.max_offset
= old_qgroupid
,
1359 /* No restrictions on the other components */
1360 .key
.min_transid
= 0,
1361 .key
.max_transid
= (uint64_t) -1,
1366 r
= btrfs_is_filesystem(fd
);
1372 while (btrfs_ioctl_search_args_compare(&args
) <= 0) {
1373 const struct btrfs_ioctl_search_header
*sh
;
1376 args
.key
.nr_items
= 256;
1377 if (ioctl(fd
, BTRFS_IOC_TREE_SEARCH
, &args
) < 0) {
1378 if (errno
== ENOENT
) /* quota tree missing: quota is not enabled, hence nothing to copy */
1384 if (args
.key
.nr_items
<= 0)
1387 FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i
, sh
, args
) {
1388 const struct btrfs_qgroup_limit_item
*qli
= BTRFS_IOCTL_SEARCH_HEADER_BODY(sh
);
1389 struct btrfs_ioctl_qgroup_limit_args qargs
;
1392 /* Make sure we start the next search at least from this entry */
1393 btrfs_ioctl_search_args_set(&args
, sh
);
1395 if (sh
->objectid
!= 0)
1397 if (sh
->type
!= BTRFS_QGROUP_LIMIT_KEY
)
1399 if (sh
->offset
!= old_qgroupid
)
1402 /* We found the entry, now copy things over. */
1404 qargs
= (struct btrfs_ioctl_qgroup_limit_args
) {
1405 .qgroupid
= new_qgroupid
,
1407 .lim
.max_rfer
= le64toh(qli
->max_rfer
),
1408 .lim
.max_excl
= le64toh(qli
->max_excl
),
1409 .lim
.rsv_rfer
= le64toh(qli
->rsv_rfer
),
1410 .lim
.rsv_excl
= le64toh(qli
->rsv_excl
),
1412 .lim
.flags
= le64toh(qli
->flags
) & (BTRFS_QGROUP_LIMIT_MAX_RFER
|
1413 BTRFS_QGROUP_LIMIT_MAX_EXCL
|
1414 BTRFS_QGROUP_LIMIT_RSV_RFER
|
1415 BTRFS_QGROUP_LIMIT_RSV_EXCL
),
1419 if (ioctl(fd
, BTRFS_IOC_QGROUP_LIMIT
, &qargs
) < 0) {
1420 if (errno
== EBUSY
&& c
< 10) {
1421 (void) btrfs_quota_scan_wait(fd
);
1433 /* Increase search key by one, to read the next item, if we can. */
1434 if (!btrfs_ioctl_search_args_inc(&args
))
1441 static int copy_quota_hierarchy(int fd
, uint64_t old_subvol_id
, uint64_t new_subvol_id
) {
1442 _cleanup_free_
uint64_t *old_qgroups
= NULL
, *old_parent_qgroups
= NULL
;
1443 bool copy_from_parent
= false, insert_intermediary_qgroup
= false;
1444 int n_old_qgroups
, n_old_parent_qgroups
, r
, i
;
1445 uint64_t old_parent_id
;
1449 /* Copies a reduced form of quota information from the old to
1450 * the new subvolume. */
1452 n_old_qgroups
= btrfs_qgroup_find_parents(fd
, old_subvol_id
, &old_qgroups
);
1453 if (n_old_qgroups
<= 0) /* Nothing to copy */
1454 return n_old_qgroups
;
1456 r
= btrfs_subvol_get_parent(fd
, old_subvol_id
, &old_parent_id
);
1458 /* We have no parent, hence nothing to copy. */
1459 n_old_parent_qgroups
= 0;
1463 n_old_parent_qgroups
= btrfs_qgroup_find_parents(fd
, old_parent_id
, &old_parent_qgroups
);
1464 if (n_old_parent_qgroups
< 0)
1465 return n_old_parent_qgroups
;
1468 for (i
= 0; i
< n_old_qgroups
; i
++) {
1472 r
= btrfs_qgroupid_split(old_qgroups
[i
], NULL
, &id
);
1476 if (id
== old_subvol_id
) {
1477 /* The old subvolume was member of a qgroup
1478 * that had the same id, but a different level
1479 * as it self. Let's set up something similar
1480 * in the destination. */
1481 insert_intermediary_qgroup
= true;
1485 for (j
= 0; j
< n_old_parent_qgroups
; j
++)
1486 if (old_parent_qgroups
[j
] == old_qgroups
[i
]) {
1487 /* The old subvolume shared a common
1488 * parent qgroup with its parent
1489 * subvolume. Let's set up something
1490 * similar in the destination. */
1491 copy_from_parent
= true;
1495 if (!insert_intermediary_qgroup
&& !copy_from_parent
)
1498 return btrfs_subvol_auto_qgroup_fd(fd
, new_subvol_id
, insert_intermediary_qgroup
);
1501 static int copy_subtree_quota_limits(int fd
, uint64_t old_subvol
, uint64_t new_subvol
) {
1502 uint64_t old_subtree_qgroup
, new_subtree_qgroup
;
1506 /* First copy the leaf limits */
1507 r
= btrfs_qgroup_copy_limits(fd
, old_subvol
, new_subvol
);
1512 /* Then, try to copy the subtree limits, if there are any. */
1513 r
= btrfs_subvol_find_subtree_qgroup(fd
, old_subvol
, &old_subtree_qgroup
);
1519 r
= btrfs_subvol_find_subtree_qgroup(fd
, new_subvol
, &new_subtree_qgroup
);
1525 r
= btrfs_qgroup_copy_limits(fd
, old_subtree_qgroup
, new_subtree_qgroup
);
1532 static int subvol_snapshot_children(int old_fd
, int new_fd
, const char *subvolume
, uint64_t old_subvol_id
, BtrfsSnapshotFlags flags
) {
1534 struct btrfs_ioctl_search_args args
= {
1535 .key
.tree_id
= BTRFS_ROOT_TREE_OBJECTID
,
1537 .key
.min_objectid
= BTRFS_FIRST_FREE_OBJECTID
,
1538 .key
.max_objectid
= BTRFS_LAST_FREE_OBJECTID
,
1540 .key
.min_type
= BTRFS_ROOT_BACKREF_KEY
,
1541 .key
.max_type
= BTRFS_ROOT_BACKREF_KEY
,
1543 .key
.min_transid
= 0,
1544 .key
.max_transid
= (uint64_t) -1,
1547 struct btrfs_ioctl_vol_args_v2 vol_args
= {
1548 .flags
= flags
& BTRFS_SNAPSHOT_READ_ONLY
? BTRFS_SUBVOL_RDONLY
: 0,
1551 _cleanup_close_
int subvolume_fd
= -1;
1552 uint64_t new_subvol_id
;
1555 assert(old_fd
>= 0);
1556 assert(new_fd
>= 0);
1559 strncpy(vol_args
.name
, subvolume
, sizeof(vol_args
.name
)-1);
1561 if (ioctl(new_fd
, BTRFS_IOC_SNAP_CREATE_V2
, &vol_args
) < 0)
1564 if (!(flags
& BTRFS_SNAPSHOT_RECURSIVE
) &&
1565 !(flags
& BTRFS_SNAPSHOT_QUOTA
))
1568 if (old_subvol_id
== 0) {
1569 r
= btrfs_subvol_get_id_fd(old_fd
, &old_subvol_id
);
1574 r
= btrfs_subvol_get_id(new_fd
, vol_args
.name
, &new_subvol_id
);
1578 if (flags
& BTRFS_SNAPSHOT_QUOTA
)
1579 (void) copy_quota_hierarchy(new_fd
, old_subvol_id
, new_subvol_id
);
1581 if (!(flags
& BTRFS_SNAPSHOT_RECURSIVE
)) {
1583 if (flags
& BTRFS_SNAPSHOT_QUOTA
)
1584 (void) copy_subtree_quota_limits(new_fd
, old_subvol_id
, new_subvol_id
);
1589 args
.key
.min_offset
= args
.key
.max_offset
= old_subvol_id
;
1591 while (btrfs_ioctl_search_args_compare(&args
) <= 0) {
1592 const struct btrfs_ioctl_search_header
*sh
;
1595 args
.key
.nr_items
= 256;
1596 if (ioctl(old_fd
, BTRFS_IOC_TREE_SEARCH
, &args
) < 0)
1599 if (args
.key
.nr_items
<= 0)
1602 FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i
, sh
, args
) {
1603 _cleanup_free_
char *p
= NULL
, *c
= NULL
, *np
= NULL
;
1604 struct btrfs_ioctl_ino_lookup_args ino_args
;
1605 const struct btrfs_root_ref
*ref
;
1606 _cleanup_close_
int old_child_fd
= -1, new_child_fd
= -1;
1608 btrfs_ioctl_search_args_set(&args
, sh
);
1610 if (sh
->type
!= BTRFS_ROOT_BACKREF_KEY
)
1613 /* Avoid finding the source subvolume a second
1615 if (sh
->offset
!= old_subvol_id
)
1618 /* Avoid running into loops if the new
1619 * subvolume is below the old one. */
1620 if (sh
->objectid
== new_subvol_id
)
1623 ref
= BTRFS_IOCTL_SEARCH_HEADER_BODY(sh
);
1624 p
= strndup((char*) ref
+ sizeof(struct btrfs_root_ref
), le64toh(ref
->name_len
));
1629 ino_args
.treeid
= old_subvol_id
;
1630 ino_args
.objectid
= htole64(ref
->dirid
);
1632 if (ioctl(old_fd
, BTRFS_IOC_INO_LOOKUP
, &ino_args
) < 0)
1635 /* The kernel returns an empty name if the
1636 * subvolume is in the top-level directory,
1637 * and otherwise appends a slash, so that we
1638 * can just concatenate easily here, without
1639 * adding a slash. */
1640 c
= strappend(ino_args
.name
, p
);
1644 old_child_fd
= openat(old_fd
, c
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
|O_DIRECTORY
);
1645 if (old_child_fd
< 0)
1648 np
= strjoin(subvolume
, "/", ino_args
.name
);
1652 new_child_fd
= openat(new_fd
, np
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
|O_DIRECTORY
);
1653 if (new_child_fd
< 0)
1656 if (flags
& BTRFS_SNAPSHOT_READ_ONLY
) {
1657 /* If the snapshot is read-only we
1658 * need to mark it writable
1659 * temporarily, to put the subsnapshot
1662 if (subvolume_fd
< 0) {
1663 subvolume_fd
= openat(new_fd
, subvolume
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
|O_DIRECTORY
);
1664 if (subvolume_fd
< 0)
1668 r
= btrfs_subvol_set_read_only_fd(subvolume_fd
, false);
1673 /* When btrfs clones the subvolumes, child
1674 * subvolumes appear as empty directories. Remove
1675 * them, so that we can create a new snapshot
1677 if (unlinkat(new_child_fd
, p
, AT_REMOVEDIR
) < 0) {
1680 if (flags
& BTRFS_SNAPSHOT_READ_ONLY
)
1681 (void) btrfs_subvol_set_read_only_fd(subvolume_fd
, true);
1686 r
= subvol_snapshot_children(old_child_fd
, new_child_fd
, p
, sh
->objectid
, flags
& ~BTRFS_SNAPSHOT_FALLBACK_COPY
);
1688 /* Restore the readonly flag */
1689 if (flags
& BTRFS_SNAPSHOT_READ_ONLY
) {
1692 k
= btrfs_subvol_set_read_only_fd(subvolume_fd
, true);
1693 if (r
>= 0 && k
< 0)
1701 /* Increase search key by one, to read the next item, if we can. */
1702 if (!btrfs_ioctl_search_args_inc(&args
))
1706 if (flags
& BTRFS_SNAPSHOT_QUOTA
)
1707 (void) copy_subtree_quota_limits(new_fd
, old_subvol_id
, new_subvol_id
);
1712 int btrfs_subvol_snapshot_fd(int old_fd
, const char *new_path
, BtrfsSnapshotFlags flags
) {
1713 _cleanup_close_
int new_fd
= -1;
1714 const char *subvolume
;
1717 assert(old_fd
>= 0);
1720 r
= btrfs_is_subvol_fd(old_fd
);
1724 bool plain_directory
= false;
1726 /* If the source isn't a proper subvolume, fail unless fallback is requested */
1727 if (!(flags
& BTRFS_SNAPSHOT_FALLBACK_COPY
))
1730 r
= btrfs_subvol_make(new_path
);
1731 if (r
== -ENOTTY
&& (flags
& BTRFS_SNAPSHOT_FALLBACK_DIRECTORY
)) {
1732 /* If the destination doesn't support subvolumes, then use a plain directory, if that's requested. */
1733 if (mkdir(new_path
, 0755) < 0)
1736 plain_directory
= true;
1740 r
= copy_directory_fd(old_fd
, new_path
, COPY_MERGE
|COPY_REFLINK
);
1744 if (flags
& BTRFS_SNAPSHOT_READ_ONLY
) {
1746 if (plain_directory
) {
1747 /* Plain directories have no recursive read-only flag, but something pretty close to
1748 * it: the IMMUTABLE bit. Let's use this here, if this is requested. */
1750 if (flags
& BTRFS_SNAPSHOT_FALLBACK_IMMUTABLE
)
1751 (void) chattr_path(new_path
, FS_IMMUTABLE_FL
, FS_IMMUTABLE_FL
);
1753 r
= btrfs_subvol_set_read_only(new_path
, true);
1762 (void) rm_rf(new_path
, REMOVE_ROOT
|REMOVE_PHYSICAL
|REMOVE_SUBVOLUME
);
1766 r
= extract_subvolume_name(new_path
, &subvolume
);
1770 new_fd
= open_parent(new_path
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
|O_DIRECTORY
);
1774 return subvol_snapshot_children(old_fd
, new_fd
, subvolume
, 0, flags
);
1777 int btrfs_subvol_snapshot(const char *old_path
, const char *new_path
, BtrfsSnapshotFlags flags
) {
1778 _cleanup_close_
int old_fd
= -1;
1783 old_fd
= open(old_path
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
|O_DIRECTORY
);
1787 return btrfs_subvol_snapshot_fd(old_fd
, new_path
, flags
);
1790 int btrfs_qgroup_find_parents(int fd
, uint64_t qgroupid
, uint64_t **ret
) {
1792 struct btrfs_ioctl_search_args args
= {
1793 /* Tree of quota items */
1794 .key
.tree_id
= BTRFS_QUOTA_TREE_OBJECTID
,
1796 /* Look precisely for the quota relation items */
1797 .key
.min_type
= BTRFS_QGROUP_RELATION_KEY
,
1798 .key
.max_type
= BTRFS_QGROUP_RELATION_KEY
,
1800 /* No restrictions on the other components */
1801 .key
.min_offset
= 0,
1802 .key
.max_offset
= (uint64_t) -1,
1804 .key
.min_transid
= 0,
1805 .key
.max_transid
= (uint64_t) -1,
1808 _cleanup_free_
uint64_t *items
= NULL
;
1809 size_t n_items
= 0, n_allocated
= 0;
1815 if (qgroupid
== 0) {
1816 r
= btrfs_subvol_get_id_fd(fd
, &qgroupid
);
1820 r
= btrfs_is_filesystem(fd
);
1827 args
.key
.min_objectid
= args
.key
.max_objectid
= qgroupid
;
1829 while (btrfs_ioctl_search_args_compare(&args
) <= 0) {
1830 const struct btrfs_ioctl_search_header
*sh
;
1833 args
.key
.nr_items
= 256;
1834 if (ioctl(fd
, BTRFS_IOC_TREE_SEARCH
, &args
) < 0) {
1835 if (errno
== ENOENT
) /* quota tree missing: quota is disabled */
1841 if (args
.key
.nr_items
<= 0)
1844 FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i
, sh
, args
) {
1846 /* Make sure we start the next search at least from this entry */
1847 btrfs_ioctl_search_args_set(&args
, sh
);
1849 if (sh
->type
!= BTRFS_QGROUP_RELATION_KEY
)
1851 if (sh
->offset
< sh
->objectid
)
1853 if (sh
->objectid
!= qgroupid
)
1856 if (!GREEDY_REALLOC(items
, n_allocated
, n_items
+1))
1859 items
[n_items
++] = sh
->offset
;
1862 /* Increase search key by one, to read the next item, if we can. */
1863 if (!btrfs_ioctl_search_args_inc(&args
))
1875 return (int) n_items
;
1878 int btrfs_subvol_auto_qgroup_fd(int fd
, uint64_t subvol_id
, bool insert_intermediary_qgroup
) {
1879 _cleanup_free_
uint64_t *qgroups
= NULL
;
1880 uint64_t parent_subvol
;
1881 bool changed
= false;
1887 * Sets up the specified subvolume's qgroup automatically in
1890 * If insert_intermediary_qgroup is false, the subvolume's
1891 * leaf qgroup will be assigned to the same parent qgroups as
1892 * the subvolume's parent subvolume.
1894 * If insert_intermediary_qgroup is true a new intermediary
1895 * higher-level qgroup is created, with a higher level number,
1896 * but reusing the id of the subvolume. The level number is
1897 * picked as one smaller than the lowest level qgroup the
1898 * parent subvolume is a member of. If the parent subvolume's
1899 * leaf qgroup is assigned to no higher-level qgroup a new
1900 * qgroup of level 255 is created instead. Either way, the new
1901 * qgroup is then assigned to the parent's higher-level
1902 * qgroup, and the subvolume itself is assigned to it.
1904 * If the subvolume is already assigned to a higher level
1905 * qgroup, no operation is executed.
1907 * Effectively this means: regardless if
1908 * insert_intermediary_qgroup is true or not, after this
1909 * function is invoked the subvolume will be accounted within
1910 * the same qgroups as the parent. However, if it is true, it
1911 * will also get its own higher-level qgroup, which may in
1912 * turn be used by subvolumes created beneath this subvolume
1915 * This hence defines a simple default qgroup setup for
1916 * subvolumes, as long as this function is invoked on each
1917 * created subvolume: each subvolume is always accounting
1918 * together with its immediate parents. Optionally, if
1919 * insert_intermediary_qgroup is true, it will also get a
1920 * qgroup that then includes all its own child subvolumes.
1923 if (subvol_id
== 0) {
1924 r
= btrfs_is_subvol_fd(fd
);
1930 r
= btrfs_subvol_get_id_fd(fd
, &subvol_id
);
1935 n
= btrfs_qgroup_find_parents(fd
, subvol_id
, &qgroups
);
1938 if (n
> 0) /* already parent qgroups set up, let's bail */
1941 qgroups
= mfree(qgroups
);
1943 r
= btrfs_subvol_get_parent(fd
, subvol_id
, &parent_subvol
);
1945 /* No parent, hence no qgroup memberships */
1950 n
= btrfs_qgroup_find_parents(fd
, parent_subvol
, &qgroups
);
1955 if (insert_intermediary_qgroup
) {
1956 uint64_t lowest
= 256, new_qgroupid
;
1957 bool created
= false;
1960 /* Determine the lowest qgroup that the parent
1961 * subvolume is assigned to. */
1963 for (i
= 0; i
< n
; i
++) {
1966 r
= btrfs_qgroupid_split(qgroups
[i
], &level
, NULL
);
1974 if (lowest
<= 1) /* There are no levels left we could use insert an intermediary qgroup at */
1977 r
= btrfs_qgroupid_make(lowest
- 1, subvol_id
, &new_qgroupid
);
1981 /* Create the new intermediary group, unless it already exists */
1982 r
= btrfs_qgroup_create(fd
, new_qgroupid
);
1983 if (r
< 0 && r
!= -EEXIST
)
1986 changed
= created
= true;
1988 for (i
= 0; i
< n
; i
++) {
1989 r
= btrfs_qgroup_assign(fd
, new_qgroupid
, qgroups
[i
]);
1990 if (r
< 0 && r
!= -EEXIST
) {
1992 (void) btrfs_qgroup_destroy_recursive(fd
, new_qgroupid
);
2000 r
= btrfs_qgroup_assign(fd
, subvol_id
, new_qgroupid
);
2001 if (r
< 0 && r
!= -EEXIST
) {
2003 (void) btrfs_qgroup_destroy_recursive(fd
, new_qgroupid
);
2012 /* Assign our subvolume to all the same qgroups as the parent */
2014 for (i
= 0; i
< n
; i
++) {
2015 r
= btrfs_qgroup_assign(fd
, subvol_id
, qgroups
[i
]);
2016 if (r
< 0 && r
!= -EEXIST
)
2026 int btrfs_subvol_auto_qgroup(const char *path
, uint64_t subvol_id
, bool create_intermediary_qgroup
) {
2027 _cleanup_close_
int fd
= -1;
2029 fd
= open(path
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
|O_DIRECTORY
);
2033 return btrfs_subvol_auto_qgroup_fd(fd
, subvol_id
, create_intermediary_qgroup
);
2036 int btrfs_subvol_get_parent(int fd
, uint64_t subvol_id
, uint64_t *ret
) {
2038 struct btrfs_ioctl_search_args args
= {
2039 /* Tree of tree roots */
2040 .key
.tree_id
= BTRFS_ROOT_TREE_OBJECTID
,
2042 /* Look precisely for the subvolume items */
2043 .key
.min_type
= BTRFS_ROOT_BACKREF_KEY
,
2044 .key
.max_type
= BTRFS_ROOT_BACKREF_KEY
,
2046 /* No restrictions on the other components */
2047 .key
.min_offset
= 0,
2048 .key
.max_offset
= (uint64_t) -1,
2050 .key
.min_transid
= 0,
2051 .key
.max_transid
= (uint64_t) -1,
2058 if (subvol_id
== 0) {
2059 r
= btrfs_subvol_get_id_fd(fd
, &subvol_id
);
2063 r
= btrfs_is_filesystem(fd
);
2070 args
.key
.min_objectid
= args
.key
.max_objectid
= subvol_id
;
2072 while (btrfs_ioctl_search_args_compare(&args
) <= 0) {
2073 const struct btrfs_ioctl_search_header
*sh
;
2076 args
.key
.nr_items
= 256;
2077 if (ioctl(fd
, BTRFS_IOC_TREE_SEARCH
, &args
) < 0)
2078 return negative_errno();
2080 if (args
.key
.nr_items
<= 0)
2083 FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i
, sh
, args
) {
2085 if (sh
->type
!= BTRFS_ROOT_BACKREF_KEY
)
2087 if (sh
->objectid
!= subvol_id
)