Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 35adedb8830cf948b43b86231991124b > files > 215

gfs2-utils-0.1.62-39.el5.src.rpm

commit 9fb243836b132d7699af9405307279174d23ba33
Author: Bob Peterson <rpeterso@redhat.com>
Date:   Thu Aug 8 14:50:04 2013 -0500

    gfs2_tool: Update /etc/mtab with metafs mounts, handle interrupts
    
    This patch gives libgfs2 the ability to add the metafs to the
    /etc/mtab file, so that a "mount" will show it and "umount -a -tgfs2"
    will unmount it. At the same time, it also catches interrupt signals
    while gfs2_tool df is running, and if interrupted, it unmounts the
    metafs.
    
    rhbz#994643

diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index 95a4ddb..90bfe08 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -541,6 +541,8 @@ extern int gfs2_query(int *setonabort, struct gfs2_options *opts,
 /* misc.c */
 #define SYS_BASE "/sys/fs/gfs2"
 
+extern int metafs_interrupted;
+
 extern char *get_list(void);
 extern char **str2lines(char *str);
 extern char *find_debugfs_mount(void);
diff --git a/gfs2/libgfs2/misc.c b/gfs2/libgfs2/misc.c
index 3ff1dc4..590800f 100644
--- a/gfs2/libgfs2/misc.c
+++ b/gfs2/libgfs2/misc.c
@@ -30,12 +30,14 @@
 #include <sys/statfs.h>
 #include <mntent.h>
 #include <sys/time.h>
+#include <signal.h>
 
 #include "libgfs2.h"
 
 #define PAGE_SIZE (4096)
 
 static char sysfs_buf[PAGE_SIZE];
+int metafs_interrupted = 0;
 
 int compute_heightsize(struct gfs2_sbd *sdp, uint64_t *heightsize,
 		       uint32_t bsize1, int diptrs, int inptrs)
@@ -221,30 +223,47 @@ lock_for_admin(struct gfs2_sbd *sdp)
 		printf("Got it.\n");
 }
 
