summaryrefslogtreecommitdiff
path: root/mkfs/rootdir.c
diff options
context:
space:
mode:
authorQu Wenruo <wqu@suse.com>2017-10-19 13:41:38 +0800
committerDavid Sterba <dsterba@suse.com>2018-01-08 18:11:33 +0100
commit8719161b4c2cefdf1bbb87800ee6fada57bcac9c (patch)
treefe3251b3e3e32229b22eeef2947a9256c8d03e12 /mkfs/rootdir.c
parent075580471e0f7435c52df486eb4354031337a7d3 (diff)
btrfs-progs: mkfs: move source dir size calculation to its own files
Also rename the function from size_sourcedir() to mkfs_size_dir(). Signed-off-by: Qu Wenruo <wqu@suse.com> Reviewed-by: Nikolay Borisov <nborisov@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'mkfs/rootdir.c')
-rw-r--r--mkfs/rootdir.c63
1 files changed, 63 insertions, 0 deletions
diff --git a/mkfs/rootdir.c b/mkfs/rootdir.c
index 2cc8a3ac..83a3191d 100644
--- a/mkfs/rootdir.c
+++ b/mkfs/rootdir.c
@@ -24,6 +24,7 @@
#include <dirent.h>
#include <unistd.h>
#include <fcntl.h>
+#include <ftw.h>
#include "ctree.h"
#include "internal.h"
#include "disk-io.h"
@@ -33,6 +34,15 @@
#include "mkfs/rootdir.h"
#include "send-utils.h"
+/*
+ * This ignores symlinks with unreadable targets and subdirs that can't
+ * be read. It's a best-effort to give a rough estimate of the size of
+ * a subdir. It doesn't guarantee that prepopulating btrfs from this
+ * tree won't still run out of space.
+ */
+static u64 global_total_size;
+static u64 fs_block_size;
+
static u64 index_cnt = 2;
static int add_directory_items(struct btrfs_trans_handle *trans,
@@ -670,3 +680,56 @@ fail:
out:
return ret;
}
+
+static int ftw_add_entry_size(const char *fpath, const struct stat *st,
+ int type)
+{
+ if (type == FTW_F || type == FTW_D)
+ global_total_size += round_up(st->st_size, fs_block_size);
+
+ return 0;
+}
+
+u64 btrfs_mkfs_size_dir(const char *dir_name, u64 sectorsize,
+ u64 *num_of_meta_chunks_ret, u64 *size_of_data_ret)
+{
+ u64 dir_size = 0;
+ u64 total_size = 0;
+ int ret;
+ u64 default_chunk_size = SZ_8M;
+ u64 allocated_meta_size = SZ_8M;
+ u64 allocated_total_size = 20 * SZ_1M; /* 20MB */
+ u64 num_of_meta_chunks = 0;
+ u64 num_of_data_chunks = 0;
+ u64 num_of_allocated_meta_chunks =
+ allocated_meta_size / default_chunk_size;
+
+ global_total_size = 0;
+ fs_block_size = sectorsize;
+ ret = ftw(dir_name, ftw_add_entry_size, 10);
+ dir_size = global_total_size;
+ if (ret < 0) {
+ error("ftw subdir walk of %s failed: %s", dir_name,
+ strerror(errno));
+ exit(1);
+ }
+
+ num_of_data_chunks = (dir_size + default_chunk_size - 1) /
+ default_chunk_size;
+
+ num_of_meta_chunks = (dir_size / 2) / default_chunk_size;
+ if (((dir_size / 2) % default_chunk_size) != 0)
+ num_of_meta_chunks++;
+ if (num_of_meta_chunks <= num_of_allocated_meta_chunks)
+ num_of_meta_chunks = 0;
+ else
+ num_of_meta_chunks -= num_of_allocated_meta_chunks;
+
+ total_size = allocated_total_size +
+ (num_of_data_chunks * default_chunk_size) +
+ (num_of_meta_chunks * default_chunk_size);
+
+ *num_of_meta_chunks_ret = num_of_meta_chunks;
+ *size_of_data_ret = num_of_data_chunks * default_chunk_size;
+ return total_size;
+}