gfs2-utils: master - gfs2_grow: fix growing on full filesystems

Benjamin Marzinski bmarzins at fedoraproject.org
Wed Nov 24 19:24:11 UTC 2010


Gitweb:        http://git.fedorahosted.org/git/gfs2-utils.git?p=gfs2-utils.git;a=commitdiff;h=29685b697efe63402e55629812f7ae22391b2e38
Commit:        29685b697efe63402e55629812f7ae22391b2e38
Parent:        97368b361627c1a89f7e241297541118018504c9
Author:        Benjamin Marzinski <bmarzins at redhat.com>
AuthorDate:    Wed Nov 24 13:15:05 2010 -0600
Committer:     Benjamin Marzinski <bmarzins at redhat.com>
CommitterDate: Wed Nov 24 13:15:05 2010 -0600

gfs2_grow: fix growing on full filesystems

gfs2_grow was unable to grow completely full filesystems if there wasn't
enough space in the last rindex block for another rindex entry. Now
mkfs.gfs2 makes sure to allocate enough space for another entry without
increasing the file size, and gfs2_grow uses the fallocate system call
to do the same.

Signed-off-by: Benjamin Marzinski <bmarzins at redhat.com>
---
 gfs2/libgfs2/fs_ops.c     |    6 +++---
 gfs2/libgfs2/libgfs2.h    |    6 ++++--
 gfs2/libgfs2/structures.c |    7 ++++++-
 gfs2/mkfs/main_grow.c     |   32 +++++++++++++++++++++++++++++++-
 4 files changed, 44 insertions(+), 7 deletions(-)

diff --git a/gfs2/libgfs2/fs_ops.c b/gfs2/libgfs2/fs_ops.c
index e0b3e7c..047fcca 100644
--- a/gfs2/libgfs2/fs_ops.c
+++ b/gfs2/libgfs2/fs_ops.c
@@ -577,8 +577,8 @@ static void copy_from_mem(struct gfs2_buffer_head *bh, void **buf,
 	*p += size;
 }
 
-int gfs2_writei(struct gfs2_inode *ip, void *buf,
-				uint64_t offset, unsigned int size)
+int __gfs2_writei(struct gfs2_inode *ip, void *buf,
+		  uint64_t offset, unsigned int size, int resize)
 {
 	struct gfs2_sbd *sdp = ip->i_sbd;
 	struct gfs2_buffer_head *bh;
@@ -649,7 +649,7 @@ int gfs2_writei(struct gfs2_inode *ip, void *buf,
 		o = (isdir) ? sizeof(struct gfs2_meta_header) : 0;
 	}
 
-	if (ip->i_di.di_size < start + copied) {
+	if (resize && ip->i_di.di_size < start + copied) {
 		bmodified(ip->i_bh);
 		ip->i_di.di_size = start + copied;
 	}
diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index c798bda..5545b52 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -435,8 +435,10 @@ extern uint64_t meta_alloc(struct gfs2_inode *ip);
 extern uint64_t dinode_alloc(struct gfs2_sbd *sdp);
 extern int gfs2_readi(struct gfs2_inode *ip, void *buf, uint64_t offset,
 		      unsigned int size);
-extern int gfs2_writei(struct gfs2_inode *ip, void *buf, uint64_t offset,
-		       unsigned int size);
+#define gfs2_writei(ip, buf, offset, size) \
+	__gfs2_writei(ip, buf, offset, size, 1)
+extern int __gfs2_writei(struct gfs2_inode *ip, void *buf, uint64_t offset,
+			 unsigned int size, int resize);
 extern struct gfs2_buffer_head *get_file_buf(struct gfs2_inode *ip,
 					     uint64_t lbn, int prealloc);
 extern struct gfs2_buffer_head *init_dinode(struct gfs2_sbd *sdp,
diff --git a/gfs2/libgfs2/structures.c b/gfs2/libgfs2/structures.c
index a46fb8d..c8a2f50 100644
--- a/gfs2/libgfs2/structures.c
+++ b/gfs2/libgfs2/structures.c
@@ -326,10 +326,15 @@ int build_rindex(struct gfs2_sbd *sdp)
 		gfs2_rindex_out(&rl->ri, buf);
 
 		count = gfs2_writei(ip, buf, ip->i_di.di_size,
-							sizeof(struct gfs2_rindex));
+				    sizeof(struct gfs2_rindex));
 		if (count != sizeof(struct gfs2_rindex))
 			return -1;
 	}
+	memset(buf, 0, sizeof(struct gfs2_rindex));
+	count = __gfs2_writei(ip, buf, ip->i_di.di_size,
+			      sizeof(struct gfs2_rindex), 0);
+	if (count != sizeof(struct gfs2_rindex))
+		return -1;
 
 	if (sdp->debug) {
 		printf("\nResource Index:\n");
diff --git a/gfs2/mkfs/main_grow.c b/gfs2/mkfs/main_grow.c
index 6e4d549..d38d34e 100644
--- a/gfs2/mkfs/main_grow.c
+++ b/gfs2/mkfs/main_grow.c
@@ -18,6 +18,7 @@
 #include <errno.h>
 #include <stdarg.h>
 #include <linux/types.h>
+#include <linux/falloc.h>
 #include <libintl.h>
 #define _(String) gettext(String)
 
@@ -186,6 +187,7 @@ static void fix_rindex(struct gfs2_sbd *sdp, int rindex_fd, int old_rg_count)
 	char *buf, *bufptr;
 	osi_list_t *tmp;
 	ssize_t writelen;
+	struct stat statbuf;
 
 	/* Count the number of new RGs. */
 	rg = 0;
@@ -211,14 +213,42 @@ static void fix_rindex(struct gfs2_sbd *sdp, int rindex_fd, int old_rg_count)
 	gfs2_rgrp_free(&sdp->rglist);
 	fsync(sdp->device_fd);
 	if (!test) {
+		if (fstat(rindex_fd, &statbuf) != 0) {
+			log_crit("Can't stat rindex : %s\n", strerror(errno));
+			goto out;
+		}
+		if (statbuf.st_size !=
+		    old_rg_count * sizeof(struct gfs2_rindex)) {
+			log_crit("Incorrect rindex size. want %ld(%d RGs), "
+				 "have %ld\n",
+				 old_rg_count * sizeof(struct gfs2_rindex),
+				 old_rg_count, statbuf.st_size);
+			goto out;
+		}
 		/* Now write the new RGs to the end of the rindex */
 		lseek(rindex_fd, 0, SEEK_END);
 		count = write(rindex_fd, buf, writelen);
-		if (count != writelen)
+		if (count != writelen) {
 			log_crit("Error writing new rindex entries;"
 				 "aborted.\n");
+			if (count > 0)
+				goto trunc;
+			else
+				goto out;
+		}
+		if (fallocate(rindex_fd, FALLOC_FL_KEEP_SIZE, statbuf.st_size + writelen, sizeof(struct gfs2_rindex)) != 0)
+			log_crit("Error fallocating extra space : %s\n",
+				 strerror(errno));
 		fsync(rindex_fd);
 	}
+out:
+	free(buf);
+	return;
+trunc:
+	count = (count / sizeof(struct gfs2_rindex)) + old_rg_count;
+	log_crit("truncating rindex to %ld\n",
+		 (off_t)count * sizeof(struct gfs2_rindex));
+	ftruncate(rindex_fd, (off_t)count * sizeof(struct gfs2_rindex));
 	free(buf);
 }
 


More information about the cluster-commits mailing list