-void
-mount_gfs2_meta(struct gfs2_sbd *sdp)
+static void remove_mtab_entry(struct gfs2_sbd *sdp)
 {
-	int ret;
-
-	memset(sdp->metafs_path, 0, PATH_MAX);
-	snprintf(sdp->metafs_path, PATH_MAX - 1, "/tmp/.gfs2meta.XXXXXX");
-
-	if(!mkdtemp(sdp->metafs_path))
-		die("Couldn't create %s : %s\n", sdp->metafs_path,
+	FILE *mtab, *mtabnew;
+	struct mntent *mountent;
+	char mtab_tmpfn[PATH_MAX];
+	int error, fd;
+
+	mtab = setmntent("/etc/mtab", "rt");
+	if (mtab == NULL)
+		die("Couldn't open /etc/mtab for writing: %s\n",
+		    strerror(errno));
+	strcpy(mtab_tmpfn, "/etc/mtab.XXXXXX");
+	fd = mkstemp(mtab_tmpfn);
+	if (fd < 0)
+		die("Couldn't open temporary mtab file for writing: %s\n",
 		    strerror(errno));
 
-	ret = mount(sdp->path_name, sdp->metafs_path, "gfs2meta", 0, NULL);
-	if (ret) {
-		rmdir(sdp->metafs_path);
-		die("Couldn't mount %s : %s\n", sdp->metafs_path,
+	mtabnew = fdopen(fd, "wt");
+	if (mtabnew == NULL)
+		die("Couldn't open %s for writing : %s\n", mtab_tmpfn,
 		    strerror(errno));
+
+	while ((mountent = getmntent(mtab)) != NULL) {
+		if (!strcmp(mountent->mnt_dir, sdp->metafs_path))
+			continue;
+		error = addmntent(mtabnew, mountent);
+		if (error)
+			die("Unable to remove mount entry from mtab.\n");
 	}
-	lock_for_admin(sdp);
+
+	endmntent(mtab);
+	fclose(mtabnew);
+	close(fd);
+	if (rename(mtab_tmpfn, "/etc/mtab"))
+		fprintf(stderr, "Unable to remove mount entry from mtab.\n");
 }
 
 void cleanup_metafs(struct gfs2_sbd *sdp)
 {
 	int ret;
+	struct sigaction sa = {	.sa_handler = SIG_DFL };
 
 	if (sdp->metafs_fd <= 0)
 		return;
@@ -257,6 +276,68 @@ void cleanup_metafs(struct gfs2_sbd *sdp)
 			sdp->metafs_path, strerror(errno));
 	else
 		rmdir(sdp->metafs_path);
+	sigaction(SIGINT, &sa, NULL);
+	sigaction(SIGILL, &sa, NULL);
+	sigaction(SIGTERM, &sa, NULL);
+	sigaction(SIGHUP, &sa, NULL);
+	sigaction(SIGABRT, &sa, NULL);
+	sigaction(SIGSEGV, &sa, NULL);
+	sigaction(SIGCONT, &sa, NULL);
+	sigaction(SIGUSR1, &sa, NULL);
+	sigaction(SIGUSR2, &sa, NULL);
+	metafs_interrupted = 0;
+	remove_mtab_entry(sdp);
+}
+
+static void sighandler(int error)
+{
+	metafs_interrupted = 1;
+}
+
+void
+mount_gfs2_meta(struct gfs2_sbd *sdp)
+{
+	int ret;
+	struct mntent ment;
+	char mnt_type[5] = "gfs2";
+	char mnt_opts[9] = "gfs2meta";
+	FILE *mtab;
+	struct sigaction sa = {	.sa_handler = &sighandler };
+
+	memset(sdp->metafs_path, 0, PATH_MAX);
+	snprintf(sdp->metafs_path, PATH_MAX - 1, "/tmp/.gfs2meta.XXXXXX");
+
+	if(!mkdtemp(sdp->metafs_path))
+		die("Couldn't create %s : %s\n", sdp->metafs_path,
+		    strerror(errno));
+
+	mtab = setmntent("/etc/mtab", "at");
+	if (mtab == NULL)
+		die("Couldn't open /etc/mtab for writing : %s\n",
+		    strerror(errno));
+
+	sigaction(SIGINT, &sa, NULL);
+	sigaction(SIGILL, &sa, NULL);
+	sigaction(SIGTERM, &sa, NULL);
+	sigaction(SIGHUP, &sa, NULL);
+	sigaction(SIGABRT, &sa, NULL);
+	sigaction(SIGSEGV, &sa, NULL);
+	sigaction(SIGCONT, &sa, NULL);
+	sigaction(SIGUSR1, &sa, NULL);
+	sigaction(SIGUSR2, &sa, NULL);
+	ret = mount(sdp->path_name, sdp->metafs_path, "gfs2meta", 0, NULL);
+	if (ret) {
+		rmdir(sdp->metafs_path);
+		die("Couldn't mount %s : %s\n", sdp->metafs_path,
+		    strerror(errno));
+	}
+	ment.mnt_fsname = sdp->path_name;
+	ment.mnt_dir = sdp->metafs_path;
+	ment.mnt_type = mnt_type;
+	ment.mnt_opts = mnt_opts;
+	addmntent(mtab, &ment);
+	endmntent(mtab);
+	lock_for_admin(sdp);
 }
 
 static char *__get_sysfs(const char *fsname, const char *filename)
diff --git a/gfs2/mkfs/main_grow.c b/gfs2/mkfs/main_grow.c
index 9aba5da..4b87a91 100644
--- a/gfs2/mkfs/main_grow.c
+++ b/gfs2/mkfs/main_grow.c
@@ -343,6 +343,8 @@ main_grow(int argc, char *argv[])
 		/* we're only going to write out new RG information after   */
 		/* the existing RGs, and only write to the index at EOF.    */
 		ri_update(sdp, rindex_fd, &rgcount, &sane);
+		if (metafs_interrupted)
+			goto out;
 		fssize = filesystem_size(sdp);
 		if (!sdp->rgtree.osi_node) {
 			log_err(_("Error: No resource groups found.\n"));
@@ -363,9 +365,15 @@ main_grow(int argc, char *argv[])
 		else {
 			int old_rg_count;
 
+			if (metafs_interrupted)
+				goto out;
 			compute_rgrp_layout(sdp, &sdp->rgtree, TRUE);
+			if (metafs_interrupted)
+				goto out;
 			print_info(sdp);
 			initialize_new_portion(sdp, &old_rg_count);
+			if (metafs_interrupted)
+				goto out;
 			fix_rindex(sdp, rindex_fd, old_rg_count);
 		}
 	out:
@@ -377,5 +385,6 @@ main_grow(int argc, char *argv[])
 	}
 	close(sdp->path_fd);
 	sync();
-	log_notice( _("gfs2_grow complete.\n"));
+	if (!metafs_interrupted)
+		log_notice( _("gfs2_grow complete.\n"));
 }
diff --git a/gfs2/mkfs/main_jadd.c b/gfs2/mkfs/main_jadd.c
index c0945d1..8e6a3a9 100644
--- a/gfs2/mkfs/main_jadd.c
+++ b/gfs2/mkfs/main_jadd.c
@@ -509,6 +509,10 @@ main_jadd(int argc, char *argv[])
 	for (sdp->md.journals = sdp->orig_journals; 
 	     sdp->md.journals < total;
 	     sdp->md.journals++) {
+		if (metafs_interrupted) {
+			cleanup_metafs(&sbd);
+			exit(130);
+		}
 		add_ir(sdp);
 		add_sc(sdp);
 		add_qc(sdp);
diff --git a/gfs2/quota/check.c b/gfs2/quota/check.c
index 2635725..4437fd9 100644
--- a/gfs2/quota/check.c
+++ b/gfs2/quota/check.c
@@ -249,6 +249,8 @@ read_quota_file(struct gfs2_sbd *sdp, commandline_t *comline,
 			uint64_t end = fe->fe_logical + fe->fe_length, val_off;
 			unsigned int v_off;
 
+			if (metafs_interrupted)
+				break;
 			end = end > quota_file_size ? quota_file_size : end;
 			/* we only need to get the value fields, not the whole quota 
 			 * This also works when struct gfs2_quota straddle page 
@@ -514,6 +516,8 @@ set_list(struct gfs2_sbd *sdp, commandline_t *comline, int user,
 	}
 
 	for (tmp = list->next; tmp != list; tmp = tmp->next) {
+		if (metafs_interrupted)
+			goto out;
 		v = osi_list_entry(tmp, values_t, v_list);
 
 		offset = (2 * (uint64_t)v->v_id + ((user) ? 0 : 1)) *
diff --git a/gfs2/quota/main.c b/gfs2/quota/main.c
index 07aed6c..b33fdc2 100644
--- a/gfs2/quota/main.c
+++ b/gfs2/quota/main.c
@@ -394,18 +394,20 @@ do_reset(struct gfs2_sbd *sdp, commandline_t *comline)
 		    strerror(errno));
 	}
 
-	read_quota_internal(fd, 0, GQ_ID_USER, &q);
-	write_quota_internal(fd, 0, GQ_ID_USER, &q);
-
-	read_quota_internal(fd, 0, GQ_ID_GROUP, &q);
-	write_quota_internal(fd, 0, GQ_ID_GROUP, &q);
-
-	/* truncate the quota file such that only the first
-	 * two quotas(uid=0 and gid=0) remain.
-	 */
-	if (ftruncate(fd, (sizeof(struct gfs2_quota)) * 2))
-		die("couldn't truncate quota file %s\n", strerror(errno));
-	
+	if (!metafs_interrupted) {
+		read_quota_internal(fd, 0, GQ_ID_USER, &q);
+		write_quota_internal(fd, 0, GQ_ID_USER, &q);
+
+		read_quota_internal(fd, 0, GQ_ID_GROUP, &q);
+		write_quota_internal(fd, 0, GQ_ID_GROUP, &q);
+
+		/* truncate the quota file such that only the first
+		 * two quotas(uid=0 and gid=0) remain.
+		 */
+		if (ftruncate(fd, (sizeof(struct gfs2_quota)) * 2))
+			die("couldn't truncate quota file %s\n",
+			    strerror(errno));
+	}
 	close(fd);
 	close(sdp->metafs_fd);
 	cleanup_metafs(sdp);
@@ -490,6 +492,8 @@ do_list(struct gfs2_sbd *sdp, commandline_t *comline)
 			struct fiemap_extent *fe = &fmap2->fm_extents[i];
 			uint64_t end = fe->fe_logical + fe->fe_length;
 
+			if (metafs_interrupted)
+				goto fmap2_free;
 			end = end > quota_file_size ? quota_file_size : end;
 			startid = DIV_RU(fe->fe_logical, sizeof(struct gfs2_quota));
 			if (startid % 2 != pass)
@@ -553,7 +557,7 @@ do_get_one(struct gfs2_sbd *sdp, commandline_t *comline, char *filesystem)
 	strcat(quota_file, "/quota");
 
 	fd = open(quota_file, O_RDONLY);
-	if (fd < 0) {
+	if (fd < 0 || metafs_interrupted) {
 		close(sdp->metafs_fd);
 		cleanup_metafs(sdp);
 		die("can't open file %s: %s\n", quota_file,
@@ -707,7 +711,7 @@ do_set(struct gfs2_sbd *sdp, commandline_t *comline)
 	strcat(quota_file, "/quota");
 
 	fd = open(quota_file, O_RDWR);
-	if (fd < 0) {
+	if (fd < 0 || metafs_interrupted) {
 		close(sdp->metafs_fd);
 		cleanup_metafs(sdp);
 		die("can't open file %s: %s\n", quota_file,
diff --git a/gfs2/tool/df.c b/gfs2/tool/df.c
index c4a6d93..1adbc10 100644
--- a/gfs2/tool/df.c
+++ b/gfs2/tool/df.c
@@ -163,8 +163,16 @@ do_df_one(char *path)
 	/* Read the master statfs file */
 	mount_gfs2_meta(&sbd);
 
+	if (metafs_interrupted) {
+		cleanup_metafs(&sbd);
+		exit(130);
+	}
 	sprintf(statfs_fn, "%s/statfs", sbd.metafs_path);
 	statfs_fd = open(statfs_fn, O_RDONLY);
+	if (metafs_interrupted) {
+		cleanup_metafs(&sbd);
+		exit(130);
+	}
 	do_read(statfs_fd, buf, sizeof(struct gfs2_statfs_change));
 	gfs2_statfs_change_in(&sc, (char *)&buf);
 
diff --git a/gfs2/tool/misc.c b/gfs2/tool/misc.c
index 4176882..739f3a8 100644
--- a/gfs2/tool/misc.c
+++ b/gfs2/tool/misc.c
@@ -448,11 +448,19 @@ print_journals(int argc, char **argv)
 
 	sprintf(jindex_name, "%s/jindex", sbd.metafs_path);
 	jindex = opendir(jindex_name);
+	if (metafs_interrupted) {
+		cleanup_metafs(&sbd);
+		exit(130);
+	}
 	if (!jindex) {
 		die( _("Can't open %s\n"), jindex_name);
 	} else {
 		jcount = 0;
 		while ((journal = readdir(jindex))) {
+			if (metafs_interrupted) {
+				cleanup_metafs(&sbd);
+				exit(130);
+			}
 			if (journal->d_name[0] == '.')
 				continue;
 			sprintf(jname, "%s/%s", jindex_name, journal->d_name);