linux-btrfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/2] btrfs-progs: rename btrfs_scan_lblkid() to btrfs_scan_devices()
@ 2014-11-11 11:35 Karel Zak
  2014-11-11 11:35 ` [PATCH 2/2] btrfs-progs: use udev to scan for devices Karel Zak
  0 siblings, 1 reply; 3+ messages in thread
From: Karel Zak @ 2014-11-11 11:35 UTC (permalink / raw)
  To: linux-btrfs, Anand Jain; +Cc: dsterba, Karel Zak

It seems like bad idea to use a library name (lblkid) within generic
function name. The currently used scanning library is implementation
detail and this detail should be hidden for rest of the code.

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 cmds-device.c     | 2 +-
 cmds-filesystem.c | 2 +-
 disk-io.c         | 2 +-
 utils.c           | 6 +++---
 utils.h           | 2 +-
 5 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/cmds-device.c b/cmds-device.c
index 9323986..e18ef4b 100644
--- a/cmds-device.c
+++ b/cmds-device.c
@@ -235,7 +235,7 @@ static int cmd_scan_dev(int argc, char **argv)
 
 	if (all || argc == 1) {
 		printf("Scanning for Btrfs filesystems\n");
-		ret = btrfs_scan_lblkid();
+		ret = btrfs_scan_devices();
 		if (ret)
 			fprintf(stderr, "ERROR: error %d while scanning\n", ret);
 		ret = btrfs_register_all_devices();
diff --git a/cmds-filesystem.c b/cmds-filesystem.c
index e4b2785..25ef382 100644
--- a/cmds-filesystem.c
+++ b/cmds-filesystem.c
@@ -948,7 +948,7 @@ static int cmd_show(int argc, char **argv)
 		goto out;
 
 devs_only:
-	ret = btrfs_scan_lblkid();
+	ret = btrfs_scan_devices();
 
 	if (ret) {
 		fprintf(stderr, "ERROR: %d while scanning\n", ret);
diff --git a/disk-io.c b/disk-io.c
index bade5f0..85a2a57 100644
--- a/disk-io.c
+++ b/disk-io.c
@@ -1019,7 +1019,7 @@ int btrfs_scan_fs_devices(int fd, const char *path,
 	}
 
 	if (total_devs != 1) {
-		ret = btrfs_scan_lblkid();
+		ret = btrfs_scan_devices();
 		if (ret)
 			return ret;
 	}
diff --git a/utils.c b/utils.c
index 4b3bace..cc33cfc 100644
--- a/utils.c
+++ b/utils.c
@@ -1188,7 +1188,7 @@ int check_mounted_where(int fd, const char *file, char *where, int size,
 
 	/* scan other devices */
 	if (is_btrfs && total_devs > 1) {
-		ret = btrfs_scan_lblkid();
+		ret = btrfs_scan_devices();
 		if (ret)
 			return ret;
 	}
@@ -1270,7 +1270,7 @@ int btrfs_register_one_device(const char *fname)
 
 /*
  * Register all devices in the fs_uuid list created in the user
- * space. Ensure btrfs_scan_lblkid() is called before this func.
+ * space. Ensure btrfs_scan_devices() is called before this func.
  */
 int btrfs_register_all_devices(void)
 {
@@ -2181,7 +2181,7 @@ int test_dev_for_mkfs(char *file, int force_overwrite, char *estr)
 	return 0;
 }
 
-int btrfs_scan_lblkid()
+int btrfs_scan_devices()
 {
 	int fd = -1;
 	int ret;
diff --git a/utils.h b/utils.h
index 8c94624..919dfcf 100644
--- a/utils.h
+++ b/utils.h
@@ -128,7 +128,7 @@ int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf,
 			   int verify);
 int ask_user(char *question);
 int lookup_ino_rootid(int fd, u64 *rootid);
-int btrfs_scan_lblkid(void);
+int btrfs_scan_devices(void);
 int get_btrfs_mount(const char *dev, char *mp, size_t mp_size);
 int find_mount_root(const char *path, char **mount_root);
 int get_device_info(int fd, u64 devid,
-- 
1.9.3


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH 2/2] btrfs-progs: use udev to scan for devices
  2014-11-11 11:35 [PATCH 1/2] btrfs-progs: rename btrfs_scan_lblkid() to btrfs_scan_devices() Karel Zak
@ 2014-11-11 11:35 ` Karel Zak
  2014-11-11 12:40   ` [PATCH 2/2] btrfs-progs: use udev to scan for devices (v2) Karel Zak
  0 siblings, 1 reply; 3+ messages in thread
From: Karel Zak @ 2014-11-11 11:35 UTC (permalink / raw)
  To: linux-btrfs, Anand Jain; +Cc: dsterba, Karel Zak

Currently btrfs uses libblkid to scan for block devices with BTRFS.
The disadvantage is that this method is expensive. The udevd maintains
information about all block devices in udev db and all devices are
probed by udevd (it's linked with libblkid). We don't have to duplicate
this thing in btrfs.

This patch links btrfs with libudev, the original blkid based method
is used as fallback (for systems without udev, etc.)

Note that btrfs-progs project does not use autoconf, so dependence on
libudev is hardcoded to Makefile for now. It would be probably better
to add ./configure script to the project and make dependence on
libudev optional.

udev:
	# time ./btrfs device scan
	Scanning for Btrfs filesystems
	real    0m0.012s
	user    0m0.004s
	sys     0m0.003s

blkid:
	# time ./btrfs device scan
	Scanning for Btrfs filesystems
	real    0m0.076s
	user    0m0.008s
	sys     0m0.024s

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 Makefile |   2 +-
 utils.c  | 107 +++++++++++++++++++++++++++++++++++++++++++++++++--------------
 2 files changed, 84 insertions(+), 25 deletions(-)

diff --git a/Makefile b/Makefile
index 203597c..768c5e0 100644
--- a/Makefile
+++ b/Makefile
@@ -26,7 +26,7 @@ TESTS = fsck-tests.sh convert-tests.sh
 INSTALL = install
 prefix ?= /usr/local
 bindir = $(prefix)/bin
-lib_LIBS = -luuid -lblkid -lm -lz -llzo2 -L.
+lib_LIBS = -ludev -luuid -lblkid -lm -lz -llzo2 -L.
 libdir ?= $(prefix)/lib
 incdir = $(prefix)/include/btrfs
 LIBS = $(lib_LIBS) $(libs_static)
diff --git a/utils.c b/utils.c
index cc33cfc..5c71336 100644
--- a/utils.c
+++ b/utils.c
@@ -38,6 +38,7 @@
 #include <linux/kdev_t.h>
 #include <limits.h>
 #include <blkid/blkid.h>
+#include <libudev.h>
 #include "kerncompat.h"
 #include "radix-tree.h"
 #include "ctree.h"
@@ -2181,20 +2182,34 @@ int test_dev_for_mkfs(char *file, int force_overwrite, char *estr)
 	return 0;
 }
 
-int btrfs_scan_devices()
+static int scan_device(const char *path)
+{
+	int rc;
+	int fd = open(path, O_RDONLY);
+	struct btrfs_fs_devices *devs = NULL;
+	u64 ndevs;
+
+	if (fd < 0) {
+		printf("ERROR: could not open %s\n", path);
+		return 1;
+	}
+
+	rc = btrfs_scan_one_device(fd, path, &devs, &ndevs, BTRFS_SUPER_INFO_OFFSET, 0);
+	if (rc)
+		printf("ERROR: could not scan %s\n", path);
+
+	close(fd);
+	return rc;
+}
+
+
+static int btrfs_scan_devices_by_blkid(void)
 {
-	int fd = -1;
-	int ret;
-	u64 num_devices;
-	struct btrfs_fs_devices *tmp_devices;
 	blkid_dev_iterate iter = NULL;
 	blkid_dev dev = NULL;
 	blkid_cache cache = NULL;
 	char path[PATH_MAX];
 
-	if (btrfs_scan_done)
-		return 0;
-
 	if (blkid_get_cache(&cache, 0) < 0) {
 		printf("ERROR: lblkid cache get failed\n");
 		return 1;
@@ -2209,29 +2224,73 @@ int btrfs_scan_devices()
 		/* if we are here its definitely a btrfs disk*/
 		strncpy(path, blkid_dev_devname(dev), PATH_MAX);
 
-		fd = open(path, O_RDONLY);
-		if (fd < 0) {
-			printf("ERROR: could not open %s\n", path);
-			continue;
-		}
-		ret = btrfs_scan_one_device(fd, path, &tmp_devices,
-				&num_devices, BTRFS_SUPER_INFO_OFFSET, 0);
-		if (ret) {
-			printf("ERROR: could not scan %s\n", path);
-			close (fd);
-			continue;
-		}
-
-		close(fd);
+		scan_device(path);
 	}
 	blkid_dev_iterate_end(iter);
 	blkid_put_cache(cache);
 
-	btrfs_scan_done = 1;
-
 	return 0;
 }
 
+static int btrfs_scan_devices_by_udev(void)
+{
+	int rc = 1;
+	struct udev *udev = NULL;
+	struct udev_enumerate *en = NULL;
+	struct udev_list_entry *ent, *devs;
+
+	udev = udev_new();
+	if (!udev)
+		goto done;
+	en = udev_enumerate_new(udev);
+	if (!en)
+		goto done;
+
+	udev_enumerate_add_match_subsystem(en, "block");
+	if (udev_enumerate_scan_devices(en) != 0)
+		goto done;
+	devs = udev_enumerate_get_list_entry(en);
+	if (!devs)
+		goto done;
+
+	udev_list_entry_foreach(ent, devs) {
+		const char *val, *name = udev_list_entry_get_name(ent);
+		struct udev_device *dev = udev_device_new_from_syspath(udev, name);
+
+		if (!dev)
+			continue;
+		val = udev_device_get_property_value(dev, "ID_FS_TYPE");
+		if (val && strcmp(val, "btrfs") == 0) {
+			const char *path = udev_device_get_devnode(dev);
+			if (path)
+				scan_device(path);
+		}
+		udev_device_unref(dev);
+	}
+
+	rc = 0;
+done:
+	udev_enumerate_unref(en);
+	udev_unref(udev);
+
+	return rc;
+}
+
+int btrfs_scan_devices()
+{
+	int rc = 1;
+
+	if (btrfs_scan_done)
+		return 0;
+
+	rc = btrfs_scan_devices_by_udev();
+	if (rc)
+		rc = btrfs_scan_devices_by_blkid();
+
+	btrfs_scan_done = 1;
+	return rc;
+}
+
 int is_vol_small(char *file)
 {
 	int fd = -1;
-- 
1.9.3


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH 2/2] btrfs-progs: use udev to scan for devices (v2)
  2014-11-11 11:35 ` [PATCH 2/2] btrfs-progs: use udev to scan for devices Karel Zak
