diff --git a/lib/libzpool/Makefile.am b/lib/libzpool/Makefile.am index a353583eb430..edac1f1b2707 100644 --- a/lib/libzpool/Makefile.am +++ b/lib/libzpool/Makefile.am @@ -1,217 +1,217 @@ include $(srcdir)/%D%/include/Makefile.am libzpool_la_CFLAGS = $(AM_CFLAGS) $(KERNEL_CFLAGS) $(LIBRARY_CFLAGS) libzpool_la_CFLAGS += $(ZLIB_CFLAGS) libzpool_la_CPPFLAGS = $(AM_CPPFLAGS) $(FORCEDEBUG_CPPFLAGS) libzpool_la_CPPFLAGS += -I$(srcdir)/include/os/@ac_system_l@/zfs libzpool_la_CPPFLAGS += -DLIB_ZPOOL_BUILD lib_LTLIBRARIES += libzpool.la CPPCHECKTARGETS += libzpool.la dist_libzpool_la_SOURCES = \ %D%/abd_os.c \ %D%/arc_os.c \ %D%/kernel.c \ %D%/taskq.c \ %D%/util.c \ %D%/vdev_label_os.c \ - %D%/zfs_racct.c + %D%/zfs_racct.c \ + %D%/zfs_debug.c nodist_libzpool_la_SOURCES = \ module/lua/lapi.c \ module/lua/lauxlib.c \ module/lua/lbaselib.c \ module/lua/lcode.c \ module/lua/lcompat.c \ module/lua/lcorolib.c \ module/lua/lctype.c \ module/lua/ldebug.c \ module/lua/ldo.c \ module/lua/lfunc.c \ module/lua/lgc.c \ module/lua/llex.c \ module/lua/lmem.c \ module/lua/lobject.c \ module/lua/lopcodes.c \ module/lua/lparser.c \ module/lua/lstate.c \ module/lua/lstring.c \ module/lua/lstrlib.c \ module/lua/ltable.c \ module/lua/ltablib.c \ module/lua/ltm.c \ module/lua/lvm.c \ module/lua/lzio.c \ \ module/os/linux/zfs/vdev_file.c \ - module/os/linux/zfs/zfs_debug.c \ module/os/linux/zfs/zio_crypt.c \ \ module/zcommon/cityhash.c \ module/zcommon/simd_stat.c \ module/zcommon/zfeature_common.c \ module/zcommon/zfs_comutil.c \ module/zcommon/zfs_deleg.c \ module/zcommon/zfs_fletcher.c \ module/zcommon/zfs_fletcher_aarch64_neon.c \ module/zcommon/zfs_fletcher_avx512.c \ module/zcommon/zfs_fletcher_intel.c \ module/zcommon/zfs_fletcher_sse.c \ module/zcommon/zfs_fletcher_superscalar.c \ module/zcommon/zfs_fletcher_superscalar4.c \ module/zcommon/zfs_namecheck.c \ module/zcommon/zfs_prop.c \ module/zcommon/zfs_valstr.c \ module/zcommon/zpool_prop.c \ module/zcommon/zprop_common.c \ \ module/zfs/abd.c \ module/zfs/aggsum.c \ module/zfs/arc.c \ module/zfs/blake3_zfs.c \ module/zfs/blkptr.c \ module/zfs/bplist.c \ module/zfs/bpobj.c \ module/zfs/bptree.c \ module/zfs/bqueue.c \ module/zfs/btree.c \ module/zfs/brt.c \ module/zfs/dbuf.c \ module/zfs/dbuf_stats.c \ module/zfs/ddt.c \ module/zfs/ddt_zap.c \ module/zfs/dmu.c \ module/zfs/dmu_diff.c \ module/zfs/dmu_object.c \ module/zfs/dmu_objset.c \ module/zfs/dmu_recv.c \ module/zfs/dmu_redact.c \ module/zfs/dmu_send.c \ module/zfs/dmu_traverse.c \ module/zfs/dmu_tx.c \ module/zfs/dmu_zfetch.c \ module/zfs/dnode.c \ module/zfs/dnode_sync.c \ module/zfs/dsl_bookmark.c \ module/zfs/dsl_crypt.c \ module/zfs/dsl_dataset.c \ module/zfs/dsl_deadlist.c \ module/zfs/dsl_deleg.c \ module/zfs/dsl_destroy.c \ module/zfs/dsl_dir.c \ module/zfs/dsl_pool.c \ module/zfs/dsl_prop.c \ module/zfs/dsl_scan.c \ module/zfs/dsl_synctask.c \ module/zfs/dsl_userhold.c \ module/zfs/edonr_zfs.c \ module/zfs/fm.c \ module/zfs/gzip.c \ module/zfs/hkdf.c \ module/zfs/lz4.c \ module/zfs/lz4_zfs.c \ module/zfs/lzjb.c \ module/zfs/metaslab.c \ module/zfs/mmp.c \ module/zfs/multilist.c \ module/zfs/objlist.c \ module/zfs/pathname.c \ module/zfs/range_tree.c \ module/zfs/refcount.c \ module/zfs/rrwlock.c \ module/zfs/sa.c \ module/zfs/sha2_zfs.c \ module/zfs/skein_zfs.c \ module/zfs/spa.c \ module/zfs/spa_checkpoint.c \ module/zfs/spa_config.c \ module/zfs/spa_errlog.c \ module/zfs/spa_history.c \ module/zfs/spa_log_spacemap.c \ module/zfs/spa_misc.c \ module/zfs/spa_stats.c \ module/zfs/space_map.c \ module/zfs/space_reftree.c \ module/zfs/txg.c \ module/zfs/uberblock.c \ module/zfs/unique.c \ module/zfs/vdev.c \ module/zfs/vdev_draid.c \ module/zfs/vdev_draid_rand.c \ module/zfs/vdev_indirect.c \ module/zfs/vdev_indirect_births.c \ module/zfs/vdev_indirect_mapping.c \ module/zfs/vdev_initialize.c \ module/zfs/vdev_label.c \ module/zfs/vdev_mirror.c \ module/zfs/vdev_missing.c \ module/zfs/vdev_queue.c \ module/zfs/vdev_raidz.c \ module/zfs/vdev_raidz_math.c \ module/zfs/vdev_raidz_math_aarch64_neon.c \ module/zfs/vdev_raidz_math_aarch64_neonx2.c \ module/zfs/vdev_raidz_math_avx2.c \ module/zfs/vdev_raidz_math_avx512bw.c \ module/zfs/vdev_raidz_math_avx512f.c \ module/zfs/vdev_raidz_math_powerpc_altivec.c \ module/zfs/vdev_raidz_math_scalar.c \ module/zfs/vdev_raidz_math_sse2.c \ module/zfs/vdev_raidz_math_ssse3.c \ module/zfs/vdev_rebuild.c \ module/zfs/vdev_removal.c \ module/zfs/vdev_root.c \ module/zfs/vdev_trim.c \ module/zfs/zap.c \ module/zfs/zap_leaf.c \ module/zfs/zap_micro.c \ module/zfs/zcp.c \ module/zfs/zcp_get.c \ module/zfs/zcp_global.c \ module/zfs/zcp_iter.c \ module/zfs/zcp_set.c \ module/zfs/zcp_synctask.c \ module/zfs/zfeature.c \ module/zfs/zfs_byteswap.c \ module/zfs/zfs_chksum.c \ module/zfs/zfs_fm.c \ module/zfs/zfs_fuid.c \ module/zfs/zfs_ratelimit.c \ module/zfs/zfs_rlock.c \ module/zfs/zfs_sa.c \ module/zfs/zfs_znode.c \ module/zfs/zil.c \ module/zfs/zio.c \ module/zfs/zio_checksum.c \ module/zfs/zio_compress.c \ module/zfs/zio_inject.c \ module/zfs/zle.c \ module/zfs/zrlock.c \ module/zfs/zthr.c libzpool_la_LIBADD = \ libicp.la \ libunicode.la \ libnvpair.la \ libzstd.la \ libzutil.la libzpool_la_LIBADD += $(LIBCLOCK_GETTIME) $(ZLIB_LIBS) -ldl -lm libzpool_la_LDFLAGS = -pthread if !ASAN_ENABLED libzpool_la_LDFLAGS += -Wl,-z,defs endif if BUILD_FREEBSD libzpool_la_LIBADD += -lgeom endif libzpool_la_LDFLAGS += -version-info 5:0:0 if TARGET_CPU_POWERPC module/zfs/libzpool_la-vdev_raidz_math_powerpc_altivec.$(OBJEXT) : CFLAGS += -maltivec module/zfs/libzpool_la-vdev_raidz_math_powerpc_altivec.l$(OBJEXT): CFLAGS += -maltivec endif diff --git a/lib/libzpool/vdev_label_os.c b/lib/libzpool/vdev_label_os.c index 3d965b89a962..c303cba6dc09 100644 --- a/lib/libzpool/vdev_label_os.c +++ b/lib/libzpool/vdev_label_os.c @@ -1,45 +1,51 @@ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or https://opensource.org/licenses/CDDL-1.0. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 2023 by iXsystems, Inc. */ #include #include #include #include #include /* - * Check if the reserved boot area is in-use. + * Check if the reserved boot area is in-use. This is called from + * spa_vdev_attach() when adding a device to a raidz vdev, to ensure that the + * reserved area is available as scratch space for raidz expansion. * - * This function always returns 0, as there are no known external uses - * of the reserved area on Linux. + * This function currently always returns 0. On Linux, there are no known + * external uses of the reserved area. On FreeBSD, the reserved boot area is + * used when booting to a ZFS root from an MBR partition. + * + * Currently nothing using libzpool can add a disk to a pool, so this does + * nothing. */ int vdev_check_boot_reserve(spa_t *spa, vdev_t *childvd) { (void) spa; (void) childvd; return (0); } diff --git a/lib/libzpool/zfs_debug.c b/lib/libzpool/zfs_debug.c new file mode 100644 index 000000000000..df49a9a33fe8 --- /dev/null +++ b/lib/libzpool/zfs_debug.c @@ -0,0 +1,106 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or https://opensource.org/licenses/CDDL-1.0. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014 by Delphix. All rights reserved. + * Copyright (c) 2024, Rob Norris + */ + +#include + +typedef struct zfs_dbgmsg { + list_node_t zdm_node; + uint64_t zdm_timestamp; + uint_t zdm_size; + char zdm_msg[]; /* variable length allocation */ +} zfs_dbgmsg_t; + +static list_t zfs_dbgmsgs; +static kmutex_t zfs_dbgmsgs_lock; + +int zfs_dbgmsg_enable = B_TRUE; + +void +zfs_dbgmsg_init(void) +{ + list_create(&zfs_dbgmsgs, sizeof (zfs_dbgmsg_t), + offsetof(zfs_dbgmsg_t, zdm_node)); + mutex_init(&zfs_dbgmsgs_lock, NULL, MUTEX_DEFAULT, NULL); +} + +void +zfs_dbgmsg_fini(void) +{ + zfs_dbgmsg_t *zdm; + while ((zdm = list_remove_head(&zfs_dbgmsgs))) + umem_free(zdm, zdm->zdm_size); + mutex_destroy(&zfs_dbgmsgs_lock); +} + +void +__set_error(const char *file, const char *func, int line, int err) +{ + if (zfs_flags & ZFS_DEBUG_SET_ERROR) + __dprintf(B_FALSE, file, func, line, "error %lu", + (ulong_t)err); +} + +void +__zfs_dbgmsg(char *buf) +{ + uint_t size = sizeof (zfs_dbgmsg_t) + strlen(buf) + 1; + zfs_dbgmsg_t *zdm = umem_zalloc(size, KM_SLEEP); + zdm->zdm_size = size; + zdm->zdm_timestamp = gethrestime_sec(); + strcpy(zdm->zdm_msg, buf); + + mutex_enter(&zfs_dbgmsgs_lock); + list_insert_tail(&zfs_dbgmsgs, zdm); + mutex_exit(&zfs_dbgmsgs_lock); +} + +void +zfs_dbgmsg_print(int fd, const char *tag) +{ + ssize_t ret __attribute__((unused)); + + mutex_enter(&zfs_dbgmsgs_lock); + + /* + * We use write() in this function instead of printf() + * so it is safe to call from a signal handler. + */ + ret = write(fd, "ZFS_DBGMSG(", 11); + ret = write(fd, tag, strlen(tag)); + ret = write(fd, ") START:\n", 9); + + for (zfs_dbgmsg_t *zdm = list_head(&zfs_dbgmsgs); zdm != NULL; + zdm = list_next(&zfs_dbgmsgs, zdm)) { + ret = write(fd, zdm->zdm_msg, strlen(zdm->zdm_msg)); + ret = write(fd, "\n", 1); + } + + ret = write(fd, "ZFS_DBGMSG(", 11); + ret = write(fd, tag, strlen(tag)); + ret = write(fd, ") END\n", 6); + + mutex_exit(&zfs_dbgmsgs_lock); +} diff --git a/module/os/freebsd/zfs/zfs_debug.c b/module/os/freebsd/zfs/zfs_debug.c index c4cebe102075..a7ddd3c2f5eb 100644 --- a/module/os/freebsd/zfs/zfs_debug.c +++ b/module/os/freebsd/zfs/zfs_debug.c @@ -1,267 +1,231 @@ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or https://opensource.org/licenses/CDDL-1.0. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2014 by Delphix. All rights reserved. */ #include #include typedef struct zfs_dbgmsg { list_node_t zdm_node; time_t zdm_timestamp; uint_t zdm_size; char zdm_msg[]; } zfs_dbgmsg_t; static list_t zfs_dbgmsgs; static uint_t zfs_dbgmsg_size = 0; static kmutex_t zfs_dbgmsgs_lock; uint_t zfs_dbgmsg_maxsize = 4<<20; /* 4MB */ static kstat_t *zfs_dbgmsg_kstat; /* * Internal ZFS debug messages are enabled by default. * * # Print debug messages as they're logged * dtrace -n 'zfs-dbgmsg { print(stringof(arg0)); }' * * # Print all logged dbgmsg entries * sysctl kstat.zfs.misc.dbgmsg * * # Disable the kernel debug message log. * sysctl vfs.zfs.dbgmsg_enable=0 */ int zfs_dbgmsg_enable = B_TRUE; static int zfs_dbgmsg_headers(char *buf, size_t size) { (void) snprintf(buf, size, "%-12s %-8s\n", "timestamp", "message"); return (0); } static int zfs_dbgmsg_data(char *buf, size_t size, void *data) { zfs_dbgmsg_t *zdm = (zfs_dbgmsg_t *)data; (void) snprintf(buf, size, "%-12llu %-s\n", (u_longlong_t)zdm->zdm_timestamp, zdm->zdm_msg); return (0); } static void * zfs_dbgmsg_addr(kstat_t *ksp, loff_t n) { zfs_dbgmsg_t *zdm = (zfs_dbgmsg_t *)ksp->ks_private; ASSERT(MUTEX_HELD(&zfs_dbgmsgs_lock)); if (n == 0) ksp->ks_private = list_head(&zfs_dbgmsgs); else if (zdm) ksp->ks_private = list_next(&zfs_dbgmsgs, zdm); return (ksp->ks_private); } static void zfs_dbgmsg_purge(uint_t max_size) { zfs_dbgmsg_t *zdm; uint_t size; ASSERT(MUTEX_HELD(&zfs_dbgmsgs_lock)); while (zfs_dbgmsg_size > max_size) { zdm = list_remove_head(&zfs_dbgmsgs); if (zdm == NULL) return; size = zdm->zdm_size; kmem_free(zdm, size); zfs_dbgmsg_size -= size; } } static int zfs_dbgmsg_update(kstat_t *ksp, int rw) { if (rw == KSTAT_WRITE) zfs_dbgmsg_purge(0); return (0); } void zfs_dbgmsg_init(void) { list_create(&zfs_dbgmsgs, sizeof (zfs_dbgmsg_t), offsetof(zfs_dbgmsg_t, zdm_node)); mutex_init(&zfs_dbgmsgs_lock, NULL, MUTEX_DEFAULT, NULL); zfs_dbgmsg_kstat = kstat_create("zfs", 0, "dbgmsg", "misc", KSTAT_TYPE_RAW, 0, KSTAT_FLAG_VIRTUAL); if (zfs_dbgmsg_kstat) { zfs_dbgmsg_kstat->ks_lock = &zfs_dbgmsgs_lock; zfs_dbgmsg_kstat->ks_ndata = UINT32_MAX; zfs_dbgmsg_kstat->ks_private = NULL; zfs_dbgmsg_kstat->ks_update = zfs_dbgmsg_update; kstat_set_raw_ops(zfs_dbgmsg_kstat, zfs_dbgmsg_headers, zfs_dbgmsg_data, zfs_dbgmsg_addr); kstat_install(zfs_dbgmsg_kstat); } } void zfs_dbgmsg_fini(void) { if (zfs_dbgmsg_kstat) kstat_delete(zfs_dbgmsg_kstat); - /* - * TODO - decide how to make this permanent - */ -#ifdef _KERNEL + mutex_enter(&zfs_dbgmsgs_lock); zfs_dbgmsg_purge(0); mutex_exit(&zfs_dbgmsgs_lock); mutex_destroy(&zfs_dbgmsgs_lock); -#endif } void __zfs_dbgmsg(char *buf) { zfs_dbgmsg_t *zdm; uint_t size; DTRACE_PROBE1(zfs__dbgmsg, char *, buf); size = sizeof (zfs_dbgmsg_t) + strlen(buf) + 1; zdm = kmem_zalloc(size, KM_SLEEP); zdm->zdm_size = size; zdm->zdm_timestamp = gethrestime_sec(); strcpy(zdm->zdm_msg, buf); mutex_enter(&zfs_dbgmsgs_lock); list_insert_tail(&zfs_dbgmsgs, zdm); zfs_dbgmsg_size += size; zfs_dbgmsg_purge(zfs_dbgmsg_maxsize); mutex_exit(&zfs_dbgmsgs_lock); } void __set_error(const char *file, const char *func, int line, int err) { /* * To enable this: * * $ echo 512 >/sys/module/zfs/parameters/zfs_flags */ if (zfs_flags & ZFS_DEBUG_SET_ERROR) __dprintf(B_FALSE, file, func, line, "error %lu", (ulong_t)err); } -#ifdef _KERNEL void __dprintf(boolean_t dprint, const char *file, const char *func, int line, const char *fmt, ...) { const char *newfile; va_list adx; size_t size; char *buf; char *nl; int i; size = 1024; buf = kmem_alloc(size, KM_SLEEP); /* * Get rid of annoying prefix to filename. */ newfile = strrchr(file, '/'); if (newfile != NULL) { newfile = newfile + 1; /* Get rid of leading / */ } else { newfile = file; } i = snprintf(buf, size, "%s:%d:%s(): ", newfile, line, func); if (i < size) { va_start(adx, fmt); (void) vsnprintf(buf + i, size - i, fmt, adx); va_end(adx); } /* * Get rid of trailing newline. */ nl = strrchr(buf, '\n'); if (nl != NULL) *nl = '\0'; __zfs_dbgmsg(buf); kmem_free(buf, size); } -#else - -void -zfs_dbgmsg_print(int fd, const char *tag) -{ - ssize_t ret __attribute__((unused)); - - /* - * We use write() in this function instead of printf() - * so it is safe to call from a signal handler. - */ - ret = write(fd, "ZFS_DBGMSG(", 11); - ret = write(fd, tag, strlen(tag)); - ret = write(fd, ") START:\n", 9); - - mutex_enter(&zfs_dbgmsgs_lock); - - for (zfs_dbgmsg_t *zdm = list_head(&zfs_dbgmsgs); zdm != NULL; - zdm = list_next(&zfs_dbgmsgs, zdm)) - ret = write(fd, zdm->zdm_msg, strlen(zdm->zdm_msg)); - ret = write(fd, "\n", 1); - } - - ret = write(fd, "ZFS_DBGMSG(", 11); - ret = write(fd, tag, strlen(tag)); - ret = write(fd, ") END\n", 6); - - mutex_exit(&zfs_dbgmsgs_lock); -} -#endif /* _KERNEL */ - ZFS_MODULE_PARAM(zfs, zfs_, dbgmsg_enable, INT, ZMOD_RW, "Enable ZFS debug message log"); ZFS_MODULE_PARAM(zfs, zfs_, dbgmsg_maxsize, UINT, ZMOD_RW, "Maximum ZFS debug log size"); diff --git a/module/os/linux/zfs/zfs_debug.c b/module/os/linux/zfs/zfs_debug.c index 733b4a574bf5..92e2d69ee06b 100644 --- a/module/os/linux/zfs/zfs_debug.c +++ b/module/os/linux/zfs/zfs_debug.c @@ -1,259 +1,219 @@ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or https://opensource.org/licenses/CDDL-1.0. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2014 by Delphix. All rights reserved. */ #include #include typedef struct zfs_dbgmsg { procfs_list_node_t zdm_node; uint64_t zdm_timestamp; uint_t zdm_size; char zdm_msg[]; /* variable length allocation */ } zfs_dbgmsg_t; static procfs_list_t zfs_dbgmsgs; static uint_t zfs_dbgmsg_size = 0; static uint_t zfs_dbgmsg_maxsize = 4<<20; /* 4MB */ /* * Internal ZFS debug messages are enabled by default. * * # Print debug messages * cat /proc/spl/kstat/zfs/dbgmsg * * # Disable the kernel debug message log. * echo 0 > /sys/module/zfs/parameters/zfs_dbgmsg_enable * * # Clear the kernel debug message log. * echo 0 >/proc/spl/kstat/zfs/dbgmsg */ int zfs_dbgmsg_enable = B_TRUE; static int zfs_dbgmsg_show_header(struct seq_file *f) { seq_printf(f, "%-12s %-8s\n", "timestamp", "message"); return (0); } static int zfs_dbgmsg_show(struct seq_file *f, void *p) { zfs_dbgmsg_t *zdm = (zfs_dbgmsg_t *)p; seq_printf(f, "%-12llu %-s\n", (u_longlong_t)zdm->zdm_timestamp, zdm->zdm_msg); return (0); } static void zfs_dbgmsg_purge(uint_t max_size) { while (zfs_dbgmsg_size > max_size) { zfs_dbgmsg_t *zdm = list_remove_head(&zfs_dbgmsgs.pl_list); if (zdm == NULL) return; uint_t size = zdm->zdm_size; kmem_free(zdm, size); zfs_dbgmsg_size -= size; } } static int zfs_dbgmsg_clear(procfs_list_t *procfs_list) { (void) procfs_list; mutex_enter(&zfs_dbgmsgs.pl_lock); zfs_dbgmsg_purge(0); mutex_exit(&zfs_dbgmsgs.pl_lock); return (0); } void zfs_dbgmsg_init(void) { procfs_list_install("zfs", NULL, "dbgmsg", 0600, &zfs_dbgmsgs, zfs_dbgmsg_show, zfs_dbgmsg_show_header, zfs_dbgmsg_clear, offsetof(zfs_dbgmsg_t, zdm_node)); } void zfs_dbgmsg_fini(void) { procfs_list_uninstall(&zfs_dbgmsgs); zfs_dbgmsg_purge(0); - /* - * TODO - decide how to make this permanent - */ -#ifdef _KERNEL procfs_list_destroy(&zfs_dbgmsgs); -#endif } void __set_error(const char *file, const char *func, int line, int err) { /* * To enable this: * * $ echo 512 >/sys/module/zfs/parameters/zfs_flags */ if (zfs_flags & ZFS_DEBUG_SET_ERROR) __dprintf(B_FALSE, file, func, line, "error %lu", (ulong_t)err); } void __zfs_dbgmsg(char *buf) { uint_t size = sizeof (zfs_dbgmsg_t) + strlen(buf) + 1; zfs_dbgmsg_t *zdm = kmem_zalloc(size, KM_SLEEP); zdm->zdm_size = size; zdm->zdm_timestamp = gethrestime_sec(); strcpy(zdm->zdm_msg, buf); mutex_enter(&zfs_dbgmsgs.pl_lock); procfs_list_add(&zfs_dbgmsgs, zdm); zfs_dbgmsg_size += size; zfs_dbgmsg_purge(zfs_dbgmsg_maxsize); mutex_exit(&zfs_dbgmsgs.pl_lock); } -#ifdef _KERNEL - void __dprintf(boolean_t dprint, const char *file, const char *func, int line, const char *fmt, ...) { const char *newfile; va_list adx; size_t size; char *buf; char *nl; int i; char *prefix = (dprint) ? "dprintf: " : ""; size = 1024; buf = kmem_alloc(size, KM_SLEEP); /* * Get rid of annoying prefix to filename. */ newfile = strrchr(file, '/'); if (newfile != NULL) { newfile = newfile + 1; /* Get rid of leading / */ } else { newfile = file; } i = snprintf(buf, size, "%s%s:%d:%s(): ", prefix, newfile, line, func); if (i < size) { va_start(adx, fmt); (void) vsnprintf(buf + i, size - i, fmt, adx); va_end(adx); } /* * Get rid of trailing newline for dprintf logs. */ if (dprint && buf[0] != '\0') { nl = &buf[strlen(buf) - 1]; if (*nl == '\n') *nl = '\0'; } /* * To get this data enable the zfs__dprintf trace point as shown: * * # Enable zfs__dprintf tracepoint, clear the tracepoint ring buffer * $ echo 1 > /sys/kernel/debug/tracing/events/zfs/enable * $ echo 0 > /sys/kernel/debug/tracing/trace * * # Dump the ring buffer. * $ cat /sys/kernel/debug/tracing/trace */ DTRACE_PROBE1(zfs__dprintf, char *, buf); /* * To get this data: * * $ cat /proc/spl/kstat/zfs/dbgmsg * * To clear the buffer: * $ echo 0 > /proc/spl/kstat/zfs/dbgmsg */ __zfs_dbgmsg(buf); kmem_free(buf, size); } -#else - -void -zfs_dbgmsg_print(int fd, const char *tag) -{ - ssize_t ret __attribute__((unused)); - - mutex_enter(&zfs_dbgmsgs.pl_lock); - - /* - * We use write() in this function instead of printf() - * so it is safe to call from a signal handler. - */ - ret = write(fd, "ZFS_DBGMSG(", 11); - ret = write(fd, tag, strlen(tag)); - ret = write(fd, ") START:\n", 9); - - for (zfs_dbgmsg_t *zdm = list_head(&zfs_dbgmsgs.pl_list); zdm != NULL; - zdm = list_next(&zfs_dbgmsgs.pl_list, zdm)) { - ret = write(fd, zdm->zdm_msg, strlen(zdm->zdm_msg)); - ret = write(fd, "\n", 1); - } - - ret = write(fd, "ZFS_DBGMSG(", 11); - ret = write(fd, tag, strlen(tag)); - ret = write(fd, ") END\n", 6); - - mutex_exit(&zfs_dbgmsgs.pl_lock); -} -#endif /* _KERNEL */ - -#ifdef _KERNEL module_param(zfs_dbgmsg_enable, int, 0644); MODULE_PARM_DESC(zfs_dbgmsg_enable, "Enable ZFS debug message log"); /* BEGIN CSTYLED */ module_param(zfs_dbgmsg_maxsize, uint, 0644); /* END CSTYLED */ MODULE_PARM_DESC(zfs_dbgmsg_maxsize, "Maximum ZFS debug log size"); -#endif