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 "btrfs-ctree.h"
42 #include "btrfs-util.h"
43 #include "chattr-util.h"
45 #include "device-nodes.h"
51 #include "path-util.h"
53 #include "smack-util.h"
54 #include "sparse-endian.h"
55 #include "stat-util.h"
56 #include "string-util.h"
57 #include "time-util.h"
60 /* WARNING: Be careful with file system ioctls! When we get an fd, we
61 * need to make sure it either refers to only a regular file or
62 * directory, or that it is located on btrfs, before invoking any
63 * btrfs ioctls. The ioctl numbers are reused by some device drivers
64 * (such as DRM), and hence might have bad effects when invoked on
65 * device nodes (that reference drivers) rather than fds to normal
66 * files or directories. */
68 static int validate_subvolume_name(const char *name
) {
70 if (!filename_is_valid(name
))
73 if (strlen(name
) > BTRFS_SUBVOL_NAME_MAX
)
79 static int open_parent(const char *path
, int flags
) {
80 _cleanup_free_
char *parent
= NULL
;
85 parent
= dirname_malloc(path
);
89 fd
= open(parent
, flags
);
96 static int extract_subvolume_name(const char *path
, const char **subvolume
) {
105 r
= validate_subvolume_name(fn
);
113 int btrfs_is_filesystem(int fd
) {
118 if (fstatfs(fd
, &sfs
) < 0)
121 return F_TYPE_EQUAL(sfs
.f_type
, BTRFS_SUPER_MAGIC
);
124 int btrfs_is_subvol_fd(int fd
) {
129 /* On btrfs subvolumes always have the inode 256 */
131 if (fstat(fd
, &st
) < 0)
134 if (!S_ISDIR(st
.st_mode
) || st
.st_ino
!= 256)
137 return btrfs_is_filesystem(fd
);
140 int btrfs_is_subvol(const char *path
) {
141 _cleanup_close_
int fd
= -1;
145 fd
= open(path
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
|O_DIRECTORY
);
149 return btrfs_is_subvol_fd(fd
);
152 int btrfs_subvol_make(const char *path
) {
153 struct btrfs_ioctl_vol_args args
= {};
154 _cleanup_close_
int fd
= -1;
155 const char *subvolume
;
160 r
= extract_subvolume_name(path
, &subvolume
);
164 fd
= open_parent(path
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
|O_DIRECTORY
);
168 strncpy(args
.name
, subvolume
, sizeof(args
.name
)-1);
170 if (ioctl(fd
, BTRFS_IOC_SUBVOL_CREATE
, &args
) < 0)
176 int btrfs_subvol_set_read_only_fd(int fd
, bool b
) {
177 uint64_t flags
, nflags
;
182 if (fstat(fd
, &st
) < 0)
185 if (!S_ISDIR(st
.st_mode
) || st
.st_ino
!= 256)
188 if (ioctl(fd
, BTRFS_IOC_SUBVOL_GETFLAGS
, &flags
) < 0)
192 nflags
= flags
| BTRFS_SUBVOL_RDONLY
;
194 nflags
= flags
& ~BTRFS_SUBVOL_RDONLY
;
199 if (ioctl(fd
, BTRFS_IOC_SUBVOL_SETFLAGS
, &nflags
) < 0)
205 int btrfs_subvol_set_read_only(const char *path
, bool b
) {
206 _cleanup_close_
int fd
= -1;
208 fd
= open(path
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
|O_DIRECTORY
);
212 return btrfs_subvol_set_read_only_fd(fd
, b
);
215 int btrfs_subvol_get_read_only_fd(int fd
) {
221 if (fstat(fd
, &st
) < 0)
224 if (!S_ISDIR(st
.st_mode
) || st
.st_ino
!= 256)
227 if (ioctl(fd
, BTRFS_IOC_SUBVOL_GETFLAGS
, &flags
) < 0)
230 return !!(flags
& BTRFS_SUBVOL_RDONLY
);
233 int btrfs_reflink(int infd
, int outfd
) {
240 /* Make sure we invoke the ioctl on a regular file, so that no
241 * device driver accidentally gets it. */
243 if (fstat(outfd
, &st
) < 0)
246 if (!S_ISREG(st
.st_mode
))
249 r
= ioctl(outfd
, BTRFS_IOC_CLONE
, infd
);
256 int btrfs_clone_range(int infd
, uint64_t in_offset
, int outfd
, uint64_t out_offset
, uint64_t sz
) {
257 struct btrfs_ioctl_clone_range_args args
= {
259 .src_offset
= in_offset
,
261 .dest_offset
= out_offset
,
270 if (fstat(outfd
, &st
) < 0)
273 if (!S_ISREG(st
.st_mode
))
276 r
= ioctl(outfd
, BTRFS_IOC_CLONE_RANGE
, &args
);
283 int btrfs_get_block_device_fd(int fd
, dev_t
*dev
) {
284 struct btrfs_ioctl_fs_info_args fsi
= {};
291 r
= btrfs_is_filesystem(fd
);
297 if (ioctl(fd
, BTRFS_IOC_FS_INFO
, &fsi
) < 0)
300 /* We won't do this for btrfs RAID */
301 if (fsi
.num_devices
!= 1)
304 for (id
= 1; id
<= fsi
.max_id
; id
++) {
305 struct btrfs_ioctl_dev_info_args di
= {
310 if (ioctl(fd
, BTRFS_IOC_DEV_INFO
, &di
) < 0) {
317 if (stat((char*) di
.path
, &st
) < 0)
320 if (!S_ISBLK(st
.st_mode
))
323 if (major(st
.st_rdev
) == 0)
333 int btrfs_get_block_device(const char *path
, dev_t
*dev
) {
334 _cleanup_close_
int fd
= -1;
339 fd
= open(path
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
);
343 return btrfs_get_block_device_fd(fd
, dev
);
346 int btrfs_subvol_get_id_fd(int fd
, uint64_t *ret
) {
347 struct btrfs_ioctl_ino_lookup_args args
= {
348 .objectid
= BTRFS_FIRST_FREE_OBJECTID
355 r
= btrfs_is_filesystem(fd
);
361 if (ioctl(fd
, BTRFS_IOC_INO_LOOKUP
, &args
) < 0)
368 int btrfs_subvol_get_id(int fd
, const char *subvol
, uint64_t *ret
) {
369 _cleanup_close_
int subvol_fd
= -1;
374 subvol_fd
= openat(fd
, subvol
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
|O_NOFOLLOW
);
378 return btrfs_subvol_get_id_fd(subvol_fd
, ret
);
381 static bool btrfs_ioctl_search_args_inc(struct btrfs_ioctl_search_args
*args
) {
384 /* the objectid, type, offset together make up the btrfs key,
385 * which is considered a single 136byte integer when
386 * comparing. This call increases the counter by one, dealing
387 * with the overflow between the overflows */
389 if (args
->key
.min_offset
< (uint64_t) -1) {
390 args
->key
.min_offset
++;
394 if (args
->key
.min_type
< (uint8_t) -1) {
395 args
->key
.min_type
++;
396 args
->key
.min_offset
= 0;
400 if (args
->key
.min_objectid
< (uint64_t) -1) {
401 args
->key
.min_objectid
++;
402 args
->key
.min_offset
= 0;
403 args
->key
.min_type
= 0;
410 static void btrfs_ioctl_search_args_set(struct btrfs_ioctl_search_args
*args
, const struct btrfs_ioctl_search_header
*h
) {
414 args
->key
.min_objectid
= h
->objectid
;
415 args
->key
.min_type
= h
->type
;
416 args
->key
.min_offset
= h
->offset
;
419 static int btrfs_ioctl_search_args_compare(const struct btrfs_ioctl_search_args
*args
) {
422 /* Compare min and max */
424 if (args
->key
.min_objectid
< args
->key
.max_objectid
)
426 if (args
->key
.min_objectid
> args
->key
.max_objectid
)
429 if (args
->key
.min_type
< args
->key
.max_type
)
431 if (args
->key
.min_type
> args
->key
.max_type
)
434 if (args
->key
.min_offset
< args
->key
.max_offset
)
436 if (args
->key
.min_offset
> args
->key
.max_offset
)
442 #define FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i, sh, args) \
444 (sh) = (const struct btrfs_ioctl_search_header*) (args).buf; \
445 (i) < (args).key.nr_items; \
447 (sh) = (const struct btrfs_ioctl_search_header*) ((uint8_t*) (sh) + sizeof(struct btrfs_ioctl_search_header) + (sh)->len))
449 #define BTRFS_IOCTL_SEARCH_HEADER_BODY(sh) \
450 ((void*) ((uint8_t*) sh + sizeof(struct btrfs_ioctl_search_header)))
452 int btrfs_subvol_get_info_fd(int fd
, uint64_t subvol_id
, BtrfsSubvolInfo
*ret
) {
453 struct btrfs_ioctl_search_args args
= {
454 /* Tree of tree roots */
455 .key
.tree_id
= BTRFS_ROOT_TREE_OBJECTID
,
457 /* Look precisely for the subvolume items */
458 .key
.min_type
= BTRFS_ROOT_ITEM_KEY
,
459 .key
.max_type
= BTRFS_ROOT_ITEM_KEY
,
462 .key
.max_offset
= (uint64_t) -1,
464 /* No restrictions on the other components */
465 .key
.min_transid
= 0,
466 .key
.max_transid
= (uint64_t) -1,
475 if (subvol_id
== 0) {
476 r
= btrfs_subvol_get_id_fd(fd
, &subvol_id
);
480 r
= btrfs_is_filesystem(fd
);
487 args
.key
.min_objectid
= args
.key
.max_objectid
= subvol_id
;
489 while (btrfs_ioctl_search_args_compare(&args
) <= 0) {
490 const struct btrfs_ioctl_search_header
*sh
;
493 args
.key
.nr_items
= 256;
494 if (ioctl(fd
, BTRFS_IOC_TREE_SEARCH
, &args
) < 0)
497 if (args
.key
.nr_items
<= 0)
500 FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i
, sh
, args
) {
502 const struct btrfs_root_item
*ri
;
504 /* Make sure we start the next search at least from this entry */
505 btrfs_ioctl_search_args_set(&args
, sh
);
507 if (sh
->objectid
!= subvol_id
)
509 if (sh
->type
!= BTRFS_ROOT_ITEM_KEY
)
512 /* Older versions of the struct lacked the otime setting */
513 if (sh
->len
< offsetof(struct btrfs_root_item
, otime
) + sizeof(struct btrfs_timespec
))
516 ri
= BTRFS_IOCTL_SEARCH_HEADER_BODY(sh
);
518 ret
->otime
= (usec_t
) le64toh(ri
->otime
.sec
) * USEC_PER_SEC
+
519 (usec_t
) le32toh(ri
->otime
.nsec
) / NSEC_PER_USEC
;
521 ret
->subvol_id
= subvol_id
;
522 ret
->read_only
= !!(le64toh(ri
->flags
) & BTRFS_ROOT_SUBVOL_RDONLY
);
524 assert_cc(sizeof(ri
->uuid
) == sizeof(ret
->uuid
));
525 memcpy(&ret
->uuid
, ri
->uuid
, sizeof(ret
->uuid
));
526 memcpy(&ret
->parent_uuid
, ri
->parent_uuid
, sizeof(ret
->parent_uuid
));
532 /* Increase search key by one, to read the next item, if we can. */
533 if (!btrfs_ioctl_search_args_inc(&args
))
544 int btrfs_qgroup_get_quota_fd(int fd
, uint64_t qgroupid
, BtrfsQuotaInfo
*ret
) {
546 struct btrfs_ioctl_search_args args
= {
547 /* Tree of quota items */
548 .key
.tree_id
= BTRFS_QUOTA_TREE_OBJECTID
,
550 /* The object ID is always 0 */
551 .key
.min_objectid
= 0,
552 .key
.max_objectid
= 0,
554 /* Look precisely for the quota items */
555 .key
.min_type
= BTRFS_QGROUP_STATUS_KEY
,
556 .key
.max_type
= BTRFS_QGROUP_LIMIT_KEY
,
558 /* No restrictions on the other components */
559 .key
.min_transid
= 0,
560 .key
.max_transid
= (uint64_t) -1,
563 bool found_info
= false, found_limit
= false;
570 r
= btrfs_subvol_get_id_fd(fd
, &qgroupid
);
574 r
= btrfs_is_filesystem(fd
);
581 args
.key
.min_offset
= args
.key
.max_offset
= qgroupid
;
583 while (btrfs_ioctl_search_args_compare(&args
) <= 0) {
584 const struct btrfs_ioctl_search_header
*sh
;
587 args
.key
.nr_items
= 256;
588 if (ioctl(fd
, BTRFS_IOC_TREE_SEARCH
, &args
) < 0) {
589 if (errno
== ENOENT
) /* quota tree is missing: quota disabled */
595 if (args
.key
.nr_items
<= 0)
598 FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i
, sh
, args
) {
600 /* Make sure we start the next search at least from this entry */
601 btrfs_ioctl_search_args_set(&args
, sh
);
603 if (sh
->objectid
!= 0)
605 if (sh
->offset
!= qgroupid
)
608 if (sh
->type
== BTRFS_QGROUP_INFO_KEY
) {
609 const struct btrfs_qgroup_info_item
*qii
= BTRFS_IOCTL_SEARCH_HEADER_BODY(sh
);
611 ret
->referenced
= le64toh(qii
->rfer
);
612 ret
->exclusive
= le64toh(qii
->excl
);
616 } else if (sh
->type
== BTRFS_QGROUP_LIMIT_KEY
) {
617 const struct btrfs_qgroup_limit_item
*qli
= BTRFS_IOCTL_SEARCH_HEADER_BODY(sh
);
619 if (le64toh(qli
->flags
) & BTRFS_QGROUP_LIMIT_MAX_RFER
)
620 ret
->referenced_max
= le64toh(qli
->max_rfer
);
622 ret
->referenced_max
= (uint64_t) -1;
624 if (le64toh(qli
->flags
) & BTRFS_QGROUP_LIMIT_MAX_EXCL
)
625 ret
->exclusive_max
= le64toh(qli
->max_excl
);
627 ret
->exclusive_max
= (uint64_t) -1;
632 if (found_info
&& found_limit
)
636 /* Increase search key by one, to read the next item, if we can. */
637 if (!btrfs_ioctl_search_args_inc(&args
))
642 if (!found_limit
&& !found_info
)
646 ret
->referenced
= (uint64_t) -1;
647 ret
->exclusive
= (uint64_t) -1;
651 ret
->referenced_max
= (uint64_t) -1;
652 ret
->exclusive_max
= (uint64_t) -1;
658 int btrfs_qgroup_get_quota(const char *path
, uint64_t qgroupid
, BtrfsQuotaInfo
*ret
) {
659 _cleanup_close_
int fd
= -1;
661 fd
= open(path
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
|O_NOFOLLOW
);
665 return btrfs_qgroup_get_quota_fd(fd
, qgroupid
, ret
);
668 int btrfs_subvol_find_subtree_qgroup(int fd
, uint64_t subvol_id
, uint64_t *ret
) {
669 uint64_t level
, lowest
= (uint64_t) -1, lowest_qgroupid
= 0;
670 _cleanup_free_
uint64_t *qgroups
= NULL
;
676 /* This finds the "subtree" qgroup for a specific
677 * subvolume. This only works for subvolumes that have been
678 * prepared with btrfs_subvol_auto_qgroup_fd() with
679 * insert_intermediary_qgroup=true (or equivalent). For others
680 * it will return the leaf qgroup instead. The two cases may
681 * be distuingished via the return value, which is 1 in case
682 * an appropriate "subtree" qgroup was found, and 0
685 if (subvol_id
== 0) {
686 r
= btrfs_subvol_get_id_fd(fd
, &subvol_id
);
691 r
= btrfs_qgroupid_split(subvol_id
, &level
, NULL
);
694 if (level
!= 0) /* Input must be a leaf qgroup */
697 n
= btrfs_qgroup_find_parents(fd
, subvol_id
, &qgroups
);
701 for (i
= 0; i
< n
; i
++) {
704 r
= btrfs_qgroupid_split(qgroups
[i
], &level
, &id
);
711 if (lowest
== (uint64_t) -1 || level
< lowest
) {
712 lowest_qgroupid
= qgroups
[i
];
717 if (lowest
== (uint64_t) -1) {
718 /* No suitable higher-level qgroup found, let's return
719 * the leaf qgroup instead, and indicate that with the
726 *ret
= lowest_qgroupid
;
730 int btrfs_subvol_get_subtree_quota_fd(int fd
, uint64_t subvol_id
, BtrfsQuotaInfo
*ret
) {
737 /* This determines the quota data of the qgroup with the
738 * lowest level, that shares the id part with the specified
739 * subvolume. This is useful for determining the quota data
740 * for entire subvolume subtrees, as long as the subtrees have
741 * been set up with btrfs_qgroup_subvol_auto_fd() or in a
744 r
= btrfs_subvol_find_subtree_qgroup(fd
, subvol_id
, &qgroupid
);
748 return btrfs_qgroup_get_quota_fd(fd
, qgroupid
, ret
);
751 int btrfs_subvol_get_subtree_quota(const char *path
, uint64_t subvol_id
, BtrfsQuotaInfo
*ret
) {
752 _cleanup_close_
int fd
= -1;
754 fd
= open(path
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
|O_NOFOLLOW
);
758 return btrfs_subvol_get_subtree_quota_fd(fd
, subvol_id
, ret
);
761 int btrfs_defrag_fd(int fd
) {
766 if (fstat(fd
, &st
) < 0)
769 if (!S_ISREG(st
.st_mode
))
772 if (ioctl(fd
, BTRFS_IOC_DEFRAG
, NULL
) < 0)
778 int btrfs_defrag(const char *p
) {
779 _cleanup_close_
int fd
= -1;
781 fd
= open(p
, O_RDWR
|O_CLOEXEC
|O_NOCTTY
|O_NOFOLLOW
);
785 return btrfs_defrag_fd(fd
);
788 int btrfs_quota_enable_fd(int fd
, bool b
) {
789 struct btrfs_ioctl_quota_ctl_args args
= {
790 .cmd
= b
? BTRFS_QUOTA_CTL_ENABLE
: BTRFS_QUOTA_CTL_DISABLE
,
796 r
= btrfs_is_filesystem(fd
);
802 if (ioctl(fd
, BTRFS_IOC_QUOTA_CTL
, &args
) < 0)
808 int btrfs_quota_enable(const char *path
, bool b
) {
809 _cleanup_close_
int fd
= -1;
811 fd
= open(path
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
|O_NOFOLLOW
);
815 return btrfs_quota_enable_fd(fd
, b
);
818 int btrfs_qgroup_set_limit_fd(int fd
, uint64_t qgroupid
, uint64_t referenced_max
) {
820 struct btrfs_ioctl_qgroup_limit_args args
= {
821 .lim
.max_rfer
= referenced_max
,
822 .lim
.flags
= BTRFS_QGROUP_LIMIT_MAX_RFER
,
830 r
= btrfs_subvol_get_id_fd(fd
, &qgroupid
);
834 r
= btrfs_is_filesystem(fd
);
841 args
.qgroupid
= qgroupid
;
844 if (ioctl(fd
, BTRFS_IOC_QGROUP_LIMIT
, &args
) < 0) {
846 if (errno
== EBUSY
&& c
< 10) {
847 (void) btrfs_quota_scan_wait(fd
);
860 int btrfs_qgroup_set_limit(const char *path
, uint64_t qgroupid
, uint64_t referenced_max
) {
861 _cleanup_close_
int fd
= -1;
863 fd
= open(path
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
|O_NOFOLLOW
);
867 return btrfs_qgroup_set_limit_fd(fd
, qgroupid
, referenced_max
);
870 int btrfs_subvol_set_subtree_quota_limit_fd(int fd
, uint64_t subvol_id
, uint64_t referenced_max
) {
876 r
= btrfs_subvol_find_subtree_qgroup(fd
, subvol_id
, &qgroupid
);
880 return btrfs_qgroup_set_limit_fd(fd
, qgroupid
, referenced_max
);
883 int btrfs_subvol_set_subtree_quota_limit(const char *path
, uint64_t subvol_id
, uint64_t referenced_max
) {
884 _cleanup_close_
int fd
= -1;
886 fd
= open(path
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
|O_NOFOLLOW
);
890 return btrfs_subvol_set_subtree_quota_limit_fd(fd
, subvol_id
, referenced_max
);
893 int btrfs_resize_loopback_fd(int fd
, uint64_t new_size
, bool grow_only
) {
894 struct btrfs_ioctl_vol_args args
= {};
895 char p
[SYS_BLOCK_PATH_MAX("/loop/backing_file")];
896 _cleanup_free_
char *backing
= NULL
;
897 _cleanup_close_
int loop_fd
= -1, backing_fd
= -1;
902 /* In contrast to btrfs quota ioctls ftruncate() cannot make sense of "infinity" or file sizes > 2^31 */
903 if (!FILE_SIZE_VALID(new_size
))
906 /* btrfs cannot handle file systems < 16M, hence use this as minimum */
907 if (new_size
< 16*1024*1024)
908 new_size
= 16*1024*1024;
910 r
= btrfs_get_block_device_fd(fd
, &dev
);
916 xsprintf_sys_block_path(p
, "/loop/backing_file", dev
);
917 r
= read_one_line_file(p
, &backing
);
922 if (isempty(backing
) || !path_is_absolute(backing
))
925 backing_fd
= open(backing
, O_RDWR
|O_CLOEXEC
|O_NOCTTY
);
929 if (fstat(backing_fd
, &st
) < 0)
931 if (!S_ISREG(st
.st_mode
))
934 if (new_size
== (uint64_t) st
.st_size
)
937 if (grow_only
&& new_size
< (uint64_t) st
.st_size
)
940 xsprintf_sys_block_path(p
, NULL
, dev
);
941 loop_fd
= open(p
, O_RDWR
|O_CLOEXEC
|O_NOCTTY
);
945 if (snprintf(args
.name
, sizeof(args
.name
), "%" PRIu64
, new_size
) >= (int) sizeof(args
.name
))
948 if (new_size
< (uint64_t) st
.st_size
) {
949 /* Decrease size: first decrease btrfs size, then shorten loopback */
950 if (ioctl(fd
, BTRFS_IOC_RESIZE
, &args
) < 0)
954 if (ftruncate(backing_fd
, new_size
) < 0)
957 if (ioctl(loop_fd
, LOOP_SET_CAPACITY
, 0) < 0)
960 if (new_size
> (uint64_t) st
.st_size
) {
961 /* Increase size: first enlarge loopback, then increase btrfs size */
962 if (ioctl(fd
, BTRFS_IOC_RESIZE
, &args
) < 0)
966 /* Make sure the free disk space is correctly updated for both file systems */
968 (void) fsync(backing_fd
);
973 int btrfs_resize_loopback(const char *p
, uint64_t new_size
, bool grow_only
) {
974 _cleanup_close_
int fd
= -1;
976 fd
= open(p
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
);
980 return btrfs_resize_loopback_fd(fd
, new_size
, grow_only
);
983 int btrfs_qgroupid_make(uint64_t level
, uint64_t id
, uint64_t *ret
) {
986 if (level
>= (UINT64_C(1) << (64 - BTRFS_QGROUP_LEVEL_SHIFT
)))
989 if (id
>= (UINT64_C(1) << BTRFS_QGROUP_LEVEL_SHIFT
))
992 *ret
= (level
<< BTRFS_QGROUP_LEVEL_SHIFT
) | id
;
996 int btrfs_qgroupid_split(uint64_t qgroupid
, uint64_t *level
, uint64_t *id
) {
1000 *level
= qgroupid
>> BTRFS_QGROUP_LEVEL_SHIFT
;
1003 *id
= qgroupid
& ((UINT64_C(1) << BTRFS_QGROUP_LEVEL_SHIFT
) - 1);
1008 static int qgroup_create_or_destroy(int fd
, bool b
, uint64_t qgroupid
) {
1010 struct btrfs_ioctl_qgroup_create_args args
= {
1012 .qgroupid
= qgroupid
,
1017 r
= btrfs_is_filesystem(fd
);
1024 if (ioctl(fd
, BTRFS_IOC_QGROUP_CREATE
, &args
) < 0) {
1026 /* If quota is not enabled, we get EINVAL. Turn this into a recognizable error */
1027 if (errno
== EINVAL
)
1028 return -ENOPROTOOPT
;
1030 if (errno
== EBUSY
&& c
< 10) {
1031 (void) btrfs_quota_scan_wait(fd
);
1044 int btrfs_qgroup_create(int fd
, uint64_t qgroupid
) {
1045 return qgroup_create_or_destroy(fd
, true, qgroupid
);
1048 int btrfs_qgroup_destroy(int fd
, uint64_t qgroupid
) {
1049 return qgroup_create_or_destroy(fd
, false, qgroupid
);
1052 int btrfs_qgroup_destroy_recursive(int fd
, uint64_t qgroupid
) {
1053 _cleanup_free_
uint64_t *qgroups
= NULL
;
1057 /* Destroys the specified qgroup, but unassigns it from all
1058 * its parents first. Also, it recursively destroys all
1059 * qgroups it is assgined to that have the same id part of the
1060 * qgroupid as the specified group. */
1062 r
= btrfs_qgroupid_split(qgroupid
, NULL
, &subvol_id
);
1066 n
= btrfs_qgroup_find_parents(fd
, qgroupid
, &qgroups
);
1070 for (i
= 0; i
< n
; i
++) {
1073 r
= btrfs_qgroupid_split(qgroups
[i
], NULL
, &id
);
1077 r
= btrfs_qgroup_unassign(fd
, qgroupid
, qgroups
[i
]);
1081 if (id
!= subvol_id
)
1084 /* The parent qgroupid shares the same id part with
1085 * us? If so, destroy it too. */
1087 (void) btrfs_qgroup_destroy_recursive(fd
, qgroups
[i
]);
1090 return btrfs_qgroup_destroy(fd
, qgroupid
);
1093 int btrfs_quota_scan_start(int fd
) {
1094 struct btrfs_ioctl_quota_rescan_args args
= {};
1098 if (ioctl(fd
, BTRFS_IOC_QUOTA_RESCAN
, &args
) < 0)
1104 int btrfs_quota_scan_wait(int fd
) {
1107 if (ioctl(fd
, BTRFS_IOC_QUOTA_RESCAN_WAIT
) < 0)
1113 int btrfs_quota_scan_ongoing(int fd
) {
1114 struct btrfs_ioctl_quota_rescan_args args
= {};
1118 if (ioctl(fd
, BTRFS_IOC_QUOTA_RESCAN_STATUS
, &args
) < 0)
1121 return !!args
.flags
;
1124 static int qgroup_assign_or_unassign(int fd
, bool b
, uint64_t child
, uint64_t parent
) {
1125 struct btrfs_ioctl_qgroup_assign_args args
= {
1133 r
= btrfs_is_filesystem(fd
);
1140 r
= ioctl(fd
, BTRFS_IOC_QGROUP_ASSIGN
, &args
);
1142 if (errno
== EBUSY
&& c
< 10) {
1143 (void) btrfs_quota_scan_wait(fd
);
1153 /* If the return value is > 0, we need to request a rescan */
1155 (void) btrfs_quota_scan_start(fd
);
1160 int btrfs_qgroup_assign(int fd
, uint64_t child
, uint64_t parent
) {
1161 return qgroup_assign_or_unassign(fd
, true, child
, parent
);
1164 int btrfs_qgroup_unassign(int fd
, uint64_t child
, uint64_t parent
) {
1165 return qgroup_assign_or_unassign(fd
, false, child
, parent
);
1168 static int subvol_remove_children(int fd
, const char *subvolume
, uint64_t subvol_id
, BtrfsRemoveFlags flags
) {
1169 struct btrfs_ioctl_search_args args
= {
1170 .key
.tree_id
= BTRFS_ROOT_TREE_OBJECTID
,
1172 .key
.min_objectid
= BTRFS_FIRST_FREE_OBJECTID
,
1173 .key
.max_objectid
= BTRFS_LAST_FREE_OBJECTID
,
1175 .key
.min_type
= BTRFS_ROOT_BACKREF_KEY
,
1176 .key
.max_type
= BTRFS_ROOT_BACKREF_KEY
,
1178 .key
.min_transid
= 0,
1179 .key
.max_transid
= (uint64_t) -1,
1182 struct btrfs_ioctl_vol_args vol_args
= {};
1183 _cleanup_close_
int subvol_fd
= -1;
1185 bool made_writable
= false;
1191 if (fstat(fd
, &st
) < 0)
1194 if (!S_ISDIR(st
.st_mode
))
1197 subvol_fd
= openat(fd
, subvolume
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
|O_DIRECTORY
|O_NOFOLLOW
);
1201 if (subvol_id
== 0) {
1202 r
= btrfs_subvol_get_id_fd(subvol_fd
, &subvol_id
);
1207 /* First, try to remove the subvolume. If it happens to be
1208 * already empty, this will just work. */
1209 strncpy(vol_args
.name
, subvolume
, sizeof(vol_args
.name
)-1);
1210 if (ioctl(fd
, BTRFS_IOC_SNAP_DESTROY
, &vol_args
) >= 0) {
1211 (void) btrfs_qgroup_destroy_recursive(fd
, subvol_id
); /* for the leaf subvolumes, the qgroup id is identical to the subvol id */
1214 if (!(flags
& BTRFS_REMOVE_RECURSIVE
) || errno
!= ENOTEMPTY
)
1217 /* OK, the subvolume is not empty, let's look for child
1218 * subvolumes, and remove them, first */
1220 args
.key
.min_offset
= args
.key
.max_offset
= subvol_id
;
1222 while (btrfs_ioctl_search_args_compare(&args
) <= 0) {
1223 const struct btrfs_ioctl_search_header
*sh
;
1226 args
.key
.nr_items
= 256;
1227 if (ioctl(fd
, BTRFS_IOC_TREE_SEARCH
, &args
) < 0)
1230 if (args
.key
.nr_items
<= 0)
1233 FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i
, sh
, args
) {
1234 _cleanup_free_
char *p
= NULL
;
1235 const struct btrfs_root_ref
*ref
;
1236 struct btrfs_ioctl_ino_lookup_args ino_args
;
1238 btrfs_ioctl_search_args_set(&args
, sh
);
1240 if (sh
->type
!= BTRFS_ROOT_BACKREF_KEY
)
1242 if (sh
->offset
!= subvol_id
)
1245 ref
= BTRFS_IOCTL_SEARCH_HEADER_BODY(sh
);
1247 p
= strndup((char*) ref
+ sizeof(struct btrfs_root_ref
), le64toh(ref
->name_len
));
1252 ino_args
.treeid
= subvol_id
;
1253 ino_args
.objectid
= htole64(ref
->dirid
);
1255 if (ioctl(fd
, BTRFS_IOC_INO_LOOKUP
, &ino_args
) < 0)
1258 if (!made_writable
) {
1259 r
= btrfs_subvol_set_read_only_fd(subvol_fd
, false);
1263 made_writable
= true;
1266 if (isempty(ino_args
.name
))
1267 /* Subvolume is in the top-level
1268 * directory of the subvolume. */
1269 r
= subvol_remove_children(subvol_fd
, p
, sh
->objectid
, flags
);
1271 _cleanup_close_
int child_fd
= -1;
1273 /* Subvolume is somewhere further down,
1274 * hence we need to open the
1275 * containing directory first */
1277 child_fd
= openat(subvol_fd
, ino_args
.name
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
|O_DIRECTORY
|O_NOFOLLOW
);
1281 r
= subvol_remove_children(child_fd
, p
, sh
->objectid
, flags
);
1287 /* Increase search key by one, to read the next item, if we can. */
1288 if (!btrfs_ioctl_search_args_inc(&args
))
1292 /* OK, the child subvolumes should all be gone now, let's try
1293 * again to remove the subvolume */
1294 if (ioctl(fd
, BTRFS_IOC_SNAP_DESTROY
, &vol_args
) < 0)
1297 (void) btrfs_qgroup_destroy_recursive(fd
, subvol_id
);
1301 int btrfs_subvol_remove(const char *path
, BtrfsRemoveFlags flags
) {
1302 _cleanup_close_
int fd
= -1;
1303 const char *subvolume
;
1308 r
= extract_subvolume_name(path
, &subvolume
);
1312 fd
= open_parent(path
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
|O_DIRECTORY
);
1316 return subvol_remove_children(fd
, subvolume
, 0, flags
);
1319 int btrfs_subvol_remove_fd(int fd
, const char *subvolume
, BtrfsRemoveFlags flags
) {
1320 return subvol_remove_children(fd
, subvolume
, 0, flags
);
1323 int btrfs_qgroup_copy_limits(int fd
, uint64_t old_qgroupid
, uint64_t new_qgroupid
) {
1325 struct btrfs_ioctl_search_args args
= {
1326 /* Tree of quota items */
1327 .key
.tree_id
= BTRFS_QUOTA_TREE_OBJECTID
,
1329 /* The object ID is always 0 */
1330 .key
.min_objectid
= 0,
1331 .key
.max_objectid
= 0,
1333 /* Look precisely for the quota items */
1334 .key
.min_type
= BTRFS_QGROUP_LIMIT_KEY
,
1335 .key
.max_type
= BTRFS_QGROUP_LIMIT_KEY
,
1337 /* For our qgroup */
1338 .key
.min_offset
= old_qgroupid
,
1339 .key
.max_offset
= old_qgroupid
,
1341 /* No restrictions on the other components */
1342 .key
.min_transid
= 0,
1343 .key
.max_transid
= (uint64_t) -1,
1348 r
= btrfs_is_filesystem(fd
);
1354 while (btrfs_ioctl_search_args_compare(&args
) <= 0) {
1355 const struct btrfs_ioctl_search_header
*sh
;
1358 args
.key
.nr_items
= 256;
1359 if (ioctl(fd
, BTRFS_IOC_TREE_SEARCH
, &args
) < 0) {
1360 if (errno
== ENOENT
) /* quota tree missing: quota is not enabled, hence nothing to copy */
1366 if (args
.key
.nr_items
<= 0)
1369 FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i
, sh
, args
) {
1370 const struct btrfs_qgroup_limit_item
*qli
= BTRFS_IOCTL_SEARCH_HEADER_BODY(sh
);
1371 struct btrfs_ioctl_qgroup_limit_args qargs
;
1374 /* Make sure we start the next search at least from this entry */
1375 btrfs_ioctl_search_args_set(&args
, sh
);
1377 if (sh
->objectid
!= 0)
1379 if (sh
->type
!= BTRFS_QGROUP_LIMIT_KEY
)
1381 if (sh
->offset
!= old_qgroupid
)
1384 /* We found the entry, now copy things over. */
1386 qargs
= (struct btrfs_ioctl_qgroup_limit_args
) {
1387 .qgroupid
= new_qgroupid
,
1389 .lim
.max_rfer
= le64toh(qli
->max_rfer
),
1390 .lim
.max_excl
= le64toh(qli
->max_excl
),
1391 .lim
.rsv_rfer
= le64toh(qli
->rsv_rfer
),
1392 .lim
.rsv_excl
= le64toh(qli
->rsv_excl
),
1394 .lim
.flags
= le64toh(qli
->flags
) & (BTRFS_QGROUP_LIMIT_MAX_RFER
|
1395 BTRFS_QGROUP_LIMIT_MAX_EXCL
|
1396 BTRFS_QGROUP_LIMIT_RSV_RFER
|
1397 BTRFS_QGROUP_LIMIT_RSV_EXCL
),
1401 if (ioctl(fd
, BTRFS_IOC_QGROUP_LIMIT
, &qargs
) < 0) {
1402 if (errno
== EBUSY
&& c
< 10) {
1403 (void) btrfs_quota_scan_wait(fd
);
1415 /* Increase search key by one, to read the next item, if we can. */
1416 if (!btrfs_ioctl_search_args_inc(&args
))
1423 static int copy_quota_hierarchy(int fd
, uint64_t old_subvol_id
, uint64_t new_subvol_id
) {
1424 _cleanup_free_
uint64_t *old_qgroups
= NULL
, *old_parent_qgroups
= NULL
;
1425 bool copy_from_parent
= false, insert_intermediary_qgroup
= false;
1426 int n_old_qgroups
, n_old_parent_qgroups
, r
, i
;
1427 uint64_t old_parent_id
;
1431 /* Copies a reduced form of quota information from the old to
1432 * the new subvolume. */
1434 n_old_qgroups
= btrfs_qgroup_find_parents(fd
, old_subvol_id
, &old_qgroups
);
1435 if (n_old_qgroups
<= 0) /* Nothing to copy */
1436 return n_old_qgroups
;
1438 r
= btrfs_subvol_get_parent(fd
, old_subvol_id
, &old_parent_id
);
1440 /* We have no parent, hence nothing to copy. */
1441 n_old_parent_qgroups
= 0;
1445 n_old_parent_qgroups
= btrfs_qgroup_find_parents(fd
, old_parent_id
, &old_parent_qgroups
);
1446 if (n_old_parent_qgroups
< 0)
1447 return n_old_parent_qgroups
;
1450 for (i
= 0; i
< n_old_qgroups
; i
++) {
1454 r
= btrfs_qgroupid_split(old_qgroups
[i
], NULL
, &id
);
1458 if (id
== old_subvol_id
) {
1459 /* The old subvolume was member of a qgroup
1460 * that had the same id, but a different level
1461 * as it self. Let's set up something similar
1462 * in the destination. */
1463 insert_intermediary_qgroup
= true;
1467 for (j
= 0; j
< n_old_parent_qgroups
; j
++)
1468 if (old_parent_qgroups
[j
] == old_qgroups
[i
]) {
1469 /* The old subvolume shared a common
1470 * parent qgroup with its parent
1471 * subvolume. Let's set up something
1472 * similar in the destination. */
1473 copy_from_parent
= true;
1477 if (!insert_intermediary_qgroup
&& !copy_from_parent
)
1480 return btrfs_subvol_auto_qgroup_fd(fd
, new_subvol_id
, insert_intermediary_qgroup
);
1483 static int copy_subtree_quota_limits(int fd
, uint64_t old_subvol
, uint64_t new_subvol
) {
1484 uint64_t old_subtree_qgroup
, new_subtree_qgroup
;
1488 /* First copy the leaf limits */
1489 r
= btrfs_qgroup_copy_limits(fd
, old_subvol
, new_subvol
);
1494 /* Then, try to copy the subtree limits, if there are any. */
1495 r
= btrfs_subvol_find_subtree_qgroup(fd
, old_subvol
, &old_subtree_qgroup
);
1501 r
= btrfs_subvol_find_subtree_qgroup(fd
, new_subvol
, &new_subtree_qgroup
);
1507 r
= btrfs_qgroup_copy_limits(fd
, old_subtree_qgroup
, new_subtree_qgroup
);
1514 static int subvol_snapshot_children(int old_fd
, int new_fd
, const char *subvolume
, uint64_t old_subvol_id
, BtrfsSnapshotFlags flags
) {
1516 struct btrfs_ioctl_search_args args
= {
1517 .key
.tree_id
= BTRFS_ROOT_TREE_OBJECTID
,
1519 .key
.min_objectid
= BTRFS_FIRST_FREE_OBJECTID
,
1520 .key
.max_objectid
= BTRFS_LAST_FREE_OBJECTID
,
1522 .key
.min_type
= BTRFS_ROOT_BACKREF_KEY
,
1523 .key
.max_type
= BTRFS_ROOT_BACKREF_KEY
,
1525 .key
.min_transid
= 0,
1526 .key
.max_transid
= (uint64_t) -1,
1529 struct btrfs_ioctl_vol_args_v2 vol_args
= {
1530 .flags
= flags
& BTRFS_SNAPSHOT_READ_ONLY
? BTRFS_SUBVOL_RDONLY
: 0,
1533 _cleanup_close_
int subvolume_fd
= -1;
1534 uint64_t new_subvol_id
;
1537 assert(old_fd
>= 0);
1538 assert(new_fd
>= 0);
1541 strncpy(vol_args
.name
, subvolume
, sizeof(vol_args
.name
)-1);
1543 if (ioctl(new_fd
, BTRFS_IOC_SNAP_CREATE_V2
, &vol_args
) < 0)
1546 if (!(flags
& BTRFS_SNAPSHOT_RECURSIVE
) &&
1547 !(flags
& BTRFS_SNAPSHOT_QUOTA
))
1550 if (old_subvol_id
== 0) {
1551 r
= btrfs_subvol_get_id_fd(old_fd
, &old_subvol_id
);
1556 r
= btrfs_subvol_get_id(new_fd
, vol_args
.name
, &new_subvol_id
);
1560 if (flags
& BTRFS_SNAPSHOT_QUOTA
)
1561 (void) copy_quota_hierarchy(new_fd
, old_subvol_id
, new_subvol_id
);
1563 if (!(flags
& BTRFS_SNAPSHOT_RECURSIVE
)) {
1565 if (flags
& BTRFS_SNAPSHOT_QUOTA
)
1566 (void) copy_subtree_quota_limits(new_fd
, old_subvol_id
, new_subvol_id
);
1571 args
.key
.min_offset
= args
.key
.max_offset
= old_subvol_id
;
1573 while (btrfs_ioctl_search_args_compare(&args
) <= 0) {
1574 const struct btrfs_ioctl_search_header
*sh
;
1577 args
.key
.nr_items
= 256;
1578 if (ioctl(old_fd
, BTRFS_IOC_TREE_SEARCH
, &args
) < 0)
1581 if (args
.key
.nr_items
<= 0)
1584 FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i
, sh
, args
) {
1585 _cleanup_free_
char *p
= NULL
, *c
= NULL
, *np
= NULL
;
1586 struct btrfs_ioctl_ino_lookup_args ino_args
;
1587 const struct btrfs_root_ref
*ref
;
1588 _cleanup_close_
int old_child_fd
= -1, new_child_fd
= -1;
1590 btrfs_ioctl_search_args_set(&args
, sh
);
1592 if (sh
->type
!= BTRFS_ROOT_BACKREF_KEY
)
1595 /* Avoid finding the source subvolume a second
1597 if (sh
->offset
!= old_subvol_id
)
1600 /* Avoid running into loops if the new
1601 * subvolume is below the old one. */
1602 if (sh
->objectid
== new_subvol_id
)
1605 ref
= BTRFS_IOCTL_SEARCH_HEADER_BODY(sh
);
1606 p
= strndup((char*) ref
+ sizeof(struct btrfs_root_ref
), le64toh(ref
->name_len
));
1611 ino_args
.treeid
= old_subvol_id
;
1612 ino_args
.objectid
= htole64(ref
->dirid
);
1614 if (ioctl(old_fd
, BTRFS_IOC_INO_LOOKUP
, &ino_args
) < 0)
1617 /* The kernel returns an empty name if the
1618 * subvolume is in the top-level directory,
1619 * and otherwise appends a slash, so that we
1620 * can just concatenate easily here, without
1621 * adding a slash. */
1622 c
= strappend(ino_args
.name
, p
);
1626 old_child_fd
= openat(old_fd
, c
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
|O_DIRECTORY
|O_NOFOLLOW
);
1627 if (old_child_fd
< 0)
1630 np
= strjoin(subvolume
, "/", ino_args
.name
);
1634 new_child_fd
= openat(new_fd
, np
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
|O_DIRECTORY
|O_NOFOLLOW
);
1635 if (new_child_fd
< 0)
1638 if (flags
& BTRFS_SNAPSHOT_READ_ONLY
) {
1639 /* If the snapshot is read-only we
1640 * need to mark it writable
1641 * temporarily, to put the subsnapshot
1644 if (subvolume_fd
< 0) {
1645 subvolume_fd
= openat(new_fd
, subvolume
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
|O_DIRECTORY
|O_NOFOLLOW
);
1646 if (subvolume_fd
< 0)
1650 r
= btrfs_subvol_set_read_only_fd(subvolume_fd
, false);
1655 /* When btrfs clones the subvolumes, child
1656 * subvolumes appear as empty directories. Remove
1657 * them, so that we can create a new snapshot
1659 if (unlinkat(new_child_fd
, p
, AT_REMOVEDIR
) < 0) {
1662 if (flags
& BTRFS_SNAPSHOT_READ_ONLY
)
1663 (void) btrfs_subvol_set_read_only_fd(subvolume_fd
, true);
1668 r
= subvol_snapshot_children(old_child_fd
, new_child_fd
, p
, sh
->objectid
, flags
& ~BTRFS_SNAPSHOT_FALLBACK_COPY
);
1670 /* Restore the readonly flag */
1671 if (flags
& BTRFS_SNAPSHOT_READ_ONLY
) {
1674 k
= btrfs_subvol_set_read_only_fd(subvolume_fd
, true);
1675 if (r
>= 0 && k
< 0)
1683 /* Increase search key by one, to read the next item, if we can. */
1684 if (!btrfs_ioctl_search_args_inc(&args
))
1688 if (flags
& BTRFS_SNAPSHOT_QUOTA
)
1689 (void) copy_subtree_quota_limits(new_fd
, old_subvol_id
, new_subvol_id
);
1694 int btrfs_subvol_snapshot_fd(int old_fd
, const char *new_path
, BtrfsSnapshotFlags flags
) {
1695 _cleanup_close_
int new_fd
= -1;
1696 const char *subvolume
;
1699 assert(old_fd
>= 0);
1702 r
= btrfs_is_subvol_fd(old_fd
);
1706 bool plain_directory
= false;
1708 /* If the source isn't a proper subvolume, fail unless fallback is requested */
1709 if (!(flags
& BTRFS_SNAPSHOT_FALLBACK_COPY
))
1712 r
= btrfs_subvol_make(new_path
);
1713 if (r
== -ENOTTY
&& (flags
& BTRFS_SNAPSHOT_FALLBACK_DIRECTORY
)) {
1714 /* If the destination doesn't support subvolumes, then use a plain directory, if that's requested. */
1715 if (mkdir(new_path
, 0755) < 0)
1718 plain_directory
= true;
1722 r
= copy_directory_fd(old_fd
, new_path
, COPY_MERGE
|COPY_REFLINK
);
1726 if (flags
& BTRFS_SNAPSHOT_READ_ONLY
) {
1728 if (plain_directory
) {
1729 /* Plain directories have no recursive read-only flag, but something pretty close to
1730 * it: the IMMUTABLE bit. Let's use this here, if this is requested. */
1732 if (flags
& BTRFS_SNAPSHOT_FALLBACK_IMMUTABLE
)
1733 (void) chattr_path(new_path
, FS_IMMUTABLE_FL
, FS_IMMUTABLE_FL
);
1735 r
= btrfs_subvol_set_read_only(new_path
, true);
1744 (void) rm_rf(new_path
, REMOVE_ROOT
|REMOVE_PHYSICAL
|REMOVE_SUBVOLUME
);
1748 r
= extract_subvolume_name(new_path
, &subvolume
);
1752 new_fd
= open_parent(new_path
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
|O_DIRECTORY
);
1756 return subvol_snapshot_children(old_fd
, new_fd
, subvolume
, 0, flags
);
1759 int btrfs_subvol_snapshot(const char *old_path
, const char *new_path
, BtrfsSnapshotFlags flags
) {
1760 _cleanup_close_
int old_fd
= -1;
1765 old_fd
= open(old_path
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
|O_DIRECTORY
);
1769 return btrfs_subvol_snapshot_fd(old_fd
, new_path
, flags
);
1772 int btrfs_qgroup_find_parents(int fd
, uint64_t qgroupid
, uint64_t **ret
) {
1774 struct btrfs_ioctl_search_args args
= {
1775 /* Tree of quota items */
1776 .key
.tree_id
= BTRFS_QUOTA_TREE_OBJECTID
,
1778 /* Look precisely for the quota relation items */
1779 .key
.min_type
= BTRFS_QGROUP_RELATION_KEY
,
1780 .key
.max_type
= BTRFS_QGROUP_RELATION_KEY
,
1782 /* No restrictions on the other components */
1783 .key
.min_offset
= 0,
1784 .key
.max_offset
= (uint64_t) -1,
1786 .key
.min_transid
= 0,
1787 .key
.max_transid
= (uint64_t) -1,
1790 _cleanup_free_
uint64_t *items
= NULL
;
1791 size_t n_items
= 0, n_allocated
= 0;
1797 if (qgroupid
== 0) {
1798 r
= btrfs_subvol_get_id_fd(fd
, &qgroupid
);
1802 r
= btrfs_is_filesystem(fd
);
1809 args
.key
.min_objectid
= args
.key
.max_objectid
= qgroupid
;
1811 while (btrfs_ioctl_search_args_compare(&args
) <= 0) {
1812 const struct btrfs_ioctl_search_header
*sh
;
1815 args
.key
.nr_items
= 256;
1816 if (ioctl(fd
, BTRFS_IOC_TREE_SEARCH
, &args
) < 0) {
1817 if (errno
== ENOENT
) /* quota tree missing: quota is disabled */
1823 if (args
.key
.nr_items
<= 0)
1826 FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i
, sh
, args
) {
1828 /* Make sure we start the next search at least from this entry */
1829 btrfs_ioctl_search_args_set(&args
, sh
);
1831 if (sh
->type
!= BTRFS_QGROUP_RELATION_KEY
)
1833 if (sh
->offset
< sh
->objectid
)
1835 if (sh
->objectid
!= qgroupid
)
1838 if (!GREEDY_REALLOC(items
, n_allocated
, n_items
+1))
1841 items
[n_items
++] = sh
->offset
;
1844 /* Increase search key by one, to read the next item, if we can. */
1845 if (!btrfs_ioctl_search_args_inc(&args
))
1857 return (int) n_items
;
1860 int btrfs_subvol_auto_qgroup_fd(int fd
, uint64_t subvol_id
, bool insert_intermediary_qgroup
) {
1861 _cleanup_free_
uint64_t *qgroups
= NULL
;
1862 uint64_t parent_subvol
;
1863 bool changed
= false;
1869 * Sets up the specified subvolume's qgroup automatically in
1872 * If insert_intermediary_qgroup is false, the subvolume's
1873 * leaf qgroup will be assigned to the same parent qgroups as
1874 * the subvolume's parent subvolume.
1876 * If insert_intermediary_qgroup is true a new intermediary
1877 * higher-level qgroup is created, with a higher level number,
1878 * but reusing the id of the subvolume. The level number is
1879 * picked as one smaller than the lowest level qgroup the
1880 * parent subvolume is a member of. If the parent subvolume's
1881 * leaf qgroup is assigned to no higher-level qgroup a new
1882 * qgroup of level 255 is created instead. Either way, the new
1883 * qgroup is then assigned to the parent's higher-level
1884 * qgroup, and the subvolume itself is assigned to it.
1886 * If the subvolume is already assigned to a higher level
1887 * qgroup, no operation is executed.
1889 * Effectively this means: regardless if
1890 * insert_intermediary_qgroup is true or not, after this
1891 * function is invoked the subvolume will be accounted within
1892 * the same qgroups as the parent. However, if it is true, it
1893 * will also get its own higher-level qgroup, which may in
1894 * turn be used by subvolumes created beneath this subvolume
1897 * This hence defines a simple default qgroup setup for
1898 * subvolumes, as long as this function is invoked on each
1899 * created subvolume: each subvolume is always accounting
1900 * together with its immediate parents. Optionally, if
1901 * insert_intermediary_qgroup is true, it will also get a
1902 * qgroup that then includes all its own child subvolumes.
1905 if (subvol_id
== 0) {
1906 r
= btrfs_is_subvol_fd(fd
);
1912 r
= btrfs_subvol_get_id_fd(fd
, &subvol_id
);
1917 n
= btrfs_qgroup_find_parents(fd
, subvol_id
, &qgroups
);
1920 if (n
> 0) /* already parent qgroups set up, let's bail */
1923 qgroups
= mfree(qgroups
);
1925 r
= btrfs_subvol_get_parent(fd
, subvol_id
, &parent_subvol
);
1927 /* No parent, hence no qgroup memberships */
1932 n
= btrfs_qgroup_find_parents(fd
, parent_subvol
, &qgroups
);
1937 if (insert_intermediary_qgroup
) {
1938 uint64_t lowest
= 256, new_qgroupid
;
1939 bool created
= false;
1942 /* Determine the lowest qgroup that the parent
1943 * subvolume is assigned to. */
1945 for (i
= 0; i
< n
; i
++) {
1948 r
= btrfs_qgroupid_split(qgroups
[i
], &level
, NULL
);
1956 if (lowest
<= 1) /* There are no levels left we could use insert an intermediary qgroup at */
1959 r
= btrfs_qgroupid_make(lowest
- 1, subvol_id
, &new_qgroupid
);
1963 /* Create the new intermediary group, unless it already exists */
1964 r
= btrfs_qgroup_create(fd
, new_qgroupid
);
1965 if (r
< 0 && r
!= -EEXIST
)
1968 changed
= created
= true;
1970 for (i
= 0; i
< n
; i
++) {
1971 r
= btrfs_qgroup_assign(fd
, new_qgroupid
, qgroups
[i
]);
1972 if (r
< 0 && r
!= -EEXIST
) {
1974 (void) btrfs_qgroup_destroy_recursive(fd
, new_qgroupid
);
1982 r
= btrfs_qgroup_assign(fd
, subvol_id
, new_qgroupid
);
1983 if (r
< 0 && r
!= -EEXIST
) {
1985 (void) btrfs_qgroup_destroy_recursive(fd
, new_qgroupid
);
1994 /* Assign our subvolume to all the same qgroups as the parent */
1996 for (i
= 0; i
< n
; i
++) {
1997 r
= btrfs_qgroup_assign(fd
, subvol_id
, qgroups
[i
]);
1998 if (r
< 0 && r
!= -EEXIST
)
2008 int btrfs_subvol_auto_qgroup(const char *path
, uint64_t subvol_id
, bool create_intermediary_qgroup
) {
2009 _cleanup_close_
int fd
= -1;
2011 fd
= open(path
, O_RDONLY
|O_NOCTTY
|O_CLOEXEC
|O_DIRECTORY
);
2015 return btrfs_subvol_auto_qgroup_fd(fd
, subvol_id
, create_intermediary_qgroup
);
2018 int btrfs_subvol_get_parent(int fd
, uint64_t subvol_id
, uint64_t *ret
) {
2020 struct btrfs_ioctl_search_args args
= {
2021 /* Tree of tree roots */
2022 .key
.tree_id
= BTRFS_ROOT_TREE_OBJECTID
,
2024 /* Look precisely for the subvolume items */
2025 .key
.min_type
= BTRFS_ROOT_BACKREF_KEY
,
2026 .key
.max_type
= BTRFS_ROOT_BACKREF_KEY
,
2028 /* No restrictions on the other components */
2029 .key
.min_offset
= 0,
2030 .key
.max_offset
= (uint64_t) -1,
2032 .key
.min_transid
= 0,
2033 .key
.max_transid
= (uint64_t) -1,
2040 if (subvol_id
== 0) {
2041 r
= btrfs_subvol_get_id_fd(fd
, &subvol_id
);
2045 r
= btrfs_is_filesystem(fd
);
2052 args
.key
.min_objectid
= args
.key
.max_objectid
= subvol_id
;
2054 while (btrfs_ioctl_search_args_compare(&args
) <= 0) {
2055 const struct btrfs_ioctl_search_header
*sh
;
2058 args
.key
.nr_items
= 256;
2059 if (ioctl(fd
, BTRFS_IOC_TREE_SEARCH
, &args
) < 0)
2060 return negative_errno();
2062 if (args
.key
.nr_items
<= 0)
2065 FOREACH_BTRFS_IOCTL_SEARCH_HEADER(i
, sh
, args
) {
2067 if (sh
->type
!= BTRFS_ROOT_BACKREF_KEY
)
2069 if (sh
->objectid
!= subvol_id
)