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