diff mbox

[1/5,v5] btrfs-progs: make btrfs dev scan multi path aware

Message ID 1364378856-21053-2-git-send-email-anand.jain@oracle.com (mailing list archive)
State Under Review, archived
Headers show

Commit Message

Anand Jain March 27, 2013, 10:07 a.m. UTC
We should avoid using non multi-path (mp) path for mp disks
 As of now there is no good way (like api) to check that.
 A workaround way is to check if the O_EXCL open is unsuccessful.
 This is safe since otherwise the BTRFS_IOC_SCAN_DEV ioctl would
 fail if the disk-path can not be opened with the flag O_EXCL set.

 This patch also includes some (error) print format changes related
 to the btrfs dev scan..

Signed-off-by: Anand Jain <anand.jain@oracle.com>
---
 cmds-device.c | 53 +++++++++++++++++++++++++++++++++++++++--------------
 utils.c       | 31 ++++++++++++++++++++++++-------
 2 files changed, 63 insertions(+), 21 deletions(-)

Comments

Anand Jain April 11, 2013, 9:57 a.m. UTC | #1
This patch is replaced By:

btrfs-progs: avoid ioctl for multipath-dev with its non-multipath path

  which is also sent to this mailing list.

thanks, Anand


On 03/27/2013 06:07 PM, Anand Jain wrote:
>   We should avoid using non multi-path (mp) path for mp disks
>   As of now there is no good way (like api) to check that.
>   A workaround way is to check if the O_EXCL open is unsuccessful.
>   This is safe since otherwise the BTRFS_IOC_SCAN_DEV ioctl would
>   fail if the disk-path can not be opened with the flag O_EXCL set.
>
>   This patch also includes some (error) print format changes related
>   to the btrfs dev scan..
>
> Signed-off-by: Anand Jain <anand.jain@oracle.com>
> ---
>   cmds-device.c | 53 +++++++++++++++++++++++++++++++++++++++--------------
>   utils.c       | 31 ++++++++++++++++++++++++-------
>   2 files changed, 63 insertions(+), 21 deletions(-)
>
> diff --git a/cmds-device.c b/cmds-device.c
> index 41e79d3..b8d05fd 100644
> --- a/cmds-device.c
> +++ b/cmds-device.c
> @@ -185,7 +185,7 @@ static const char * const cmd_scan_dev_usage[] = {
>
>   static int cmd_scan_dev(int argc, char **argv)
>   {
> -	int	i, fd, e;
> +	int	i, fd, e, ret = 0;
>   	int	checklist = 1;
>   	int	devstart = 1;
>
> @@ -197,6 +197,21 @@ static int cmd_scan_dev(int argc, char **argv)
>   		devstart += 1;
>   	}
>
> +	fd = open("/dev/btrfs-control", O_RDWR);
> +	e = errno;
> +	if (fd < 0) {
> +		FILE *mfd = popen("lsmod | grep btrfs", "r");
> +		char buf[16];
> +
> +		if (fread (buf, 1, sizeof (buf), mfd) > 0)
> +			fprintf(stderr, "ERROR: failed to open "\
> +				"/dev/btrfs-control - %s\n", strerror(e));
> +		else
> +			fprintf(stderr, "ERROR: btrfs kernel module "\
> +				"is not loaded\n");
> +		return 10;
> +	}
> +
>   	if(argc<=devstart){
>
>   		int ret;
> @@ -210,20 +225,30 @@ static int cmd_scan_dev(int argc, char **argv)
>   			fprintf(stderr, "ERROR: error %d while scanning\n", ret);
>   			return 18;
>   		}
> +		printf("done\n");
>   		return 0;
>   	}
>
> -	fd = open("/dev/btrfs-control", O_RDWR);
> -	if (fd < 0) {
> -		perror("failed to open /dev/btrfs-control");
> -		return 10;
> -	}
> -
> +	printf("Scanning for Btrfs in\n");
>   	for( i = devstart ; i < argc ; i++ ){
> +		int fdt;
>   		struct btrfs_ioctl_vol_args args;
> -		int ret;
> +		printf("  %s ", argv[i]);
> +		fflush(stdout);
>
> -		printf("Scanning for Btrfs filesystems in '%s'\n", argv[i]);
> +		/*
> +		 * If for a multipath (mp) disk user provides the
> +		 * non-mp path then open with flag O_EXCL will fail,
> +		 * (also ioctl opens with O_EXCL), So test it before
> +		 * calling ioctl.
> +		 */
> +		fdt = open(argv[i], O_RDONLY|O_EXCL);
> +		if (fdt < 0) {
> +			perror("ERROR");
> +			ret = -1;
> +			continue;
> +		}
> +		close(fdt);
>
>   		strncpy_null(args.name, argv[i]);
>   		/*
> @@ -235,15 +260,15 @@ static int cmd_scan_dev(int argc, char **argv)
>   		e = errno;
>
>   		if( ret < 0 ){
> -			close(fd);
> -			fprintf(stderr, "ERROR: unable to scan the device '%s' - %s\n",
> -				argv[i], strerror(e));
> -			return 11;
> +			fprintf(stderr, "ERROR: unable to scan - %s\n",
> +				strerror(e));
> +			ret = -1;
>   		}
> +		printf("found\n");
>   	}
>
>   	close(fd);
> -	return 0;
> +	return ret;
>   }
>
>   static const char * const cmd_ready_dev_usage[] = {
> diff --git a/utils.c b/utils.c
> index a4f7b06..3a0d444 100644
> --- a/utils.c
> +++ b/utils.c
> @@ -1105,25 +1105,32 @@ again:
>   		if (!S_ISBLK(st.st_mode)) {
>   			continue;
>   		}
> -		fd = open(fullpath, O_RDONLY);
> +		fd = open(fullpath, O_RDONLY|O_EXCL);
>   		if (fd < 0) {
>   			/* ignore the following errors:
>   				ENXIO (device don't exists)
>   				ENOMEDIUM (No medium found ->
>   					like a cd tray empty)
> +				EBUSY (when mp disk is opened
> +					using non-mp path).
>   			*/
> -			if(errno != ENXIO && errno != ENOMEDIUM)
> +			if(errno != ENXIO && errno != ENOMEDIUM &&
> +				errno != EBUSY)
>   				fprintf(stderr, "failed to read %s: %s\n",
>   					fullpath, strerror(errno));
>   			continue;
>   		}
> +		close(fd);
> +
> +		fd = open(fullpath, O_RDONLY);
>   		ret = btrfs_scan_one_device(fd, fullpath, &tmp_devices,
>   					    &num_devices,
>   					    BTRFS_SUPER_INFO_OFFSET);
> +		close(fd);
> +
>   		if (ret == 0 && run_ioctl > 0) {
>   			btrfs_register_one_device(fullpath);
>   		}
> -		close(fd);
>   	}
>   	if (!list_empty(&pending_list)) {
>   		free(pending);
> @@ -1442,19 +1449,29 @@ scan_again:
>   			continue;
>   		}
>
> -		fd = open(fullpath, O_RDONLY);
> +		/* This will fail for the multi path devices
> +		* when non multipath path is used. So we avoid
> +		* sending it to the kernel which eventually will
> +		* fail.
> +		*/
> +		fd = open(fullpath, O_RDONLY|O_EXCL);
>   		if (fd < 0) {
> -			fprintf(stderr, "failed to open %s: %s\n",
> -				fullpath, strerror(errno));
> +			if (errno != EBUSY) {
> +				fprintf(stderr, "failed to open %s: %s\n",
> +					fullpath, strerror(errno));
> +			}
>   			continue;
>   		}
> +		close(fd);
> +
> +		fd = open(fullpath, O_RDONLY);
>   		ret = btrfs_scan_one_device(fd, fullpath, &tmp_devices,
>   					    &num_devices,
>   					    BTRFS_SUPER_INFO_OFFSET);
> +		close(fd);
>   		if (ret == 0 && run_ioctl > 0) {
>   			btrfs_register_one_device(fullpath);
>   		}
> -		close(fd);
>   	}
>
>   	fclose(proc_partitions);
>
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/cmds-device.c b/cmds-device.c
index 41e79d3..b8d05fd 100644
--- a/cmds-device.c
+++ b/cmds-device.c
@@ -185,7 +185,7 @@  static const char * const cmd_scan_dev_usage[] = {
 
 static int cmd_scan_dev(int argc, char **argv)
 {
-	int	i, fd, e;
+	int	i, fd, e, ret = 0;
 	int	checklist = 1;
 	int	devstart = 1;
 
@@ -197,6 +197,21 @@  static int cmd_scan_dev(int argc, char **argv)
 		devstart += 1;
 	}
 
+	fd = open("/dev/btrfs-control", O_RDWR);
+	e = errno;
+	if (fd < 0) {
+		FILE *mfd = popen("lsmod | grep btrfs", "r");
+		char buf[16];
+
+		if (fread (buf, 1, sizeof (buf), mfd) > 0)
+			fprintf(stderr, "ERROR: failed to open "\
+				"/dev/btrfs-control - %s\n", strerror(e));
+		else
+			fprintf(stderr, "ERROR: btrfs kernel module "\
+				"is not loaded\n");
+		return 10;
+	}
+
 	if(argc<=devstart){
 
 		int ret;
@@ -210,20 +225,30 @@  static int cmd_scan_dev(int argc, char **argv)
 			fprintf(stderr, "ERROR: error %d while scanning\n", ret);
 			return 18;
 		}
+		printf("done\n");
 		return 0;
 	}
 
