You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
101 lines
3.3 KiB
101 lines
3.3 KiB
From 458939e5d9441448f87d3a6d45c84e041ee14786 Mon Sep 17 00:00:00 2001 |
|
From: Andreas Dilger <adilger@dilger.ca> |
|
Date: Fri, 22 Jun 2018 18:08:54 -0400 |
|
Subject: [PATCH 2/2] e2fsck: set dir_nlink feature if large dir exists |
|
|
|
commit 1a8015773a9316ee90f713c275fb3a38731735e4 |
|
|
|
If there is a directory with more than EXT2_LINK_MAX (65000) |
|
subdirectories, but the DIR_NLINK feature is not set in the |
|
superblock, the feature should be set before continuing on |
|
to change the on-disk directory link count to 1. |
|
|
|
While most filesystems should have DIR_NLINK set (it was set |
|
by default for all ext4 filesystems, and all kernels between |
|
2.6.23 and 4.12 automatically set it if the directory link |
|
count grew too large), it is possible that this flag is lost |
|
due to disk corruption or for an upgraded filesystem. We no |
|
longer want kernels to automatically enable features. |
|
|
|
Addresses: https://bugzilla.kernel.org/show_bug.cgi?id=196405 |
|
Signed-off-by: Andreas Dilger <adilger@dilger.ca> |
|
Signed-off-by: Theodore Ts'o <tytso@mit.edu> |
|
--- |
|
e2fsck/pass4.c | 14 +++++++++++++- |
|
e2fsck/problem.c | 5 +++++ |
|
e2fsck/problem.h | 3 +++ |
|
3 files changed, 21 insertions(+), 1 deletion(-) |
|
|
|
diff --git a/e2fsck/pass4.c b/e2fsck/pass4.c |
|
index 21d93f0c..ad95227c 100644 |
|
--- a/e2fsck/pass4.c |
|
+++ b/e2fsck/pass4.c |
|
@@ -98,6 +98,7 @@ void e2fsck_pass4(e2fsck_t ctx) |
|
#endif |
|
struct problem_context pctx; |
|
__u16 link_count, link_counted; |
|
+ int dir_nlink_fs; |
|
char *buf = 0; |
|
dgrp_t group, maxgroup; |
|
|
|
@@ -112,6 +113,9 @@ void e2fsck_pass4(e2fsck_t ctx) |
|
if (!(ctx->options & E2F_OPT_PREEN)) |
|
fix_problem(ctx, PR_4_PASS_HEADER, &pctx); |
|
|
|
+ dir_nlink_fs = EXT2_HAS_RO_COMPAT_FEATURE(fs->super, |
|
+ EXT4_FEATURE_RO_COMPAT_DIR_NLINK); |
|
+ |
|
group = 0; |
|
maxgroup = fs->group_desc_count; |
|
if (ctx->progress) |
|
@@ -158,8 +162,16 @@ void e2fsck_pass4(e2fsck_t ctx) |
|
&link_counted); |
|
} |
|
isdir = ext2fs_test_inode_bitmap2(ctx->inode_dir_map, i); |
|
- if (isdir && (link_counted > EXT2_LINK_MAX)) |
|
+ if (isdir && (link_counted > EXT2_LINK_MAX)) { |
|
+ if (!dir_nlink_fs && |
|
+ fix_problem(ctx, PR_4_DIR_NLINK_FEATURE, &pctx)) { |
|
+ fs->super->s_feature_ro_compat |= |
|
+ EXT4_FEATURE_RO_COMPAT_DIR_NLINK; |
|
+ ext2fs_mark_super_dirty(fs); |
|
+ dir_nlink_fs = 1; |
|
+ } |
|
link_counted = 1; |
|
+ } |
|
if (link_counted != link_count) { |
|
e2fsck_read_inode(ctx, i, inode, "pass4"); |
|
pctx.ino = i; |
|
diff --git a/e2fsck/problem.c b/e2fsck/problem.c |
|
index c3ba631b..0210ff8f 100644 |
|
--- a/e2fsck/problem.c |
|
+++ b/e2fsck/problem.c |
|
@@ -1576,6 +1576,11 @@ static struct e2fsck_problem problem_table[] = { |
|
"They @s the same!\n"), |
|
PROMPT_NONE, 0 }, |
|
|
|
+ /* directory exceeds max links, but no DIR_NLINK feature in superblock*/ |
|
+ { PR_4_DIR_NLINK_FEATURE, |
|
+ N_("@d exceeds max links, but no DIR_NLINK feature in @S.\n"), |
|
+ PROMPT_FIX, 0 }, |
|
+ |
|
/* Pass 5 errors */ |
|
|
|
/* Pass 5: Checking group summary information */ |
|
diff --git a/e2fsck/problem.h b/e2fsck/problem.h |
|
index cf2df8ce..5712de59 100644 |
|
--- a/e2fsck/problem.h |
|
+++ b/e2fsck/problem.h |
|
@@ -1040,6 +1040,9 @@ struct problem_context { |
|
/* Update quota information if it is inconsistent */ |
|
#define PR_6_UPDATE_QUOTAS 0x060002 |
|
|
|
+/* directory exceeds max links, but no DIR_NLINK feature in superblock */ |
|
+#define PR_4_DIR_NLINK_FEATURE 0x040006 |
|
+ |
|
/* |
|
* Function declarations |
|
*/ |
|
-- |
|
2.20.1 |
|
|
|
|