diff mbox

[1/3] mke2fs: enable large directroy support

Message ID CAO3qy=F_CxQQ0bUtOm5CZbE0QQ78vyviMStOgg8nryUZZymung@mail.gmail.com
State Not Applicable, archived
Headers show

Commit Message

Artem Blagodarenko Jan. 24, 2017, 4:34 p.m. UTC
The INCOMPAT_LARGEDIR feature allows larger directories to
be created, both with directory sizes over 2GB and and a
maximum htree depth of 3 instead of the current limit of 2.
These features are needed in order to exceed the currently
limit of approximately 10M entries in a single directory.

debugfs, e2fsck, ext2fs, mke2fs and tune2fs support is
added.

Signed-off-by: Alexey Lyashkov <alexey.lyashkov@seagate.com>
Signed-off-by: Artem Blagodarenko <artem.blagodarenko@seagate.com>
---
 debugfs/debugfs.c            |   16 +++++++---------
 debugfs/set_fields.c         |    1 -
 e2fsck/message.c             |    4 ----
 e2fsck/pass1.c               |    5 ++---
 e2fsck/pass2.c               |   11 ++---------
 e2fsck/problem.c             |    5 -----
 e2fsck/problem.h             |    3 ---
 lib/ext2fs/ext2_fs.h         |    9 ++++-----
 lib/ext2fs/ext2fs.h          |   15 ++++++++++++++-
 lib/ext2fs/swapfs.c          |    2 +-
 misc/mke2fs.c                |    3 ++-
 misc/tune2fs.c               |    3 ++-
 tests/d_special_files/expect |   10 +++++-----
 tests/f_badcluster/expect    |   14 +++++++-------
 tests/f_recnect_bad/expect.1 |    3 ---
 15 files changed, 46 insertions(+), 58 deletions(-)

--

Comments