-	fd = open("/dev/btrfs-control", O_RDWR);
-	if (fd < 0) {
-		perror("failed to open /dev/btrfs-control");
-		return 10;
-	}
-
+	printf("Scanning for Btrfs in\n");
 	for( i = devstart ; i < argc ; i++ ){
+		int fdt;
 		struct btrfs_ioctl_vol_args args;
-		int ret;
+		printf("  %s ", argv[i]);
+		fflush(stdout);
 
-		printf("Scanning for Btrfs filesystems in '%s'\n", argv[i]);
+		/*
+		 * If for a multipath (mp) disk user provides the
+		 * non-mp path then open with flag O_EXCL will fail,
+		 * (also ioctl opens with O_EXCL), So test it before
+		 * calling ioctl.
+		 */
+		fdt = open(argv[i], O_RDONLY|O_EXCL);
+		if (fdt < 0) {
+			perror("ERROR");
+			ret = -1;
+			continue;
+		}
+		close(fdt);
 
 		strncpy_null(args.name, argv[i]);
 		/*
@@ -235,15 +260,15 @@  static int cmd_scan_dev(int argc, char **argv)
 		e = errno;
 
 		if( ret < 0 ){
-			close(fd);
-			fprintf(stderr, "ERROR: unable to scan the device '%s' - %s\n",
-				argv[i], strerror(e));
-			return 11;
+			fprintf(stderr, "ERROR: unable to scan - %s\n",
+				strerror(e));
+			ret = -1;
 		}
+		printf("found\n");
 	}
 
 	close(fd);
-	return 0;
+	return ret;
 }
 
 static const char * const cmd_ready_dev_usage[] = {
diff --git a/utils.c b/utils.c
index a4f7b06..3a0d444 100644
--- a/utils.c
+++ b/utils.c
@@ -1105,25 +1105,32 @@  again:
 		if (!S_ISBLK(st.st_mode)) {
 			continue;
 		}
-		fd = open(fullpath, O_RDONLY);
+		fd = open(fullpath, O_RDONLY|O_EXCL);
 		if (fd < 0) {
 			/* ignore the following errors:
 				ENXIO (device don't exists) 
 				ENOMEDIUM (No medium found -> 
 					like a cd tray empty)
+				EBUSY (when mp disk is opened
+					using non-mp path).
 			*/
-			if(errno != ENXIO && errno != ENOMEDIUM) 
+			if(errno != ENXIO && errno != ENOMEDIUM &&
+				errno != EBUSY)
 				fprintf(stderr, "failed to read %s: %s\n", 
 					fullpath, strerror(errno));
 			continue;
 		}
