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.
102 lines
3.3 KiB
102 lines
3.3 KiB
4 years ago
|
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
|
||
|
|