aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJorgen Lundman <[email protected]>2012-12-17 10:33:57 +0900
committerBrian Behlendorf <[email protected]>2012-12-18 11:02:28 -0800
commit6c2856726fbae681649930d9620d9087080e58fc (patch)
tree8221f09d650f39d29569c82c8d50fb19bdea370f
parent5e6320cd1262de6eada39751807c31c059517d01 (diff)
Fix using zvol as slog device
During the original ZoL port the vdev_uses_zvols() function was disabled until it could be properly implemented. This prevented a zpool from use a zvol for its slog device. This patch implements that missing functionality by adding a zvol_is_zvol() function to zvol.c. Given the full path to a device it will lookup the device and verify its major number against the registered zvol major number for the system. If they match we know the device is a zvol. Signed-off-by: Brian Behlendorf <[email protected]> Closes #1131
-rw-r--r--include/sys/vdev.h1
-rw-r--r--include/sys/zvol.h1
-rw-r--r--module/zfs/vdev.c20
-rw-r--r--module/zfs/zvol.c23
4 files changed, 31 insertions, 14 deletions
diff --git a/include/sys/vdev.h b/include/sys/vdev.h
index 50dbe695c..005578398 100644
--- a/include/sys/vdev.h
+++ b/include/sys/vdev.h
@@ -48,7 +48,6 @@ extern int zfs_nocacheflush;
extern int vdev_open(vdev_t *);
extern void vdev_open_children(vdev_t *);
-extern boolean_t vdev_uses_zvols(vdev_t *);
extern int vdev_validate(vdev_t *, boolean_t);
extern void vdev_close(vdev_t *);
extern int vdev_create(vdev_t *, uint64_t txg, boolean_t isreplace);
diff --git a/include/sys/zvol.h b/include/sys/zvol.h
index 815b186e0..185d64523 100644
--- a/include/sys/zvol.h
+++ b/include/sys/zvol.h
@@ -36,6 +36,7 @@
extern int zvol_check_volsize(uint64_t volsize, uint64_t blocksize);
extern int zvol_check_volblocksize(uint64_t volblocksize);
extern int zvol_get_stats(objset_t *os, nvlist_t *nv);
+extern boolean_t zvol_is_zvol(const char *);
extern void zvol_create_cb(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx);
extern int zvol_create_minor(const char *);
extern int zvol_create_minors(const char *);
diff --git a/module/zfs/vdev.c b/module/zfs/vdev.c
index e0d82e673..e374f6d78 100644
--- a/module/zfs/vdev.c
+++ b/module/zfs/vdev.c
@@ -42,6 +42,7 @@
#include <sys/arc.h>
#include <sys/zil.h>
#include <sys/dsl_scan.h>
+#include <sys/zvol.h>
/*
* Virtual device management.
@@ -1074,27 +1075,20 @@ vdev_open_child(void *arg)
vd->vdev_open_thread = NULL;
}
-boolean_t
+static boolean_t
vdev_uses_zvols(vdev_t *vd)
{
-/*
- * Stacking zpools on top of zvols is unsupported until we implement a method
- * for determining if an arbitrary block device is a zvol without using the
- * path. Solaris would check the 'zvol' path component but this does not
- * exist in the Linux port, so we really should do something like stat the
- * file and check the major number. This is complicated by the fact that
- * we need to do this portably in user or kernel space.
- */
-#if 0
int c;
- if (vd->vdev_path && strncmp(vd->vdev_path, ZVOL_DIR,
- strlen(ZVOL_DIR)) == 0)
+#ifdef _KERNEL
+ if (zvol_is_zvol(vd->vdev_path))
return (B_TRUE);
+#endif
+
for (c = 0; c < vd->vdev_children; c++)
if (vdev_uses_zvols(vd->vdev_child[c]))
return (B_TRUE);
-#endif
+
return (B_FALSE);
}
diff --git a/module/zfs/zvol.c b/module/zfs/zvol.c
index 5d4802560..7a448f194 100644
--- a/module/zfs/zvol.c
+++ b/module/zfs/zvol.c
@@ -141,6 +141,29 @@ zvol_find_by_name(const char *name)
return NULL;
}
+
+/*
+ * Given a path, return TRUE if path is a ZVOL.
+ */
+boolean_t
+zvol_is_zvol(const char *device)
+{
+ struct block_device *bdev;
+ unsigned int major;
+
+ bdev = lookup_bdev(device);
+ if (IS_ERR(bdev))
+ return (B_FALSE);
+
+ major = MAJOR(bdev->bd_dev);
+ bdput(bdev);
+
+ if (major == zvol_major)
+ return (B_TRUE);
+
+ return (B_FALSE);
+}
+
/*
* ZFS_IOC_CREATE callback handles dmu zvol and zap object creation.
*/