Skip to content

Commit

Permalink
Fix using zvol as slog device
Browse files Browse the repository at this point in the history
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 openzfs#1131
  • Loading branch information
lundman authored and unya committed Dec 13, 2013
1 parent ec54d68 commit 8b1deb0
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 14 deletions.
1 change: 0 additions & 1 deletion include/sys/vdev.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ extern int zfs_trim_zero;

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);
Expand Down
1 change: 1 addition & 0 deletions include/sys/zvol.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 *);
Expand Down
20 changes: 7 additions & 13 deletions module/zfs/vdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include <sys/zil.h>
#include <sys/dsl_scan.h>
#include <sys/trim_map.h>
#include <sys/zvol.h>

/*
* Virtual device management.
Expand Down Expand Up @@ -1086,27 +1087,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);
}

Expand Down
23 changes: 23 additions & 0 deletions module/zfs/zvol.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down

0 comments on commit 8b1deb0

Please sign in to comment.