1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2014 Lennart Poettering
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.
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.
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/>.
25 #include <linux/loop.h>
30 #include <sys/ioctl.h>
32 #include <sys/statfs.h>
33 #include <sys/sysmacros.h>
36 #if HAVE_LINUX_BTRFS_H
37 #include <linux/btrfs.h>
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"
46 #include "device-nodes.h"
52 #include "path-util.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"
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. */
69 static int validate_subvolume_name(const char *name
) {
71 if (!filename_is_valid(name
))
74 if (strlen(name
) > BTRFS_SUBVOL_NAME_MAX
)
80 static int open_parent(const char *path
, int flags
) {
81 _cleanup_free_
char *parent
= NULL
;
86 parent
= dirname_malloc(path
);
90 fd
= open(parent
, flags
);
97 static int extract_subvolume_name(const char *path
, const char **subvolume
) {
106 r
= validate_subvolume_name(fn
);
114 int btrfs_is_filesystem(int fd
) {
119 if (fstatfs(fd
, &sfs
) < 0)
122 return F_TYPE_EQUAL(sfs
.f_type
, BTRFS_SUPER_MAGIC
);
125 int btrfs_is_subvol_fd(int fd
) {
130 /* On btrfs subvolumes always have the inode 256 */
132 if (fstat(fd
, &st
) < 0)
135 if (!S_ISDIR(st
.st_mode
) || st
.st_ino
!= 256)
138 return btrfs_is_filesystem(fd
);
141 int btrfs_is_subvol(const char *path
) {
142 _cleanup_close_
int fd
= -1;
146 fd
= open(path
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
|O_DIRECTORY
);
150 return btrfs_is_subvol_fd(fd
);
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
;
161 r
= extract_subvolume_name(path
, &subvolume
);
165 fd
= open_parent(path
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
|O_DIRECTORY
);
169 strncpy(args
.name
, subvolume
, sizeof(args
.name
)-1);
171 if (ioctl(fd
, BTRFS_IOC_SUBVOL_CREATE
, &args
) < 0)
177 int btrfs_subvol_set_read_only_fd(int fd
, bool b
) {
178 uint64_t flags
, nflags
;
183 if (fstat(fd
, &st
) < 0)
186 if (!S_ISDIR(st
.st_mode
) || st
.st_ino
!= 256)
189 if (ioctl(fd
, BTRFS_IOC_SUBVOL_GETFLAGS
, &flags
) < 0)
193 nflags
= flags
| BTRFS_SUBVOL_RDONLY
;
195 nflags
= flags
& ~BTRFS_SUBVOL_RDONLY
;
200 if (ioctl(fd
, BTRFS_IOC_SUBVOL_SETFLAGS
, &nflags
) < 0)
206 int btrfs_subvol_set_read_only(const char *path
, bool b
) {
207 _cleanup_close_
int fd
= -1;
209 fd
= open(path
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
|O_DIRECTORY
);
213 return btrfs_subvol_set_read_only_fd(fd
, b
);
216 int btrfs_subvol_get_read_only_fd(int fd
) {
222 if (fstat(fd
, &st
) < 0)
225 if (!S_ISDIR(st
.st_mode
) || st
.st_ino
!= 256)
228 if (ioctl(fd
, BTRFS_IOC_SUBVOL_GETFLAGS
, &flags
) < 0)
231 return !!(flags
& BTRFS_SUBVOL_RDONLY
);
234 int btrfs_reflink(int infd
, int outfd
) {
241 /* Make sure we invoke the ioctl on a regular file, so that no
242 * device driver accidentally gets it. */
244 if (fstat(outfd
, &st
) < 0)
247 if (!S_ISREG(st
.st_mode
))
250 r
= ioctl(outfd
, BTRFS_IOC_CLONE
, infd
);
257 int btrfs_clone_range(int infd
, uint64_t in_offset
, int outfd
, uint64_t out_offset
, uint64_t sz
) {
258 struct btrfs_ioctl_clone_range_args args
= {
260 .src_offset
= in_offset
,
262 .dest_offset
= out_offset
,
271 if (fstat(outfd
, &st
) < 0)
274 if (!S_ISREG(st
.st_mode
))
277 r
= ioctl(outfd
, BTRFS_IOC_CLONE_RANGE
, &args
);
284 int btrfs_get_block_device_fd(int fd
, dev_t
*dev
) {
285 struct btrfs_ioctl_fs_info_args fsi
= {};
292 r
= btrfs_is_filesystem(fd
);
298 if (ioctl(fd
, BTRFS_IOC_FS_INFO
, &fsi
) < 0)
301 /* We won't do this for btrfs RAID */
302 if (fsi
.num_devices
!= 1)
305 for (id
= 1; id
<= fsi
.max_id
; id
++) {
306 struct btrfs_ioctl_dev_info_args di
= {
311 if (ioctl(fd
, BTRFS_IOC_DEV_INFO
, &di
) < 0) {
318 if (stat((char*) di
.path
, &st
) < 0)
321 if (!S_ISBLK(st
.st_mode
))
324 if (major(st
.st_rdev
) == 0)
334 int btrfs_get_block_device(const char *path
, dev_t
*dev
) {
335 _cleanup_close_
int fd
= -1;
340 fd
= open(path
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
);
344 return btrfs_get_block_device_fd(fd
, dev
);
347 int btrfs_subvol_get_id_fd(int fd
, uint64_t *ret
) {
348 struct btrfs_ioctl_ino_lookup_args args
= {
349 .objectid
= BTRFS_FIRST_FREE_OBJECTID
356 r
= btrfs_is_filesystem(fd
);
362 if (ioctl(fd
, BTRFS_IOC_INO_LOOKUP
, &args
) < 0)
369 int btrfs_subvol_get_id(int fd
, const char *subvol
, uint64_t *ret
) {
370 _cleanup_close_
int subvol_fd
= -1;
375 subvol_fd
= openat(fd
, subvol
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
|O_NOFOLLOW
);
379 return btrfs_subvol_get_id_fd(subvol_fd
, ret
);
382 static bool btrfs_ioctl_search_args_inc(struct btrfs_ioctl_search_args
*args
) {
385 /* the objectid, type, offset together make up the btrfs key,
386 * which is considered a single 136byte integer when
387 * comparing. This call increases the counter by one, dealing
388 * with the overflow between the overflows */
390 if (args
->key
.min_offset
< (uint64_t) -1) {
391 args
->key
.min_offset
++;
395 if (args
->key
.min_type
< (uint8_t) -1) {
396 args
->key
.min_type
++;
397 args
->key
.min_offset
= 0;
401 if (args
->key
.min_objectid
< (uint64_t) -1) {
402 args
->key
.min_objectid
++;
403 args
->key
.min_offset
= 0;
404 args
->key
.min_type
= 0;
411 static void btrfs_ioctl_search_args_set(struct btrfs_ioctl_search_args
*args
, const struct btrfs_ioctl_search_header
*h
) {
415 args
->key
.min_objectid
= h
->objectid
;
416 args
->key
.min_type
= h
->type
;
417 args
->key
.min_offset
= h
->offset
;
420 static int btrfs_ioctl_search_args_compare(const struct btrfs_ioctl_search_args
*args
) {
423 /* Compare min and max */
425 if (args
->key
.min_objectid
< args
->key
.max_objectid
)
427 if (args
->key
.min_objectid
> args
->key
.max_objectid
)
430 if (args
->key
.min_type
< args
->key
.max_type
)
432 if (args
->key
.min_type
> args
->key
.max_type
)
435 if (args
->key
.min_offset
< args
->key
.max_offset
)
437 if (args
->key
.min_offset
> args
->key
.max_offset
)
443 #define FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i, sh, args) \
445 (sh) = (const struct btrfs_ioctl_search_header*) (args).buf; \
446 (i) < (args).key.nr_items; \
448 (sh) = (const struct btrfs_ioctl_search_header*) ((uint8_t*) (sh) + sizeof(struct btrfs_ioctl_search_header) + (sh)->len))
450 #define BTRFS_IOCTL_SEARCH_HEADER_BODY(sh) \
451 ((void*) ((uint8_t*) sh + sizeof(struct btrfs_ioctl_search_header)))
453 int btrfs_subvol_get_info_fd(int fd
, uint64_t subvol_id
, BtrfsSubvolInfo
*ret
) {
454 struct btrfs_ioctl_search_args args
= {
455 /* Tree of tree roots */
456 .key
.tree_id
= BTRFS_ROOT_TREE_OBJECTID
,
458 /* Look precisely for the subvolume items */
459 .key
.min_type
= BTRFS_ROOT_ITEM_KEY
,
460 .key
.max_type
= BTRFS_ROOT_ITEM_KEY
,
463 .key
.max_offset
= (uint64_t) -1,
465 /* No restrictions on the other components */
466 .key
.min_transid
= 0,
467 .key
.max_transid
= (uint64_t) -1,
476 if (subvol_id
== 0) {
477 r
= btrfs_subvol_get_id_fd(fd
, &subvol_id
);
481 r
= btrfs_is_filesystem(fd
);
488 args
.key
.min_objectid
= args
.key
.max_objectid
= subvol_id
;
490 while (btrfs_ioctl_search_args_compare(&args
) <= 0) {
491 const struct btrfs_ioctl_search_header
*sh
;
494 args
.key
.nr_items
= 256;
495 if (ioctl(fd
, BTRFS_IOC_TREE_SEARCH
, &args
) < 0)
498 if (args
.key
.nr_items
<= 0)
501 FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i
, sh
, args
) {
503 const struct btrfs_root_item
*ri
;
505 /* Make sure we start the next search at least from this entry */
506 btrfs_ioctl_search_args_set(&args
, sh
);
508 if (sh
->objectid
!= subvol_id
)
510 if (sh
->type
!= BTRFS_ROOT_ITEM_KEY
)
513 /* Older versions of the struct lacked the otime setting */
514 if (sh
->len
< offsetof(struct btrfs_root_item
, otime
) + sizeof(struct btrfs_timespec
))
517 ri
= BTRFS_IOCTL_SEARCH_HEADER_BODY(sh
);
519 ret
->otime
= (usec_t
) le64toh(ri
->otime
.sec
) * USEC_PER_SEC
+
520 (usec_t
) le32toh(ri
->otime
.nsec
) / NSEC_PER_USEC
;
522 ret
->subvol_id
= subvol_id
;
523 ret
->read_only
= !!(le64toh(ri
->flags
) & BTRFS_ROOT_SUBVOL_RDONLY
);
525 assert_cc(sizeof(ri
->uuid
) == sizeof(ret
->uuid
));
526 memcpy(&ret
->uuid
, ri
->uuid
, sizeof(ret
->uuid
));
527 memcpy(&ret
->parent_uuid
, ri
->parent_uuid
, sizeof(ret
->parent_uuid
));
533 /* Increase search key by one, to read the next item, if we can. */
534 if (!btrfs_ioctl_search_args_inc(&args
))
545 int btrfs_qgroup_get_quota_fd(int fd
, uint64_t qgroupid
, BtrfsQuotaInfo
*ret
) {
547 struct btrfs_ioctl_search_args args
= {
548 /* Tree of quota items */
549 .key
.tree_id
= BTRFS_QUOTA_TREE_OBJECTID
,
551 /* The object ID is always 0 */
552 .key
.min_objectid
= 0,
553 .key
.max_objectid
= 0,
555 /* Look precisely for the quota items */
556 .key
.min_type
= BTRFS_QGROUP_STATUS_KEY
,
557 .key
.max_type
= BTRFS_QGROUP_LIMIT_KEY
,
559 /* No restrictions on the other components */
560 .key
.min_transid
= 0,
561 .key
.max_transid
= (uint64_t) -1,
564 bool found_info
= false, found_limit
= false;
571 r
= btrfs_subvol_get_id_fd(fd
, &qgroupid
);
575 r
= btrfs_is_filesystem(fd
);
582 args
.key
.min_offset
= args
.key
.max_offset
= qgroupid
;
584 while (btrfs_ioctl_search_args_compare(&args
) <= 0) {
585 const struct btrfs_ioctl_search_header
*sh
;
588 args
.key
.nr_items
= 256;
589 if (ioctl(fd
, BTRFS_IOC_TREE_SEARCH
, &args
) < 0) {
590 if (errno
== ENOENT
) /* quota tree is missing: quota disabled */
596 if (args
.key
.nr_items
<= 0)
599 FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i
, sh
, args
) {
601 /* Make sure we start the next search at least from this entry */
602 btrfs_ioctl_search_args_set(&args
, sh
);
604 if (sh
->objectid
!= 0)
606 if (sh
->offset
!= qgroupid
)
609 if (sh
->type
== BTRFS_QGROUP_INFO_KEY
) {
610 const struct btrfs_qgroup_info_item
*qii
= BTRFS_IOCTL_SEARCH_HEADER_BODY(sh
);
612 ret
->referenced
= le64toh(qii
->rfer
);
613 ret
->exclusive
= le64toh(qii
->excl
);
617 } else if (sh
->type
== BTRFS_QGROUP_LIMIT_KEY
) {
618 const struct btrfs_qgroup_limit_item
*qli
= BTRFS_IOCTL_SEARCH_HEADER_BODY(sh
);
620 if (le64toh(qli
->flags
) & BTRFS_QGROUP_LIMIT_MAX_RFER
)
621 ret
->referenced_max
= le64toh(qli
->max_rfer
);
623 ret
->referenced_max
= (uint64_t) -1;
625 if (le64toh(qli
->flags
) & BTRFS_QGROUP_LIMIT_MAX_EXCL
)
626 ret
->exclusive_max
= le64toh(qli
->max_excl
);
628 ret
->exclusive_max
= (uint64_t) -1;
633 if (found_info
&& found_limit
)
637 /* Increase search key by one, to read the next item, if we can. */
638 if (!btrfs_ioctl_search_args_inc(&args
))
643 if (!found_limit
&& !found_info
)
647 ret
->referenced
= (uint64_t) -1;
648 ret
->exclusive
= (uint64_t) -1;
652 ret
->referenced_max
= (uint64_t) -1;
653 ret
->exclusive_max
= (uint64_t) -1;
659 int btrfs_qgroup_get_quota(const char *path
, uint64_t qgroupid
, BtrfsQuotaInfo
*ret
) {
660 _cleanup_close_
int fd
= -1;
662 fd
= open(path
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
|O_NOFOLLOW
);
666 return btrfs_qgroup_get_quota_fd(fd
, qgroupid
, ret
);
669 int btrfs_subvol_find_subtree_qgroup(int fd
, uint64_t subvol_id
, uint64_t *ret
) {
670 uint64_t level
, lowest
= (uint64_t) -1, lowest_qgroupid
= 0;
671 _cleanup_free_
uint64_t *qgroups
= NULL
;
677 /* This finds the "subtree" qgroup for a specific
678 * subvolume. This only works for subvolumes that have been
679 * prepared with btrfs_subvol_auto_qgroup_fd() with
680 * insert_intermediary_qgroup=true (or equivalent). For others
681 * it will return the leaf qgroup instead. The two cases may
682 * be distuingished via the return value, which is 1 in case
683 * an appropriate "subtree" qgroup was found, and 0
686 if (subvol_id
== 0) {
687 r
= btrfs_subvol_get_id_fd(fd
, &subvol_id
);
692 r
= btrfs_qgroupid_split(subvol_id
, &level
, NULL
);
695 if (level
!= 0) /* Input must be a leaf qgroup */
698 n
= btrfs_qgroup_find_parents(fd
, subvol_id
, &qgroups
);
702 for (i
= 0; i
< n
; i
++) {
705 r
= btrfs_qgroupid_split(qgroups
[i
], &level
, &id
);
712 if (lowest
== (uint64_t) -1 || level
< lowest
) {
713 lowest_qgroupid
= qgroups
[i
];
718 if (lowest
== (uint64_t) -1) {
719 /* No suitable higher-level qgroup found, let's return
720 * the leaf qgroup instead, and indicate that with the
727 *ret
= lowest_qgroupid
;
731 int btrfs_subvol_get_subtree_quota_fd(int fd
, uint64_t subvol_id
, BtrfsQuotaInfo
*ret
) {
738 /* This determines the quota data of the qgroup with the
739 * lowest level, that shares the id part with the specified
740 * subvolume. This is useful for determining the quota data
741 * for entire subvolume subtrees, as long as the subtrees have
742 * been set up with btrfs_qgroup_subvol_auto_fd() or in a
745 r
= btrfs_subvol_find_subtree_qgroup(fd
, subvol_id
, &qgroupid
);
749 return btrfs_qgroup_get_quota_fd(fd
, qgroupid
, ret
);
752 int btrfs_subvol_get_subtree_quota(const char *path
, uint64_t subvol_id
, BtrfsQuotaInfo
*ret
) {
753 _cleanup_close_
int fd
= -1;
755 fd
= open(path
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
|O_NOFOLLOW
);
759 return btrfs_subvol_get_subtree_quota_fd(fd
, subvol_id
, ret
);
762 int btrfs_defrag_fd(int fd
) {
767 if (fstat(fd
, &st
) < 0)
770 if (!S_ISREG(st
.st_mode
))
773 if (ioctl(fd
, BTRFS_IOC_DEFRAG
, NULL
) < 0)
779 int btrfs_defrag(const char *p
) {
780 _cleanup_close_
int fd
= -1;
782 fd
= open(p
, O_RDWR
|O_CLOEXEC
|O_NOCTTY
|O_NOFOLLOW
);
786 return btrfs_defrag_fd(fd
);
789 int btrfs_quota_enable_fd(int fd
, bool b
) {
790 struct btrfs_ioctl_quota_ctl_args args
= {
791 .cmd
= b
? BTRFS_QUOTA_CTL_ENABLE
: BTRFS_QUOTA_CTL_DISABLE
,
797 r
= btrfs_is_filesystem(fd
);
803 if (ioctl(fd
, BTRFS_IOC_QUOTA_CTL
, &args
) < 0)
809 int btrfs_quota_enable(const char *path
, bool b
) {
810 _cleanup_close_
int fd
= -1;
812 fd
= open(path
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
|O_NOFOLLOW
);
816 return btrfs_quota_enable_fd(fd
, b
);
819 int btrfs_qgroup_set_limit_fd(int fd
, uint64_t qgroupid
, uint64_t referenced_max
) {
821 struct btrfs_ioctl_qgroup_limit_args args
= {
822 .lim
.max_rfer
= referenced_max
,
823 .lim
.flags
= BTRFS_QGROUP_LIMIT_MAX_RFER
,
831 r
= btrfs_subvol_get_id_fd(fd
, &qgroupid
);
835 r
= btrfs_is_filesystem(fd
);
842 args
.qgroupid
= qgroupid
;
845 if (ioctl(fd
, BTRFS_IOC_QGROUP_LIMIT
, &args
) < 0) {
847 if (errno
== EBUSY
&& c
< 10) {
848 (void) btrfs_quota_scan_wait(fd
);
861 int btrfs_qgroup_set_limit(const char *path
, uint64_t qgroupid
, uint64_t referenced_max
) {
862 _cleanup_close_
int fd
= -1;
864 fd
= open(path
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
|O_NOFOLLOW
);
868 return btrfs_qgroup_set_limit_fd(fd
, qgroupid
, referenced_max
);
871 int btrfs_subvol_set_subtree_quota_limit_fd(int fd
, uint64_t subvol_id
, uint64_t referenced_max
) {
877 r
= btrfs_subvol_find_subtree_qgroup(fd
, subvol_id
, &qgroupid
);
881 return btrfs_qgroup_set_limit_fd(fd
, qgroupid
, referenced_max
);
884 int btrfs_subvol_set_subtree_quota_limit(const char *path
, uint64_t subvol_id
, uint64_t referenced_max
) {
885 _cleanup_close_
int fd
= -1;
887 fd
= open(path
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
|O_NOFOLLOW
);
891 return btrfs_subvol_set_subtree_quota_limit_fd(fd
, subvol_id
, referenced_max
);
894 int btrfs_resize_loopback_fd(int fd
, uint64_t new_size
, bool grow_only
) {
895 struct btrfs_ioctl_vol_args args
= {};
896 char p
[SYS_BLOCK_PATH_MAX("/loop/backing_file")];
897 _cleanup_free_
char *backing
= NULL
;
898 _cleanup_close_
int loop_fd
= -1, backing_fd
= -1;
903 /* In contrast to btrfs quota ioctls ftruncate() cannot make sense of "infinity" or file sizes > 2^31 */
904 if (!FILE_SIZE_VALID(new_size
))
907 /* btrfs cannot handle file systems < 16M, hence use this as minimum */
908 if (new_size
< 16*1024*1024)
909 new_size
= 16*1024*1024;
911 r
= btrfs_get_block_device_fd(fd
, &dev
);
917 xsprintf_sys_block_path(p
, "/loop/backing_file", dev
);
918 r
= read_one_line_file(p
, &backing
);
923 if (isempty(backing
) || !path_is_absolute(backing
))
926 backing_fd
= open(backing
, O_RDWR
|O_CLOEXEC
|O_NOCTTY
);
930 if (fstat(backing_fd
, &st
) < 0)
932 if (!S_ISREG(st
.st_mode
))
935 if (new_size
== (uint64_t) st
.st_size
)
938 if (grow_only
&& new_size
< (uint64_t) st
.st_size
)
941 xsprintf_sys_block_path(p
, NULL
, dev
);
942 loop_fd
= open(p
, O_RDWR
|O_CLOEXEC
|O_NOCTTY
);
946 if (snprintf(args
.name
, sizeof(args
.name
), "%" PRIu64
, new_size
) >= (int) sizeof(args
.name
))
949 if (new_size
< (uint64_t) st
.st_size
) {
950 /* Decrease size: first decrease btrfs size, then shorten loopback */
951 if (ioctl(fd
, BTRFS_IOC_RESIZE
, &args
) < 0)
955 if (ftruncate(backing_fd
, new_size
) < 0)
958 if (ioctl(loop_fd
, LOOP_SET_CAPACITY
, 0) < 0)
961 if (new_size
> (uint64_t) st
.st_size
) {
962 /* Increase size: first enlarge loopback, then increase btrfs size */
963 if (ioctl(fd
, BTRFS_IOC_RESIZE
, &args
) < 0)
967 /* Make sure the free disk space is correctly updated for both file systems */
969 (void) fsync(backing_fd
);
974 int btrfs_resize_loopback(const char *p
, uint64_t new_size
, bool grow_only
) {
975 _cleanup_close_
int fd
= -1;
977 fd
= open(p
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
);
981 return btrfs_resize_loopback_fd(fd
, new_size
, grow_only
);
984 int btrfs_qgroupid_make(uint64_t level
, uint64_t id
, uint64_t *ret
) {
987 if (level
>= (UINT64_C(1) << (64 - BTRFS_QGROUP_LEVEL_SHIFT
)))
990 if (id
>= (UINT64_C(1) << BTRFS_QGROUP_LEVEL_SHIFT
))
993 *ret
= (level
<< BTRFS_QGROUP_LEVEL_SHIFT
) | id
;
997 int btrfs_qgroupid_split(uint64_t qgroupid
, uint64_t *level
, uint64_t *id
) {
1001 *level
= qgroupid
>> BTRFS_QGROUP_LEVEL_SHIFT
;
1004 *id
= qgroupid
& ((UINT64_C(1) << BTRFS_QGROUP_LEVEL_SHIFT
) - 1);
1009 static int qgroup_create_or_destroy(int fd
, bool b
, uint64_t qgroupid
) {
1011 struct btrfs_ioctl_qgroup_create_args args
= {
1013 .qgroupid
= qgroupid
,
1018 r
= btrfs_is_filesystem(fd
);
1025 if (ioctl(fd
, BTRFS_IOC_QGROUP_CREATE
, &args
) < 0) {
1027 /* If quota is not enabled, we get EINVAL. Turn this into a recognizable error */
1028 if (errno
== EINVAL
)
1029 return -ENOPROTOOPT
;
1031 if (errno
== EBUSY
&& c
< 10) {
1032 (void) btrfs_quota_scan_wait(fd
);
1045 int btrfs_qgroup_create(int fd
, uint64_t qgroupid
) {
1046 return qgroup_create_or_destroy(fd
, true, qgroupid
);
1049 int btrfs_qgroup_destroy(int fd
, uint64_t qgroupid
) {
1050 return qgroup_create_or_destroy(fd
, false, qgroupid
);
1053 int btrfs_qgroup_destroy_recursive(int fd
, uint64_t qgroupid
) {
1054 _cleanup_free_
uint64_t *qgroups
= NULL
;
1058 /* Destroys the specified qgroup, but unassigns it from all
1059 * its parents first. Also, it recursively destroys all
1060 * qgroups it is assgined to that have the same id part of the
1061 * qgroupid as the specified group. */
1063 r
= btrfs_qgroupid_split(qgroupid
, NULL
, &subvol_id
);
1067 n
= btrfs_qgroup_find_parents(fd
, qgroupid
, &qgroups
);
1071 for (i
= 0; i
< n
; i
++) {
1074 r
= btrfs_qgroupid_split(qgroups
[i
], NULL
, &id
);
1078 r
= btrfs_qgroup_unassign(fd
, qgroupid
, qgroups
[i
]);
1082 if (id
!= subvol_id
)
1085 /* The parent qgroupid shares the same id part with
1086 * us? If so, destroy it too. */
1088 (void) btrfs_qgroup_destroy_recursive(fd
, qgroups
[i
]);
1091 return btrfs_qgroup_destroy(fd
, qgroupid
);
1094 int btrfs_quota_scan_start(int fd
) {
1095 struct btrfs_ioctl_quota_rescan_args args
= {};
1099 if (ioctl(fd
, BTRFS_IOC_QUOTA_RESCAN
, &args
) < 0)
1105 int btrfs_quota_scan_wait(int fd
) {
1108 if (ioctl(fd
, BTRFS_IOC_QUOTA_RESCAN_WAIT
) < 0)
1114 int btrfs_quota_scan_ongoing(int fd
) {
1115 struct btrfs_ioctl_quota_rescan_args args
= {};
1119 if (ioctl(fd
, BTRFS_IOC_QUOTA_RESCAN_STATUS
, &args
) < 0)
1122 return !!args
.flags
;
1125 static int qgroup_assign_or_unassign(int fd
, bool b
, uint64_t child
, uint64_t parent
) {
1126 struct btrfs_ioctl_qgroup_assign_args args
= {
1134 r
= btrfs_is_filesystem(fd
);
1141 r
= ioctl(fd
, BTRFS_IOC_QGROUP_ASSIGN
, &args
);
1143 if (errno
== EBUSY
&& c
< 10) {
1144 (void) btrfs_quota_scan_wait(fd
);
1154 /* If the return value is > 0, we need to request a rescan */
1156 (void) btrfs_quota_scan_start(fd
);
1161 int btrfs_qgroup_assign(int fd
, uint64_t child
, uint64_t parent
) {
1162 return qgroup_assign_or_unassign(fd
, true, child
, parent
);
1165 int btrfs_qgroup_unassign(int fd
, uint64_t child
, uint64_t parent
) {
1166 return qgroup_assign_or_unassign(fd
, false, child
, parent
);
1169 static int subvol_remove_children(int fd
, const char *subvolume
, uint64_t subvol_id
, BtrfsRemoveFlags flags
) {
1170 struct btrfs_ioctl_search_args args
= {
1171 .key
.tree_id
= BTRFS_ROOT_TREE_OBJECTID
,
1173 .key
.min_objectid
= BTRFS_FIRST_FREE_OBJECTID
,
1174 .key
.max_objectid
= BTRFS_LAST_FREE_OBJECTID
,
1176 .key
.min_type
= BTRFS_ROOT_BACKREF_KEY
,
1177 .key
.max_type
= BTRFS_ROOT_BACKREF_KEY
,
1179 .key
.min_transid
= 0,
1180 .key
.max_transid
= (uint64_t) -1,
1183 struct btrfs_ioctl_vol_args vol_args
= {};
1184 _cleanup_close_
int subvol_fd
= -1;
1186 bool made_writable
= false;
1192 if (fstat(fd
, &st
) < 0)
1195 if (!S_ISDIR(st
.st_mode
))
1198 subvol_fd
= openat(fd
, subvolume
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
|O_DIRECTORY
|O_NOFOLLOW
);
1202 if (subvol_id
== 0) {
1203 r
= btrfs_subvol_get_id_fd(subvol_fd
, &subvol_id
);
1208 /* First, try to remove the subvolume. If it happens to be
1209 * already empty, this will just work. */
1210 strncpy(vol_args
.name
, subvolume
, sizeof(vol_args
.name
)-1);
1211 if (ioctl(fd
, BTRFS_IOC_SNAP_DESTROY
, &vol_args
) >= 0) {
1212 (void) btrfs_qgroup_destroy_recursive(fd
, subvol_id
); /* for the leaf subvolumes, the qgroup id is identical to the subvol id */
1215 if (!(flags
& BTRFS_REMOVE_RECURSIVE
) || errno
!= ENOTEMPTY
)
1218 /* OK, the subvolume is not empty, let's look for child
1219 * subvolumes, and remove them, first */
1221 args
.key
.min_offset
= args
.key
.max_offset
= subvol_id
;
1223 while (btrfs_ioctl_search_args_compare(&args
) <= 0) {
1224 const struct btrfs_ioctl_search_header
*sh
;
1227 args
.key
.nr_items
= 256;
1228 if (ioctl(fd
, BTRFS_IOC_TREE_SEARCH
, &args
) < 0)
1231 if (args
.key
.nr_items
<= 0)
1234 FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i
, sh
, args
) {
1235 _cleanup_free_
char *p
= NULL
;
1236 const struct btrfs_root_ref
*ref
;
1237 struct btrfs_ioctl_ino_lookup_args ino_args
;
1239 btrfs_ioctl_search_args_set(&args
, sh
);
1241 if (sh
->type
!= BTRFS_ROOT_BACKREF_KEY
)
1243 if (sh
->offset
!= subvol_id
)
1246 ref
= BTRFS_IOCTL_SEARCH_HEADER_BODY(sh
);
1248 p
= strndup((char*) ref
+ sizeof(struct btrfs_root_ref
), le64toh(ref
->name_len
));
1253 ino_args
.treeid
= subvol_id
;
1254 ino_args
.objectid
= htole64(ref
->dirid
);
1256 if (ioctl(fd
, BTRFS_IOC_INO_LOOKUP
, &ino_args
) < 0)
1259 if (!made_writable
) {
1260 r
= btrfs_subvol_set_read_only_fd(subvol_fd
, false);
1264 made_writable
= true;
1267 if (isempty(ino_args
.name
))
1268 /* Subvolume is in the top-level
1269 * directory of the subvolume. */
1270 r
= subvol_remove_children(subvol_fd
, p
, sh
->objectid
, flags
);
1272 _cleanup_close_
int child_fd
= -1;
1274 /* Subvolume is somewhere further down,
1275 * hence we need to open the
1276 * containing directory first */
1278 child_fd
= openat(subvol_fd
, ino_args
.name
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
|O_DIRECTORY
|O_NOFOLLOW
);
1282 r
= subvol_remove_children(child_fd
, p
, sh
->objectid
, flags
);
1288 /* Increase search key by one, to read the next item, if we can. */
1289 if (!btrfs_ioctl_search_args_inc(&args
))
1293 /* OK, the child subvolumes should all be gone now, let's try
1294 * again to remove the subvolume */
1295 if (ioctl(fd
, BTRFS_IOC_SNAP_DESTROY
, &vol_args
) < 0)
1298 (void) btrfs_qgroup_destroy_recursive(fd
, subvol_id
);
1302 int btrfs_subvol_remove(const char *path
, BtrfsRemoveFlags flags
) {
1303 _cleanup_close_
int fd
= -1;
1304 const char *subvolume
;
1309 r
= extract_subvolume_name(path
, &subvolume
);
1313 fd
= open_parent(path
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
|O_DIRECTORY
);
1317 return subvol_remove_children(fd
, subvolume
, 0, flags
);
1320 int btrfs_subvol_remove_fd(int fd
, const char *subvolume
, BtrfsRemoveFlags flags
) {
1321 return subvol_remove_children(fd
, subvolume
, 0, flags
);
1324 int btrfs_qgroup_copy_limits(int fd
, uint64_t old_qgroupid
, uint64_t new_qgroupid
) {
1326 struct btrfs_ioctl_search_args args
= {
1327 /* Tree of quota items */
1328 .key
.tree_id
= BTRFS_QUOTA_TREE_OBJECTID
,
1330 /* The object ID is always 0 */
1331 .key
.min_objectid
= 0,
1332 .key
.max_objectid
= 0,
1334 /* Look precisely for the quota items */
1335 .key
.min_type
= BTRFS_QGROUP_LIMIT_KEY
,
1336 .key
.max_type
= BTRFS_QGROUP_LIMIT_KEY
,
1338 /* For our qgroup */
1339 .key
.min_offset
= old_qgroupid
,
1340 .key
.max_offset
= old_qgroupid
,
1342 /* No restrictions on the other components */
1343 .key
.min_transid
= 0,
1344 .key
.max_transid
= (uint64_t) -1,
1349 r
= btrfs_is_filesystem(fd
);
1355 while (btrfs_ioctl_search_args_compare(&args
) <= 0) {
1356 const struct btrfs_ioctl_search_header
*sh
;
1359 args
.key
.nr_items
= 256;
1360 if (ioctl(fd
, BTRFS_IOC_TREE_SEARCH
, &args
) < 0) {
1361 if (errno
== ENOENT
) /* quota tree missing: quota is not enabled, hence nothing to copy */
1367 if (args
.key
.nr_items
<= 0)
1370 FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i
, sh
, args
) {
1371 const struct btrfs_qgroup_limit_item
*qli
= BTRFS_IOCTL_SEARCH_HEADER_BODY(sh
);
1372 struct btrfs_ioctl_qgroup_limit_args qargs
;
1375 /* Make sure we start the next search at least from this entry */
1376 btrfs_ioctl_search_args_set(&args
, sh
);
1378 if (sh
->objectid
!= 0)
1380 if (sh
->type
!= BTRFS_QGROUP_LIMIT_KEY
)
1382 if (sh
->offset
!= old_qgroupid
)
1385 /* We found the entry, now copy things over. */
1387 qargs
= (struct btrfs_ioctl_qgroup_limit_args
) {
1388 .qgroupid
= new_qgroupid
,
1390 .lim
.max_rfer
= le64toh(qli
->max_rfer
),
1391 .lim
.max_excl
= le64toh(qli
->max_excl
),
1392 .lim
.rsv_rfer
= le64toh(qli
->rsv_rfer
),
1393 .lim
.rsv_excl
= le64toh(qli
->rsv_excl
),
1395 .lim
.flags
= le64toh(qli
->flags
) & (BTRFS_QGROUP_LIMIT_MAX_RFER
|
1396 BTRFS_QGROUP_LIMIT_MAX_EXCL
|
1397 BTRFS_QGROUP_LIMIT_RSV_RFER
|
1398 BTRFS_QGROUP_LIMIT_RSV_EXCL
),
1402 if (ioctl(fd
, BTRFS_IOC_QGROUP_LIMIT
, &qargs
) < 0) {
1403 if (errno
== EBUSY
&& c
< 10) {
1404 (void) btrfs_quota_scan_wait(fd
);
1416 /* Increase search key by one, to read the next item, if we can. */
1417 if (!btrfs_ioctl_search_args_inc(&args
))
1424 static int copy_quota_hierarchy(int fd
, uint64_t old_subvol_id
, uint64_t new_subvol_id
) {
1425 _cleanup_free_
uint64_t *old_qgroups
= NULL
, *old_parent_qgroups
= NULL
;
1426 bool copy_from_parent
= false, insert_intermediary_qgroup
= false;
1427 int n_old_qgroups
, n_old_parent_qgroups
, r
, i
;
1428 uint64_t old_parent_id
;
1432 /* Copies a reduced form of quota information from the old to
1433 * the new subvolume. */
1435 n_old_qgroups
= btrfs_qgroup_find_parents(fd
, old_subvol_id
, &old_qgroups
);
1436 if (n_old_qgroups
<= 0) /* Nothing to copy */
1437 return n_old_qgroups
;
1439 r
= btrfs_subvol_get_parent(fd
, old_subvol_id
, &old_parent_id
);
1441 /* We have no parent, hence nothing to copy. */
1442 n_old_parent_qgroups
= 0;
1446 n_old_parent_qgroups
= btrfs_qgroup_find_parents(fd
, old_parent_id
, &old_parent_qgroups
);
1447 if (n_old_parent_qgroups
< 0)
1448 return n_old_parent_qgroups
;
1451 for (i
= 0; i
< n_old_qgroups
; i
++) {
1455 r
= btrfs_qgroupid_split(old_qgroups
[i
], NULL
, &id
);
1459 if (id
== old_subvol_id
) {
1460 /* The old subvolume was member of a qgroup
1461 * that had the same id, but a different level
1462 * as it self. Let's set up something similar
1463 * in the destination. */
1464 insert_intermediary_qgroup
= true;
1468 for (j
= 0; j
< n_old_parent_qgroups
; j
++)
1469 if (old_parent_qgroups
[j
] == old_qgroups
[i
]) {
1470 /* The old subvolume shared a common
1471 * parent qgroup with its parent
1472 * subvolume. Let's set up something
1473 * similar in the destination. */
1474 copy_from_parent
= true;
1478 if (!insert_intermediary_qgroup
&& !copy_from_parent
)
1481 return btrfs_subvol_auto_qgroup_fd(fd
, new_subvol_id
, insert_intermediary_qgroup
);
1484 static int copy_subtree_quota_limits(int fd
, uint64_t old_subvol
, uint64_t new_subvol
) {
1485 uint64_t old_subtree_qgroup
, new_subtree_qgroup
;
1489 /* First copy the leaf limits */
1490 r
= btrfs_qgroup_copy_limits(fd
, old_subvol
, new_subvol
);
1495 /* Then, try to copy the subtree limits, if there are any. */
1496 r
= btrfs_subvol_find_subtree_qgroup(fd
, old_subvol
, &old_subtree_qgroup
);
1502 r
= btrfs_subvol_find_subtree_qgroup(fd
, new_subvol
, &new_subtree_qgroup
);
1508 r
= btrfs_qgroup_copy_limits(fd
, old_subtree_qgroup
, new_subtree_qgroup
);
1515 static int subvol_snapshot_children(int old_fd
, int new_fd
, const char *subvolume
, uint64_t old_subvol_id
, BtrfsSnapshotFlags flags
) {
1517 struct btrfs_ioctl_search_args args
= {
1518 .key
.tree_id
= BTRFS_ROOT_TREE_OBJECTID
,
1520 .key
.min_objectid
= BTRFS_FIRST_FREE_OBJECTID
,
1521 .key
.max_objectid
= BTRFS_LAST_FREE_OBJECTID
,
1523 .key
.min_type
= BTRFS_ROOT_BACKREF_KEY
,
1524 .key
.max_type
= BTRFS_ROOT_BACKREF_KEY
,
1526 .key
.min_transid
= 0,
1527 .key
.max_transid
= (uint64_t) -1,
1530 struct btrfs_ioctl_vol_args_v2 vol_args
= {
1531 .flags
= flags
& BTRFS_SNAPSHOT_READ_ONLY
? BTRFS_SUBVOL_RDONLY
: 0,
1534 _cleanup_close_
int subvolume_fd
= -1;
1535 uint64_t new_subvol_id
;
1538 assert(old_fd
>= 0);
1539 assert(new_fd
>= 0);
1542 strncpy(vol_args
.name
, subvolume
, sizeof(vol_args
.name
)-1);
1544 if (ioctl(new_fd
, BTRFS_IOC_SNAP_CREATE_V2
, &vol_args
) < 0)
1547 if (!(flags
& BTRFS_SNAPSHOT_RECURSIVE
) &&
1548 !(flags
& BTRFS_SNAPSHOT_QUOTA
))
1551 if (old_subvol_id
== 0) {
1552 r
= btrfs_subvol_get_id_fd(old_fd
, &old_subvol_id
);
1557 r
= btrfs_subvol_get_id(new_fd
, vol_args
.name
, &new_subvol_id
);
1561 if (flags
& BTRFS_SNAPSHOT_QUOTA
)
1562 (void) copy_quota_hierarchy(new_fd
, old_subvol_id
, new_subvol_id
);
1564 if (!(flags
& BTRFS_SNAPSHOT_RECURSIVE
)) {
1566 if (flags
& BTRFS_SNAPSHOT_QUOTA
)
1567 (void) copy_subtree_quota_limits(new_fd
, old_subvol_id
, new_subvol_id
);
1572 args
.key
.min_offset
= args
.key
.max_offset
= old_subvol_id
;
1574 while (btrfs_ioctl_search_args_compare(&args
) <= 0) {
1575 const struct btrfs_ioctl_search_header
*sh
;
1578 args
.key
.nr_items
= 256;
1579 if (ioctl(old_fd
, BTRFS_IOC_TREE_SEARCH
, &args
) < 0)
1582 if (args
.key
.nr_items
<= 0)
1585 FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i
, sh
, args
) {
1586 _cleanup_free_
char *p
= NULL
, *c
= NULL
, *np
= NULL
;
1587 struct btrfs_ioctl_ino_lookup_args ino_args
;
1588 const struct btrfs_root_ref
*ref
;
1589 _cleanup_close_
int old_child_fd
= -1, new_child_fd
= -1;
1591 btrfs_ioctl_search_args_set(&args
, sh
);
1593 if (sh
->type
!= BTRFS_ROOT_BACKREF_KEY
)
1596 /* Avoid finding the source subvolume a second
1598 if (sh
->offset
!= old_subvol_id
)
1601 /* Avoid running into loops if the new
1602 * subvolume is below the old one. */
1603 if (sh
->objectid
== new_subvol_id
)
1606 ref
= BTRFS_IOCTL_SEARCH_HEADER_BODY(sh
);
1607 p
= strndup((char*) ref
+ sizeof(struct btrfs_root_ref
), le64toh(ref
->name_len
));
1612 ino_args
.treeid
= old_subvol_id
;
1613 ino_args
.objectid
= htole64(ref
->dirid
);
1615 if (ioctl(old_fd
, BTRFS_IOC_INO_LOOKUP
, &ino_args
) < 0)
1618 /* The kernel returns an empty name if the
1619 * subvolume is in the top-level directory,
1620 * and otherwise appends a slash, so that we
1621 * can just concatenate easily here, without
1622 * adding a slash. */
1623 c
= strappend(ino_args
.name
, p
);
1627 old_child_fd
= openat(old_fd
, c
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
|O_DIRECTORY
|O_NOFOLLOW
);
1628 if (old_child_fd
< 0)
1631 np
= strjoin(subvolume
, "/", ino_args
.name
);
1635 new_child_fd
= openat(new_fd
, np
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
|O_DIRECTORY
|O_NOFOLLOW
);
1636 if (new_child_fd
< 0)
1639 if (flags
& BTRFS_SNAPSHOT_READ_ONLY
) {
1640 /* If the snapshot is read-only we
1641 * need to mark it writable
1642 * temporarily, to put the subsnapshot
1645 if (subvolume_fd
< 0) {
1646 subvolume_fd
= openat(new_fd
, subvolume
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
|O_DIRECTORY
|O_NOFOLLOW
);
1647 if (subvolume_fd
< 0)
1651 r
= btrfs_subvol_set_read_only_fd(subvolume_fd
, false);
1656 /* When btrfs clones the subvolumes, child
1657 * subvolumes appear as empty directories. Remove
1658 * them, so that we can create a new snapshot
1660 if (unlinkat(new_child_fd
, p
, AT_REMOVEDIR
) < 0) {
1663 if (flags
& BTRFS_SNAPSHOT_READ_ONLY
)
1664 (void) btrfs_subvol_set_read_only_fd(subvolume_fd
, true);
1669 r
= subvol_snapshot_children(old_child_fd
, new_child_fd
, p
, sh
->objectid
, flags
& ~BTRFS_SNAPSHOT_FALLBACK_COPY
);
1671 /* Restore the readonly flag */
1672 if (flags
& BTRFS_SNAPSHOT_READ_ONLY
) {
1675 k
= btrfs_subvol_set_read_only_fd(subvolume_fd
, true);
1676 if (r
>= 0 && k
< 0)
1684 /* Increase search key by one, to read the next item, if we can. */
1685 if (!btrfs_ioctl_search_args_inc(&args
))
1689 if (flags
& BTRFS_SNAPSHOT_QUOTA
)
1690 (void) copy_subtree_quota_limits(new_fd
, old_subvol_id
, new_subvol_id
);
1695 int btrfs_subvol_snapshot_fd(int old_fd
, const char *new_path
, BtrfsSnapshotFlags flags
) {
1696 _cleanup_close_
int new_fd
= -1;
1697 const char *subvolume
;
1700 assert(old_fd
>= 0);
1703 r
= btrfs_is_subvol_fd(old_fd
);
1707 bool plain_directory
= false;
1709 /* If the source isn't a proper subvolume, fail unless fallback is requested */
1710 if (!(flags
& BTRFS_SNAPSHOT_FALLBACK_COPY
))
1713 r
= btrfs_subvol_make(new_path
);
1714 if (r
== -ENOTTY
&& (flags
& BTRFS_SNAPSHOT_FALLBACK_DIRECTORY
)) {
1715 /* If the destination doesn't support subvolumes, then use a plain directory, if that's requested. */
1716 if (mkdir(new_path
, 0755) < 0)
1719 plain_directory
= true;
1723 r
= copy_directory_fd(old_fd
, new_path
, COPY_MERGE
|COPY_REFLINK
);
1727 if (flags
& BTRFS_SNAPSHOT_READ_ONLY
) {
1729 if (plain_directory
) {
1730 /* Plain directories have no recursive read-only flag, but something pretty close to
1731 * it: the IMMUTABLE bit. Let's use this here, if this is requested. */
1733 if (flags
& BTRFS_SNAPSHOT_FALLBACK_IMMUTABLE
)
1734 (void) chattr_path(new_path
, FS_IMMUTABLE_FL
, FS_IMMUTABLE_FL
);
1736 r
= btrfs_subvol_set_read_only(new_path
, true);
1745 (void) rm_rf(new_path
, REMOVE_ROOT
|REMOVE_PHYSICAL
|REMOVE_SUBVOLUME
);
1749 r
= extract_subvolume_name(new_path
, &subvolume
);
1753 new_fd
= open_parent(new_path
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
|O_DIRECTORY
);
1757 return subvol_snapshot_children(old_fd
, new_fd
, subvolume
, 0, flags
);
1760 int btrfs_subvol_snapshot(const char *old_path
, const char *new_path
, BtrfsSnapshotFlags flags
) {
1761 _cleanup_close_
int old_fd
= -1;
1766 old_fd
= open(old_path
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
|O_DIRECTORY
);
1770 return btrfs_subvol_snapshot_fd(old_fd
, new_path
, flags
);
1773 int btrfs_qgroup_find_parents(int fd
, uint64_t qgroupid
, uint64_t **ret
) {
1775 struct btrfs_ioctl_search_args args
= {
1776 /* Tree of quota items */
1777 .key
.tree_id
= BTRFS_QUOTA_TREE_OBJECTID
,
1779 /* Look precisely for the quota relation items */
1780 .key
.min_type
= BTRFS_QGROUP_RELATION_KEY
,
1781 .key
.max_type
= BTRFS_QGROUP_RELATION_KEY
,
1783 /* No restrictions on the other components */
1784 .key
.min_offset
= 0,
1785 .key
.max_offset
= (uint64_t) -1,
1787 .key
.min_transid
= 0,
1788 .key
.max_transid
= (uint64_t) -1,
1791 _cleanup_free_
uint64_t *items
= NULL
;
1792 size_t n_items
= 0, n_allocated
= 0;
1798 if (qgroupid
== 0) {
1799 r
= btrfs_subvol_get_id_fd(fd
, &qgroupid
);
1803 r
= btrfs_is_filesystem(fd
);
1810 args
.key
.min_objectid
= args
.key
.max_objectid
= qgroupid
;
1812 while (btrfs_ioctl_search_args_compare(&args
) <= 0) {
1813 const struct btrfs_ioctl_search_header
*sh
;
1816 args
.key
.nr_items
= 256;
1817 if (ioctl(fd
, BTRFS_IOC_TREE_SEARCH
, &args
) < 0) {
1818 if (errno
== ENOENT
) /* quota tree missing: quota is disabled */
1824 if (args
.key
.nr_items
<= 0)
1827 FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i
, sh
, args
) {
1829 /* Make sure we start the next search at least from this entry */
1830 btrfs_ioctl_search_args_set(&args
, sh
);
1832 if (sh
->type
!= BTRFS_QGROUP_RELATION_KEY
)
1834 if (sh
->offset
< sh
->objectid
)
1836 if (sh
->objectid
!= qgroupid
)
1839 if (!GREEDY_REALLOC(items
, n_allocated
, n_items
+1))
1842 items
[n_items
++] = sh
->offset
;
1845 /* Increase search key by one, to read the next item, if we can. */
1846 if (!btrfs_ioctl_search_args_inc(&args
))
1858 return (int) n_items
;
1861 int btrfs_subvol_auto_qgroup_fd(int fd
, uint64_t subvol_id
, bool insert_intermediary_qgroup
) {
1862 _cleanup_free_
uint64_t *qgroups
= NULL
;
1863 uint64_t parent_subvol
;
1864 bool changed
= false;
1870 * Sets up the specified subvolume's qgroup automatically in
1873 * If insert_intermediary_qgroup is false, the subvolume's
1874 * leaf qgroup will be assigned to the same parent qgroups as
1875 * the subvolume's parent subvolume.
1877 * If insert_intermediary_qgroup is true a new intermediary
1878 * higher-level qgroup is created, with a higher level number,
1879 * but reusing the id of the subvolume. The level number is
1880 * picked as one smaller than the lowest level qgroup the
1881 * parent subvolume is a member of. If the parent subvolume's
1882 * leaf qgroup is assigned to no higher-level qgroup a new
1883 * qgroup of level 255 is created instead. Either way, the new
1884 * qgroup is then assigned to the parent's higher-level
1885 * qgroup, and the subvolume itself is assigned to it.
1887 * If the subvolume is already assigned to a higher level
1888 * qgroup, no operation is executed.
1890 * Effectively this means: regardless if
1891 * insert_intermediary_qgroup is true or not, after this
1892 * function is invoked the subvolume will be accounted within
1893 * the same qgroups as the parent. However, if it is true, it
1894 * will also get its own higher-level qgroup, which may in
1895 * turn be used by subvolumes created beneath this subvolume
1898 * This hence defines a simple default qgroup setup for
1899 * subvolumes, as long as this function is invoked on each
1900 * created subvolume: each subvolume is always accounting
1901 * together with its immediate parents. Optionally, if
1902 * insert_intermediary_qgroup is true, it will also get a
1903 * qgroup that then includes all its own child subvolumes.
1906 if (subvol_id
== 0) {
1907 r
= btrfs_is_subvol_fd(fd
);
1913 r
= btrfs_subvol_get_id_fd(fd
, &subvol_id
);
1918 n
= btrfs_qgroup_find_parents(fd
, subvol_id
, &qgroups
);
1921 if (n
> 0) /* already parent qgroups set up, let's bail */
1924 qgroups
= mfree(qgroups
);
1926 r
= btrfs_subvol_get_parent(fd
, subvol_id
, &parent_subvol
);
1928 /* No parent, hence no qgroup memberships */
1933 n
= btrfs_qgroup_find_parents(fd
, parent_subvol
, &qgroups
);
1938 if (insert_intermediary_qgroup
) {
1939 uint64_t lowest
= 256, new_qgroupid
;
1940 bool created
= false;
1943 /* Determine the lowest qgroup that the parent
1944 * subvolume is assigned to. */
1946 for (i
= 0; i
< n
; i
++) {
1949 r
= btrfs_qgroupid_split(qgroups
[i
], &level
, NULL
);
1957 if (lowest
<= 1) /* There are no levels left we could use insert an intermediary qgroup at */
1960 r
= btrfs_qgroupid_make(lowest
- 1, subvol_id
, &new_qgroupid
);
1964 /* Create the new intermediary group, unless it already exists */
1965 r
= btrfs_qgroup_create(fd
, new_qgroupid
);
1966 if (r
< 0 && r
!= -EEXIST
)
1969 changed
= created
= true;
1971 for (i
= 0; i
< n
; i
++) {
1972 r
= btrfs_qgroup_assign(fd
, new_qgroupid
, qgroups
[i
]);
1973 if (r
< 0 && r
!= -EEXIST
) {
1975 (void) btrfs_qgroup_destroy_recursive(fd
, new_qgroupid
);
1983 r
= btrfs_qgroup_assign(fd
, subvol_id
, new_qgroupid
);
1984 if (r
< 0 && r
!= -EEXIST
) {
1986 (void) btrfs_qgroup_destroy_recursive(fd
, new_qgroupid
);
1995 /* Assign our subvolume to all the same qgroups as the parent */
1997 for (i
= 0; i
< n
; i
++) {
1998 r
= btrfs_qgroup_assign(fd
, subvol_id
, qgroups
[i
]);
1999 if (r
< 0 && r
!= -EEXIST
)
2009 int btrfs_subvol_auto_qgroup(const char *path
, uint64_t subvol_id
, bool create_intermediary_qgroup
) {
2010 _cleanup_close_
int fd
= -1;
2012 fd
= open(path
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
|O_DIRECTORY
);
2016 return btrfs_subvol_auto_qgroup_fd(fd
, subvol_id
, create_intermediary_qgroup
);
2019 int btrfs_subvol_get_parent(int fd
, uint64_t subvol_id
, uint64_t *ret
) {
2021 struct btrfs_ioctl_search_args args
= {
2022 /* Tree of tree roots */
2023 .key
.tree_id
= BTRFS_ROOT_TREE_OBJECTID
,
2025 /* Look precisely for the subvolume items */
2026 .key
.min_type
= BTRFS_ROOT_BACKREF_KEY
,
2027 .key
.max_type
= BTRFS_ROOT_BACKREF_KEY
,
2029 /* No restrictions on the other components */
2030 .key
.min_offset
= 0,
2031 .key
.max_offset
= (uint64_t) -1,
2033 .key
.min_transid
= 0,
2034 .key
.max_transid
= (uint64_t) -1,
2041 if (subvol_id
== 0) {
2042 r
= btrfs_subvol_get_id_fd(fd
, &subvol_id
);
2046 r
= btrfs_is_filesystem(fd
);
2053 args
.key
.min_objectid
= args
.key
.max_objectid
= subvol_id
;
2055 while (btrfs_ioctl_search_args_compare(&args
) <= 0) {
2056 const struct btrfs_ioctl_search_header
*sh
;
2059 args
.key
.nr_items
= 256;
2060 if (ioctl(fd
, BTRFS_IOC_TREE_SEARCH
, &args
) < 0)
2061 return negative_errno();
2063 if (args
.key
.nr_items
<= 0)
2066 FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i
, sh
, args
) {
2068 if (sh
->type
!= BTRFS_ROOT_BACKREF_KEY
)
2070 if (sh
->objectid
!= subvol_id
)