diff --git a/SOURCES/bz1942434-1-gfs2_jadd_Use_fallocate_to_preallocate_journals.patch b/SOURCES/bz1942434-1-gfs2_jadd_Use_fallocate_to_preallocate_journals.patch new file mode 100644 index 0000000..9edf9da --- /dev/null +++ b/SOURCES/bz1942434-1-gfs2_jadd_Use_fallocate_to_preallocate_journals.patch @@ -0,0 +1,79 @@ +commit 13e09a3519cc7cbf9417acc86a6d046bdba71a9f +Author: Andrew Price +Date: Thu Mar 18 17:30:53 2021 +0000 + + gfs2_jadd: Use fallocate to preallocate journals + + Fall back to writes for ancient kernels and use larger writes in that + case to reduce the chance of fragmentation. + + Resolves: rhbz#1942434 + + Signed-off-by: Andrew Price + +diff --git a/gfs2/mkfs/main_jadd.c b/gfs2/mkfs/main_jadd.c +index ea89c96b..b0cffbac 100644 +--- a/gfs2/mkfs/main_jadd.c ++++ b/gfs2/mkfs/main_jadd.c +@@ -474,6 +474,43 @@ static uint64_t find_block_address(int fd, off_t offset, unsigned bsize) + } + #endif + ++static int alloc_new_journal(int fd, unsigned bytes) ++{ ++#define ALLOC_BUF_SIZE (4 << 20) ++ unsigned left = bytes; ++ int error; ++ char *buf; ++ ++ error = fallocate(fd, 0, 0, bytes); ++ if (error == 0) ++ return 0; ++ if (errno != EOPNOTSUPP) ++ goto out_errno; ++ ++ /* No fallocate support, fall back to writes */ ++ buf = calloc(1, ALLOC_BUF_SIZE); ++ if (buf == NULL) ++ goto out_errno; ++ ++ while (left > 0) { ++ unsigned sz = ALLOC_BUF_SIZE; ++ ++ if (left < ALLOC_BUF_SIZE) ++ sz = left; ++ ++ if (pwrite(fd, buf, sz, bytes - left) != sz) { ++ free(buf); ++ goto out_errno; ++ } ++ left -= sz; ++ } ++ free(buf); ++ return 0; ++out_errno: ++ perror("Failed to allocate space for new journal"); ++ return -1; ++} ++ + static int add_j(struct gfs2_sbd *sdp, struct jadd_opts *opts) + { + int fd, error = 0; +@@ -490,14 +527,9 @@ static int add_j(struct gfs2_sbd *sdp, struct jadd_opts *opts) + if ((error = set_flags(fd, JA_FL_CLEAR, FS_JOURNAL_DATA_FL))) + goto close_fd; + +- memset(buf, 0, sdp->bsize); +- for (x=0; xbsize) != sdp->bsize) { +- perror("add_j write"); +- error = -1; +- goto close_fd; +- } +- } ++ error = alloc_new_journal(fd, sdp->jsize << 20); ++ if (error != 0) ++ goto close_fd; + + if ((error = lseek(fd, 0, SEEK_SET)) < 0) { + perror("add_j lseek"); diff --git a/SOURCES/bz1942434-2-gfs2_jadd_Don_t_fsync_after_each_block_written.patch b/SOURCES/bz1942434-2-gfs2_jadd_Don_t_fsync_after_each_block_written.patch new file mode 100644 index 0000000..d45260f --- /dev/null +++ b/SOURCES/bz1942434-2-gfs2_jadd_Don_t_fsync_after_each_block_written.patch @@ -0,0 +1,54 @@ +commit 11070364f04a111212efcc2604840eee71f32c8f +Author: Andrew Price +Date: Thu Mar 18 17:50:16 2021 +0000 + + gfs2_jadd: Don't fsync after each block written + + gfs2_jadd has always called fsync() after writing each block of the + journal. There doesn't seem to be any need for that so take the fsync() + call out of the loop. + + Add an additional fsync() after preallocation to make sure we're in good + shape before writing the log headers. + + In my tests this reduces the time to add one journal from 5 minutes to + 9 seconds. + + Resolves: rhbz#1942434 + + Signed-off-by: Andrew Price + +diff --git a/gfs2/mkfs/main_jadd.c b/gfs2/mkfs/main_jadd.c +index b0cffbac..6aff97c3 100644 +--- a/gfs2/mkfs/main_jadd.c ++++ b/gfs2/mkfs/main_jadd.c +@@ -531,6 +531,11 @@ static int add_j(struct gfs2_sbd *sdp, struct jadd_opts *opts) + if (error != 0) + goto close_fd; + ++ error = fsync(fd); ++ if (error != 0) { ++ perror("Failed to sync journal metadata"); ++ goto close_fd; ++ } + if ((error = lseek(fd, 0, SEEK_SET)) < 0) { + perror("add_j lseek"); + goto close_fd; +@@ -574,12 +579,12 @@ static int add_j(struct gfs2_sbd *sdp, struct jadd_opts *opts) + seq = 0; + off += sdp->bsize; + +- if ((error = fsync(fd))) { +- perror("add_j fsync"); +- goto close_fd; +- } + } +- ++ error = fsync(fd); ++ if (error != 0) { ++ perror("Failed to sync journal metadata"); ++ goto close_fd; ++ } + sprintf(new_name, "journal%u", opts->journals); + error = rename2system(opts, opts->jindex, new_name); + if (error < 0 && errno != EEXIST){ diff --git a/SPECS/gfs2-utils.spec b/SPECS/gfs2-utils.spec index 0b74653..61ed698 100644 --- a/SPECS/gfs2-utils.spec +++ b/SPECS/gfs2-utils.spec @@ -12,7 +12,7 @@ Name: gfs2-utils Version: 3.2.0 -Release: 10%{?dist} +Release: 11%{?dist} License: GPLv2+ and LGPLv2+ Group: System Environment/Kernel Summary: Utilities for managing the global file system (GFS2) @@ -44,6 +44,9 @@ Patch7: bz1833141-1-gfs2_jadd_Handle_out_of_space_issues.patch Patch8: bz1833141-2-gfs2_jadd_error_handling_overhaul.patch Patch9: bz1818983-gfs2_5_Update_some_mentions_of_gfs2_tool.patch Patch10: bz1779806-mkfs_gfs2_Tighten_minimum_journal_size_checks.patch +Patch11: bz1942434-1-gfs2_jadd_Use_fallocate_to_preallocate_journals.patch +Patch12: bz1942434-2-gfs2_jadd_Don_t_fsync_after_each_block_written.patch + %prep %setup -q -n gfs2-utils-%{version} @@ -58,6 +61,9 @@ Patch10: bz1779806-mkfs_gfs2_Tighten_minimum_journal_size_checks.patch %patch8 -p1 -b .bz1833141-2-gfs2_jadd_error_handling_overhaul %patch9 -p1 -b .bz1818983-gfs2_5_Update_some_mentions_of_gfs2_tool %patch10 -p1 -b .bz1779806-mkfs_gfs2_Tighten_minimum_journal_size_checks +%patch11 -p1 -b .bz1942434-1-gfs2_jadd_Use_fallocate_to_preallocate_journals +%patch12 -p1 -b .bz1942434-2-gfs2_jadd_Don_t_fsync_after_each_block_written + %build ./autogen.sh @@ -97,6 +103,11 @@ modifying, and correcting inconsistencies in GFS2 file systems. %{_prefix}/lib/udev/rules.d/82-gfs2-withdraw.rules %changelog +* Wed Mar 24 2021 Andrew Price - 3.2.0-11 +- gfs2_jadd: Use fallocate to preallocate journals +- gfs2_jadd: Don't fsync after each block written + Resolves: rhbz#1942434 + * Thu Nov 12 2020 Andrew Price - 3.2.0-10 - mkfs.gfs2: Tighten minimum journal size checks Resolves: rhbz#1779806