1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 #include <linux/btrfs.h>
4 #include <linux/magic.h>
8 #include "blockdev-util.h"
10 #include "missing_fs.h"
11 #include "missing_magic.h"
12 #include "missing_xfs.h"
13 #include "resize-fs.h"
14 #include "stat-util.h"
16 int resize_fs(int fd
, uint64_t sz
, uint64_t *ret_size
) {
21 /* Rounds down to next block size */
23 if (sz
<= 0 || sz
== UINT64_MAX
)
26 if (fstatfs(fd
, &sfs
) < 0)
29 if (is_fs_type(&sfs
, EXT4_SUPER_MAGIC
)) {
32 if (sz
< EXT4_MINIMAL_SIZE
)
37 if (ioctl(fd
, EXT4_IOC_RESIZE_FS
, &u
) < 0)
41 *ret_size
= u
* sfs
.f_bsize
;
43 } else if (is_fs_type(&sfs
, BTRFS_SUPER_MAGIC
)) {
44 struct btrfs_ioctl_vol_args args
= {};
46 /* 256M is the minimize size enforced by the btrfs kernel code when resizing (which is
47 * strange btw, as mkfs.btrfs is fine creating file systems > 109M). It will return EINVAL in
48 * that case, let's catch this error beforehand though, and report a more explanatory
51 if (sz
< BTRFS_MINIMAL_SIZE
)
54 sz
-= sz
% sfs
.f_bsize
;
56 xsprintf(args
.name
, "%" PRIu64
, sz
);
58 if (ioctl(fd
, BTRFS_IOC_RESIZE
, &args
) < 0)
64 } else if (is_fs_type(&sfs
, XFS_SUPER_MAGIC
)) {
68 if (sz
< XFS_MINIMAL_SIZE
)
71 if (ioctl(fd
, XFS_IOC_FSGEOMETRY
, &geo
) < 0)
74 d
= (xfs_growfs_data_t
) {
75 .imaxpct
= geo
.imaxpct
,
76 .newblocks
= sz
/ geo
.blocksize
,
79 if (ioctl(fd
, XFS_IOC_FSGROWFSDATA
, &d
) < 0)
83 *ret_size
= d
.newblocks
* geo
.blocksize
;
91 uint64_t minimal_size_by_fs_magic(statfs_f_type_t magic
) {
95 case (statfs_f_type_t
) EXT4_SUPER_MAGIC
:
96 return EXT4_MINIMAL_SIZE
;
98 case (statfs_f_type_t
) XFS_SUPER_MAGIC
:
99 return XFS_MINIMAL_SIZE
;
101 case (statfs_f_type_t
) BTRFS_SUPER_MAGIC
:
102 return BTRFS_MINIMAL_SIZE
;
109 uint64_t minimal_size_by_fs_name(const char *name
) {
111 if (streq_ptr(name
, "ext4"))
112 return EXT4_MINIMAL_SIZE
;
114 if (streq_ptr(name
, "xfs"))
115 return XFS_MINIMAL_SIZE
;
117 if (streq_ptr(name
, "btrfs"))
118 return BTRFS_MINIMAL_SIZE
;
123 /* Returns true for the only fs that can online shrink *and* grow */
124 bool fs_can_online_shrink_and_grow(statfs_f_type_t magic
) {
125 return magic
== (statfs_f_type_t
) BTRFS_SUPER_MAGIC
;