Whamcloud - gitweb
LU-16843 ldiskfs: merge extent blocks
authorAlex Zhuravlev <bzzz@whamcloud.com>
Mon, 12 Jun 2023 05:20:16 +0000 (08:20 +0300)
committerAndreas Dilger <adilger@whamcloud.com>
Sat, 29 Jul 2023 07:58:02 +0000 (07:58 +0000)
There are cases (e.g. file written synchronously with discontiguous
blocks that are later filled in) when a lot of extents are created
initially, then the extents get merged over time, but there is no
way to merge the index blocks.  This can cause a very deep extent
index tree (above 5 levels) and cause problems like:

  inode has invalid extent depth: 6

Merge leave/index blocks (one at each level at most) to right/left
when extents are removed from the index.

submitted to ext4@ maillist:
https://lore.kernel.org/linux-ext4/7A2B8861-96AA-4815-BB58-180F63F62436@whamcloud.com/

Lustre-change: https://review.whamcloud.com/51096
Lustre-commit: 0f7e6c02a9ea5b85d8d97f724bed318268cea60f

Signed-off-by: Alex Zhuravlev <bzzz@whamcloud.com>
Change-Id: I746c0917e746eb442d3c69a23f591d9cdade76fa
Reviewed-on: https://review.whamcloud.com/c/ex/lustre-release/+/51272
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
26 files changed:
ldiskfs/kernel_patches/patches/rhel7.9/ext4-ext-merge.patch [new file with mode: 0644]
ldiskfs/kernel_patches/patches/rhel8/ext4-ext-merge.patch [new file with mode: 0644]
ldiskfs/kernel_patches/series/ldiskfs-3.10-rhel7.6.series
ldiskfs/kernel_patches/series/ldiskfs-3.10-rhel7.7.series
ldiskfs/kernel_patches/series/ldiskfs-3.10-rhel7.8.series
ldiskfs/kernel_patches/series/ldiskfs-3.10-rhel7.9.series
ldiskfs/kernel_patches/series/ldiskfs-4.12-sles15-22.series
ldiskfs/kernel_patches/series/ldiskfs-4.12-sles15.series
ldiskfs/kernel_patches/series/ldiskfs-4.12-sles15sp1-7.series
ldiskfs/kernel_patches/series/ldiskfs-4.12-sles15sp1.series
ldiskfs/kernel_patches/series/ldiskfs-4.15.0-20-ubuntu18.series
ldiskfs/kernel_patches/series/ldiskfs-4.15.0-24-ubuntu18.series
ldiskfs/kernel_patches/series/ldiskfs-4.18-rhel8.1.series
ldiskfs/kernel_patches/series/ldiskfs-4.18-rhel8.2.series
ldiskfs/kernel_patches/series/ldiskfs-4.18-rhel8.3.series
ldiskfs/kernel_patches/series/ldiskfs-4.18-rhel8.4.series
ldiskfs/kernel_patches/series/ldiskfs-4.18-rhel8.5.series
ldiskfs/kernel_patches/series/ldiskfs-4.18-rhel8.6.series
ldiskfs/kernel_patches/series/ldiskfs-4.18-rhel8.7.series
ldiskfs/kernel_patches/series/ldiskfs-4.18-rhel8.series
ldiskfs/kernel_patches/series/ldiskfs-5.0.0-13-ubuntu19.series
ldiskfs/kernel_patches/series/ldiskfs-5.4.0-42-ubuntu20.series
ldiskfs/kernel_patches/series/ldiskfs-5.4.0-66-ubuntu20.series
ldiskfs/kernel_patches/series/ldiskfs-5.4.0-ml.series
ldiskfs/kernel_patches/series/ldiskfs-5.4.21-ml.series
ldiskfs/kernel_patches/series/ldiskfs-5.8.0-ml.series

