diff options
Diffstat (limited to 'lib/libzpool')
-rw-r--r-- | lib/libzpool/include/sys/zfs_context.h | 66 | ||||
-rw-r--r-- | lib/libzpool/kernel.c | 66 | ||||
-rw-r--r-- | lib/libzpool/taskq.c | 49 | ||||
-rw-r--r-- | lib/libzpool/util.c | 5 |
4 files changed, 158 insertions, 28 deletions
diff --git a/lib/libzpool/include/sys/zfs_context.h b/lib/libzpool/include/sys/zfs_context.h index 230c233a2..9a6d712e5 100644 --- a/lib/libzpool/include/sys/zfs_context.h +++ b/lib/libzpool/include/sys/zfs_context.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -75,6 +75,7 @@ extern "C" { #include <sys/u8_textprep.h> #include <sys/sysevent/eventdefs.h> #include <sys/sysevent/dev.h> +#include <sys/sunddi.h> /* * Debugging @@ -105,21 +106,27 @@ extern void vpanic(const char *, __va_list); #define fm_panic panic +extern int aok; + /* This definition is copied from assert.h. */ #if defined(__STDC__) #if __STDC_VERSION__ - 0 >= 199901L -#define verify(EX) (void)((EX) || \ +#define zverify(EX) (void)((EX) || (aok) || \ (__assert_c99(#EX, __FILE__, __LINE__, __func__), 0)) #else -#define verify(EX) (void)((EX) || (__assert(#EX, __FILE__, __LINE__), 0)) +#define zverify(EX) (void)((EX) || (aok) || \ + (__assert(#EX, __FILE__, __LINE__), 0)) #endif /* __STDC_VERSION__ - 0 >= 199901L */ #else -#define verify(EX) (void)((EX) || (_assert("EX", __FILE__, __LINE__), 0)) +#define zverify(EX) (void)((EX) || (aok) || \ + (_assert("EX", __FILE__, __LINE__), 0)) #endif /* __STDC__ */ -#define VERIFY verify -#define ASSERT assert +#define VERIFY zverify +#define ASSERT zverify +#undef assert +#define assert zverify extern void __assert(const char *, const char *, int); @@ -130,7 +137,7 @@ extern void __assert(const char *, const char *, int); #define VERIFY3_IMPL(LEFT, OP, RIGHT, TYPE) do { \ const TYPE __left = (TYPE)(LEFT); \ const TYPE __right = (TYPE)(RIGHT); \ - if (!(__left OP __right)) { \ + if (!(__left OP __right) && (!aok)) { \ char *__buf = alloca(256); \ (void) snprintf(__buf, 256, "%s %s %s (0x%llx %s 0x%llx)", \ #LEFT, #OP, #RIGHT, \ @@ -196,6 +203,18 @@ typedef struct kthread kthread_t; #define thread_create(stk, stksize, func, arg, len, pp, state, pri) \ zk_thread_create(func, arg) #define thread_exit() thr_exit(NULL) +#define thread_join(t) panic("libzpool cannot join threads") + +#define newproc(f, a, cid, pri, ctp, pid) (ENOSYS) + +/* in libzpool, p0 exists only to have its address taken */ +struct proc { + uintptr_t this_is_never_used_dont_dereference_it; +}; + +extern struct proc p0; + +#define PS_NONE -1 extern kthread_t *zk_thread_create(void (*func)(), void *arg); @@ -318,20 +337,27 @@ typedef void (task_func_t)(void *); #define TASKQ_PREPOPULATE 0x0001 #define TASKQ_CPR_SAFE 0x0002 /* Use CPR safe protocol */ #define TASKQ_DYNAMIC 0x0004 /* Use dynamic thread scheduling */ -#define TASKQ_THREADS_CPU_PCT 0x0008 /* Use dynamic thread scheduling */ +#define TASKQ_THREADS_CPU_PCT 0x0008 /* Scale # threads by # cpus */ +#define TASKQ_DC_BATCH 0x0010 /* Mark threads as batch */ #define TQ_SLEEP KM_SLEEP /* Can block for memory */ #define TQ_NOSLEEP KM_NOSLEEP /* cannot block for memory; may fail */ -#define TQ_NOQUEUE 0x02 /* Do not enqueue if can't dispatch */ +#define TQ_NOQUEUE 0x02 /* Do not enqueue if can't dispatch */ +#define TQ_FRONT 0x08 /* Queue in front */ extern taskq_t *system_taskq; extern taskq_t *taskq_create(const char *, int, pri_t, int, int, uint_t); +#define taskq_create_proc(a, b, c, d, e, p, f) \ + (taskq_create(a, b, c, d, e, f)) +#define taskq_create_sysdc(a, b, d, e, p, dc, f) \ + (taskq_create(a, b, maxclsyspri, d, e, f)) extern taskqid_t taskq_dispatch(taskq_t *, task_func_t, void *, uint_t); extern void taskq_destroy(taskq_t *); extern void taskq_wait(taskq_t *); extern int taskq_member(taskq_t *, void *); extern void system_taskq_init(void); +extern void system_taskq_fini(void); #define XVA_MAPSIZE 3 #define XVA_MAGIC 0x78766174 @@ -345,6 +371,7 @@ typedef struct vnode { char *v_path; } vnode_t; +#define AV_SCANSTAMP_SZ 32 /* length of anti-virus scanstamp */ typedef struct xoptattr { timestruc_t xoa_createtime; /* Create time of file */ @@ -360,6 +387,8 @@ typedef struct xoptattr { uint8_t xoa_opaque; uint8_t xoa_av_quarantined; uint8_t xoa_av_modified; + uint8_t xoa_av_scanstamp[AV_SCANSTAMP_SZ]; + uint8_t xoa_reparse; } xoptattr_t; typedef struct vattr { @@ -406,9 +435,11 @@ typedef struct vsecattr { #define CRCREAT 0 +extern int fop_getattr(vnode_t *vp, vattr_t *vap); + #define VOP_CLOSE(vp, f, c, o, cr, ct) 0 #define VOP_PUTPAGE(vp, of, sz, fl, cr, ct) 0 -#define VOP_GETATTR(vp, vap, fl, cr, ct) ((vap)->va_size = (vp)->v_size, 0) +#define VOP_GETATTR(vp, vap, fl, cr, ct) fop_getattr((vp), (vap)); #define VOP_FSYNC(vp, f, cr, ct) fsync((vp)->v_fd) @@ -433,13 +464,18 @@ extern vnode_t *rootdir; /* * Random stuff */ -#define lbolt (gethrtime() >> 23) -#define lbolt64 (gethrtime() >> 23) +#define ddi_get_lbolt() (gethrtime() >> 23) +#define ddi_get_lbolt64() (gethrtime() >> 23) #define hz 119 /* frequency when using gethrtime() >> 23 for lbolt */ extern void delay(clock_t ticks); #define gethrestime_sec() time(NULL) +#define gethrestime(t) \ + do {\ + (t)->tv_sec = gethrestime_sec();\ + (t)->tv_nsec = 0;\ + } while (0); #define max_ncpus 64 @@ -490,6 +526,9 @@ typedef struct callb_cpr { #define zone_dataset_visible(x, y) (1) #define INGLOBALZONE(z) (1) +extern char *kmem_asprintf(const char *fmt, ...); +#define strfree(str) kmem_free((str), strlen(str)+1) + /* * Hostname information */ @@ -497,6 +536,9 @@ extern char hw_serial[]; /* for userland-emulated hostid access */ extern int ddi_strtoul(const char *str, char **nptr, int base, unsigned long *result); +extern int ddi_strtoull(const char *str, char **nptr, int base, + u_longlong_t *result); + /* ZFS Boot Related stuff. */ struct _buf { diff --git a/lib/libzpool/kernel.c b/lib/libzpool/kernel.c index 89108fe5b..5284c1253 100644 --- a/lib/libzpool/kernel.c +++ b/lib/libzpool/kernel.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -42,6 +42,7 @@ * Emulation of kernel services in userland. */ +int aok; uint64_t physmem; vnode_t *rootdir = (vnode_t *)0xabcd1234; char hw_serial[HW_HOSTID_LEN]; @@ -50,6 +51,9 @@ struct utsname utsname = { "userland", "libzpool", "1", "1", "na" }; +/* this only exists to have its address taken */ +struct proc p0; + /* * ========================================================================= * threads @@ -269,7 +273,7 @@ cv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime) clock_t delta; top: - delta = abstime - lbolt; + delta = abstime - ddi_get_lbolt(); if (delta <= 0) return (-1); @@ -444,6 +448,24 @@ vn_close(vnode_t *vp) umem_free(vp, sizeof (vnode_t)); } +/* + * At a minimum we need to update the size since vdev_reopen() + * will no longer call vn_openat(). + */ +int +fop_getattr(vnode_t *vp, vattr_t *vap) +{ + struct stat64 st; + + if (fstat64(vp->v_fd, &st) == -1) { + close(vp->v_fd); + return (errno); + } + + vap->va_size = st.st_size; + return (0); +} + #ifdef ZFS_DEBUG /* @@ -754,6 +776,17 @@ ddi_strtoul(const char *hw_serial, char **nptr, int base, unsigned long *result) return (0); } +int +ddi_strtoull(const char *str, char **nptr, int base, u_longlong_t *result) +{ + char *end; + + *result = strtoull(str, &end, base); + if (*result == 0) + return (errno); + return (0); +} + /* * ========================================================================= * kernel emulation setup & teardown @@ -779,7 +812,8 @@ kernel_init(int mode) dprintf("physmem = %llu pages (%.2f GB)\n", physmem, (double)physmem * sysconf(_SC_PAGE_SIZE) / (1ULL << 30)); - (void) snprintf(hw_serial, sizeof (hw_serial), "%ld", gethostid()); + (void) snprintf(hw_serial, sizeof (hw_serial), "%ld", + (mode & FWRITE) ? gethostid() : 0); VERIFY((random_fd = open("/dev/random", O_RDONLY)) != -1); VERIFY((urandom_fd = open("/dev/urandom", O_RDONLY)) != -1); @@ -794,6 +828,8 @@ kernel_fini(void) { spa_fini(); + system_taskq_fini(); + close(random_fd); close(urandom_fd); @@ -884,3 +920,27 @@ ksiddomain_rele(ksiddomain_t *ksid) spa_strfree(ksid->kd_name); umem_free(ksid, sizeof (ksiddomain_t)); } + +/* + * Do not change the length of the returned string; it must be freed + * with strfree(). + */ +char * +kmem_asprintf(const char *fmt, ...) +{ + int size; + va_list adx; + char *buf; + + va_start(adx, fmt); + size = vsnprintf(NULL, 0, fmt, adx) + 1; + va_end(adx); + + buf = kmem_alloc(size, KM_SLEEP); + + va_start(adx, fmt); + size = vsnprintf(buf, size, fmt, adx); + va_end(adx); + + return (buf); +} diff --git a/lib/libzpool/taskq.c b/lib/libzpool/taskq.c index 1a73fe83c..8db5d11c1 100644 --- a/lib/libzpool/taskq.c +++ b/lib/libzpool/taskq.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -49,6 +49,8 @@ struct taskq { int tq_nalloc; int tq_minalloc; int tq_maxalloc; + kcondvar_t tq_maxalloc_cv; + int tq_maxalloc_wait; task_t *tq_freelist; task_t tq_task; }; @@ -57,26 +59,36 @@ static task_t * task_alloc(taskq_t *tq, int tqflags) { task_t *t; + int rv; - if ((t = tq->tq_freelist) != NULL && tq->tq_nalloc >= tq->tq_minalloc) { +again: if ((t = tq->tq_freelist) != NULL && tq->tq_nalloc >= tq->tq_minalloc) { tq->tq_freelist = t->task_next; } else { - mutex_exit(&tq->tq_lock); if (tq->tq_nalloc >= tq->tq_maxalloc) { - if (!(tqflags & KM_SLEEP)) { - mutex_enter(&tq->tq_lock); + if (!(tqflags & KM_SLEEP)) return (NULL); - } + /* * We don't want to exceed tq_maxalloc, but we can't * wait for other tasks to complete (and thus free up * task structures) without risking deadlock with * the caller. So, we just delay for one second - * to throttle the allocation rate. + * to throttle the allocation rate. If we have tasks + * complete before one second timeout expires then + * taskq_ent_free will signal us and we will + * immediately retry the allocation. */ - delay(hz); + tq->tq_maxalloc_wait++; + rv = cv_timedwait(&tq->tq_maxalloc_cv, + &tq->tq_lock, ddi_get_lbolt() + hz); + tq->tq_maxalloc_wait--; + if (rv > 0) + goto again; /* signaled */ } + mutex_exit(&tq->tq_lock); + t = kmem_alloc(sizeof (task_t), tqflags); + mutex_enter(&tq->tq_lock); if (t != NULL) tq->tq_nalloc++; @@ -96,6 +108,9 @@ task_free(taskq_t *tq, task_t *t) kmem_free(t, sizeof (task_t)); mutex_enter(&tq->tq_lock); } + + if (tq->tq_maxalloc_wait) + cv_signal(&tq->tq_maxalloc_cv); } taskqid_t @@ -114,8 +129,13 @@ taskq_dispatch(taskq_t *tq, task_func_t func, void *arg, uint_t tqflags) mutex_exit(&tq->tq_lock); return (0); } - t->task_next = &tq->tq_task; - t->task_prev = tq->tq_task.task_prev; + if (tqflags & TQ_FRONT) { + t->task_next = tq->tq_task.task_next; + t->task_prev = &tq->tq_task; + } else { + t->task_next = &tq->tq_task; + t->task_prev = tq->tq_task.task_prev; + } t->task_next->task_prev = t; t->task_prev->task_next = t; t->task_func = func; @@ -191,6 +211,7 @@ taskq_create(const char *name, int nthreads, pri_t pri, mutex_init(&tq->tq_lock, NULL, MUTEX_DEFAULT, NULL); cv_init(&tq->tq_dispatch_cv, NULL, CV_DEFAULT, NULL); cv_init(&tq->tq_wait_cv, NULL, CV_DEFAULT, NULL); + cv_init(&tq->tq_maxalloc_cv, NULL, CV_DEFAULT, NULL); tq->tq_flags = flags | TASKQ_ACTIVE; tq->tq_active = nthreads; tq->tq_nthreads = nthreads; @@ -247,6 +268,7 @@ taskq_destroy(taskq_t *tq) mutex_destroy(&tq->tq_lock); cv_destroy(&tq->tq_dispatch_cv); cv_destroy(&tq->tq_wait_cv); + cv_destroy(&tq->tq_maxalloc_cv); kmem_free(tq, sizeof (taskq_t)); } @@ -272,3 +294,10 @@ system_taskq_init(void) system_taskq = taskq_create("system_taskq", 64, minclsyspri, 4, 512, TASKQ_DYNAMIC | TASKQ_PREPOPULATE); } + +void +system_taskq_fini(void) +{ + taskq_destroy(system_taskq); + system_taskq = NULL; /* defensive */ +} diff --git a/lib/libzpool/util.c b/lib/libzpool/util.c index 781edb6e8..9b99531fd 100644 --- a/lib/libzpool/util.c +++ b/lib/libzpool/util.c @@ -19,8 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. */ #include <assert.h> @@ -90,7 +89,7 @@ show_vdev_stats(const char *desc, const char *ctype, nvlist_t *nv, int indent) if (is_log) prefix = "log "; - if (nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_STATS, + if (nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&vs, &c) != 0) vs = &v0; |