]> git.ipfire.org Git - thirdparty/e2fsprogs.git/commitdiff
e2fsprogs-nlinks-flag.patch
authorAndreas Dilger <adilger@sun.com>
Sat, 2 Feb 2008 08:36:10 +0000 (01:36 -0700)
committerTheodore Ts'o <tytso@mit.edu>
Mon, 11 Feb 2008 03:21:57 +0000 (22:21 -0500)
If there are any directories with > 65000 subdirectories, enable the
DIR_NLINK feature in the superblock.  If there are any directories
that formerly had > 65000 subdirs (i_links_count == 1) but no longer
do, don't consider this an error to alert the user about, but silently
fix the link count to the currently counted link count.

The DIR_NLINK feature is not disabled if set but no many-subdir directories
are found, so that the kernel is not required to enable it on-the-fly.  The
admin should set it with tune2fs instead.

e2fsck/pass4.c
e2fsck/problem.c
e2fsck/problem.h
misc/tune2fs.8.in
misc/tune2fs.c

index ad3a22ec78a10e560e63c3686c7363c6ab9996fc..5caf590f7d29a7bbe64d23516b863f127d3ac28d 100644 (file)
@@ -101,6 +101,7 @@ void e2fsck_pass4(e2fsck_t ctx)
        struct problem_context  pctx;
        __u16   link_count;
        __u32   link_counted;
+       __u32   many_subdirs = 0;
        char    *buf = 0;
        int     group, maxgroup;
        
@@ -182,7 +183,20 @@ void e2fsck_pass4(e2fsck_t ctx)
                                e2fsck_write_inode(ctx, i, inode, "pass4");
                        }
                }
+               if (link_count == 1 && link_counted > EXT2_LINK_MAX)
+                       many_subdirs++;
        }
+
+       if (many_subdirs) {
+               if (!(fs->super->s_feature_ro_compat &
+                     EXT4_FEATURE_RO_COMPAT_DIR_NLINK) &&
+                   fix_problem(ctx, PR_4_FEATURE_DIR_NLINK, &pctx)) {
+                       fs->super->s_feature_ro_compat |=
+                               EXT4_FEATURE_RO_COMPAT_DIR_NLINK;
+                       ext2fs_mark_super_dirty(fs);
+               }
+       }
+
        ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0;
        ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0;
        ext2fs_free_inode_bitmap(ctx->inode_bb_map);
index 6b0b512c0669dc76ad3f26bf5daab3ef47f08a61..bc0607ff6bf15e91353c0e9134a54a53b861271d 100644 (file)
@@ -1446,6 +1446,11 @@ static struct e2fsck_problem problem_table[] = {
          "They @s the same!\n"),
          PROMPT_NONE, 0 },
 
+       /* DIR_NLINK flag not set but dirs with > 65000 subdirs found */
+       { PR_4_FEATURE_DIR_NLINK,
+         N_("@f has @d with > 65000 subdirs, but no DIR_NLINK flag in @S.\n"),
+          PROMPT_FIX, 0 },
+
        /* Pass 5 errors */
                  
        /* Pass 5: Checking group summary information */
index 62e102de5a715b44ed870e404cb4f69c4652a9f4..8594f573a5374609f0897b7e1758e5b3845ff0f3 100644 (file)
@@ -873,6 +873,10 @@ struct problem_context {
 /* Inconsistent inode count information cached */
 #define PR_4_INCONSISTENT_COUNT        0x040004
 
+/* Directory with > EXT2_LINK_MAX subdirs found but
+ * EXT4_FEATURE_RO_COMPAT_DIR_NLINK flag is not set */
+#define PR_4_FEATURE_DIR_NLINK 0x040005
+
 /*
  * Pass 5 errors
  */
index a135920c373b3621b1136ab1e30fcef496fd9032..b348507484dff717c1c81837a40ab29e2fa7ce3e 100644 (file)
@@ -400,6 +400,10 @@ The following filesystem features can be set or cleared using
 .B dir_index
 Use hashed b-trees to speed up lookups in large directories.
 .TP
+.B dir_nlink
+Allow directories to have more than 65000 subdirectories (read-only
+compatible).
+.TP
 .B filetype
 Store file type information in directory entries.
 .TP
index 416ea4f80934ba46d037b1d17af0fedd22432929..f7b61b67af920619a11b0479dbb31eeb6b3bdfba 100644 (file)
@@ -110,7 +110,8 @@ static __u32 ok_features[3] = {
                EXT2_FEATURE_COMPAT_DIR_INDEX,  /* Compat */
        EXT2_FEATURE_INCOMPAT_FILETYPE,         /* Incompat */
        EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|    /* R/O compat */
-               EXT4_FEATURE_RO_COMPAT_GDT_CSUM
+               EXT4_FEATURE_RO_COMPAT_GDT_CSUM |
+               EXT4_FEATURE_RO_COMPAT_DIR_NLINK
 };
 
 /*
@@ -298,6 +299,7 @@ static void update_feature_set(ext2_filsys fs, char *features)
        int sparse, old_sparse, filetype, old_filetype;
        int journal, old_journal, dxdir, old_dxdir, uninit;
        struct ext2_super_block *sb= fs->super;
+       int dir_nlink, old_dir_nlink;
        __u32   old_compat, old_incompat, old_ro_compat, old_uninit;
 
        old_compat = sb->s_feature_compat;
@@ -306,6 +308,8 @@ static void update_feature_set(ext2_filsys fs, char *features)
 
        old_sparse = sb->s_feature_ro_compat &
                EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
+       old_dir_nlink = sb->s_feature_ro_compat &
+               EXT4_FEATURE_RO_COMPAT_DIR_NLINK;
        old_filetype = sb->s_feature_incompat &
                EXT2_FEATURE_INCOMPAT_FILETYPE;
        old_journal = sb->s_feature_compat &
@@ -322,6 +326,8 @@ static void update_feature_set(ext2_filsys fs, char *features)
        }
        sparse = sb->s_feature_ro_compat &
                EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
+       dir_nlink = sb->s_feature_ro_compat &
+               EXT4_FEATURE_RO_COMPAT_DIR_NLINK;
        filetype = sb->s_feature_incompat &
                EXT2_FEATURE_INCOMPAT_FILETYPE;
        journal = sb->s_feature_compat &