+		close(fd);
+
+		fd = open(fullpath, O_RDONLY);
 		ret = btrfs_scan_one_device(fd, fullpath, &tmp_devices,
 					    &num_devices,
 					    BTRFS_SUPER_INFO_OFFSET);
+		close(fd);
+
 		if (ret == 0 && run_ioctl > 0) {
 			btrfs_register_one_device(fullpath);
 		}
-		close(fd);
 	}
 	if (!list_empty(&pending_list)) {
 		free(pending);
@@ -1442,19 +1449,29 @@  scan_again:
 			continue;
 		}
 
-		fd = open(fullpath, O_RDONLY);
+		/* This will fail for the multi path devices
+		* when non multipath path is used. So we avoid
+		* sending it to the kernel which eventually will
+		* fail.
+		*/
+		fd = open(fullpath, O_RDONLY|O_EXCL);
 		if (fd < 0) {
-			fprintf(stderr, "failed to open %s: %s\n",
-				fullpath, strerror(errno));
+			if (errno != EBUSY) {
+				fprintf(stderr, "failed to open %s: %s\n",
+					fullpath, strerror(errno));
+			}
 			continue;
 		}
+		close(fd);
+
+		fd = open(fullpath, O_RDONLY);
 		ret = btrfs_scan_one_device(fd, fullpath, &tmp_devices,
 					    &num_devices,
 					    BTRFS_SUPER_INFO_OFFSET);
+		close(fd);
 		if (ret == 0 && run_ioctl > 0) {
 			btrfs_register_one_device(fullpath);
 		}
-		close(fd);
 	}
 
 	fclose(proc_partitions);