@ 2014-11-11 12:40   ` Karel Zak
  0 siblings, 0 replies; 3+ messages in thread
From: Karel Zak @ 2014-11-11 12:40 UTC (permalink / raw)
  To: linux-btrfs, Anand Jain; +Cc: dsterba, Karel Zak

Currently btrfs uses libblkid to scan for block devices with BTRFS.
The disadvantage is that this method is expensive. The udevd maintains
information about all block devices in udev db and all devices are
probed by udevd (it's linked with libblkid). We don't have to duplicate
this thing in btrfs.

This patch links btrfs with libudev, the original blkid based method
is used as fallback (for systems without udev, etc.)

Note that btrfs-progs project does not use autoconf, so dependence on
libudev is hardcoded to Makefile for now. It would be probably better
to add ./configure script to the project and make dependence on
libudev optional.

udev:
	# time ./btrfs device scan
	Scanning for Btrfs filesystems
	real    0m0.012s
	user    0m0.004s
	sys     0m0.003s

blkid:
	# time ./btrfs device scan
	Scanning for Btrfs filesystems
	real    0m0.076s
	user    0m0.008s
	sys     0m0.024s

V2:
	- use udev_enumerate_add_match_property()

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 Makefile |   2 +-
 utils.c  | 104 ++++++++++++++++++++++++++++++++++++++++++++++++---------------
 2 files changed, 81 insertions(+), 25 deletions(-)

diff --git a/Makefile b/Makefile
index 203597c..768c5e0 100644
--- a/Makefile
+++ b/Makefile
@@ -26,7 +26,7 @@ TESTS = fsck-tests.sh convert-tests.sh
 INSTALL = install
 prefix ?= /usr/local
 bindir = $(prefix)/bin
-lib_LIBS = -luuid -lblkid -lm -lz -llzo2 -L.
+lib_LIBS = -ludev -luuid -lblkid -lm -lz -llzo2 -L.
 libdir ?= $(prefix)/lib
 incdir = $(prefix)/include/btrfs
 LIBS = $(lib_LIBS) $(libs_static)
diff --git a/utils.c b/utils.c
index cc33cfc..8555589 100644
--- a/utils.c
+++ b/utils.c
@@ -38,6 +38,7 @@
 #include <linux/kdev_t.h>
 #include <limits.h>
 #include <blkid/blkid.h>
+#include <libudev.h>
 #include "kerncompat.h"
 #include "radix-tree.h"
 #include "ctree.h"
@@ -2181,20 +2182,34 @@ int test_dev_for_mkfs(char *file, int force_overwrite, char *estr)
 	return 0;
 }
 
-int btrfs_scan_devices()
+static int scan_device(const char *path)
+{
+	int rc;
+	int fd = open(path, O_RDONLY);
+	struct btrfs_fs_devices *devs = NULL;
+	u64 ndevs;
+
+	if (fd < 0) {
+		printf("ERROR: could not open %s\n", path);
+		return 1;
+	}
+
+	rc = btrfs_scan_one_device(fd, path, &devs, &ndevs, BTRFS_SUPER_INFO_OFFSET, 0);
+	if (rc)
+		printf("ERROR: could not scan %s\n", path);
+
+	close(fd);
+	return rc;
+}
+
+
+static int btrfs_scan_devices_by_blkid(void)
 {
-	int fd = -1;
-	int ret;
-	u64 num_devices;
-	struct btrfs_fs_devices *tmp_devices;
 	blkid_dev_iterate iter = NULL;
 	blkid_dev dev = NULL;
 	blkid_cache cache = NULL;
 	char path[PATH_MAX];
 
-	if (btrfs_scan_done)
-		return 0;
-
 	if (blkid_get_cache(&cache, 0) < 0) {
 		printf("ERROR: lblkid cache get failed\n");
 		return 1;
@@ -2209,29 +2224,70 @@ int btrfs_scan_devices()
 		/* if we are here its definitely a btrfs disk*/
 		strncpy(path, blkid_dev_devname(dev), PATH_MAX);
 
-		fd = open(path, O_RDONLY);
-		if (fd < 0) {
-			printf("ERROR: could not open %s\n", path);
-			continue;
-		}
-		ret = btrfs_scan_one_device(fd, path, &tmp_devices,
-				&num_devices, BTRFS_SUPER_INFO_OFFSET, 0);
-		if (ret) {
-			printf("ERROR: could not scan %s\n", path);
-			close (fd);
-			continue;
-		}
-
-		close(fd);
+		scan_device(path);
 	}
 	blkid_dev_iterate_end(iter);
 	blkid_put_cache(cache);
 
-	btrfs_scan_done = 1;
-
 	return 0;
 }
 
+static int btrfs_scan_devices_by_udev(void)
+{
+	int rc = 1;
+	struct udev *udev = NULL;
+	struct udev_enumerate *en = NULL;
+	struct udev_list_entry *ent, *devs;
+
+	udev = udev_new();
+	if (!udev)
+		goto done;
+	en = udev_enumerate_new(udev);
+	if (!en)
+		goto done;
+
+	udev_enumerate_add_match_subsystem(en, "block");
+	udev_enumerate_add_match_property(en, "ID_FS_TYPE", "btrfs");
+	if (udev_enumerate_scan_devices(en) != 0)
+		goto done;
+	devs = udev_enumerate_get_list_entry(en);
+	if (!devs)
+		goto done;
+
+	udev_list_entry_foreach(ent, devs) {
+		struct udev_device *dev = udev_device_new_from_syspath(udev,
+						udev_list_entry_get_name(ent));
+		if (dev) {
+			const char *path = udev_device_get_devnode(dev);
+			if (path)
+				scan_device(path);
+			udev_device_unref(dev);
+		}
+	}
+
+	rc = 0;
+done:
+	udev_enumerate_unref(en);
+	udev_unref(udev);
+
+	return rc;
+}
+
+int btrfs_scan_devices()
+{
+	int rc = 1;
+
+	if (btrfs_scan_done)
+		return 0;
+
+	rc = btrfs_scan_devices_by_udev();
+	if (rc)
+		rc = btrfs_scan_devices_by_blkid();
+
+	btrfs_scan_done = 1;
+	return rc;
+}
+
 int is_vol_small(char *file)
 {
 	int fd = -1;
-- 
1.9.3


^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2014-11-11 12:40 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-11-11 11:35 [PATCH 1/2] btrfs-progs: rename btrfs_scan_lblkid() to btrfs_scan_devices() Karel Zak
2014-11-11 11:35 ` [PATCH 2/2] btrfs-progs: use udev to scan for devices Karel Zak
2014-11-11 12:40   ` [PATCH 2/2] btrfs-progs: use udev to scan for devices (v2) Karel Zak

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).