Blame SOURCES/e2fsprogs-1.42.9-14-e2fsck-set-dir_nlink-feature-if-large-dir-exists.patch

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