diff options
author | Alex Wilson <alex.wilson@joyent.com> | 2015-08-28 18:03:26 -0700 |
---|---|---|
committer | Robert Mustacchi <rm@joyent.com> | 2015-09-01 17:28:54 -0700 |
commit | 0ad555ad6a787635be8c8a424168dc59cfbce6c7 (patch) | |
tree | 5cdd4cf2e87316026bc1b56cb8f13aec9ceb451a | |
parent | 2becb8cdf9cd77e1a76224f216be15d6ae3b9ec9 (diff) | |
download | illumos-joyent-0ad555ad6a787635be8c8a424168dc59cfbce6c7.tar.gz |
6174 /dev/zvol does not show pool directories
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Jason King <jason.brian.king@gmail.com>
Approved by: Dan McDonald <danmcd@omniti.com>
-rw-r--r-- | usr/src/uts/common/fs/dev/sdev_vfsops.c | 17 | ||||
-rw-r--r-- | usr/src/uts/common/fs/dev/sdev_zvolops.c | 91 | ||||
-rw-r--r-- | usr/src/uts/common/sys/fs/sdev_impl.h | 4 |
3 files changed, 91 insertions, 21 deletions
diff --git a/usr/src/uts/common/fs/dev/sdev_vfsops.c b/usr/src/uts/common/fs/dev/sdev_vfsops.c index ea9cb6374a..00e981ce9c 100644 --- a/usr/src/uts/common/fs/dev/sdev_vfsops.c +++ b/usr/src/uts/common/fs/dev/sdev_vfsops.c @@ -21,6 +21,7 @@ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright 2015 Joyent, Inc. All rights reserved. */ /* @@ -56,6 +57,7 @@ #include <sys/fs/dv_node.h> #include <sys/sunndi.h> #include <sys/mntent.h> +#include <sys/disp.h> /* * /dev vfs operations. @@ -66,6 +68,7 @@ */ struct sdev_data *sdev_origins; /* mount info for origins under /dev */ kmutex_t sdev_lock; /* used for mount/unmount/rename synchronization */ +taskq_t *sdev_taskq = NULL; /* * static @@ -254,6 +257,20 @@ sdev_mount(struct vfs *vfsp, struct vnode *mvp, struct mounta *uap, mutex_enter(&sdev_lock); /* + * Check that the taskq has been created. We can't do this in our + * _init or devinit because they run too early for ddi_taskq_create. + */ + if (sdev_taskq == NULL) { + sdev_taskq = taskq_create("sdev", 1, minclsyspri, 1, 1, 0); + if (sdev_taskq == NULL) { + error = ENOMEM; + mutex_exit(&sdev_lock); + VN_RELE(avp); + goto cleanup; + } + } + + /* * handling installation */ if (uap->flags & MS_REMOUNT) { diff --git a/usr/src/uts/common/fs/dev/sdev_zvolops.c b/usr/src/uts/common/fs/dev/sdev_zvolops.c index e4c3acf787..54061b48cf 100644 --- a/usr/src/uts/common/fs/dev/sdev_zvolops.c +++ b/usr/src/uts/common/fs/dev/sdev_zvolops.c @@ -41,14 +41,18 @@ #include <sys/vfs_opreg.h> struct vnodeops *devzvol_vnodeops; +static major_t devzvol_major; +static taskq_ent_t devzvol_zclist_task; + +static kmutex_t devzvol_mtx; +/* Below are protected by devzvol_mtx */ +static boolean_t devzvol_isopen; +static boolean_t devzvol_zclist_task_running = B_FALSE; static uint64_t devzvol_gen = 0; static uint64_t devzvol_zclist; static size_t devzvol_zclist_size; static ldi_ident_t devzvol_li; static ldi_handle_t devzvol_lh; -static kmutex_t devzvol_mtx; -static boolean_t devzvol_isopen; -static major_t devzvol_major; /* * we need to use ddi_mod* since fs/dev gets loaded early on in @@ -310,19 +314,20 @@ devzvol_validate(struct sdev_node *dv) } /* - * creates directories as needed in response to a readdir + * Taskq callback to update the devzvol_zclist. + * + * We need to defer this to the taskq to avoid it running with a user + * context that might be associated with some non-global zone, and thus + * not being able to list all of the pools on the entire system. */ -void -devzvol_create_pool_dirs(struct vnode *dvp) +/*ARGSUSED*/ +static void +devzvol_update_zclist_cb(void *arg) { zfs_cmd_t *zc; - nvlist_t *nv = NULL; - nvpair_t *elem = NULL; - size_t size; - int pools = 0; - int rc; + int rc; + size_t size; - sdcmn_err13(("devzvol_create_pool_dirs")); zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP); mutex_enter(&devzvol_mtx); zc->zc_cookie = devzvol_gen; @@ -337,22 +342,67 @@ devzvol_create_pool_dirs(struct vnode *dvp) kmem_free((void *)(uintptr_t)devzvol_zclist, devzvol_zclist_size); devzvol_zclist = zc->zc_nvlist_dst; + /* Keep the alloc'd size, not the nvlist size. */ devzvol_zclist_size = size; break; - case EEXIST: + default: /* - * no change in the configuration; still need - * to do lookups in case we did a lookup in - * zvol/rdsk but not zvol/dsk (or vice versa) + * Either there was no change in pool configuration + * since we last asked (rc == EEXIST) or we got a + * catastrophic error. + * + * Give up memory and exit. */ kmem_free((void *)(uintptr_t)zc->zc_nvlist_dst, size); break; - default: - kmem_free((void *)(uintptr_t)zc->zc_nvlist_dst, - size); - goto out; } + + VERIFY(devzvol_zclist_task_running == B_TRUE); + devzvol_zclist_task_running = B_FALSE; + mutex_exit(&devzvol_mtx); + + kmem_free(zc, sizeof (zfs_cmd_t)); +} + +static void +devzvol_update_zclist(void) +{ + mutex_enter(&devzvol_mtx); + if (devzvol_zclist_task_running == B_TRUE) { + mutex_exit(&devzvol_mtx); + goto wait; + } + + devzvol_zclist_task_running = B_TRUE; + + taskq_dispatch_ent(sdev_taskq, devzvol_update_zclist_cb, NULL, 0, + &devzvol_zclist_task); + + mutex_exit(&devzvol_mtx); + +wait: + taskq_wait(sdev_taskq); +} + +/* + * Creates sub-directories for each zpool as needed in response to a + * readdir on one of the /dev/zvol/{dsk,rdsk} directories. + */ +void +devzvol_create_pool_dirs(struct vnode *dvp) +{ + nvlist_t *nv = NULL; + nvpair_t *elem = NULL; + int pools = 0; + int rc; + + sdcmn_err13(("devzvol_create_pool_dirs")); + + devzvol_update_zclist(); + + mutex_enter(&devzvol_mtx); + rc = nvlist_unpack((char *)(uintptr_t)devzvol_zclist, devzvol_zclist_size, &nv, 0); if (rc) { @@ -385,7 +435,6 @@ devzvol_create_pool_dirs(struct vnode *dvp) } out: mutex_exit(&devzvol_mtx); - kmem_free(zc, sizeof (zfs_cmd_t)); } /*ARGSUSED3*/ diff --git a/usr/src/uts/common/sys/fs/sdev_impl.h b/usr/src/uts/common/sys/fs/sdev_impl.h index 19a147d88a..7ea6b88ec2 100644 --- a/usr/src/uts/common/sys/fs/sdev_impl.h +++ b/usr/src/uts/common/sys/fs/sdev_impl.h @@ -20,6 +20,7 @@ */ /* * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2015 Joyent, Inc. All rights reserved. */ #ifndef _SYS_SDEV_IMPL_H @@ -35,6 +36,7 @@ extern "C" { #include <sys/vfs_opreg.h> #include <sys/list.h> #include <sys/nvpair.h> +#include <sys/sunddi.h> /* * sdev_nodes are the file-system specific part of the @@ -541,6 +543,8 @@ extern int sdev_nc_disable; extern int sdev_nc_disable_reset; extern int sdev_nc_verbose; +extern taskq_t *sdev_taskq; + /* * misc. defines */ |