diff mbox

Btrfs-progs: avoid to scan cdrom and floppy

Message ID 201011112027.55875.kreijack@libero.it (mailing list archive)
State New, archived
Headers show

Commit Message

Goffredo Baroncelli Nov. 11, 2010, 7:27 p.m. UTC
None
diff mbox

Patch

diff --git a/btrfs.c b/btrfs.c
index 46314cf..d850e60 100644
--- a/btrfs.c
+++ b/btrfs.c
@@ -83,9 +83,10 @@  static struct Command commands[] = {
 		"will occupe all available space on the device."
 	},
 	{ do_show_filesystem, 999,
-	  "filesystem show", "[<uuid>|<label>]\n"
+	  "filesystem show", "[--all-devices][<uuid>|<label>]\n"
 		"Show the info of a btrfs filesystem. If no <uuid> or <label>\n"
-		"is passed, info of all the btrfs filesystem are shown."
+		"is passed, info of all the btrfs filesystem are shown.\n"
+		"If --all-devices is passed, all devices are scanned."
 	},
 	{ do_df_filesystem, 1,
 	  "filesystem df", "<path>\n"
@@ -96,9 +97,10 @@  static struct Command commands[] = {
 		"Balance the chunks across the device."
 	},
 	{ do_scan,
-	  999, "device scan", "[<device> [<device>..]\n"
+	  999, "device scan", "[--all-devices|<device> [<device>..]\n"
 		"Scan all device for or the passed device for a btrfs\n"
-		"filesystem."
+		"filesystem.\n"
+		"If --all-devices is passed, all devices are scanned."
 	},
 	{ do_add_volume, -2,
 	  "device add", "<dev> [<dev>..] <path>\n"
diff --git a/btrfs.devices b/btrfs.devices
new file mode 100644
index 0000000..ffeb8b6
--- /dev/null
+++ b/btrfs.devices
@@ -0,0 +1,24 @@ 
+#
+#	This file lists the devices which have to be skipped or not
+#	during the command 'btrfs filesystem show' and 'btrfs device scan'
+#
+#	These lines may contain a shell wildcard pattern (*,?,[]).
+#
+#	If a line starts with "!" and matches a device, the device is skipped
+#	If a line matches a device, the device is evaluated
+#	If a device is not matched by any line, the device is evaluated.
+#
+#	The lines starting with "#" are comments. The lines empty are
+#	ignored 
+#
+
+
+
+# There are two default rules which are added automatically
+#
+# skip floppy
+# !/dev/fd*
+#
+# skip cdrom
+# !/dev/sr*
+#
diff --git a/btrfs_cmds.c b/btrfs_cmds.c
index 8031c58..a573008 100644
--- a/btrfs_cmds.c
+++ b/btrfs_cmds.c
@@ -529,11 +529,25 @@  int do_fssync(int argc, char **argv)
 int do_scan(int argc, char **argv)
 {
 	int	i, fd;
-	if(argc<=1){
+	int	checklist = 1;
+	int	devstart = 1;
+
+	if( argc >= 2 && !strcmp(argv[1],"--all-devices")){
+
+		if( argc >2 ){
+			fprintf(stderr, "ERROR: too may arguments\n");
+                        return 22;
+                }
+
+		checklist = 0;
+		devstart += 1;
+	}
+
+	if(argc<=devstart){
 		int ret;
 
 		printf("Scanning for Btrfs filesystems\n");
-		ret = btrfs_scan_one_dir("/dev", 1);
+		ret = btrfs_scan_block_devices(1, checklist);
 		if (ret){
 			fprintf(stderr, "ERROR: error %d while scanning\n", ret);
 			return 18;
@@ -547,7 +561,7 @@  int do_scan(int argc, char **argv)
 		return 10;
 	}
 
-	for( i = 1 ; i < argc ; i++ ){
+	for( i = devstart ; i < argc ; i++ ){
 		struct btrfs_ioctl_vol_args args;
 		int ret;
 
@@ -666,15 +680,30 @@  int do_show_filesystem(int argc, char **argv)
 	struct list_head *all_uuids;
 	struct btrfs_fs_devices *fs_devices;
 	struct list_head *cur_uuid;
-	char *search = argv[1];
+	char *search=0;
 	int ret;
+	int checklist = 1;
+	int searchstart = 1;
 
-	ret = btrfs_scan_one_dir("/dev", 0);
+	if( argc >= 2 && !strcmp(argv[1],"--all-devices")){
+		checklist = 0;
+		searchstart += 1;
+	}
+
+	if( argc > searchstart+1 ){
+		fprintf(stderr, "ERROR: too many arguments\n");
+		return 22;
+	}	
+
+	ret = btrfs_scan_block_devices(0, checklist);
 	if (ret){
 		fprintf(stderr, "ERROR: error %d while scanning\n", ret);
 		return 18;
 	}
 
+	if(searchstart < argc)
+		search = argv[searchstart];
+
 	all_uuids = btrfs_scanned_uuids();
 	list_for_each(cur_uuid, all_uuids) {
 		fs_devices = list_entry(cur_uuid, struct btrfs_fs_devices,
diff --git a/man/btrfs.8.in b/man/btrfs.8.in
index 26ef982..77b13f6 100644
--- a/man/btrfs.8.in
+++ b/man/btrfs.8.in
@@ -21,9 +21,9 @@  btrfs \- control a btrfs filesystem
 .PP
 \fBbtrfs\fP \fBfilesystem resize\fP\fI [+/\-]<size>[gkm]|max <filesystem>\fP
 .PP
-\fBbtrfs\fP \fBdevice scan\fP\fI [<device> [<device>..]]\fP
+\fBbtrfs\fP \fBfilesystem show\fP\fI [--all-devices] <uuid>|<label> [<uuid>|<label>...]\fP
 .PP
-\fBbtrfs\fP \fBdevice show\fP\fI <dev>|<label> [<dev>|<label>...]\fP
+\fBbtrfs\fP \fBdevice scan\fP\fI [--all-devices][<device> [<device>..]]\fP
 .PP
 \fBbtrfs\fP \fBdevice balance\fP\fI <path> \fP
 .PP
@@ -106,9 +106,10 @@  is returned by the \fBsubvolume list\fR command.
 Defragment files and/or directories.
 .TP
 
-\fBdevice scan\fR \fI[<device> [<device>..]]\fR
+\fBdevice scan\fR \fI[--all-devices][<device> [<device>..]]\fR
 Scan devices for a btrfs filesystem. If no devices are passed, \fBbtrfs\fR scans
-all the block devices.
+all the block devices. If --all-devices is passed, the file /etc/btrfs.devices
+are ignored and all devices are scanned.
 .TP
 
 \fBfilesystem sync\fR\fI <path> \fR
@@ -138,9 +139,10 @@  can expand the partition before enlarging the filesystem and shrink the
 partition after reducing the size of the filesystem.
 .TP
 
-\fBfilesystem show\fR [<uuid>|<label>]\fR
+\fBfilesystem show\fR [--all-devices][<uuid>|<label>]\fR
 Show the btrfs filesystem with some additional info. If no UUID or label is
-passed, \fBbtrfs\fR show info of all the btrfs filesystem.
+passed, \fBbtrfs\fR show info of all the btrfs filesystem. If --all-devices
+is passed, the file /etc/btrfs.devices are ignored and all devices are scanned.
 .TP
 
 \fBdevice balance\fR \fI<path>\fR
@@ -160,6 +162,14 @@  Remove device(s) from a filesystem identified by \fI<path>\fR.
 \fBbtrfs\fR returns a zero exist status if it succeeds. Non zero is returned in
 case of failure.
 
+.SH FILES
+The file \fB/etc/btrfs.devices\fR contains a list of devices which have to be
+skipped (or not) when the commands \fBbtrfs filesystem show\fR and
+\fBbtrfs device scan\fR are executed. If a line starts with '!', and matches
+a device, this device is skipped. If a line matches a device, this device is
+evaluated. If this file doesn't exists, the default rules are to skip floppy
+and cdrom.The shell wildcard may be used.
+
 .SH AVAILABILITY
 .B btrfs
 is part of btrfs-progs. Btrfs filesystem is currently under heavy development,
diff --git a/utils.c b/utils.c
index fd894f3..6112137 100644
--- a/utils.c
+++ b/utils.c
@@ -35,6 +35,8 @@ 
 #include <linux/major.h>
 #include <linux/kdev_t.h>
 #include <limits.h>
+#include <ctype.h>
+#include <fnmatch.h>
 #include "kerncompat.h"
 #include "radix-tree.h"
 #include "ctree.h"
@@ -833,7 +835,185 @@  void btrfs_register_one_device(char *fname)
 	close(fd);
 }
 
-int btrfs_scan_one_dir(char *dirname, int run_ioctl)
+
+static char **device_checklist = 0;
+static int  device_checklist_count = 0;
+/*
+ *	Default device black list:
+ *	If the line starts with a "!" the device has to be skipped
+ *	otherwise the device is OK
+ */
+static char *default_checklist[] = {
+	"!/dev/fd*",
+	"!/dev/sr*",
+	0
+};
+/* add an entry in the checklist */
+static int device_checklist_add(char *entry)
+{
+	char	*cpy;
+	char	**res;
+
+	device_checklist_count += 1;
+	res = realloc(device_checklist, 
+				sizeof(char*)*device_checklist_count);
+	if( !res ){
+		free(device_checklist);
+		device_checklist_count = 0;
+		return -1;
+	}
+	device_checklist = res;
+
+	cpy = strdup(entry);
+	if( !cpy ){
+                free(device_checklist);
+                device_checklist_count = 0;
+                return -1;
+        }
+
+	device_checklist[device_checklist_count-1] = cpy;
+	return 0;
+}
+
+/* 
+ * init the check list on teh basis of the default check list
+ * and the check list stored in the file "fn"
+ */
+static int init_device_checklist(char *fn)
+{
+
+	char	buf[1024];
+	int	i;
+	FILE	*fp;
+
+	if(device_checklist_count)
+		return 0;
+
+	if( fn == 0 )
+		return 0;	/* no extra rules provided */
+
+	fp = fopen(fn, "r");
+	if(!fp)
+		return 0;	/* the file doesn't exist */
+
+	while(fgets(buf,1023, fp)){
+		char	*p = buf;
+		char	*l;
+		while (isblank(*p)) p++;
+		l = p;
+		while( *l != '\n' && *l != '\r' && *l ) l++;
+		*l = 0;
+
+		if( *p == '#' || *p == 0 )
+			continue;
+
+		if(device_checklist_add(p)){
+			fclose(fp);
+			return -2;
+		}
+	}
+	fclose(fp);
+
+	for(i=0; default_checklist[i] ; i++ )
+		if(device_checklist_add(default_checklist[i]))
+			return -3;
+
+	
+	return 0;
+}
+
+/* 
+ * This function test if "dev" has to be skipped on the basis of the
+ * checklist; return values:
+ *	0 -> skip the deive
+ *	1 -> teh device is ok
+ */
+static int test_device(char *dev )
+{
+	int	i;
+	for( i = 0 ; i < device_checklist_count ; i++ ){
+		int	res;
+		char	*rule;
+
+		rule = device_checklist[i];
+
+		if( rule[0] == '!' ){
+			res = 0;	/* if match, skip the device */
+			rule++;
+		}else{
+			res = 1;	/* if match, the device is ok */
+		}
+
+		if( !fnmatch(rule, dev, 0 ) )
+			return res;
+
+	}
+	return 1;
+}
+
+int btrfs_scan_block_devices(int run_ioctl, int checklist)
+{
+
+	struct stat st;
+	int ret;
+	int fd;
+	struct btrfs_fs_devices *tmp_devices;
+	u64 num_devices;
+	FILE *proc_partitions;
+	int i;
+	char buf[1024];
+	char name[100], fullpath[110];
+
+	if(checklist)
+		init_device_checklist(BTRFSDEVICELIST);
+
+	proc_partitions = fopen("/proc/partitions","r");
+	if (!proc_partitions) {
+		fprintf(stderr, "Unable to open '/proc/partitions' for scanning\n");
+		return -ENOENT;
+	}
+	/* skip the header */
+	for(i=0; i < 2 ; i++)
+		if(!fgets(buf, 1023, proc_partitions)){
+		fprintf(stderr, "Unable to read '/proc/partitions' for scanning\n");
+		fclose(proc_partitions);
+		return -ENOENT;
+	}
+
+	strcpy(fullpath,"/dev/");
+	while(fgets(buf, 1023, proc_partitions)) {
+
+		i = sscanf(buf," %*d %*d %*d %99s", fullpath+5);
+		ret = lstat(fullpath, &st);
+		if (ret < 0) {
+			fprintf(stderr, "failed to stat %s\n", fullpath);
+			continue;
+		}
+		if (!S_ISBLK(st.st_mode)) {
+			continue;
+		}
+		if (checklist && !test_device(fullpath)){
+			continue;
+		}
+		fd = open(fullpath, O_RDONLY);
+		if (fd < 0) {
+			fprintf(stderr, "failed to read %s\n", fullpath);
+			continue;
+		}
+		ret = btrfs_scan_one_device(fd, fullpath, &tmp_devices,
+					    &num_devices,
+					    BTRFS_SUPER_INFO_OFFSET);
+		if (ret == 0 && run_ioctl > 0) {
+			btrfs_register_one_device(fullpath);
+		}
+		close(fd);
+	}
+
+	fclose(proc_partitions);
+	return 0;
+}
+
+int btrfs_scan_one_dir_checklist(char *dirname, int run_ioctl, int checklist)
 {
 	DIR *dirp = NULL;
 	struct dirent *dirent;
@@ -848,6 +1028,9 @@  int btrfs_scan_one_dir(char *dirname, int run_ioctl)
 	struct btrfs_fs_devices *tmp_devices;
 	u64 num_devices;
 
+	if(checklist)
+		init_device_checklist(BTRFSDEVICELIST);
+
 	INIT_LIST_HEAD(&pending_list);
 
 	pending = malloc(sizeof(*pending));
@@ -867,7 +1050,8 @@  again:
 	}
 	dirp = opendir(dirname);
 	if (!dirp) {
-		fprintf(stderr, "Unable to open /sys/block for scanning\n");
+		fprintf(stderr, "Unable to open '%s' for scanning\n", 
+			dirname);
 		return -ENOENT;
 	}
 	while(1) {
@@ -900,6 +1084,9 @@  again:
 		if (!S_ISBLK(st.st_mode)) {
 			continue;
 		}
+		if (checklist && !test_device(fullpath)){
+			continue;
+		}
 		fd = open(fullpath, O_RDONLY);
 		if (fd < 0) {
 			fprintf(stderr, "failed to read %s\n", fullpath);
@@ -929,6 +1116,11 @@  fail:
 	return ret;
 }
 
+int btrfs_scan_one_dir(char *dirname, int run_ioctl)
+{
+	return btrfs_scan_one_dir_checklist(dirname, run_ioctl, 0);
+}
+
 int btrfs_scan_for_fsid(struct btrfs_fs_devices *fs_devices, u64 total_devs,
 			int run_ioctls)
 {
diff --git a/utils.h b/utils.h
index 9dce5b0..b815f9b 100644
--- a/utils.h
+++ b/utils.h
@@ -36,8 +36,13 @@  int btrfs_scan_for_fsid(struct btrfs_fs_devices *fs_devices, u64 
total_devs,
 			int run_ioctls);
 void btrfs_register_one_device(char *fname);
 int btrfs_scan_one_dir(char *dirname, int run_ioctl);
+int btrfs_scan_one_dir_checklist(char *dirname, int run_ioctl, int checklist);
 int check_mounted(const char *devicename);
 int btrfs_device_already_in_root(struct btrfs_root *root, int fd,
 				 int super_offset);
 char *pretty_sizes(u64 size);
+int btrfs_scan_block_devices(int run_ioctl, int checklist);
+
+#define BTRFSDEVICELIST "/etc/btrfs.devices"
+