summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mkfs.c30
-rw-r--r--utils.c20
-rw-r--r--utils.h22
3 files changed, 72 insertions, 0 deletions
diff --git a/mkfs.c b/mkfs.c
index 7695c015..52b9a8d2 100644
--- a/mkfs.c
+++ b/mkfs.c
@@ -1451,6 +1451,36 @@ int main(int ac, char **av)
}
}
+ /* Check device/block_count after the leafsize is determined */
+ if (block_count && block_count < btrfs_min_dev_size(leafsize)) {
+ fprintf(stderr,
+ "Size '%llu' is too small to make a usable filesystem\n",
+ block_count);
+ fprintf(stderr,
+ "Minimum size for btrfs filesystem is %llu\n",
+ btrfs_min_dev_size(leafsize));
+ exit(1);
+ }
+ for (i = saved_optind; i < saved_optind + dev_cnt; i++) {
+ char *path;
+
+ path = av[i];
+ ret = test_minimum_size(path, leafsize);
+ if (ret < 0) {
+ fprintf(stderr, "Failed to check size for '%s': %s\n",
+ path, strerror(-ret));
+ exit (1);
+ }
+ if (ret > 0) {
+ fprintf(stderr,
+ "'%s' is too small to make a usable filesystem\n",
+ path);
+ fprintf(stderr,
+ "Minimum size for each btrfs device is %llu.\n",
+ btrfs_min_dev_size(leafsize));
+ exit(1);
+ }
+ }
ret = test_num_disk_vs_raid(metadata_profile, data_profile,
dev_cnt, mixed, estr);
if (ret) {
diff --git a/utils.c b/utils.c
index 46c3a431..c139eb2e 100644
--- a/utils.c
+++ b/utils.c
@@ -2344,3 +2344,23 @@ int find_mount_root(const char *path, char **mount_root)
free(longest_match);
return ret;
}
+
+int test_minimum_size(const char *file, u32 leafsize)
+{
+ int fd;
+ struct stat statbuf;
+
+ fd = open(file, O_RDONLY);
+ if (fd < 0)
+ return -errno;
+ if (stat(file, &statbuf) < 0) {
+ close(fd);
+ return -errno;
+ }
+ if (btrfs_device_size(fd, &statbuf) < btrfs_min_dev_size(leafsize)) {
+ close(fd);
+ return 1;
+ }
+ close(fd);
+ return 0;
+}
diff --git a/utils.h b/utils.h
index 37fe1ba0..6599ee4d 100644
--- a/utils.h
+++ b/utils.h
@@ -105,4 +105,26 @@ int get_device_info(int fd, u64 devid,
struct btrfs_ioctl_dev_info_args *di_args);
int test_uuid_unique(char *fs_uuid);
+int test_minimum_size(const char *file, u32 leafsize);
+
+/*
+ * Btrfs minimum size calculation is complicated, it should include at least:
+ * 1. system group size
+ * 2. minimum global block reserve
+ * 3. metadata used at mkfs
+ * 4. space reservation to create uuid for first mount.
+ * Also, raid factor should also be taken into consideration.
+ * To avoid the overkill calculation, (system group + global block rsv) * 2
+ * for *EACH* device should be good enough.
+ */
+static inline u64 btrfs_min_global_blk_rsv_size(u32 leafsize)
+{
+ return leafsize << 10;
+}
+static inline u64 btrfs_min_dev_size(u32 leafsize)
+{
+ return 2 * (BTRFS_MKFS_SYSTEM_GROUP_SIZE +
+ btrfs_min_global_blk_rsv_size(leafsize));
+}
+
#endif