gfs2-utils: master - mkfs.gfs2: Avoid a rename race when checking file contents

Andrew Price andyp at fedoraproject.org
Thu Jul 12 16:13:21 UTC 2012


Gitweb:        http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=04bb1157cd4967c3d935a3c77c9ba0f176dcff43
Commit:        04bb1157cd4967c3d935a3c77c9ba0f176dcff43
Parent:        aaa9d0c9f75936ef8cc19d8cfc4f48f8b4bfdd59
Author:        Andrew Price <anprice at redhat.com>
AuthorDate:    Fri Jul 6 12:50:12 2012 +0100
Committer:     Andrew Price <anprice at redhat.com>
CommitterDate: Fri Jul 6 12:50:12 2012 +0100

mkfs.gfs2: Avoid a rename race when checking file contents

Currently there is a slight chance that mkfs.gfs2 could report the
incorrect contents of the target if another file is renamed into place.
This is because we pass the target name to the file command and file
opens it again. This patch tries to avoid that condition by using the
/proc/$pid/fd/$device_fd symlink, which changes when the open file is
renamed, instead.

Signed-off-by: Andrew Price <anprice at redhat.com>
---
 gfs2/mkfs/main_mkfs.c |   11 +++++++++--
 1 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/gfs2/mkfs/main_mkfs.c b/gfs2/mkfs/main_mkfs.c
index 957b144..2d529d7 100644
--- a/gfs2/mkfs/main_mkfs.c
+++ b/gfs2/mkfs/main_mkfs.c
@@ -426,7 +426,7 @@ static void check_dev_content(const char *devname)
 	char content[1024] = { 0, };
 	char * args[] = {
 		(char *)"/usr/bin/file",
-		(char *)"-bs",
+		(char *)"-bsL",
 		(char *)devname,
 		NULL };
 	int p[2] = {-1, -1};
@@ -557,6 +557,7 @@ void main_mkfs(int argc, char *argv[])
 	int rgsize_specified = 0;
 	unsigned char uuid[16];
 	char *absname = NULL;
+	char *fdpath = NULL;
 	int islnk = 0;
 
 	memset(sdp, 0, sizeof(struct gfs2_sbd));
@@ -587,13 +588,19 @@ void main_mkfs(int argc, char *argv[])
 		exit(EXIT_FAILURE);
 	}
 
+	if (asprintf(&fdpath, "/proc/%d/fd/%d", getpid(), sdp->device_fd) < 0) {
+		perror(_("Failed to build string"));
+		exit(EXIT_FAILURE);
+	}
+
 	if (!sdp->override) {
 		islnk = is_symlink(sdp->device_name, &absname);
 		printf(_("This will destroy any data on %s.\n"), islnk ? absname : sdp->device_name);
-		check_dev_content(islnk ? absname : sdp->device_name);
 		free(absname);
+		check_dev_content(fdpath);
 		are_you_sure();
 	}
+	free(fdpath);
 
 	if (sdp->bsize == -1) {
 		if (S_ISREG(sdp->dinfo.stat.st_mode))


More information about the cluster-commits mailing list