Blame SOURCES/bz1837640-1-gfs2_jadd_Handle_out_of_space_issues.patch

9257a6
commit f65ec019aebc11d6a30cf9d4eb5f7a1fce4db3d3
9257a6
Author: Abhi Das <adas@redhat.com>
9257a6
Date:   Mon May 11 09:22:31 2020 -0500
9257a6
9257a6
    gfs2_jadd: Handle out-of-space issues
9257a6
    
9257a6
    If gfs2_jadd runs out of disk space while adding journals, it does
9257a6
    not exit gracefully. It partially does its job and bails out when
9257a6
    it hits -ENOSPC. This leaves the metafs mounted and most likely a
9257a6
    corrupted filesystem that even fsck.gfs2 can't fix.
9257a6
    
9257a6
    This patch adds a pre-check that ensures that the journals requested
9257a6
    will fit in the available space before proceeding. Note that this is
9257a6
    not foolproof because gfs2_jadd operates on a mounted filesystem.
9257a6
    While it is required that the filesystem be idle (and mounted on only
9257a6
    one node) while gfs2_jadd is being run, there is nothing stopping a
9257a6
    user from having some I/O process competing with gfs2_jadd for disk
9257a6
    blocks and consequently crashing it.
9257a6
    
9257a6
    Resolves: rhbz#1837640
9257a6
    
9257a6
    Signed-off-by: Abhi Das <adas@redhat.com>
9257a6
9257a6
diff --git a/gfs2/mkfs/main_jadd.c b/gfs2/mkfs/main_jadd.c
9257a6
index de5d9c53..948f67a1 100644
9257a6
--- a/gfs2/mkfs/main_jadd.c
9257a6
+++ b/gfs2/mkfs/main_jadd.c
9257a6
@@ -390,6 +390,8 @@ static void gather_info(struct gfs2_sbd *sdp, struct jadd_opts *opts)
9257a6
 		exit(EXIT_FAILURE);
9257a6
 	}
9257a6
 	sdp->bsize = statbuf.f_bsize;
9257a6
+	sdp->blks_total = statbuf.f_blocks;
9257a6
+	sdp->blks_alloced = sdp->blks_total - statbuf.f_bfree;
9257a6
 }
9257a6
 
9257a6
 static void find_current_journals(struct jadd_opts *opts)
9257a6
@@ -489,13 +491,43 @@ static void add_j(struct gfs2_sbd *sdp, struct jadd_opts *opts)
9257a6
 	}
9257a6
 }
9257a6
 
9257a6
+static int check_fit(struct gfs2_sbd *sdp, struct jadd_opts *opts)
9257a6
+{
9257a6
+	/* Compute how much space we'll need for the new journals
9257a6
+	 * Number of blocks needed per added journal:
9257a6
+	 * 1 block for the ir inode
9257a6
+	 * 1 block for the sc inode
9257a6
+	 * for sizes of the qc and journal inodes, use lgfs2_space_for_data()
9257a6
+	 * to calculate.
9257a6
+	 */
9257a6
+	uint64_t blks_per_j, total_blks;
9257a6
+
9257a6
+	blks_per_j = 1 + 1 +
9257a6
+		lgfs2_space_for_data(sdp, sdp->bsize, sdp->qcsize << 20) +
9257a6
+		lgfs2_space_for_data(sdp, sdp->bsize, sdp->jsize << 20);
9257a6
+	total_blks = opts->journals * blks_per_j;
9257a6
+
9257a6
+	if (total_blks > (sdp->blks_total - sdp->blks_alloced)) {
9257a6
+		printf( _("\nInsufficient space on the device to add %u %uMB "
9257a6
+			  "journals (%uMB QC size)\n\n"),
9257a6
+			opts->journals, sdp->jsize, sdp->qcsize);
9257a6
+		printf( _("Required space  : %*lu blks (%lu blks per "
9257a6
+			  "journal)\n"), 10, total_blks, blks_per_j);
9257a6
+		printf( _("Available space : %*lu blks\n\n"), 10,
9257a6
+			sdp->blks_total - sdp->blks_alloced);
9257a6
+		errno = ENOSPC;
9257a6
+		return 1;
9257a6
+	}
9257a6
+	return 0;
9257a6
+}
9257a6
+
9257a6
 int main(int argc, char *argv[])
9257a6
 {
9257a6
 	struct jadd_opts opts = {0};
9257a6
 	struct gfs2_sbd sbd, *sdp = &sbd;
9257a6
 	struct metafs mfs = {0};
9257a6
 	struct mntent *mnt;
9257a6
-	unsigned int total;
9257a6
+	unsigned int total, ret = 0;
9257a6
 
9257a6
 	setlocale(LC_ALL, "");
9257a6
 	textdomain("gfs2-utils");
9257a6
@@ -536,6 +568,12 @@ int main(int argc, char *argv[])
9257a6
 	}
9257a6
 	find_current_journals(&opts);
9257a6
 
9257a6
+	ret = check_fit(sdp, &opts);
9257a6
+	if (ret) {
9257a6
+		perror(_("Failed to add journals"));
9257a6
+		goto out;
9257a6
+	}
9257a6
+
9257a6
 	total = opts.orig_journals + opts.journals;
9257a6
 	for (opts.journals = opts.orig_journals;
9257a6
 	     opts.journals < total;
9257a6
@@ -550,13 +588,16 @@ int main(int argc, char *argv[])
9257a6
 		add_j(sdp, &opts);
9257a6
 	}
9257a6
 
9257a6
+out:
9257a6
 	free(opts.new_inode);
9257a6
 	free(opts.per_node);
9257a6
 	free(opts.jindex);
9257a6
 	close(sdp->path_fd);
9257a6
 	cleanup_metafs(&mfs;;
9257a6
 	sync();
9257a6
-	print_results(&opts);
9257a6
 
9257a6
-	return 0;
9257a6
+	if (!ret)
9257a6
+		print_results(&opts);
9257a6
+
9257a6
+	return ret;
9257a6
 }