diff --git a/ldiskfs/kernel_patches/patches/rhel7.9/ext4-ext-merge.patch b/ldiskfs/kernel_patches/patches/rhel7.9/ext4-ext-merge.patch
new file mode 100644 (file)
index 0000000..b59d2c8
--- /dev/null
@@ -0,0 +1,219 @@
+Index: linux-4.18.0-80.1.2.el8_0/fs/ext4/extents.c
+===================================================================
+--- linux-4.18.0-80.1.2.el8_0.orig/fs/ext4/extents.c
++++ linux-4.18.0-80.1.2.el8_0/fs/ext4/extents.c
+@@ -1888,7 +1944,7 @@ static void ext4_ext_try_to_merge_up(
+  * This function tries to merge the @ex extent to neighbours in the tree, then
+  * tries to collapse the extent tree into the inode.
+  */
+-static void ext4_ext_try_to_merge(handle_t *handle,
++static int ext4_ext_try_to_merge(handle_t *handle,
+                                 struct inode *inode,
+                                 struct ext4_ext_path *path,
+                                 struct ext4_extent *ex)
+@@ -1905,9 +1961,177 @@ static void ext4_ext_try_to_merge(han
+               merge_done = ext4_ext_try_to_merge_right(inode, path, ex - 1);
+       if (!merge_done)
+-              (void) ext4_ext_try_to_merge_right(inode, path, ex);
++              merge_done = ext4_ext_try_to_merge_right(inode, path, ex);
+       ext4_ext_try_to_merge_up(handle, inode, path);
++
++      return merge_done;
++}
++
++/*
++ * This function tries to merge blocks from @path into @npath
++ */
++static int ext4_ext_merge_blocks(handle_t *handle,
++                              struct inode *inode,
++                              struct ext4_ext_path *path,
++                              struct ext4_ext_path *npath)
++{
++      unsigned int depth = ext_depth(inode);
++      int used, nused, free, i, k, err;
++      ext4_lblk_t next;
++
++      if (path[depth].p_hdr == npath[depth].p_hdr)
++              return 0;
++
++      used = le16_to_cpu(path[depth].p_hdr->eh_entries);
++      free = le16_to_cpu(npath[depth].p_hdr->eh_max) -
++              le16_to_cpu(npath[depth].p_hdr->eh_entries);
++      if (free < used)
++              return 0;
++
++      err = ext4_ext_get_access(handle, inode, path + depth);
++      if (err)
++              return err;
++      err = ext4_ext_get_access(handle, inode, npath + depth);
++      if (err)
++              return err;
++
++      /* move entries from the current leave to the next one */
++      nused = le16_to_cpu(npath[depth].p_hdr->eh_entries);
++      memmove(EXT_FIRST_EXTENT(npath[depth].p_hdr) + used,
++              EXT_FIRST_EXTENT(npath[depth].p_hdr),
++              nused * sizeof(struct ext4_extent));
++      memcpy(EXT_FIRST_EXTENT(npath[depth].p_hdr),
++              EXT_FIRST_EXTENT(path[depth].p_hdr),
++              used * sizeof(struct ext4_extent));
++      le16_add_cpu(&npath[depth].p_hdr->eh_entries, used);
++      le16_add_cpu(&path[depth].p_hdr->eh_entries, -used);
++      ext4_ext_try_to_merge_right(inode, npath,
++                                      EXT_FIRST_EXTENT(npath[depth].p_hdr));
++
++      err = ext4_ext_dirty(handle, inode, path + depth);
++      if (err)
++              return err;
++      err = ext4_ext_dirty(handle, inode, npath + depth);
++      if (err)
++              return err;
++
++      /* otherwise the index won't get corrected */
++      npath[depth].p_ext = EXT_FIRST_EXTENT(npath[depth].p_hdr);
++      err = ext4_ext_correct_indexes(handle, inode, npath);
++      if (err)
++              return err;
++
++      for (i = depth - 1; i >= 0; i--) {
++
++              next = ext4_idx_pblock(path[i].p_idx);
++              ext4_free_blocks(handle, inode, NULL, next, 1,
++                              EXT4_FREE_BLOCKS_METADATA |
++                              EXT4_FREE_BLOCKS_FORGET);
++              err = ext4_ext_get_access(handle, inode, path + i);
++              if (err)
++                      return err;
++              le16_add_cpu(&path[i].p_hdr->eh_entries, -1);
++              if (le16_to_cpu(path[i].p_hdr->eh_entries) == 0) {
++                      /* whole index block collapsed, go up */
++                      continue;
++              }
++              /* remove index pointer */
++              used = EXT_LAST_INDEX(path[i].p_hdr) - path[i].p_idx + 1;
++              memmove(path[i].p_idx, path[i].p_idx + 1,
++                      used * sizeof(struct ext4_extent_idx));
++
++              err = ext4_ext_dirty(handle, inode, path + i);
++              if (err)
++                      return err;
++
++              if (path[i].p_hdr == npath[i].p_hdr)
++                      break;
++
++              /* try to move index pointers */
++              used = le16_to_cpu(path[i].p_hdr->eh_entries);
++              free = le16_to_cpu(npath[i].p_hdr->eh_max) -
++                      le16_to_cpu(npath[i].p_hdr->eh_entries);
++              if (used > free)
++                      break;
++              err = ext4_ext_get_access(handle, inode, npath + i);
++              if (err)
++                      return err;
++              memmove(EXT_FIRST_INDEX(npath[i].p_hdr) + used,
++                      EXT_FIRST_INDEX(npath[i].p_hdr),
++                      npath[i].p_hdr->eh_entries * sizeof(struct ext4_extent_idx));
++              memcpy(EXT_FIRST_INDEX(npath[i].p_hdr), EXT_FIRST_INDEX(path[i].p_hdr),
++                      used * sizeof(struct ext4_extent_idx));
++              le16_add_cpu(&path[i].p_hdr->eh_entries, -used);
++              le16_add_cpu(&npath[i].p_hdr->eh_entries, used);
++              err = ext4_ext_dirty(handle, inode, path + i);
++              if (err)
++                      return err;
++              err = ext4_ext_dirty(handle, inode, npath + i);
++              if (err)
++                      return err;
++
++              /* correct index above */
++              for (k = i; k > 0; k--) {
++                      err = ext4_ext_get_access(handle, inode, npath + k - 1);
++                      if (err)
++                              return err;
++                      npath[k-1].p_idx->ei_block =
++                              EXT_FIRST_INDEX(npath[k].p_hdr)->ei_block;
++                      err = ext4_ext_dirty(handle, inode, npath + k - 1);
++                      if (err)
++                              return err;
++              }
++      }
++
++      /*
++       * TODO: given we've got two paths, it should be possible to
++       * collapse those two blocks into the root one in some cases
++       */
++      return 1;
++}
++
++static int ext4_ext_try_to_merge_blocks(handle_t *handle,
++              struct inode *inode,
++              struct ext4_ext_path *path)
++{
++      struct ext4_ext_path *npath = NULL;
++      unsigned int depth = ext_depth(inode);
++      ext4_lblk_t next;
++      int used, rc = 0;
++
++      if (depth == 0)
++              return 0;
++
++      used = le16_to_cpu(path[depth].p_hdr->eh_entries);
++      /* XXX: think of a good value here */
++      if (used > 100)
++              return 0;
++
++      /* try to merge to the next block */
++      next = ext4_ext_next_leaf_block(path);
++      if (next == EXT_MAX_BLOCKS)
++              return 0;
++      npath = ext4_ext_find_extent(inode, next, NULL, 0);
++      if (IS_ERR(npath))
++              return 0;
++      rc = ext4_ext_merge_blocks(handle, inode, path, npath);
++      ext4_ext_drop_refs(npath);
++      kfree(npath);
++      if (rc)
++              return rc > 0 ? 0 : rc;
++
++      /* try to merge with the previous block */
++      if (EXT_FIRST_EXTENT(path[depth].p_hdr)->ee_block == 0)
++              return 0;
++      next = EXT_FIRST_EXTENT(path[depth].p_hdr)->ee_block - 1;
++      npath = ext4_ext_find_extent(inode, next, NULL, 0);
++      if (IS_ERR(npath))
++              return 0;
++      rc = ext4_ext_merge_blocks(handle, inode, npath, path);
++      ext4_ext_drop_refs(npath);
++      kfree(npath);
++      return rc > 0 ? 0 : rc;
+ }
+ /*
+@@ -1979,6 +2205,7 @@ int ext4_ext_insert_extent(handle_t *
+       int depth, len, err;
+       ext4_lblk_t next;
+       int mb_flags = 0, unwritten;
++      int merged = 0;
+       if (gb_flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE)
+               mb_flags |= EXT4_MB_DELALLOC_RESERVED;
+@@ -2172,8 +2399,7 @@ has_space:
+ merge:
+       /* try to merge extents */
+       if (!(gb_flags & EXT4_GET_BLOCKS_PRE_IO))
+-              ext4_ext_try_to_merge(handle, inode, path, nearex);
+-
++              merged = ext4_ext_try_to_merge(handle, inode, path, nearex);
+       /* time to correct all indexes above */
+       err = ext4_ext_correct_indexes(handle, inode, path);
+@@ -2181,6 +2407,8 @@ merge:
+               goto cleanup;
+       err = ext4_ext_dirty(handle, inode, path + path->p_depth);
++      if (!err && merged)
++              err = ext4_ext_try_to_merge_blocks(handle, inode, path);
+ cleanup:
+       ext4_ext_drop_refs(npath);
diff --git a/ldiskfs/kernel_patches/patches/rhel8/ext4-ext-merge.patch b/ldiskfs/kernel_patches/patches/rhel8/ext4-ext-merge.patch
new file mode 100644 (file)
index 0000000..3d70d6b
--- /dev/null
@@ -0,0 +1,219 @@
+Index: linux-4.18.0-80.1.2.el8_0/fs/ext4/extents.c
+===================================================================
+--- linux-4.18.0-80.1.2.el8_0.orig/fs/ext4/extents.c
++++ linux-4.18.0-80.1.2.el8_0/fs/ext4/extents.c
+@@ -1888,7 +1944,7 @@ static void ext4_ext_try_to_merge_up(
+  * This function tries to merge the @ex extent to neighbours in the tree, then
+  * tries to collapse the extent tree into the inode.
+  */
+-static void ext4_ext_try_to_merge(handle_t *handle,
++static int ext4_ext_try_to_merge(handle_t *handle,
+                                 struct inode *inode,
+                                 struct ext4_ext_path *path,
+                                 struct ext4_extent *ex)
+@@ -1905,9 +1961,177 @@ static void ext4_ext_try_to_merge(han
+               merge_done = ext4_ext_try_to_merge_right(inode, path, ex - 1);
+       if (!merge_done)
+-              (void) ext4_ext_try_to_merge_right(inode, path, ex);
++              merge_done = ext4_ext_try_to_merge_right(inode, path, ex);
+       ext4_ext_try_to_merge_up(handle, inode, path);
++
++      return merge_done;
++}
++
++/*
++ * This function tries to merge blocks from @path into @npath
++ */
++static int ext4_ext_merge_blocks(handle_t *handle,
++                              struct inode *inode,
++                              struct ext4_ext_path *path,
++                              struct ext4_ext_path *npath)
++{
++      unsigned int depth = ext_depth(inode);
++      int used, nused, free, i, k, err;
++      ext4_lblk_t next;
++
++      if (path[depth].p_hdr == npath[depth].p_hdr)
++              return 0;
++
++      used = le16_to_cpu(path[depth].p_hdr->eh_entries);
++      free = le16_to_cpu(npath[depth].p_hdr->eh_max) -
++              le16_to_cpu(npath[depth].p_hdr->eh_entries);
++      if (free < used)
++              return 0;
++
++      err = ext4_ext_get_access(handle, inode, path + depth);
++      if (err)
++              return err;
++      err = ext4_ext_get_access(handle, inode, npath + depth);
++      if (err)
++              return err;
++
++      /* move entries from the current leave to the next one */
++      nused = le16_to_cpu(npath[depth].p_hdr->eh_entries);
++      memmove(EXT_FIRST_EXTENT(npath[depth].p_hdr) + used,
++              EXT_FIRST_EXTENT(npath[depth].p_hdr),
++              nused * sizeof(struct ext4_extent));
++      memcpy(EXT_FIRST_EXTENT(npath[depth].p_hdr),
++              EXT_FIRST_EXTENT(path[depth].p_hdr),
++              used * sizeof(struct ext4_extent));
++      le16_add_cpu(&npath[depth].p_hdr->eh_entries, used);
++      le16_add_cpu(&path[depth].p_hdr->eh_entries, -used);
++      ext4_ext_try_to_merge_right(inode, npath,
++                                      EXT_FIRST_EXTENT(npath[depth].p_hdr));
++
++      err = ext4_ext_dirty(handle, inode, path + depth);
++      if (err)
++              return err;
++      err = ext4_ext_dirty(handle, inode, npath + depth);
++      if (err)
++              return err;
++
++      /* otherwise the index won't get corrected */
++      npath[depth].p_ext = EXT_FIRST_EXTENT(npath[depth].p_hdr);
++      err = ext4_ext_correct_indexes(handle, inode, npath);
++      if (err)
++              return err;
++
++      for (i = depth - 1; i >= 0; i--) {
++
++              next = ext4_idx_pblock(path[i].p_idx);
++              ext4_free_blocks(handle, inode, NULL, next, 1,
++                              EXT4_FREE_BLOCKS_METADATA |
++                              EXT4_FREE_BLOCKS_FORGET);
++              err = ext4_ext_get_access(handle, inode, path + i);
++              if (err)
++                      return err;
++              le16_add_cpu(&path[i].p_hdr->eh_entries, -1);
++              if (le16_to_cpu(path[i].p_hdr->eh_entries) == 0) {
++                      /* whole index block collapsed, go up */
++                      continue;
++              }
++              /* remove index pointer */
++              used = EXT_LAST_INDEX(path[i].p_hdr) - path[i].p_idx + 1;
++              memmove(path[i].p_idx, path[i].p_idx + 1,
++                      used * sizeof(struct ext4_extent_idx));
++
++              err = ext4_ext_dirty(handle, inode, path + i);
++              if (err)
++                      return err;
++
++              if (path[i].p_hdr == npath[i].p_hdr)
++                      break;
++
++              /* try to move index pointers */
++              used = le16_to_cpu(path[i].p_hdr->eh_entries);
++              free = le16_to_cpu(npath[i].p_hdr->eh_max) -
++                      le16_to_cpu(npath[i].p_hdr->eh_entries);
++              if (used > free)
++                      break;
++              err = ext4_ext_get_access(handle, inode, npath + i);
++              if (err)
++                      return err;
++              memmove(EXT_FIRST_INDEX(npath[i].p_hdr) + used,
++                      EXT_FIRST_INDEX(npath[i].p_hdr),
++                      npath[i].p_hdr->eh_entries * sizeof(struct ext4_extent_idx));
++              memcpy(EXT_FIRST_INDEX(npath[i].p_hdr), EXT_FIRST_INDEX(path[i].p_hdr),
++                      used * sizeof(struct ext4_extent_idx));
++              le16_add_cpu(&path[i].p_hdr->eh_entries, -used);
++              le16_add_cpu(&npath[i].p_hdr->eh_entries, used);
++              err = ext4_ext_dirty(handle, inode, path + i);
++              if (err)
++                      return err;
++              err = ext4_ext_dirty(handle, inode, npath + i);
++              if (err)
++                      return err;
++
++              /* correct index above */
++              for (k = i; k > 0; k--) {
++                      err = ext4_ext_get_access(handle, inode, npath + k - 1);
++                      if (err)
++                              return err;
++                      npath[k-1].p_idx->ei_block =
++                              EXT_FIRST_INDEX(npath[k].p_hdr)->ei_block;
++                      err = ext4_ext_dirty(handle, inode, npath + k - 1);
++                      if (err)
++                              return err;
++              }
++      }
++
++      /*
++       * TODO: given we've got two paths, it should be possible to
++       * collapse those two blocks into the root one in some cases
++       */
++      return 1;
++}
++
++static int ext4_ext_try_to_merge_blocks(handle_t *handle,
++              struct inode *inode,
++              struct ext4_ext_path *path)
++{
++      struct ext4_ext_path *npath = NULL;
++      unsigned int depth = ext_depth(inode);
++      ext4_lblk_t next;
++      int used, rc = 0;
++
++      if (depth == 0)
++              return 0;
++
++      used = le16_to_cpu(path[depth].p_hdr->eh_entries);
++      /* XXX: think of a good value here */
++      if (used > 100)
++              return 0;
++
++      /* try to merge to the next block */
++      next = ext4_ext_next_leaf_block(path);
++      if (next == EXT_MAX_BLOCKS)
++              return 0;
++      npath = ext4_find_extent(inode, next, NULL, 0);
++      if (IS_ERR(npath))
++              return 0;
++      rc = ext4_ext_merge_blocks(handle, inode, path, npath);
++      ext4_ext_drop_refs(npath);
++      kfree(npath);
++      if (rc)
++              return rc > 0 ? 0 : rc;
++
++      /* try to merge with the previous block */
++      if (EXT_FIRST_EXTENT(path[depth].p_hdr)->ee_block == 0)
++              return 0;
++      next = EXT_FIRST_EXTENT(path[depth].p_hdr)->ee_block - 1;
++      npath = ext4_find_extent(inode, next, NULL, 0);
++      if (IS_ERR(npath))
++              return 0;
++      rc = ext4_ext_merge_blocks(handle, inode, npath, path);
++      ext4_ext_drop_refs(npath);
++      kfree(npath);
++      return rc > 0 ? 0 : rc;
+ }
+ /*
+@@ -1979,6 +2205,7 @@ int ext4_ext_insert_extent(handle_t *
+       int depth, len, err;
+       ext4_lblk_t next;
+       int mb_flags = 0, unwritten;
++      int merged = 0;
+       if (gb_flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE)
+               mb_flags |= EXT4_MB_DELALLOC_RESERVED;
+@@ -2172,8 +2399,7 @@ has_space:
+ merge:
+       /* try to merge extents */
+       if (!(gb_flags & EXT4_GET_BLOCKS_PRE_IO))
+-              ext4_ext_try_to_merge(handle, inode, path, nearex);
+-
++              merged = ext4_ext_try_to_merge(handle, inode, path, nearex);
+       /* time to correct all indexes above */
+       err = ext4_ext_correct_indexes(handle, inode, path);
+@@ -2181,6 +2407,8 @@ merge:
+               goto cleanup;
+       err = ext4_ext_dirty(handle, inode, path + path->p_depth);
++      if (!err && merged)
++              err = ext4_ext_try_to_merge_blocks(handle, inode, path);
+ cleanup:
+       ext4_ext_drop_refs(npath);
index 5347bf1..eb17732 100644 (file)
@@ -54,3 +54,4 @@ rhel7.9/ext4-enc-flag.patch
 rhel7.7/ext4-ialloc-uid-gid-and-pass-owner-down.patch
 rhel7.6/ext4-projid-xattrs.patch
 rhel7.9/ext4-filename-encode.patch
+rhel7.9/ext4-ext-merge.patch
index e2f62b7..6cdfa29 100644 (file)
@@ -54,3 +54,4 @@ rhel7.9/ext4-enc-flag.patch
 rhel7.7/ext4-ialloc-uid-gid-and-pass-owner-down.patch
 rhel7.6/ext4-projid-xattrs.patch
 rhel7.9/ext4-filename-encode.patch
+rhel7.9/ext4-ext-merge.patch
index 696fd84..6fa0dc3 100644 (file)
@@ -46,3 +46,4 @@ rhel7.9/ext4-enc-flag.patch
 rhel7.7/ext4-ialloc-uid-gid-and-pass-owner-down.patch
 rhel7.6/ext4-projid-xattrs.patch
 rhel7.9/ext4-filename-encode.patch
+rhel7.9/ext4-ext-merge.patch
index fcef984..ee89365 100644 (file)
@@ -46,3 +46,4 @@ rhel7.9/ext4-enc-flag.patch
 rhel7.7/ext4-ialloc-uid-gid-and-pass-owner-down.patch
 rhel7.6/ext4-projid-xattrs.patch
 rhel7.9/ext4-filename-encode.patch
+rhel7.9/ext4-ext-merge.patch
index e8a8420..42d8bcf 100644 (file)
@@ -28,3 +28,4 @@ suse15/ext4-export-mb-stream-allocator-variables.patch
 base/ext4-no-max-dir-size-limit-for-iam-objects.patch
 rhel7.7/ext4-ialloc-uid-gid-and-pass-owner-down.patch
 base/ext4-projid-xattrs.patch
+rhel8/ext4-ext-merge.patch
index c731d36..088df6e 100644 (file)
@@ -28,3 +28,4 @@ suse15/ext4-export-mb-stream-allocator-variables.patch
 base/ext4-no-max-dir-size-limit-for-iam-objects.patch
 rhel7.7/ext4-ialloc-uid-gid-and-pass-owner-down.patch
 base/ext4-projid-xattrs.patch
+rhel8/ext4-ext-merge.patch
index e8a8420..42d8bcf 100644 (file)
@@ -28,3 +28,4 @@ suse15/ext4-export-mb-stream-allocator-variables.patch
 base/ext4-no-max-dir-size-limit-for-iam-objects.patch
 rhel7.7/ext4-ialloc-uid-gid-and-pass-owner-down.patch
 base/ext4-projid-xattrs.patch
+rhel8/ext4-ext-merge.patch
index a51161a..4ccd79d 100644 (file)
@@ -28,3 +28,4 @@ suse15/ext4-export-mb-stream-allocator-variables.patch
 base/ext4-no-max-dir-size-limit-for-iam-objects.patch
 rhel7.7/ext4-ialloc-uid-gid-and-pass-owner-down.patch
 base/ext4-projid-xattrs.patch
+rhel8/ext4-ext-merge.patch
index f345f82..e0ca387 100644 (file)
@@ -25,3 +25,4 @@ ubuntu18/ext4-include-terminating-u32-in-size-of-xattr-entries-when-expanding-in
 base/ext4-no-max-dir-size-limit-for-iam-objects.patch
 rhel7.7/ext4-ialloc-uid-gid-and-pass-owner-down.patch
 ubuntu18/ext4-projid-xattrs.patch
+rhel8/ext4-ext-merge.patch
index 2350afa..0794695 100644 (file)
@@ -26,3 +26,4 @@ suse15/ext4-export-mb-stream-allocator-variables.patch
 base/ext4-no-max-dir-size-limit-for-iam-objects.patch
 rhel8/ext4-ialloc-uid-gid-and-pass-owner-down.patch
 ubuntu18/ext4-projid-xattrs.patch
+rhel8/ext4-ext-merge.patch
index b62a740..79edfad 100644 (file)
@@ -31,3 +31,4 @@ rhel8/ext4-ialloc-uid-gid-and-pass-owner-down.patch
 base/ext4-projid-xattrs.patch
 rhel8/ext4-filename-encode.patch
 base/ext4-delayed-iput.patch
+rhel8/ext4-ext-merge.patch
index 5e7b1ea..c07c366 100644 (file)
@@ -31,3 +31,4 @@ rhel8/ext4-ialloc-uid-gid-and-pass-owner-down.patch
 base/ext4-projid-xattrs.patch
 rhel8/ext4-filename-encode.patch
 base/ext4-delayed-iput.patch
+rhel8/ext4-ext-merge.patch
index eac24a6..fe64216 100644 (file)
@@ -31,3 +31,4 @@ rhel8/ext4-ialloc-uid-gid-and-pass-owner-down.patch
 base/ext4-projid-xattrs.patch
 rhel8/ext4-filename-encode.patch
 base/ext4-delayed-iput.patch
+rhel8/ext4-ext-merge.patch
index 11e3007..ccd43f6 100644 (file)
@@ -33,3 +33,4 @@ rhel8.5/ext4-filename-encode.patch
 rhel8/ext4-old_ea_inodes_handling_fix.patch
 rhel8.4/ext4-optimize-find_delayed_extent.patch
 base/ext4-delayed-iput.patch
+rhel8/ext4-ext-merge.patch
index 5e92fa3..dd9e9bc 100644 (file)
@@ -34,3 +34,4 @@ rhel8.5/ext4-filename-encode.patch
 rhel8/ext4-old_ea_inodes_handling_fix.patch
 rhel8.4/ext4-optimize-find_delayed_extent.patch
 base/ext4-delayed-iput.patch
+rhel8/ext4-ext-merge.patch
index 5e92fa3..dd9e9bc 100644 (file)
@@ -34,3 +34,4 @@ rhel8.5/ext4-filename-encode.patch
 rhel8/ext4-old_ea_inodes_handling_fix.patch
 rhel8.4/ext4-optimize-find_delayed_extent.patch
 base/ext4-delayed-iput.patch
+rhel8/ext4-ext-merge.patch
index 7b71bc6..61d0b9a 100644 (file)
@@ -34,3 +34,4 @@ base/ext4-delayed-iput.patch
 rhel8.7/ext4-filename-encode.patch
 rhel8/ext4-old_ea_inodes_handling_fix.patch
 rhel8.4/ext4-optimize-find_delayed_extent.patch
+rhel8/ext4-ext-merge.patch
index d794945..4a21c8d 100644 (file)
@@ -33,3 +33,4 @@ rhel8/ext4-ialloc-uid-gid-and-pass-owner-down.patch
 ubuntu18/ext4-projid-xattrs.patch
 rhel8/ext4-filename-encode.patch
 base/ext4-delayed-iput.patch
+rhel8/ext4-ext-merge.patch
index b3e7c73..b13c9e0 100644 (file)
@@ -26,3 +26,4 @@ rhel8/ext4-simple-blockalloc.patch
 base/ext4-no-max-dir-size-limit-for-iam-objects.patch
 rhel8/ext4-ialloc-uid-gid-and-pass-owner-down.patch
 base/ext4-projid-xattrs.patch
+rhel8/ext4-ext-merge.patch
index f5cb25c..594d266 100644 (file)
@@ -30,3 +30,4 @@ linux-5.4/ext4-enc-flag.patch
 rhel8/ext4-ialloc-uid-gid-and-pass-owner-down.patch
 base/ext4-projid-xattrs.patch
 base/ext4-delayed-iput.patch
+rhel8/ext4-ext-merge.patch
index 0d47ecf..0460cf4 100644 (file)
@@ -30,3 +30,4 @@ linux-5.4/ext4-enc-flag.patch
 rhel8/ext4-ialloc-uid-gid-and-pass-owner-down.patch
 base/ext4-projid-xattrs.patch
 base/ext4-delayed-iput.patch
+rhel8/ext4-ext-merge.patch
index a370d0d..1d96454 100644 (file)
@@ -30,3 +30,4 @@ linux-5.4/ext4-enc-flag.patch
 rhel8/ext4-ialloc-uid-gid-and-pass-owner-down.patch
 base/ext4-projid-xattrs.patch
 base/ext4-delayed-iput.patch
+rhel8/ext4-ext-merge.patch
index f5cb25c..594d266 100644 (file)
@@ -30,3 +30,4 @@ linux-5.4/ext4-enc-flag.patch
 rhel8/ext4-ialloc-uid-gid-and-pass-owner-down.patch
 base/ext4-projid-xattrs.patch
 base/ext4-delayed-iput.patch
+rhel8/ext4-ext-merge.patch
index 579d789..8f7ef27 100644 (file)
@@ -28,3 +28,4 @@ linux-5.8/ext4-simple-blockalloc.patch
 linux-5.8/ext4-enc-flag.patch
 linux-5.8/ext4-no-max-dir-size-limit-for-iam-objects.patch
 base/ext4-projid-xattrs.patch
+rhel8/ext4-ext-merge.patch