Skip to content

Commit

Permalink
btrfs-progs: mkfs: print only first warning when --rootdir finds a ha…
Browse files Browse the repository at this point in the history
…rdlink

There's a report that newly added --rootdir print too many warnings for
hardlinks, which is maybe not that uncommon. We still want to let the
user know about that so print it just once and count how many were
found:

  $ mkfs.btrfs --rootdir ...
  WARNING: '/tmp/btrfs-progs-mkfs-rootdir-hardlinks.7RcdfR/rootdir/inside_link' has extra hardlinks, they will be converted into new inodes
  WARNING: 12 hardlinks were detected in /tmp/btrfs-progs-mkfs-rootdir-hardlinks.7RcdfR/rootdir, all converted to new inodes

Link: #872 (comment)
Signed-off-by: David Sterba <[email protected]>
  • Loading branch information
kdave committed Aug 14, 2024
1 parent 07b8c74 commit 8b36a29
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 3 deletions.
21 changes: 18 additions & 3 deletions mkfs/rootdir.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ static struct rootdir_path current_path = {
.level = 0,
};

/* Track if a hardlink was found and a warning was printed. */
static bool g_hardlink_warning;
static u64 g_hardlink_count;
static struct btrfs_trans_handle *g_trans = NULL;

static inline struct inode_entry *rootdir_path_last(struct rootdir_path *path)
Expand Down Expand Up @@ -428,9 +431,14 @@ static int ftw_add_inode(const char *full_path, const struct stat *st,
* On most filesystems st_nlink of a directory is the number of
* subdirs, including "." and "..", so skip directory inodes.
*/
if (unlikely(!S_ISDIR(st->st_mode) && st->st_nlink > 1))
warning("'%s' has extra hard links, they will be converted into new inodes",
full_path);
if (unlikely(!S_ISDIR(st->st_mode) && st->st_nlink > 1)) {
if (!g_hardlink_warning) {
warning("'%s' has extra hardlinks, they will be converted into new inodes",
full_path);
g_hardlink_warning = true;
}
g_hardlink_count++;
}

/* The rootdir itself. */
if (unlikely(ftwbuf->level == 0)) {
Expand Down Expand Up @@ -612,6 +620,8 @@ int btrfs_mkfs_fill_dir(const char *source_dir, struct btrfs_root *root)
}

g_trans = trans;
g_hardlink_warning = false;
g_hardlink_count = 0;
INIT_LIST_HEAD(&current_path.inode_list);

ret = nftw(source_dir, ftw_add_inode, 32, FTW_PHYS);
Expand All @@ -625,6 +635,11 @@ int btrfs_mkfs_fill_dir(const char *source_dir, struct btrfs_root *root)
error_msg(ERROR_MSG_COMMIT_TRANS, "%m");
goto out;
}

if (g_hardlink_warning)
warning("%llu hardlinks were detected in %s, all converted to new inodes",
g_hardlink_count, source_dir);

while (current_path.level > 0)
rootdir_path_pop(&current_path);

Expand Down
6 changes: 6 additions & 0 deletions tests/mkfs-tests/034-rootdir-extra-hard-links/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ run_check mkdir "$tmpdir/rootdir"
run_check touch "$tmpdir/rootdir/inside_link"
run_check ln "$tmpdir/rootdir/inside_link" "$tmpdir/outside_link"

# Add more links to trigger the warnings
run_check touch "$tmpdir/rootdir/link0"
for i in {1..10}; do
run_check ln "$tmpdir/rootdir/link0" "$tmpdir/rootdir/link$i"
done

run_check_mkfs_test_dev --rootdir "$tmpdir/rootdir"

# For older mkfs.btrfs --rootdir we will create inside_link with 2 links,
Expand Down

0 comments on commit 8b36a29

Please sign in to comment.