Darrick Wong Jan. 24, 2017, 6:08 p.m. UTC | #1
On Tue, Jan 24, 2017 at 07:34:13PM +0300, Artem Blagodarenko wrote:
> The INCOMPAT_LARGEDIR feature allows larger directories to
> be created, both with directory sizes over 2GB and and a
> maximum htree depth of 3 instead of the current limit of 2.
> These features are needed in order to exceed the currently
> limit of approximately 10M entries in a single directory.
> 
> debugfs, e2fsck, ext2fs, mke2fs and tune2fs support is
> added.
> 
> Signed-off-by: Alexey Lyashkov <alexey.lyashkov@seagate.com>
> Signed-off-by: Artem Blagodarenko <artem.blagodarenko@seagate.com>
> ---
>  debugfs/debugfs.c            |   16 +++++++---------
>  debugfs/set_fields.c         |    1 -
>  e2fsck/message.c             |    4 ----
>  e2fsck/pass1.c               |    5 ++---
>  e2fsck/pass2.c               |   11 ++---------
>  e2fsck/problem.c             |    5 -----
>  e2fsck/problem.h             |    3 ---
>  lib/ext2fs/ext2_fs.h         |    9 ++++-----
>  lib/ext2fs/ext2fs.h          |   15 ++++++++++++++-
>  lib/ext2fs/swapfs.c          |    2 +-
>  misc/mke2fs.c                |    3 ++-
>  misc/tune2fs.c               |    3 ++-
>  tests/d_special_files/expect |   10 +++++-----
>  tests/f_badcluster/expect    |   14 +++++++-------
>  tests/f_recnect_bad/expect.1 |    3 ---
>  15 files changed, 46 insertions(+), 58 deletions(-)
> 
> diff --git a/debugfs/debugfs.c b/debugfs/debugfs.c
> index b40d9e2..795bdc3 100644
> --- a/debugfs/debugfs.c
> +++ b/debugfs/debugfs.c
> @@ -841,16 +841,15 @@ void internal_dump_inode(FILE *out, const char *prefix,
>          fprintf(out, "%d\n", inode->i_size);
>      if (os == EXT2_OS_HURD)
>          fprintf(out,
> -            "%sFile ACL: %d    Directory ACL: %d Translator: %d\n",
> +            "%sFile ACL: %d Translator: %d\n",
>              prefix,
> -            inode->i_file_acl, LINUX_S_ISDIR(inode->i_mode) ?
> inode->i_dir_acl : 0,
> +            inode->i_file_acl,
>              inode->osd1.hurd1.h_i_translator);
>      else
> -        fprintf(out, "%sFile ACL: %llu    Directory ACL: %d\n",
> +        fprintf(out, "%sFile ACL: %llu\n",
>              prefix,
>              inode->i_file_acl | ((long long)
> -                (inode->osd2.linux2.l_i_file_acl_high) << 32),
> -            LINUX_S_ISDIR(inode->i_mode) ? inode->i_dir_acl : 0);
> +                (inode->osd2.linux2.l_i_file_acl_high) << 32));
>      if (os != EXT2_OS_HURD)
>          fprintf(out, "%sLinks: %d   Blockcount: %llu\n",
>              prefix, inode->i_links_count,
> @@ -1347,10 +1346,9 @@ void do_modify_inode(int argc, char *argv[])
>      modify_u32(argv[0], "Reserved1", decimal_format, &inode.i_reserved1);
>  #endif
>      modify_u32(argv[0], "File acl", decimal_format, &inode.i_file_acl);
> -    if (LINUX_S_ISDIR(inode.i_mode))
> -        modify_u32(argv[0], "Directory acl", decimal_format, &inode.i_dir_acl);
> -    else
> -        modify_u32(argv[0], "High 32bits of size", decimal_format,
> &inode.i_size_high);
> +
> +    modify_u32(argv[0], "High 32bits of size", decimal_format,
> +           &inode.i_size_high);

Ugh, this patch removes dir_acl /and/ adds support for 3-level htrees!

Please break this up into separate patches for each of those two changes.

"e2fsprogs: supersede i_dir_acl with i_size_high for all cases"
"e2fsprogs: add support for 3-level htree"

> 
>      if (os == EXT2_OS_HURD)
>          modify_u32(argv[0], "Translator Block",
> diff --git a/debugfs/set_fields.c b/debugfs/set_fields.c
> index ff9b7b6..ca68862 100644
> --- a/debugfs/set_fields.c
> +++ b/debugfs/set_fields.c
> @@ -212,7 +212,6 @@ static struct field_set_info inode_fields[] = {
>      /* Special case: i_file_acl_high is 2 bytes */
>      { "file_acl", &set_inode.i_file_acl,
>          &set_inode.osd2.linux2.l_i_file_acl_high, 6, parse_uint },
> -    { "dir_acl", &set_inode.i_dir_acl, NULL, 4, parse_uint, FLAG_ALIAS },
>      { "faddr", &set_inode.i_faddr, NULL, 4, parse_uint },
>      { "frag", &set_inode.osd2.hurd2.h_i_frag, NULL, 1, parse_uint,
> FLAG_ALIAS },
>      { "fsize", &set_inode.osd2.hurd2.h_i_fsize, NULL, 1, parse_uint },
> diff --git a/e2fsck/message.c b/e2fsck/message.c
> index 1c3fcd8..d21ba05 100644
> --- a/e2fsck/message.c
> +++ b/e2fsck/message.c
> @@ -318,10 +318,6 @@ static _INLINE_ void expand_inode_expression(FILE
> *f, ext2_filsys fs, char ch,
>      case 'f':
>          fprintf(f, "%llu", ext2fs_file_acl_block(fs, inode));
>          break;
> -    case 'd':
> -        fprintf(f, "%u", (LINUX_S_ISDIR(inode->i_mode) ?
> -                  inode->i_dir_acl : 0));
> -        break;
>      case 'u':
>          fprintf(f, "%d", inode_uid(*inode));
>          break;
> diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c
> index 8ef40f6..8444b37 100644
> --- a/e2fsck/pass1.c
> +++ b/e2fsck/pass1.c
> @@ -1715,8 +1715,7 @@ void e2fsck_pass1(e2fsck_t ctx)
>              frag = fsize = 0;
>          }
> 
> -        if (inode->i_faddr || frag || fsize ||
> -            (LINUX_S_ISDIR(inode->i_mode) && inode->i_dir_acl))
> +        if (inode->i_faddr || frag || fsize)
>              mark_inode_bad(ctx, ino);
>          if ((fs->super->s_creator_os != EXT2_OS_HURD) &&
>              !ext2fs_has_feature_64bit(fs->super) &&
> @@ -2469,7 +2468,7 @@ static int handle_htree(e2fsck_t ctx, struct
> problem_context *pctx,
>          return 1;
> 
>      pctx->num = root->indirect_levels;
> -    if ((root->indirect_levels > 1) &&
> +    if ((root->indirect_levels > ext2_dir_htree_level(fs)) &&
>          fix_problem(ctx, PR_1_HTREE_DEPTH, pctx))
>          return 1;
> 
> diff --git a/e2fsck/pass2.c b/e2fsck/pass2.c
> index 11c19e8..7ded7bb 100644
> --- a/e2fsck/pass2.c
> +++ b/e2fsck/pass2.c
> @@ -1058,7 +1058,8 @@ inline_read_fail:
>              dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST;
>              if ((root->reserved_zero ||
>                   root->info_length < 8 ||
> -                 root->indirect_levels > 1) &&
> +                 root->indirect_levels
> +                > ext2_dir_htree_level(fs)) &&
>                  fix_problem(ctx, PR_2_HTREE_BAD_ROOT, &cd->pctx)) {
>                  clear_htree(ctx, ino);
>                  dx_dir->numblocks = 0;
> @@ -1811,14 +1812,6 @@ int e2fsck_process_bad_inode(e2fsck_t ctx,
> ext2_ino_t dir,
>          } else
>              not_fixed++;
>      }
> -    if (inode.i_dir_acl &&
> -        LINUX_S_ISDIR(inode.i_mode)) {
> -        if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) {
> -            inode.i_dir_acl = 0;
> -            inode_modified++;
> -        } else
> -            not_fixed++;
> -    }
> 
>      if (inode_modified)
>          e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode");
> diff --git a/e2fsck/problem.c b/e2fsck/problem.c
> index 34a671e..ce2f79d 100644
> --- a/e2fsck/problem.c
> +++ b/e2fsck/problem.c
> @@ -1360,11 +1360,6 @@ static struct e2fsck_problem problem_table[] = {
>        N_("i_file_acl @F %If, @s zero.\n"),
>        PROMPT_CLEAR, 0 },
> 
> -    /* i_dir_acl should be zero */
> -    { PR_2_DIR_ACL_ZERO,
> -      N_("i_dir_acl @F %Id, @s zero.\n"),
> -      PROMPT_CLEAR, 0 },
> -
>      /* i_frag should be zero */
>      { PR_2_FRAG_ZERO,
>        N_("i_frag @F %N, @s zero.\n"),
> diff --git a/e2fsck/problem.h b/e2fsck/problem.h
> index 86cb614..f07f9b6 100644
> --- a/e2fsck/problem.h
> +++ b/e2fsck/problem.h
> @@ -808,9 +808,6 @@ struct problem_context {
>  /* i_file_acl should be zero */
>  #define PR_2_FILE_ACL_ZERO    0x02000E
> 
> -/* i_dir_acl should be zero */
> -#define PR_2_DIR_ACL_ZERO    0x02000F
> -
>  /* i_frag should be zero */
>  #define PR_2_FRAG_ZERO        0x020010
> 
> diff --git a/lib/ext2fs/ext2_fs.h b/lib/ext2fs/ext2_fs.h
> index 27a7d3a..6d9a5d0 100644
> --- a/lib/ext2fs/ext2_fs.h
> +++ b/lib/ext2fs/ext2_fs.h
> @@ -398,7 +398,7 @@ struct ext2_inode {
>      __u32    i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
>      __u32    i_generation;    /* File version (for NFS) */
>      __u32    i_file_acl;    /* File ACL */
> -    __u32    i_size_high;    /* Formerly i_dir_acl, directory ACL */
> +    __u32    i_size_high;
>      __u32    i_faddr;    /* Fragment address */
>      union {
>          struct {
> @@ -446,7 +446,7 @@ struct ext2_inode_large {
>      __u32    i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
>      __u32    i_generation;    /* File version (for NFS) */
>      __u32    i_file_acl;    /* File ACL */
> -    __u32    i_size_high;    /* Formerly i_dir_acl, directory ACL */
> +    __u32    i_size_high;
>      __u32    i_faddr;    /* Fragment address */
>      union {
>          struct {
> @@ -484,8 +484,6 @@ struct ext2_inode_large {
>  #define EXT4_EPOCH_BITS 2
>  #define EXT4_EPOCH_MASK ((1 << EXT4_EPOCH_BITS) - 1)
> 
> -#define i_dir_acl    i_size_high
> -
>  #define i_checksum_lo    osd2.linux2.l_i_checksum_lo
> 
>  #define inode_includes(size, field)            \
> @@ -923,7 +921,8 @@ EXT4_FEATURE_INCOMPAT_FUNCS(encrypt,        4, ENCRYPT)
> 
>  #define EXT2_FEATURE_COMPAT_SUPP    0
>  #define EXT2_FEATURE_INCOMPAT_SUPP    (EXT2_FEATURE_INCOMPAT_FILETYPE| \
> -                       EXT4_FEATURE_INCOMPAT_MMP)
> +                       EXT4_FEATURE_INCOMPAT_MMP|\
> +                       EXT4_FEATURE_INCOMPAT_LARGEDIR)
>  #define EXT2_FEATURE_RO_COMPAT_SUPP    (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
>                       EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
>                       EXT4_FEATURE_RO_COMPAT_DIR_NLINK| \
> diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
> index 786ded8..5e956d0 100644
> --- a/lib/ext2fs/ext2fs.h
> +++ b/lib/ext2fs/ext2fs.h
> @@ -588,7 +588,8 @@ typedef struct ext2_icount *ext2_icount_t;
>                       EXT4_FEATURE_INCOMPAT_64BIT|\
>                       EXT4_FEATURE_INCOMPAT_INLINE_DATA|\
>                       EXT4_FEATURE_INCOMPAT_ENCRYPT|\
> -                     EXT4_FEATURE_INCOMPAT_CSUM_SEED)
> +                     EXT4_FEATURE_INCOMPAT_CSUM_SEED|\
> +                     EXT4_FEATURE_INCOMPAT_LARGEDIR)
> 
>  #define EXT2_LIB_FEATURE_RO_COMPAT_SUPP
> (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|\
>                       EXT4_FEATURE_RO_COMPAT_HUGE_FILE|\
> @@ -1924,6 +1925,18 @@ _INLINE_ blk_t ext2fs_inode_data_blocks(ext2_filsys fs,
>      return (blk_t) ext2fs_inode_data_blocks2(fs, inode);
>  }
> 
> +/* htree levels for ext4 */
> +#define EXT4_HTREE_LEVEL_COMPAT 1
> +#define EXT4_HTREE_LEVEL    3

Three levels...

1k: 126^3 * 123 = ~246 million blocks
4k: 510^3 * 507 = ~67.3 billion dirent blocks.
64k: 8190^3 * 8187 = ~4.5 quadrillion dirent blocks

I was about to wonder why not permit enough levels to fill out a full
2^63 byte directory, but then considered that three is probably enough.

(Also I wasn't sure if ext4 still loads the whole dir into kernel memory...)

> +
> +_INLINE_ unsigned int ext2_dir_htree_level(ext2_filsys fs)
> +{
> +        if (EXT2_HAS_INCOMPAT_FEATURE(fs->super,
> +                          EXT4_FEATURE_INCOMPAT_LARGEDIR))

if (ext2fs_has_feature_largedir(...))

> +                    return EXT4_HTREE_LEVEL;
> +            return EXT4_HTREE_LEVEL_COMPAT;
> +}
> +
>  /*
>   * This is an efficient, overflow safe way of calculating ceil((1.0 * a) / b)
>   */
> diff --git a/lib/ext2fs/swapfs.c b/lib/ext2fs/swapfs.c
> index d63fc55..2d05ee7 100644
> --- a/lib/ext2fs/swapfs.c
> +++ b/lib/ext2fs/swapfs.c
> @@ -247,7 +247,7 @@ void ext2fs_swap_inode_full(ext2_filsys fs, struct
> ext2_inode_large *t,
>          has_extents = 1;
>      if (!hostorder && (t->i_flags & EXT4_INLINE_DATA_FL))
>          has_inline_data = 1;
> -    t->i_dir_acl = ext2fs_swab32(f->i_dir_acl);
> +    t->i_size_high = ext2fs_swab32(f->i_size_high);
>      /*
>       * Extent data and inline data are swapped on access, not here
>       */
> diff --git a/misc/mke2fs.c b/misc/mke2fs.c
> index 9f18c83..b2bf461 100644
> --- a/misc/mke2fs.c
> +++ b/misc/mke2fs.c
> @@ -1081,7 +1081,8 @@ static __u32 ok_features[3] = {
>          EXT4_FEATURE_INCOMPAT_64BIT|
>          EXT4_FEATURE_INCOMPAT_INLINE_DATA|
>          EXT4_FEATURE_INCOMPAT_ENCRYPT |
> -        EXT4_FEATURE_INCOMPAT_CSUM_SEED,
> +        EXT4_FEATURE_INCOMPAT_CSUM_SEED |
> +        EXT4_FEATURE_INCOMPAT_LARGEDIR,
>      /* R/O compat */
>      EXT2_FEATURE_RO_COMPAT_LARGE_FILE|
>          EXT4_FEATURE_RO_COMPAT_HUGE_FILE|
> diff --git a/misc/tune2fs.c b/misc/tune2fs.c
> index 6239577..f78d105 100644
> --- a/misc/tune2fs.c
> +++ b/misc/tune2fs.c
> @@ -156,7 +156,8 @@ static __u32 ok_features[3] = {
>          EXT4_FEATURE_INCOMPAT_MMP |
>          EXT4_FEATURE_INCOMPAT_64BIT |
>          EXT4_FEATURE_INCOMPAT_ENCRYPT |
> -        EXT4_FEATURE_INCOMPAT_CSUM_SEED,
> +        EXT4_FEATURE_INCOMPAT_CSUM_SEED |
> +        EXT4_FEATURE_INCOMPAT_LARGEDIR,
>      /* R/O compat */
>      EXT2_FEATURE_RO_COMPAT_LARGE_FILE |
>          EXT4_FEATURE_RO_COMPAT_HUGE_FILE|
> diff --git a/tests/d_special_files/expect b/tests/d_special_files/expect
> index f729b0f..c825932 100644
> --- a/tests/d_special_files/expect
> +++ b/tests/d_special_files/expect
> @@ -5,7 +5,7 @@ debugfs -R ''stat foo'' -w test.img
>  Inode: 12   Type: symlink    Mode:  0777   Flags: 0x0
>  Generation: 0    Version: 0x00000000
>  User:     0   Group:     0   Size: 3
> -File ACL: 0    Directory ACL: 0
> +File ACL: 0
>  Links: 1   Blockcount: 0
>  Fragment:  Address: 0    Number: 0    Size: 0
>  ctime: 0x50f560e0 -- Tue Jan 15 14:00:00 2013
> @@ -17,7 +17,7 @@ debugfs -R ''stat foo2'' -w test.img
>  Inode: 13   Type: symlink    Mode:  0777   Flags: 0x0
>  Generation: 0    Version: 0x00000000
>  User:     0   Group:     0   Size: 80
> -File ACL: 0    Directory ACL: 0
> +File ACL: 0
>  Links: 1   Blockcount: 2
>  Fragment:  Address: 0    Number: 0    Size: 0
>  ctime: 0x50f560e0 -- Tue Jan 15 14:00:00 2013
> @@ -42,7 +42,7 @@ debugfs -R ''stat pipe'' -w test.img
>  Inode: 14   Type: FIFO    Mode:  0000   Flags: 0x0
>  Generation: 0    Version: 0x00000000
>  User:     0   Group:     0   Size: 0
> -File ACL: 0    Directory ACL: 0
> +File ACL: 0
>  Links: 1   Blockcount: 0
>  Fragment:  Address: 0    Number: 0    Size: 0
>  ctime: 0x50f560e0 -- Tue Jan 15 14:00:00 2013
> @@ -55,7 +55,7 @@ debugfs -R ''stat sda'' -w test.img
>  Inode: 15   Type: block special    Mode:  0000   Flags: 0x0
>  Generation: 0    Version: 0x00000000
>  User:     0   Group:     0   Size: 0
> -File ACL: 0    Directory ACL: 0
> +File ACL: 0
>  Links: 1   Blockcount: 0
>  Fragment:  Address: 0    Number: 0    Size: 0
>  ctime: 0x50f560e0 -- Tue Jan 15 14:00:00 2013
> @@ -67,7 +67,7 @@ debugfs -R ''stat null'' -w test.img
>  Inode: 16   Type: character special    Mode:  0000   Flags: 0x0
>  Generation: 0    Version: 0x00000000
>  User:     0   Group:     0   Size: 0
> -File ACL: 0    Directory ACL: 0
> +File ACL: 0
>  Links: 1   Blockcount: 0
>  Fragment:  Address: 0    Number: 0    Size: 0
>  ctime: 0x50f560e0 -- Tue Jan 15 14:00:00 2013
> diff --git a/tests/f_badcluster/expect b/tests/f_badcluster/expect
> index 65a1641..75a3820 100644
> --- a/tests/f_badcluster/expect
> +++ b/tests/f_badcluster/expect
> @@ -116,7 +116,7 @@ debugfs: stat /a
>  Inode: 12   Type: regular    Mode:  0644   Flags: 0x80000
>  Generation: 1117152157    Version: 0x00000001
>  User:     0   Group:     0   Size: 3072
> -File ACL: 0    Directory ACL: 0
> +File ACL: 0
>  Links: 1   Blockcount: 32
>  Fragment:  Address: 0    Number: 0    Size: 0
>  ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
> @@ -128,7 +128,7 @@ debugfs: stat /b
>  Inode: 13   Type: regular    Mode:  0644   Flags: 0x80000
>  Generation: 1117152158    Version: 0x00000001
>  User:     0   Group:     0   Size: 3072
> -File ACL: 0    Directory ACL: 0
> +File ACL: 0
>  Links: 1   Blockcount: 32
>  Fragment:  Address: 0    Number: 0    Size: 0
>  ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
> @@ -140,7 +140,7 @@ debugfs: stat /c
>  Inode: 14   Type: regular    Mode:  0644   Flags: 0x80000
>  Generation: 1117152159    Version: 0x00000001
>  User:     0   Group:     0   Size: 3072
> -File ACL: 0    Directory ACL: 0
> +File ACL: 0
>  Links: 1   Blockcount: 32
>  Fragment:  Address: 0    Number: 0    Size: 0
>  ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
> @@ -152,7 +152,7 @@ debugfs: stat /d
>  Inode: 15   Type: regular    Mode:  0644   Flags: 0x80000
>  Generation: 1117152160    Version: 0x00000001
>  User:     0   Group:     0   Size: 3072
> -File ACL: 0    Directory ACL: 0
> +File ACL: 0
>  Links: 1   Blockcount: 0
>  Fragment:  Address: 0    Number: 0    Size: 0
>  ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
> @@ -163,7 +163,7 @@ debugfs: stat /e
>  Inode: 16   Type: regular    Mode:  0644   Flags: 0x80000
>  Generation: 1117152161    Version: 0x00000001
>  User:     0   Group:     0   Size: 6144
> -File ACL: 0    Directory ACL: 0
> +File ACL: 0
>  Links: 1   Blockcount: 32
>  Fragment:  Address: 0    Number: 0    Size: 0
>  ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
> @@ -175,7 +175,7 @@ debugfs: stat /f
>  Inode: 17   Type: regular    Mode:  0644   Flags: 0x80000
>  Generation: 1117152162    Version: 0x00000001
>  User:     0   Group:     0   Size: 3072
> -File ACL: 0    Directory ACL: 0
> +File ACL: 0
>  Links: 1   Blockcount: 32
>  Fragment:  Address: 0    Number: 0    Size: 0
>  ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
> @@ -187,7 +187,7 @@ debugfs: stat /g
>  Inode: 18   Type: regular    Mode:  0644   Flags: 0x80000
>  Generation: 1117152163    Version: 0x00000001
>  User:     0   Group:     0   Size: 3072
> -File ACL: 0    Directory ACL: 0
> +File ACL: 0
>  Links: 1   Blockcount: 32
>  Fragment:  Address: 0    Number: 0    Size: 0
>  ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
> diff --git a/tests/f_recnect_bad/expect.1 b/tests/f_recnect_bad/expect.1
> index 8ba81e6..6433c8d 100644
> --- a/tests/f_recnect_bad/expect.1
> +++ b/tests/f_recnect_bad/expect.1
> @@ -3,9 +3,6 @@ Pass 2: Checking directory structure
>  i_faddr for inode 15 (/test/quux) is 23, should be zero.
>  Clear? yes
> 
> -i_dir_acl for inode 15 (/test/quux) is 12, should be zero.
> -Clear? yes
> -
>  i_file_acl for inode 13 (/test/???) is 12, should be zero.
>  Clear? yes

Will a test case be provided to demonstrate that e2fsck can handle
rebuilding a >1 level htree dir?

--D
> 
> --
Artem Blagodarenko Jan. 25, 2017, 9:01 a.m. UTC | #2
Darrick, thank you for inspection.

>Please break this up into separate patches for each of those two changes.
Sure. Coming soon.

>Will a test case be provided to demonstrate that e2fsck can handle
rebuilding a >1 level htree dir?

Just send "[PATCH 3/3] tests: 3 level hash tree test" with test that
rebuild directory to 3 level tree. But it depends from "debugfs:
increase inode reference count after link" I posted some days ago.
Sorry, didn't mentioned it in the email with patch.


Best regards,
Artem Blagodarenko.

On Tue, Jan 24, 2017 at 9:08 PM, Darrick J. Wong
<darrick.wong@oracle.com> wrote:
> On Tue, Jan 24, 2017 at 07:34:13PM +0300, Artem Blagodarenko wrote:
>> The INCOMPAT_LARGEDIR feature allows larger directories to
>> be created, both with directory sizes over 2GB and and a
>> maximum htree depth of 3 instead of the current limit of 2.
>> These features are needed in order to exceed the currently
>> limit of approximately 10M entries in a single directory.
>>
>> debugfs, e2fsck, ext2fs, mke2fs and tune2fs support is
>> added.
>>
>> Signed-off-by: Alexey Lyashkov <alexey.lyashkov@seagate.com>
>> Signed-off-by: Artem Blagodarenko <artem.blagodarenko@seagate.com>
>> ---
>>  debugfs/debugfs.c            |   16 +++++++---------
>>  debugfs/set_fields.c         |    1 -
>>  e2fsck/message.c             |    4 ----
>>  e2fsck/pass1.c               |    5 ++---
>>  e2fsck/pass2.c               |   11 ++---------
>>  e2fsck/problem.c             |    5 -----
>>  e2fsck/problem.h             |    3 ---
>>  lib/ext2fs/ext2_fs.h         |    9 ++++-----
>>  lib/ext2fs/ext2fs.h          |   15 ++++++++++++++-
>>  lib/ext2fs/swapfs.c          |    2 +-
>>  misc/mke2fs.c                |    3 ++-
>>  misc/tune2fs.c               |    3 ++-
>>  tests/d_special_files/expect |   10 +++++-----
>>  tests/f_badcluster/expect    |   14 +++++++-------
>>  tests/f_recnect_bad/expect.1 |    3 ---
>>  15 files changed, 46 insertions(+), 58 deletions(-)
>>
>> diff --git a/debugfs/debugfs.c b/debugfs/debugfs.c
>> index b40d9e2..795bdc3 100644
>> --- a/debugfs/debugfs.c
>> +++ b/debugfs/debugfs.c
>> @@ -841,16 +841,15 @@ void internal_dump_inode(FILE *out, const char *prefix,
>>          fprintf(out, "%d\n", inode->i_size);
>>      if (os == EXT2_OS_HURD)
>>          fprintf(out,
>> -            "%sFile ACL: %d    Directory ACL: %d Translator: %d\n",
>> +            "%sFile ACL: %d Translator: %d\n",
>>              prefix,
>> -            inode->i_file_acl, LINUX_S_ISDIR(inode->i_mode) ?
>> inode->i_dir_acl : 0,
>> +            inode->i_file_acl,
>>              inode->osd1.hurd1.h_i_translator);
>>      else
>> -        fprintf(out, "%sFile ACL: %llu    Directory ACL: %d\n",
>> +        fprintf(out, "%sFile ACL: %llu\n",
>>              prefix,
>>              inode->i_file_acl | ((long long)
>> -                (inode->osd2.linux2.l_i_file_acl_high) << 32),
>> -            LINUX_S_ISDIR(inode->i_mode) ? inode->i_dir_acl : 0);
>> +                (inode->osd2.linux2.l_i_file_acl_high) << 32));
>>      if (os != EXT2_OS_HURD)
>>          fprintf(out, "%sLinks: %d   Blockcount: %llu\n",
>>              prefix, inode->i_links_count,
>> @@ -1347,10 +1346,9 @@ void do_modify_inode(int argc, char *argv[])
>>      modify_u32(argv[0], "Reserved1", decimal_format, &inode.i_reserved1);
>>  #endif
>>      modify_u32(argv[0], "File acl", decimal_format, &inode.i_file_acl);
>> -    if (LINUX_S_ISDIR(inode.i_mode))
>> -        modify_u32(argv[0], "Directory acl", decimal_format, &inode.i_dir_acl);
>> -    else
>> -        modify_u32(argv[0], "High 32bits of size", decimal_format,
>> &inode.i_size_high);
>> +
>> +    modify_u32(argv[0], "High 32bits of size", decimal_format,
>> +           &inode.i_size_high);
>
> Ugh, this patch removes dir_acl /and/ adds support for 3-level htrees!
>
> Please break this up into separate patches for each of those two changes.
>
> "e2fsprogs: supersede i_dir_acl with i_size_high for all cases"
> "e2fsprogs: add support for 3-level htree"
>
>>
>>      if (os == EXT2_OS_HURD)
>>          modify_u32(argv[0], "Translator Block",
>> diff --git a/debugfs/set_fields.c b/debugfs/set_fields.c
>> index ff9b7b6..ca68862 100644
>> --- a/debugfs/set_fields.c
>> +++ b/debugfs/set_fields.c
>> @@ -212,7 +212,6 @@ static struct field_set_info inode_fields[] = {
>>      /* Special case: i_file_acl_high is 2 bytes */
>>      { "file_acl", &set_inode.i_file_acl,
>>          &set_inode.osd2.linux2.l_i_file_acl_high, 6, parse_uint },
>> -    { "dir_acl", &set_inode.i_dir_acl, NULL, 4, parse_uint, FLAG_ALIAS },
>>      { "faddr", &set_inode.i_faddr, NULL, 4, parse_uint },
>>      { "frag", &set_inode.osd2.hurd2.h_i_frag, NULL, 1, parse_uint,
>> FLAG_ALIAS },
>>      { "fsize", &set_inode.osd2.hurd2.h_i_fsize, NULL, 1, parse_uint },
>> diff --git a/e2fsck/message.c b/e2fsck/message.c
>> index 1c3fcd8..d21ba05 100644
>> --- a/e2fsck/message.c
>> +++ b/e2fsck/message.c
>> @@ -318,10 +318,6 @@ static _INLINE_ void expand_inode_expression(FILE
>> *f, ext2_filsys fs, char ch,
>>      case 'f':
>>          fprintf(f, "%llu", ext2fs_file_acl_block(fs, inode));
>>          break;
>> -    case 'd':
>> -        fprintf(f, "%u", (LINUX_S_ISDIR(inode->i_mode) ?
>> -                  inode->i_dir_acl : 0));
>> -        break;
>>      case 'u':
>>          fprintf(f, "%d", inode_uid(*inode));
>>          break;
>> diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c
>> index 8ef40f6..8444b37 100644
>> --- a/e2fsck/pass1.c
>> +++ b/e2fsck/pass1.c
>> @@ -1715,8 +1715,7 @@ void e2fsck_pass1(e2fsck_t ctx)
>>              frag = fsize = 0;
>>          }
>>
>> -        if (inode->i_faddr || frag || fsize ||
>> -            (LINUX_S_ISDIR(inode->i_mode) && inode->i_dir_acl))
>> +        if (inode->i_faddr || frag || fsize)
>>              mark_inode_bad(ctx, ino);
>>          if ((fs->super->s_creator_os != EXT2_OS_HURD) &&
>>              !ext2fs_has_feature_64bit(fs->super) &&
>> @@ -2469,7 +2468,7 @@ static int handle_htree(e2fsck_t ctx, struct
>> problem_context *pctx,
>>          return 1;
>>
>>      pctx->num = root->indirect_levels;
>> -    if ((root->indirect_levels > 1) &&
>> +    if ((root->indirect_levels > ext2_dir_htree_level(fs)) &&
>>          fix_problem(ctx, PR_1_HTREE_DEPTH, pctx))
>>          return 1;
>>
>> diff --git a/e2fsck/pass2.c b/e2fsck/pass2.c
>> index 11c19e8..7ded7bb 100644
>> --- a/e2fsck/pass2.c
>> +++ b/e2fsck/pass2.c
>> @@ -1058,7 +1058,8 @@ inline_read_fail:
>>              dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST;
>>              if ((root->reserved_zero ||
>>                   root->info_length < 8 ||
>> -                 root->indirect_levels > 1) &&
>> +                 root->indirect_levels
>> +                > ext2_dir_htree_level(fs)) &&
>>                  fix_problem(ctx, PR_2_HTREE_BAD_ROOT, &cd->pctx)) {
>>                  clear_htree(ctx, ino);
>>                  dx_dir->numblocks = 0;
>> @@ -1811,14 +1812,6 @@ int e2fsck_process_bad_inode(e2fsck_t ctx,
>> ext2_ino_t dir,
>>          } else
>>              not_fixed++;
>>      }
>> -    if (inode.i_dir_acl &&
>> -        LINUX_S_ISDIR(inode.i_mode)) {
>> -        if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) {
>> -            inode.i_dir_acl = 0;
>> -            inode_modified++;
>> -        } else
>> -            not_fixed++;
>> -    }
>>
>>      if (inode_modified)
>>          e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode");
>> diff --git a/e2fsck/problem.c b/e2fsck/problem.c
>> index 34a671e..ce2f79d 100644
>> --- a/e2fsck/problem.c
>> +++ b/e2fsck/problem.c
>> @@ -1360,11 +1360,6 @@ static struct e2fsck_problem problem_table[] = {
>>        N_("i_file_acl @F %If, @s zero.\n"),
>>        PROMPT_CLEAR, 0 },
>>
>> -    /* i_dir_acl should be zero */
>> -    { PR_2_DIR_ACL_ZERO,
>> -      N_("i_dir_acl @F %Id, @s zero.\n"),
>> -      PROMPT_CLEAR, 0 },
>> -
>>      /* i_frag should be zero */
>>      { PR_2_FRAG_ZERO,
>>        N_("i_frag @F %N, @s zero.\n"),
>> diff --git a/e2fsck/problem.h b/e2fsck/problem.h
>> index 86cb614..f07f9b6 100644
>> --- a/e2fsck/problem.h
>> +++ b/e2fsck/problem.h
>> @@ -808,9 +808,6 @@ struct problem_context {
>>  /* i_file_acl should be zero */
>>  #define PR_2_FILE_ACL_ZERO    0x02000E
>>
>> -/* i_dir_acl should be zero */
>> -#define PR_2_DIR_ACL_ZERO    0x02000F
>> -
>>  /* i_frag should be zero */
>>  #define PR_2_FRAG_ZERO        0x020010
>>
>> diff --git a/lib/ext2fs/ext2_fs.h b/lib/ext2fs/ext2_fs.h
>> index 27a7d3a..6d9a5d0 100644
>> --- a/lib/ext2fs/ext2_fs.h
>> +++ b/lib/ext2fs/ext2_fs.h
>> @@ -398,7 +398,7 @@ struct ext2_inode {
>>      __u32    i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
>>      __u32    i_generation;    /* File version (for NFS) */
>>      __u32    i_file_acl;    /* File ACL */
>> -    __u32    i_size_high;    /* Formerly i_dir_acl, directory ACL */
>> +    __u32    i_size_high;
>>      __u32    i_faddr;    /* Fragment address */
>>      union {
>>          struct {
>> @@ -446,7 +446,7 @@ struct ext2_inode_large {
>>      __u32    i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
>>      __u32    i_generation;    /* File version (for NFS) */
>>      __u32    i_file_acl;    /* File ACL */
>> -    __u32    i_size_high;    /* Formerly i_dir_acl, directory ACL */
>> +    __u32    i_size_high;
>>      __u32    i_faddr;    /* Fragment address */
>>      union {
>>          struct {
>> @@ -484,8 +484,6 @@ struct ext2_inode_large {
>>  #define EXT4_EPOCH_BITS 2
>>  #define EXT4_EPOCH_MASK ((1 << EXT4_EPOCH_BITS) - 1)
>>
>> -#define i_dir_acl    i_size_high
>> -
>>  #define i_checksum_lo    osd2.linux2.l_i_checksum_lo
>>
>>  #define inode_includes(size, field)            \
>> @@ -923,7 +921,8 @@ EXT4_FEATURE_INCOMPAT_FUNCS(encrypt,        4, ENCRYPT)
>>
>>  #define EXT2_FEATURE_COMPAT_SUPP    0
>>  #define EXT2_FEATURE_INCOMPAT_SUPP    (EXT2_FEATURE_INCOMPAT_FILETYPE| \
>> -                       EXT4_FEATURE_INCOMPAT_MMP)
>> +                       EXT4_FEATURE_INCOMPAT_MMP|\
>> +                       EXT4_FEATURE_INCOMPAT_LARGEDIR)
>>  #define EXT2_FEATURE_RO_COMPAT_SUPP    (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
>>                       EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
>>                       EXT4_FEATURE_RO_COMPAT_DIR_NLINK| \
>> diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
>> index 786ded8..5e956d0 100644
>> --- a/lib/ext2fs/ext2fs.h
>> +++ b/lib/ext2fs/ext2fs.h
>> @@ -588,7 +588,8 @@ typedef struct ext2_icount *ext2_icount_t;
>>                       EXT4_FEATURE_INCOMPAT_64BIT|\
>>                       EXT4_FEATURE_INCOMPAT_INLINE_DATA|\
>>                       EXT4_FEATURE_INCOMPAT_ENCRYPT|\
>> -                     EXT4_FEATURE_INCOMPAT_CSUM_SEED)
>> +                     EXT4_FEATURE_INCOMPAT_CSUM_SEED|\
>> +                     EXT4_FEATURE_INCOMPAT_LARGEDIR)
>>
>>  #define EXT2_LIB_FEATURE_RO_COMPAT_SUPP
>> (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|\
>>                       EXT4_FEATURE_RO_COMPAT_HUGE_FILE|\
>> @@ -1924,6 +1925,18 @@ _INLINE_ blk_t ext2fs_inode_data_blocks(ext2_filsys fs,
>>      return (blk_t) ext2fs_inode_data_blocks2(fs, inode);
>>  }
>>
>> +/* htree levels for ext4 */
>> +#define EXT4_HTREE_LEVEL_COMPAT 1
>> +#define EXT4_HTREE_LEVEL    3
>
> Three levels...
>
> 1k: 126^3 * 123 = ~246 million blocks
> 4k: 510^3 * 507 = ~67.3 billion dirent blocks.
> 64k: 8190^3 * 8187 = ~4.5 quadrillion dirent blocks
>
> I was about to wonder why not permit enough levels to fill out a full
> 2^63 byte directory, but then considered that three is probably enough.
>
> (Also I wasn't sure if ext4 still loads the whole dir into kernel memory...)
>
>> +
>> +_INLINE_ unsigned int ext2_dir_htree_level(ext2_filsys fs)
>> +{
>> +        if (EXT2_HAS_INCOMPAT_FEATURE(fs->super,
>> +                          EXT4_FEATURE_INCOMPAT_LARGEDIR))
>
> if (ext2fs_has_feature_largedir(...))
>
>> +                    return EXT4_HTREE_LEVEL;
>> +            return EXT4_HTREE_LEVEL_COMPAT;
>> +}
>> +
>>  /*
>>   * This is an efficient, overflow safe way of calculating ceil((1.0 * a) / b)
>>   */
>> diff --git a/lib/ext2fs/swapfs.c b/lib/ext2fs/swapfs.c
>> index d63fc55..2d05ee7 100644
>> --- a/lib/ext2fs/swapfs.c
>> +++ b/lib/ext2fs/swapfs.c
>> @@ -247,7 +247,7 @@ void ext2fs_swap_inode_full(ext2_filsys fs, struct
>> ext2_inode_large *t,
>>          has_extents = 1;
>>      if (!hostorder && (t->i_flags & EXT4_INLINE_DATA_FL))
>>          has_inline_data = 1;
>> -    t->i_dir_acl = ext2fs_swab32(f->i_dir_acl);
>> +    t->i_size_high = ext2fs_swab32(f->i_size_high);
>>      /*
>>       * Extent data and inline data are swapped on access, not here
>>       */
>> diff --git a/misc/mke2fs.c b/misc/mke2fs.c
>> index 9f18c83..b2bf461 100644
>> --- a/misc/mke2fs.c
>> +++ b/misc/mke2fs.c
>> @@ -1081,7 +1081,8 @@ static __u32 ok_features[3] = {
>>          EXT4_FEATURE_INCOMPAT_64BIT|
>>          EXT4_FEATURE_INCOMPAT_INLINE_DATA|
>>          EXT4_FEATURE_INCOMPAT_ENCRYPT |
>> -        EXT4_FEATURE_INCOMPAT_CSUM_SEED,
>> +        EXT4_FEATURE_INCOMPAT_CSUM_SEED |
>> +        EXT4_FEATURE_INCOMPAT_LARGEDIR,
>>      /* R/O compat */
>>      EXT2_FEATURE_RO_COMPAT_LARGE_FILE|
>>          EXT4_FEATURE_RO_COMPAT_HUGE_FILE|
>> diff --git a/misc/tune2fs.c b/misc/tune2fs.c
>> index 6239577..f78d105 100644
>> --- a/misc/tune2fs.c
>> +++ b/misc/tune2fs.c
>> @@ -156,7 +156,8 @@ static __u32 ok_features[3] = {
>>          EXT4_FEATURE_INCOMPAT_MMP |
>>          EXT4_FEATURE_INCOMPAT_64BIT |
>>          EXT4_FEATURE_INCOMPAT_ENCRYPT |
>> -        EXT4_FEATURE_INCOMPAT_CSUM_SEED,
>> +        EXT4_FEATURE_INCOMPAT_CSUM_SEED |
>> +        EXT4_FEATURE_INCOMPAT_LARGEDIR,
>>      /* R/O compat */
>>      EXT2_FEATURE_RO_COMPAT_LARGE_FILE |
>>          EXT4_FEATURE_RO_COMPAT_HUGE_FILE|
>> diff --git a/tests/d_special_files/expect b/tests/d_special_files/expect
>> index f729b0f..c825932 100644
>> --- a/tests/d_special_files/expect
>> +++ b/tests/d_special_files/expect
>> @@ -5,7 +5,7 @@ debugfs -R ''stat foo'' -w test.img
>>  Inode: 12   Type: symlink    Mode:  0777   Flags: 0x0
>>  Generation: 0    Version: 0x00000000
>>  User:     0   Group:     0   Size: 3
>> -File ACL: 0    Directory ACL: 0
>> +File ACL: 0
>>  Links: 1   Blockcount: 0
>>  Fragment:  Address: 0    Number: 0    Size: 0
>>  ctime: 0x50f560e0 -- Tue Jan 15 14:00:00 2013
>> @@ -17,7 +17,7 @@ debugfs -R ''stat foo2'' -w test.img
>>  Inode: 13   Type: symlink    Mode:  0777   Flags: 0x0
>>  Generation: 0    Version: 0x00000000
>>  User:     0   Group:     0   Size: 80
>> -File ACL: 0    Directory ACL: 0
>> +File ACL: 0
>>  Links: 1   Blockcount: 2
>>  Fragment:  Address: 0    Number: 0    Size: 0
>>  ctime: 0x50f560e0 -- Tue Jan 15 14:00:00 2013
>> @@ -42,7 +42,7 @@ debugfs -R ''stat pipe'' -w test.img
>>  Inode: 14   Type: FIFO    Mode:  0000   Flags: 0x0
>>  Generation: 0    Version: 0x00000000
>>  User:     0   Group:     0   Size: 0
>> -File ACL: 0    Directory ACL: 0
>> +File ACL: 0
>>  Links: 1   Blockcount: 0
>>  Fragment:  Address: 0    Number: 0    Size: 0
>>  ctime: 0x50f560e0 -- Tue Jan 15 14:00:00 2013
>> @@ -55,7 +55,7 @@ debugfs -R ''stat sda'' -w test.img
>>  Inode: 15   Type: block special    Mode:  0000   Flags: 0x0
>>  Generation: 0    Version: 0x00000000
>>  User:     0   Group:     0   Size: 0
>> -File ACL: 0    Directory ACL: 0
>> +File ACL: 0
>>  Links: 1   Blockcount: 0
>>  Fragment:  Address: 0    Number: 0    Size: 0
>>  ctime: 0x50f560e0 -- Tue Jan 15 14:00:00 2013
>> @@ -67,7 +67,7 @@ debugfs -R ''stat null'' -w test.img
>>  Inode: 16   Type: character special    Mode:  0000   Flags: 0x0
>>  Generation: 0    Version: 0x00000000
>>  User:     0   Group:     0   Size: 0
>> -File ACL: 0    Directory ACL: 0
>> +File ACL: 0
>>  Links: 1   Blockcount: 0
>>  Fragment:  Address: 0    Number: 0    Size: 0
>>  ctime: 0x50f560e0 -- Tue Jan 15 14:00:00 2013
>> diff --git a/tests/f_badcluster/expect b/tests/f_badcluster/expect
>> index 65a1641..75a3820 100644
>> --- a/tests/f_badcluster/expect
>> +++ b/tests/f_badcluster/expect
>> @@ -116,7 +116,7 @@ debugfs: stat /a
>>  Inode: 12   Type: regular    Mode:  0644   Flags: 0x80000
>>  Generation: 1117152157    Version: 0x00000001
>>  User:     0   Group:     0   Size: 3072
>> -File ACL: 0    Directory ACL: 0
>> +File ACL: 0
>>  Links: 1   Blockcount: 32
>>  Fragment:  Address: 0    Number: 0    Size: 0
>>  ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
>> @@ -128,7 +128,7 @@ debugfs: stat /b
>>  Inode: 13   Type: regular    Mode:  0644   Flags: 0x80000
>>  Generation: 1117152158    Version: 0x00000001
>>  User:     0   Group:     0   Size: 3072
>> -File ACL: 0    Directory ACL: 0
>> +File ACL: 0
>>  Links: 1   Blockcount: 32
>>  Fragment:  Address: 0    Number: 0    Size: 0
>>  ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
>> @@ -140,7 +140,7 @@ debugfs: stat /c
>>  Inode: 14   Type: regular    Mode:  0644   Flags: 0x80000
>>  Generation: 1117152159    Version: 0x00000001
>>  User:     0   Group:     0   Size: 3072
>> -File ACL: 0    Directory ACL: 0
>> +File ACL: 0
>>  Links: 1   Blockcount: 32
>>  Fragment:  Address: 0    Number: 0    Size: 0
>>  ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
>> @@ -152,7 +152,7 @@ debugfs: stat /d
>>  Inode: 15   Type: regular    Mode:  0644   Flags: 0x80000
>>  Generation: 1117152160    Version: 0x00000001
>>  User:     0   Group:     0   Size: 3072
>> -File ACL: 0    Directory ACL: 0
>> +File ACL: 0
>>  Links: 1   Blockcount: 0
>>  Fragment:  Address: 0    Number: 0    Size: 0
>>  ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
>> @@ -163,7 +163,7 @@ debugfs: stat /e
>>  Inode: 16   Type: regular    Mode:  0644   Flags: 0x80000
>>  Generation: 1117152161    Version: 0x00000001
>>  User:     0   Group:     0   Size: 6144
>> -File ACL: 0    Directory ACL: 0
>> +File ACL: 0
>>  Links: 1   Blockcount: 32
>>  Fragment:  Address: 0    Number: 0    Size: 0
>>  ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
>> @@ -175,7 +175,7 @@ debugfs: stat /f
>>  Inode: 17   Type: regular    Mode:  0644   Flags: 0x80000
>>  Generation: 1117152162    Version: 0x00000001
>>  User:     0   Group:     0   Size: 3072
>> -File ACL: 0    Directory ACL: 0
>> +File ACL: 0
>>  Links: 1   Blockcount: 32
>>  Fragment:  Address: 0    Number: 0    Size: 0
>>  ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
>> @@ -187,7 +187,7 @@ debugfs: stat /g
>>  Inode: 18   Type: regular    Mode:  0644   Flags: 0x80000
>>  Generation: 1117152163    Version: 0x00000001
>>  User:     0   Group:     0   Size: 3072
>> -File ACL: 0    Directory ACL: 0
>> +File ACL: 0
>>  Links: 1   Blockcount: 32
>>  Fragment:  Address: 0    Number: 0    Size: 0
>>  ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
>> diff --git a/tests/f_recnect_bad/expect.1 b/tests/f_recnect_bad/expect.1
>> index 8ba81e6..6433c8d 100644
>> --- a/tests/f_recnect_bad/expect.1
>> +++ b/tests/f_recnect_bad/expect.1
>> @@ -3,9 +3,6 @@ Pass 2: Checking directory structure
>>  i_faddr for inode 15 (/test/quux) is 23, should be zero.
>>  Clear? yes
>>
>> -i_dir_acl for inode 15 (/test/quux) is 12, should be zero.
>> -Clear? yes
>> -
>>  i_file_acl for inode 13 (/test/???) is 12, should be zero.
>>  Clear? yes
>
> Will a test case be provided to demonstrate that e2fsck can handle
> rebuilding a >1 level htree dir?
>
> --D
>>
>> --
Theodore Ts'o Jan. 25, 2017, 8:31 p.m. UTC | #3
On Tue, Jan 24, 2017 at 07:34:13PM +0300, Artem Blagodarenko wrote:
> The INCOMPAT_LARGEDIR feature allows larger directories to
> be created, both with directory sizes over 2GB and and a
> maximum htree depth of 3 instead of the current limit of 2.
> These features are needed in order to exceed the currently
> limit of approximately 10M entries in a single directory.
> 
> debugfs, e2fsck, ext2fs, mke2fs and tune2fs support is
> added.
> 
> Signed-off-by: Alexey Lyashkov <alexey.lyashkov@seagate.com>
> Signed-off-by: Artem Blagodarenko <artem.blagodarenko@seagate.com>

Where are the kernel-side changes for this feature?

And could you *please* use git send-email's --chain-reply-to option,
or set the sendemail.chainReplyTo in your git config.  (Or if you're
not using git send-email, send the e-mail using that format).

It makes it much easier to figure out which patch goes with which
other patch in a patch series, especially when you start sending
revised versions of the patches.

					- Ted
Andreas Dilger Feb. 2, 2017, 5:11 p.m. UTC | #4
We have kernel-side patches for this feature. Artem, could you push a version of the ext4 patches for the latest kernel to the list?

Cheers, Andreas

> On Jan 25, 2017, at 13:31, Theodore Ts'o <tytso@mit.edu> wrote:
> 
>> On Tue, Jan 24, 2017 at 07:34:13PM +0300, Artem Blagodarenko wrote:
>> The INCOMPAT_LARGEDIR feature allows larger directories to
>> be created, both with directory sizes over 2GB and and a
>> maximum htree depth of 3 instead of the current limit of 2.
>> These features are needed in order to exceed the currently
>> limit of approximately 10M entries in a single directory.
>> 
>> debugfs, e2fsck, ext2fs, mke2fs and tune2fs support is
>> added.
>> 
>> Signed-off-by: Alexey Lyashkov <alexey.lyashkov@seagate.com>
>> Signed-off-by: Artem Blagodarenko <artem.blagodarenko@seagate.com>
> 
> Where are the kernel-side changes for this feature?
> 
> And could you *please* use git send-email's --chain-reply-to option,
> or set the sendemail.chainReplyTo in your git config.  (Or if you're
> not using git send-email, send the e-mail using that format).
> 
> It makes it much easier to figure out which patch goes with which
> other patch in a patch series, especially when you start sending
> revised versions of the patches.
> 
>                    - Ted
>
Artem Blagodarenko Feb. 12, 2017, 5:50 p.m. UTC | #5
Hello,

>We have kernel-side patches for this feature. Artem, could you push a version of the ext4 patches for the latest kernel to the list?

Yes, sure. I will push it here soon.

Best regards,
Artem Blagodarenko.

On Thu, Feb 2, 2017 at 8:11 PM, Andreas Dilger <adilger@dilger.ca> wrote:
> We have kernel-side patches for this feature. Artem, could you push a version of the ext4 patches for the latest kernel to the list?
>
> Cheers, Andreas
>
>> On Jan 25, 2017, at 13:31, Theodore Ts'o <tytso@mit.edu> wrote:
>>
>>> On Tue, Jan 24, 2017 at 07:34:13PM +0300, Artem Blagodarenko wrote:
>>> The INCOMPAT_LARGEDIR feature allows larger directories to
>>> be created, both with directory sizes over 2GB and and a
>>> maximum htree depth of 3 instead of the current limit of 2.
>>> These features are needed in order to exceed the currently
>>> limit of approximately 10M entries in a single directory.
>>>
>>> debugfs, e2fsck, ext2fs, mke2fs and tune2fs support is
>>> added.
>>>
>>> Signed-off-by: Alexey Lyashkov <alexey.lyashkov@seagate.com>
>>> Signed-off-by: Artem Blagodarenko <artem.blagodarenko@seagate.com>
>>
>> Where are the kernel-side changes for this feature?
>>
>> And could you *please* use git send-email's --chain-reply-to option,
>> or set the sendemail.chainReplyTo in your git config.  (Or if you're
>> not using git send-email, send the e-mail using that format).
>>
>> It makes it much easier to figure out which patch goes with which
>> other patch in a patch series, especially when you start sending
>> revised versions of the patches.
>>
>>                    - Ted
>>
diff mbox

Patch

diff --git a/debugfs/debugfs.c b/debugfs/debugfs.c
index b40d9e2..795bdc3 100644
--- a/debugfs/debugfs.c
+++ b/debugfs/debugfs.c
@@ -841,16 +841,15 @@  void internal_dump_inode(FILE *out, const char *prefix,
         fprintf(out, "%d\n", inode->i_size);
     if (os == EXT2_OS_HURD)
         fprintf(out,
-            "%sFile ACL: %d    Directory ACL: %d Translator: %d\n",
+            "%sFile ACL: %d Translator: %d\n",
             prefix,
-            inode->i_file_acl, LINUX_S_ISDIR(inode->i_mode) ?
inode->i_dir_acl : 0,
+            inode->i_file_acl,
             inode->osd1.hurd1.h_i_translator);
     else
-        fprintf(out, "%sFile ACL: %llu    Directory ACL: %d\n",
+        fprintf(out, "%sFile ACL: %llu\n",
             prefix,
             inode->i_file_acl | ((long long)
-                (inode->osd2.linux2.l_i_file_acl_high) << 32),
-            LINUX_S_ISDIR(inode->i_mode) ? inode->i_dir_acl : 0);
+                (inode->osd2.linux2.l_i_file_acl_high) << 32));
     if (os != EXT2_OS_HURD)
         fprintf(out, "%sLinks: %d   Blockcount: %llu\n",
             prefix, inode->i_links_count,
@@ -1347,10 +1346,9 @@  void do_modify_inode(int argc, char *argv[])
     modify_u32(argv[0], "Reserved1", decimal_format, &inode.i_reserved1);
 #endif
     modify_u32(argv[0], "File acl", decimal_format, &inode.i_file_acl);
-    if (LINUX_S_ISDIR(inode.i_mode))
-        modify_u32(argv[0], "Directory acl", decimal_format, &inode.i_dir_acl);
-    else
-        modify_u32(argv[0], "High 32bits of size", decimal_format,
&inode.i_size_high);
+
+    modify_u32(argv[0], "High 32bits of size", decimal_format,
+           &inode.i_size_high);

     if (os == EXT2_OS_HURD)
         modify_u32(argv[0], "Translator Block",
diff --git a/debugfs/set_fields.c b/debugfs/set_fields.c
index ff9b7b6..ca68862 100644
--- a/debugfs/set_fields.c
+++ b/debugfs/set_fields.c
@@ -212,7 +212,6 @@  static struct field_set_info inode_fields[] = {
     /* Special case: i_file_acl_high is 2 bytes */
     { "file_acl", &set_inode.i_file_acl,
         &set_inode.osd2.linux2.l_i_file_acl_high, 6, parse_uint },
-    { "dir_acl", &set_inode.i_dir_acl, NULL, 4, parse_uint, FLAG_ALIAS },
     { "faddr", &set_inode.i_faddr, NULL, 4, parse_uint },
     { "frag", &set_inode.osd2.hurd2.h_i_frag, NULL, 1, parse_uint,
FLAG_ALIAS },
     { "fsize", &set_inode.osd2.hurd2.h_i_fsize, NULL, 1, parse_uint },
diff --git a/e2fsck/message.c b/e2fsck/message.c
index 1c3fcd8..d21ba05 100644
--- a/e2fsck/message.c
+++ b/e2fsck/message.c
@@ -318,10 +318,6 @@  static _INLINE_ void expand_inode_expression(FILE
*f, ext2_filsys fs, char ch,
     case 'f':
         fprintf(f, "%llu", ext2fs_file_acl_block(fs, inode));
         break;
-    case 'd':
-        fprintf(f, "%u", (LINUX_S_ISDIR(inode->i_mode) ?
-                  inode->i_dir_acl : 0));
-        break;
     case 'u':
         fprintf(f, "%d", inode_uid(*inode));
         break;
diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c
index 8ef40f6..8444b37 100644
--- a/e2fsck/pass1.c
+++ b/e2fsck/pass1.c
@@ -1715,8 +1715,7 @@  void e2fsck_pass1(e2fsck_t ctx)
             frag = fsize = 0;
         }

-        if (inode->i_faddr || frag || fsize ||
-            (LINUX_S_ISDIR(inode->i_mode) && inode->i_dir_acl))
+        if (inode->i_faddr || frag || fsize)
             mark_inode_bad(ctx, ino);
         if ((fs->super->s_creator_os != EXT2_OS_HURD) &&
             !ext2fs_has_feature_64bit(fs->super) &&
@@ -2469,7 +2468,7 @@  static int handle_htree(e2fsck_t ctx, struct
problem_context *pctx,
         return 1;

     pctx->num = root->indirect_levels;
-    if ((root->indirect_levels > 1) &&
+    if ((root->indirect_levels > ext2_dir_htree_level(fs)) &&
         fix_problem(ctx, PR_1_HTREE_DEPTH, pctx))
         return 1;

diff --git a/e2fsck/pass2.c b/e2fsck/pass2.c
index 11c19e8..7ded7bb 100644
--- a/e2fsck/pass2.c
+++ b/e2fsck/pass2.c
@@ -1058,7 +1058,8 @@  inline_read_fail:
             dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST;
             if ((root->reserved_zero ||
                  root->info_length < 8 ||
-                 root->indirect_levels > 1) &&
+                 root->indirect_levels
+                > ext2_dir_htree_level(fs)) &&
                 fix_problem(ctx, PR_2_HTREE_BAD_ROOT, &cd->pctx)) {
                 clear_htree(ctx, ino);
                 dx_dir->numblocks = 0;
@@ -1811,14 +1812,6 @@  int e2fsck_process_bad_inode(e2fsck_t ctx,
ext2_ino_t dir,
         } else
             not_fixed++;
     }
-    if (inode.i_dir_acl &&
-        LINUX_S_ISDIR(inode.i_mode)) {
-        if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) {
-            inode.i_dir_acl = 0;
-            inode_modified++;
-        } else
-            not_fixed++;
-    }

     if (inode_modified)
         e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode");
diff --git a/e2fsck/problem.c b/e2fsck/problem.c
index 34a671e..ce2f79d 100644
--- a/e2fsck/problem.c
+++ b/e2fsck/problem.c
@@ -1360,11 +1360,6 @@  static struct e2fsck_problem problem_table[] = {
       N_("i_file_acl @F %If, @s zero.\n"),
       PROMPT_CLEAR, 0 },

-    /* i_dir_acl should be zero */
-    { PR_2_DIR_ACL_ZERO,
-      N_("i_dir_acl @F %Id, @s zero.\n"),
-      PROMPT_CLEAR, 0 },
-
     /* i_frag should be zero */
     { PR_2_FRAG_ZERO,
       N_("i_frag @F %N, @s zero.\n"),
diff --git a/e2fsck/problem.h b/e2fsck/problem.h
index 86cb614..f07f9b6 100644
--- a/e2fsck/problem.h
+++ b/e2fsck/problem.h
@@ -808,9 +808,6 @@  struct problem_context {
 /* i_file_acl should be zero */
 #define PR_2_FILE_ACL_ZERO    0x02000E

-/* i_dir_acl should be zero */
-#define PR_2_DIR_ACL_ZERO    0x02000F
-
 /* i_frag should be zero */
 #define PR_2_FRAG_ZERO        0x020010

diff --git a/lib/ext2fs/ext2_fs.h b/lib/ext2fs/ext2_fs.h
index 27a7d3a..6d9a5d0 100644
--- a/lib/ext2fs/ext2_fs.h
+++ b/lib/ext2fs/ext2_fs.h
@@ -398,7 +398,7 @@  struct ext2_inode {
     __u32    i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
     __u32    i_generation;    /* File version (for NFS) */
     __u32    i_file_acl;    /* File ACL */
-    __u32    i_size_high;    /* Formerly i_dir_acl, directory ACL */
+    __u32    i_size_high;
     __u32    i_faddr;    /* Fragment address */
     union {
         struct {
@@ -446,7 +446,7 @@  struct ext2_inode_large {
     __u32    i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
     __u32    i_generation;    /* File version (for NFS) */
     __u32    i_file_acl;    /* File ACL */
-    __u32    i_size_high;    /* Formerly i_dir_acl, directory ACL */
+    __u32    i_size_high;
     __u32    i_faddr;    /* Fragment address */
     union {
         struct {
@@ -484,8 +484,6 @@  struct ext2_inode_large {
 #define EXT4_EPOCH_BITS 2
 #define EXT4_EPOCH_MASK ((1 << EXT4_EPOCH_BITS) - 1)

-#define i_dir_acl    i_size_high
-
 #define i_checksum_lo    osd2.linux2.l_i_checksum_lo

 #define inode_includes(size, field)            \
@@ -923,7 +921,8 @@  EXT4_FEATURE_INCOMPAT_FUNCS(encrypt,        4, ENCRYPT)

 #define EXT2_FEATURE_COMPAT_SUPP    0
 #define EXT2_FEATURE_INCOMPAT_SUPP    (EXT2_FEATURE_INCOMPAT_FILETYPE| \
-                       EXT4_FEATURE_INCOMPAT_MMP)
+                       EXT4_FEATURE_INCOMPAT_MMP|\
+                       EXT4_FEATURE_INCOMPAT_LARGEDIR)
 #define EXT2_FEATURE_RO_COMPAT_SUPP    (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
                      EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
                      EXT4_FEATURE_RO_COMPAT_DIR_NLINK| \
diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index 786ded8..5e956d0 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -588,7 +588,8 @@  typedef struct ext2_icount *ext2_icount_t;
                      EXT4_FEATURE_INCOMPAT_64BIT|\
                      EXT4_FEATURE_INCOMPAT_INLINE_DATA|\
                      EXT4_FEATURE_INCOMPAT_ENCRYPT|\
-                     EXT4_FEATURE_INCOMPAT_CSUM_SEED)
+                     EXT4_FEATURE_INCOMPAT_CSUM_SEED|\
+                     EXT4_FEATURE_INCOMPAT_LARGEDIR)

 #define EXT2_LIB_FEATURE_RO_COMPAT_SUPP
(EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|\
                      EXT4_FEATURE_RO_COMPAT_HUGE_FILE|\
@@ -1924,6 +1925,18 @@  _INLINE_ blk_t ext2fs_inode_data_blocks(ext2_filsys fs,
     return (blk_t) ext2fs_inode_data_blocks2(fs, inode);
 }

+/* htree levels for ext4 */
+#define EXT4_HTREE_LEVEL_COMPAT 1
+#define EXT4_HTREE_LEVEL    3
+
+_INLINE_ unsigned int ext2_dir_htree_level(ext2_filsys fs)
+{
+        if (EXT2_HAS_INCOMPAT_FEATURE(fs->super,
+                          EXT4_FEATURE_INCOMPAT_LARGEDIR))
+                    return EXT4_HTREE_LEVEL;
+            return EXT4_HTREE_LEVEL_COMPAT;
+}
+
 /*
  * This is an efficient, overflow safe way of calculating ceil((1.0 * a) / b)
  */
diff --git a/lib/ext2fs/swapfs.c b/lib/ext2fs/swapfs.c
index d63fc55..2d05ee7 100644
--- a/lib/ext2fs/swapfs.c
+++ b/lib/ext2fs/swapfs.c
@@ -247,7 +247,7 @@  void ext2fs_swap_inode_full(ext2_filsys fs, struct
ext2_inode_large *t,
         has_extents = 1;
     if (!hostorder && (t->i_flags & EXT4_INLINE_DATA_FL))
         has_inline_data = 1;
-    t->i_dir_acl = ext2fs_swab32(f->i_dir_acl);
+    t->i_size_high = ext2fs_swab32(f->i_size_high);
     /*
      * Extent data and inline data are swapped on access, not here
      */
diff --git a/misc/mke2fs.c b/misc/mke2fs.c
index 9f18c83..b2bf461 100644
--- a/misc/mke2fs.c
+++ b/misc/mke2fs.c
@@ -1081,7 +1081,8 @@  static __u32 ok_features[3] = {
         EXT4_FEATURE_INCOMPAT_64BIT|
         EXT4_FEATURE_INCOMPAT_INLINE_DATA|
         EXT4_FEATURE_INCOMPAT_ENCRYPT |
-        EXT4_FEATURE_INCOMPAT_CSUM_SEED,
+        EXT4_FEATURE_INCOMPAT_CSUM_SEED |
+        EXT4_FEATURE_INCOMPAT_LARGEDIR,
     /* R/O compat */
     EXT2_FEATURE_RO_COMPAT_LARGE_FILE|
         EXT4_FEATURE_RO_COMPAT_HUGE_FILE|
diff --git a/misc/tune2fs.c b/misc/tune2fs.c
index 6239577..f78d105 100644
--- a/misc/tune2fs.c
+++ b/misc/tune2fs.c
@@ -156,7 +156,8 @@  static __u32 ok_features[3] = {
         EXT4_FEATURE_INCOMPAT_MMP |
         EXT4_FEATURE_INCOMPAT_64BIT |
         EXT4_FEATURE_INCOMPAT_ENCRYPT |
-        EXT4_FEATURE_INCOMPAT_CSUM_SEED,
+        EXT4_FEATURE_INCOMPAT_CSUM_SEED |
+        EXT4_FEATURE_INCOMPAT_LARGEDIR,
     /* R/O compat */
     EXT2_FEATURE_RO_COMPAT_LARGE_FILE |
         EXT4_FEATURE_RO_COMPAT_HUGE_FILE|
diff --git a/tests/d_special_files/expect b/tests/d_special_files/expect
index f729b0f..c825932 100644
--- a/tests/d_special_files/expect
+++ b/tests/d_special_files/expect
@@ -5,7 +5,7 @@  debugfs -R ''stat foo'' -w test.img
 Inode: 12   Type: symlink    Mode:  0777   Flags: 0x0
 Generation: 0    Version: 0x00000000
 User:     0   Group:     0   Size: 3
-File ACL: 0    Directory ACL: 0
+File ACL: 0
 Links: 1   Blockcount: 0
 Fragment:  Address: 0    Number: 0    Size: 0
 ctime: 0x50f560e0 -- Tue Jan 15 14:00:00 2013
@@ -17,7 +17,7 @@  debugfs -R ''stat foo2'' -w test.img
 Inode: 13   Type: symlink    Mode:  0777   Flags: 0x0
 Generation: 0    Version: 0x00000000
 User:     0   Group:     0   Size: 80
-File ACL: 0    Directory ACL: 0
+File ACL: 0
 Links: 1   Blockcount: 2
 Fragment:  Address: 0    Number: 0    Size: 0
 ctime: 0x50f560e0 -- Tue Jan 15 14:00:00 2013
@@ -42,7 +42,7 @@  debugfs -R ''stat pipe'' -w test.img
 Inode: 14   Type: FIFO    Mode:  0000   Flags: 0x0
 Generation: 0    Version: 0x00000000
 User:     0   Group:     0   Size: 0
-File ACL: 0    Directory ACL: 0
+File ACL: 0
 Links: 1   Blockcount: 0
 Fragment:  Address: 0    Number: 0    Size: 0
 ctime: 0x50f560e0 -- Tue Jan 15 14:00:00 2013
@@ -55,7 +55,7 @@  debugfs -R ''stat sda'' -w test.img
 Inode: 15   Type: block special    Mode:  0000   Flags: 0x0
 Generation: 0    Version: 0x00000000
 User:     0   Group:     0   Size: 0
-File ACL: 0    Directory ACL: 0
+File ACL: 0
 Links: 1   Blockcount: 0
 Fragment:  Address: 0    Number: 0    Size: 0
 ctime: 0x50f560e0 -- Tue Jan 15 14:00:00 2013
@@ -67,7 +67,7 @@  debugfs -R ''stat null'' -w test.img
 Inode: 16   Type: character special    Mode:  0000   Flags: 0x0
 Generation: 0    Version: 0x00000000
 User:     0   Group:     0   Size: 0
-File ACL: 0    Directory ACL: 0
+File ACL: 0
 Links: 1   Blockcount: 0
 Fragment:  Address: 0    Number: 0    Size: 0
 ctime: 0x50f560e0 -- Tue Jan 15 14:00:00 2013
diff --git a/tests/f_badcluster/expect b/tests/f_badcluster/expect
index 65a1641..75a3820 100644
--- a/tests/f_badcluster/expect
+++ b/tests/f_badcluster/expect
@@ -116,7 +116,7 @@  debugfs: stat /a
 Inode: 12   Type: regular    Mode:  0644   Flags: 0x80000
 Generation: 1117152157    Version: 0x00000001
 User:     0   Group:     0   Size: 3072
-File ACL: 0    Directory ACL: 0
+File ACL: 0
 Links: 1   Blockcount: 32
 Fragment:  Address: 0    Number: 0    Size: 0
 ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
@@ -128,7 +128,7 @@  debugfs: stat /b
 Inode: 13   Type: regular    Mode:  0644   Flags: 0x80000
 Generation: 1117152158    Version: 0x00000001
 User:     0   Group:     0   Size: 3072
-File ACL: 0    Directory ACL: 0
+File ACL: 0
 Links: 1   Blockcount: 32
 Fragment:  Address: 0    Number: 0    Size: 0
 ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
@@ -140,7 +140,7 @@  debugfs: stat /c
 Inode: 14   Type: regular    Mode:  0644   Flags: 0x80000
 Generation: 1117152159    Version: 0x00000001
 User:     0   Group:     0   Size: 3072
-File ACL: 0    Directory ACL: 0
+File ACL: 0
 Links: 1   Blockcount: 32
 Fragment:  Address: 0    Number: 0    Size: 0
 ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
@@ -152,7 +152,7 @@  debugfs: stat /d
 Inode: 15   Type: regular    Mode:  0644   Flags: 0x80000
 Generation: 1117152160    Version: 0x00000001
 User:     0   Group:     0   Size: 3072
-File ACL: 0    Directory ACL: 0
+File ACL: 0
 Links: 1   Blockcount: 0
 Fragment:  Address: 0    Number: 0    Size: 0
 ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
@@ -163,7 +163,7 @@  debugfs: stat /e
 Inode: 16   Type: regular    Mode:  0644   Flags: 0x80000
 Generation: 1117152161    Version: 0x00000001
 User:     0   Group:     0   Size: 6144
-File ACL: 0    Directory ACL: 0
+File ACL: 0
 Links: 1   Blockcount: 32
 Fragment:  Address: 0    Number: 0    Size: 0
 ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
@@ -175,7 +175,7 @@  debugfs: stat /f
 Inode: 17   Type: regular    Mode:  0644   Flags: 0x80000
 Generation: 1117152162    Version: 0x00000001
 User:     0   Group:     0   Size: 3072
-File ACL: 0    Directory ACL: 0
+File ACL: 0
 Links: 1   Blockcount: 32
 Fragment:  Address: 0    Number: 0    Size: 0
 ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
@@ -187,7 +187,7 @@  debugfs: stat /g
 Inode: 18   Type: regular    Mode:  0644   Flags: 0x80000
 Generation: 1117152163    Version: 0x00000001
 User:     0   Group:     0   Size: 3072
-File ACL: 0    Directory ACL: 0
+File ACL: 0
 Links: 1   Blockcount: 32
 Fragment:  Address: 0    Number: 0    Size: 0
 ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
diff --git a/tests/f_recnect_bad/expect.1 b/tests/f_recnect_bad/expect.1
index 8ba81e6..6433c8d 100644
--- a/tests/f_recnect_bad/expect.1
+++ b/tests/f_recnect_bad/expect.1
@@ -3,9 +3,6 @@  Pass 2: Checking directory structure
 i_faddr for inode 15 (/test/quux) is 23, should be zero.
 Clear? yes

-i_dir_acl for inode 15 (/test/quux) is 12, should be zero.
-Clear? yes
-
 i_file_acl for inode 13 (/test/???) is 12, should be zero.
 Clear? yes