diff -Nru spl-linux-0.6.2/config/rpm.am spl-linux-0.6.3/config/rpm.am --- spl-linux-0.6.2/config/rpm.am 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/config/rpm.am 2014-06-12 18:32:38.000000000 +0000 @@ -63,7 +63,7 @@ rpmbuild="$$rpmbuild" \ rpmspec="$$rpmspec" \ rpm-local || exit 1; \ - $(RPMBUILD) \ + LANG=C $(RPMBUILD) \ --define "_tmppath $$rpmbuild/TMP" \ --define "_topdir $$rpmbuild" \ $(def) -bs $$rpmbuild/SPECS/$$rpmspec || exit 1; \ @@ -79,7 +79,7 @@ rpmbuild="$$rpmbuild" \ rpmspec="$$rpmspec" \ rpm-local || exit 1; \ - ${RPMBUILD} \ + LANG=C ${RPMBUILD} \ --define "_tmppath $$rpmbuild/TMP" \ --define "_topdir $$rpmbuild" \ $(def) --rebuild $$rpmpkg || exit 1; \ diff -Nru spl-linux-0.6.2/config/spl-build.m4 spl-linux-0.6.3/config/spl-build.m4 --- spl-linux-0.6.2/config/spl-build.m4 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/config/spl-build.m4 2014-06-12 18:32:38.000000000 +0000 @@ -27,8 +27,7 @@ SPL_AC_TYPE_ATOMIC64_XCHG SPL_AC_TYPE_UINTPTR_T SPL_AC_2ARGS_REGISTER_SYSCTL - SPL_AC_SET_SHRINKER - SPL_AC_3ARGS_SHRINKER_CALLBACK + SPL_AC_SHRINKER_CALLBACK SPL_AC_PATH_IN_NAMEIDATA SPL_AC_TASK_CURR SPL_AC_CTL_UNNUMBERED @@ -93,6 +92,8 @@ SPL_AC_RWSEM_SPINLOCK_IS_RAW SPL_AC_SCHED_RT_HEADER SPL_AC_2ARGS_VFS_GETATTR + SPL_AC_USLEEP_RANGE + SPL_AC_KMEM_CACHE_ALLOCFLAGS ]) AC_DEFUN([SPL_AC_MODULE_SYMVERS], [ @@ -884,37 +885,18 @@ ]) ]) -dnl # -dnl # 2.6.23 API change -dnl # Old set_shrinker API replaced with register_shrinker -dnl # -AC_DEFUN([SPL_AC_SET_SHRINKER], [ - AC_MSG_CHECKING([whether set_shrinker() available]) - SPL_LINUX_TRY_COMPILE([ - #include - ],[ - return set_shrinker(DEFAULT_SEEKS, NULL); - ],[ - AC_MSG_RESULT([yes]) - AC_DEFINE(HAVE_SET_SHRINKER, 1, - [set_shrinker() available]) - ],[ - AC_MSG_RESULT([no]) - ]) -]) - -dnl # -dnl # 2.6.35 API change, -dnl # Add context to shrinker callback -dnl # -AC_DEFUN([SPL_AC_3ARGS_SHRINKER_CALLBACK], - [AC_MSG_CHECKING([whether shrinker callback wants 3 args]) +AC_DEFUN([SPL_AC_SHRINKER_CALLBACK],[ tmp_flags="$EXTRA_KCFLAGS" EXTRA_KCFLAGS="-Werror" + dnl # + dnl # 2.6.23 to 2.6.34 API change + dnl # ->shrink(int nr_to_scan, gfp_t gfp_mask) + dnl # + AC_MSG_CHECKING([whether old 2-argument shrinker exists]) SPL_LINUX_TRY_COMPILE([ #include - int shrinker_cb(struct shrinker *, int, unsigned int); + int shrinker_cb(int nr_to_scan, gfp_t gfp_mask); ],[ struct shrinker cache_shrinker = { .shrink = shrinker_cb, @@ -923,10 +905,86 @@ register_shrinker(&cache_shrinker); ],[ AC_MSG_RESULT(yes) - AC_DEFINE(HAVE_3ARGS_SHRINKER_CALLBACK, 1, - [shrinker callback wants 3 args]) + AC_DEFINE(HAVE_2ARGS_OLD_SHRINKER_CALLBACK, 1, + [old shrinker callback wants 2 args]) ],[ AC_MSG_RESULT(no) + dnl # + dnl # 2.6.35 - 2.6.39 API change + dnl # ->shrink(struct shrinker *, + dnl # int nr_to_scan, gfp_t gfp_mask) + dnl # + AC_MSG_CHECKING([whether old 3-argument shrinker exists]) + SPL_LINUX_TRY_COMPILE([ + #include + + int shrinker_cb(struct shrinker *, int nr_to_scan, + gfp_t gfp_mask); + ],[ + struct shrinker cache_shrinker = { + .shrink = shrinker_cb, + .seeks = DEFAULT_SEEKS, + }; + register_shrinker(&cache_shrinker); + ],[ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_3ARGS_SHRINKER_CALLBACK, 1, + [old shrinker callback wants 3 args]) + ],[ + AC_MSG_RESULT(no) + dnl # + dnl # 3.0 - 3.11 API change + dnl # ->shrink(struct shrinker *, + dnl # struct shrink_control *sc) + dnl # + AC_MSG_CHECKING( + [whether new 2-argument shrinker exists]) + SPL_LINUX_TRY_COMPILE([ + #include + + int shrinker_cb(struct shrinker *, + struct shrink_control *sc); + ],[ + struct shrinker cache_shrinker = { + .shrink = shrinker_cb, + .seeks = DEFAULT_SEEKS, + }; + register_shrinker(&cache_shrinker); + ],[ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_2ARGS_NEW_SHRINKER_CALLBACK, 1, + [new shrinker callback wants 2 args]) + ],[ + AC_MSG_RESULT(no) + dnl # + dnl # 3.12 API change, + dnl # ->shrink() is logically split in to + dnl # ->count_objects() and ->scan_objects() + dnl # + AC_MSG_CHECKING( + [whether ->count_objects callback exists]) + SPL_LINUX_TRY_COMPILE([ + #include + + unsigned long shrinker_cb( + struct shrinker *, + struct shrink_control *sc); + ],[ + struct shrinker cache_shrinker = { + .count_objects = shrinker_cb, + .scan_objects = shrinker_cb, + .seeks = DEFAULT_SEEKS, + }; + register_shrinker(&cache_shrinker); + ],[ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_SPLIT_SHRINKER_CALLBACK, + 1, [->count_objects exists]) + ],[ + AC_MSG_ERROR(error) + ]) + ]) + ]) ]) EXTRA_KCFLAGS="$tmp_flags" ]) @@ -1785,41 +1843,94 @@ EXTRA_KCFLAGS="$tmp_flags" ]) -dnl # -dnl # SLES API change, never adopted in mainline, -dnl # Third 'struct vfsmount *' argument removed. -dnl # AC_DEFUN([SPL_AC_2ARGS_VFS_UNLINK], [AC_MSG_CHECKING([whether vfs_unlink() wants 2 args]) SPL_LINUX_TRY_COMPILE([ #include ],[ - vfs_unlink(NULL, NULL); + vfs_unlink((struct inode *) NULL, (struct dentry *) NULL); ],[ AC_MSG_RESULT(yes) AC_DEFINE(HAVE_2ARGS_VFS_UNLINK, 1, [vfs_unlink() wants 2 args]) ],[ AC_MSG_RESULT(no) + dnl # + dnl # Linux 3.13 API change + dnl # Added delegated inode + dnl # + AC_MSG_CHECKING([whether vfs_unlink() wants 3 args]) + SPL_LINUX_TRY_COMPILE([ + #include + ],[ + vfs_unlink((struct inode *) NULL, + (struct dentry *) NULL, + (struct inode **) NULL); + ],[ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_3ARGS_VFS_UNLINK, 1, + [vfs_unlink() wants 3 args]) + ],[ + AC_MSG_ERROR(no) + ]) + ]) ]) -dnl # -dnl # SLES API change, never adopted in mainline, -dnl # Third and sixth 'struct vfsmount *' argument removed. -dnl # AC_DEFUN([SPL_AC_4ARGS_VFS_RENAME], [AC_MSG_CHECKING([whether vfs_rename() wants 4 args]) SPL_LINUX_TRY_COMPILE([ #include ],[ - vfs_rename(NULL, NULL, NULL, NULL); + vfs_rename((struct inode *) NULL, (struct dentry *) NULL, + (struct inode *) NULL, (struct dentry *) NULL); ],[ AC_MSG_RESULT(yes) AC_DEFINE(HAVE_4ARGS_VFS_RENAME, 1, [vfs_rename() wants 4 args]) ],[ AC_MSG_RESULT(no) + dnl # + dnl # Linux 3.13 API change + dnl # Added delegated inode + dnl # + AC_MSG_CHECKING([whether vfs_rename() wants 5 args]) + SPL_LINUX_TRY_COMPILE([ + #include + ],[ + vfs_rename((struct inode *) NULL, + (struct dentry *) NULL, + (struct inode *) NULL, + (struct dentry *) NULL, + (struct inode **) NULL); + ],[ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_5ARGS_VFS_RENAME, 1, + [vfs_rename() wants 5 args]) + ],[ + AC_MSG_RESULT(no) + dnl # + dnl # Linux 3.15 API change + dnl # Added flags + dnl # + AC_MSG_CHECKING([whether vfs_rename() wants 6 args]) + SPL_LINUX_TRY_COMPILE([ + #include + ],[ + vfs_rename((struct inode *) NULL, + (struct dentry *) NULL, + (struct inode *) NULL, + (struct dentry *) NULL, + (struct inode **) NULL, + (unsigned int) 0); + ],[ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_6ARGS_VFS_RENAME, 1, + [vfs_rename() wants 6 args]) + ],[ + AC_MSG_ERROR(no) + ]) + ]) ]) ]) @@ -2400,3 +2511,62 @@ ]) ]) ]) + +dnl # +dnl # 2.6.36 API compatibility. +dnl # Added usleep_range timer. +dnl # usleep_range is a finer precision implementation of msleep +dnl # designed to be a drop-in replacement for udelay where a precise +dnl # sleep / busy-wait is unnecessary. +dnl # +AC_DEFUN([SPL_AC_USLEEP_RANGE], [ + AC_MSG_CHECKING([whether usleep_range() is available]) + SPL_LINUX_TRY_COMPILE([ + #include + ],[ + usleep_range(0, 0); + ],[ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_USLEEP_RANGE, 1, + [usleep_range is available]) + ],[ + AC_MSG_RESULT(no) + ]) +]) + +dnl # +dnl # 2.6.35 API change, +dnl # The cachep->gfpflags member was renamed cachep->allocflags. These are +dnl # private allocation flags which are applied when allocating a new slab +dnl # in kmem_getpages(). Unfortunately there is no public API for setting +dnl # non-default flags. +dnl # +AC_DEFUN([SPL_AC_KMEM_CACHE_ALLOCFLAGS], [ + AC_MSG_CHECKING([whether struct kmem_cache has allocflags]) + SPL_LINUX_TRY_COMPILE([ + #include + ],[ + struct kmem_cache cachep __attribute__ ((unused)); + cachep.allocflags = GFP_KERNEL; + ],[ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_KMEM_CACHE_ALLOCFLAGS, 1, + [struct kmem_cache has allocflags]) + ],[ + AC_MSG_RESULT(no) + + AC_MSG_CHECKING([whether struct kmem_cache has gfpflags]) + SPL_LINUX_TRY_COMPILE([ + #include + ],[ + struct kmem_cache cachep __attribute__ ((unused)); + cachep.gfpflags = GFP_KERNEL; + ],[ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_KMEM_CACHE_GFPFLAGS, 1, + [struct kmem_cache has gfpflags]) + ],[ + AC_MSG_RESULT(no) + ]) + ]) +]) diff -Nru spl-linux-0.6.2/config/spl-meta.m4 spl-linux-0.6.3/config/spl-meta.m4 --- spl-linux-0.6.2/config/spl-meta.m4 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/config/spl-meta.m4 2014-06-12 18:32:38.000000000 +0000 @@ -57,7 +57,7 @@ SPL_META_RELEASE=_SPL_AC_META_GETVAL([Release]); if test ! -f ".nogitrelease" && git rev-parse --git-dir > /dev/null 2>&1; then - _match="${SPL_META_NAME}-${SPL_META_VERSION}*" + _match="${SPL_META_NAME}-${SPL_META_VERSION}" _alias=$(git describe --match=${_match} 2>/dev/null) _release=$(echo ${_alias}|cut -f3- -d'-'|sed 's/-/_/g') if test -n "${_release}"; then diff -Nru spl-linux-0.6.2/configure.ac spl-linux-0.6.3/configure.ac --- spl-linux-0.6.2/configure.ac 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/configure.ac 2014-06-12 18:32:38.000000000 +0000 @@ -50,6 +50,7 @@ Makefile man/Makefile man/man1/Makefile + man/man5/Makefile lib/Makefile cmd/Makefile module/Makefile diff -Nru spl-linux-0.6.2/debian/changelog spl-linux-0.6.3/debian/changelog --- spl-linux-0.6.2/debian/changelog 2013-08-24 00:01:29.000000000 +0000 +++ spl-linux-0.6.3/debian/changelog 2014-06-13 00:50:42.000000000 +0000 @@ -1,3 +1,117 @@ +spl-linux (0.6.3-1~precise) precise; urgency=low + + [ Darik Horn ] + * Use dh_autoreconf. + * Use dh_auto_configure. + * Revert "Set extend-diff-ignore='.*' in the debian/source/options file" + * Use the deb revision instead of the META release. + * Update changelog for 0.6.2-1~precise release + + [ Richard Yao ] + * Replace current_kernel_time() with getnstimeofday() + + [ Ned Bass ] + * Add kpreempt() compatibility macro + + [ Kohsuke Kawaguchi ] + * Document how to run SPLAT + + [ Brian Behlendorf ] + * Consistently use local_irq_disable/local_irq_enable + + [ Richard Yao ] + * Define SET_ERROR() + + [ Prakash Surya ] + * Add callbacks for displaying KSTAT_TYPE_RAW kstats + * Add wrappers for accessing PID and command info + + [ Brian Behlendorf ] + * Revert "Add KSTAT_TYPE_TXG type" + + [ Cyril Plisko ] + * Kstat to use private lock by default + + [ Ned Bass ] + * 3537 add kstat_waitq_enter and friends + * Emulate illumos interface cv_timedwait_hires() + + [ Richard Yao ] + * Linux 3.12 compat: New shrinker API + + [ Cyril Plisko ] + * Tighten spl dependency on spl-kmod + + [ Brian Behlendorf ] + * Retroactively fix bogus %changelog date + + [ Turbo Fredriksson ] + * Document SPL module parameters. + + [ Richard Yao ] + * Linux 3.13 compat: Remove unused flags variable from __cv_init() + * Linux 3.13 compat: Pass NULL for new delegated inode argument + + [ Brian Behlendorf ] + * Add module versioning + * Include linux/vmalloc.h for ARM and Sparc + * Remove default taskq thread to CPU bindings + + [ marku89 ] + * Define the needed ISA types for Sparc + + [ Brian Behlendorf ] + * Remove incorrect use of EXTRA_DIST for man pages + * splat kmem:slab_reclaim: Test cleanup + * splat cred:groupmember: Fix false positives + + [ Tim Chase ] + * Support post-3.13 kthread_create() semantics. + * De-inline spl_kthread_create(). + * Call kthread_create() correctly with fixed arguments. + + [ Richard Yao ] + * Simplify hostid logic + + [ Yuxuan Shui ] + * This patch add a CTASSERT macro for compile time assertion. + + [ Chunwei Chen ] + * Add ddi_time_after and friends + + [ Andrey Vesnovaty ] + * Expose max/min objs per slab and max slab size + + [ Richard Yao ] + * Change spl_kmem_cache_expire default setting to 2 + + [ Jorgen Lundman ] + * Add support for aarch64 (ARMv8) + + [ Chunwei Chen ] + * Fix crash when using ZFS on Ceph rbd + + [ Andrey Vesnovaty ] + * Evenly distribute the taskq threads across available CPUs + + [ Chunwei Chen ] + * Linux 3.15 compat: NICE_TO_PRIO and PRIO_TO_NICE + * Linux 3.15: vfs_rename() added a flags argument + + [ Brian Behlendorf ] + * Add KMC_SLAB cache type + * Add spl_kmem_cache_reclaim module option + * Restrict release number to META version + * Fix DKMS package upgrade and packager + + [ Turbo Fredriksson ] + * Set LANG to a reasonable default (C) + + [ Brian Behlendorf ] + * Tag spl-0.6.3 + + -- Darik Horn Thu, 12 Jun 2014 20:49:57 -0400 + spl-linux (0.6.2-1~precise) precise; urgency=low [ Jan Engelhardt ] @@ -73,7 +187,7 @@ * Revert "Set extend-diff-ignore='.*' in the debian/source/options file" * Use the deb revision instead of the META release. - -- Darik Horn Fri, 23 Aug 2013 18:54:56 -0500 + -- Darik Horn Fri, 23 Aug 2013 18:34:54 -0500 spl-linux (0.6.1-1~precise) precise; urgency=low diff -Nru spl-linux-0.6.2/debian/patches/debian-changes-0.6.3-1~precise spl-linux-0.6.3/debian/patches/debian-changes-0.6.3-1~precise --- spl-linux-0.6.2/debian/patches/debian-changes-0.6.3-1~precise 1970-01-01 00:00:00.000000000 +0000 +++ spl-linux-0.6.3/debian/patches/debian-changes-0.6.3-1~precise 2014-06-13 00:51:14.000000000 +0000 @@ -0,0 +1,165 @@ +Description: + TODO: Put a short summary on the line above and replace this paragraph + with a longer explanation of this change. Complete the meta-information + with other relevant fields (see below for details). To make it easier, the + information below has been extracted from the changelog. Adjust it or drop + it. + . + spl-linux (0.6.3-1~precise) precise; urgency=low + . + [ Darik Horn ] + * Use dh_autoreconf. + * Use dh_auto_configure. + * Revert "Set extend-diff-ignore='.*' in the debian/source/options file" + * Use the deb revision instead of the META release. + * Update changelog for 0.6.2-1~precise release + . + [ Richard Yao ] + * Replace current_kernel_time() with getnstimeofday() + . + [ Ned Bass ] + * Add kpreempt() compatibility macro + . + [ Kohsuke Kawaguchi ] + * Document how to run SPLAT + . + [ Brian Behlendorf ] + * Consistently use local_irq_disable/local_irq_enable + . + [ Richard Yao ] + * Define SET_ERROR() + . + [ Prakash Surya ] + * Add callbacks for displaying KSTAT_TYPE_RAW kstats + * Add wrappers for accessing PID and command info + . + [ Brian Behlendorf ] + * Revert "Add KSTAT_TYPE_TXG type" + . + [ Cyril Plisko ] + * Kstat to use private lock by default + . + [ Ned Bass ] + * 3537 add kstat_waitq_enter and friends + * Emulate illumos interface cv_timedwait_hires() + . + [ Richard Yao ] + * Linux 3.12 compat: New shrinker API + . + [ Cyril Plisko ] + * Tighten spl dependency on spl-kmod + . + [ Brian Behlendorf ] + * Retroactively fix bogus %changelog date + . + [ Turbo Fredriksson ] + * Document SPL module parameters. + . + [ Richard Yao ] + * Linux 3.13 compat: Remove unused flags variable from __cv_init() + * Linux 3.13 compat: Pass NULL for new delegated inode argument + . + [ Brian Behlendorf ] + * Add module versioning + * Include linux/vmalloc.h for ARM and Sparc + * Remove default taskq thread to CPU bindings + . + [ marku89 ] + * Define the needed ISA types for Sparc + . + [ Brian Behlendorf ] + * Remove incorrect use of EXTRA_DIST for man pages + * splat kmem:slab_reclaim: Test cleanup + * splat cred:groupmember: Fix false positives + . + [ Tim Chase ] + * Support post-3.13 kthread_create() semantics. + * De-inline spl_kthread_create(). + * Call kthread_create() correctly with fixed arguments. + . + [ Richard Yao ] + * Simplify hostid logic + . + [ Yuxuan Shui ] + * This patch add a CTASSERT macro for compile time assertion. + . + [ Chunwei Chen ] + * Add ddi_time_after and friends + . + [ Andrey Vesnovaty ] + * Expose max/min objs per slab and max slab size + . + [ Richard Yao ] + * Change spl_kmem_cache_expire default setting to 2 + . + [ Jorgen Lundman ] + * Add support for aarch64 (ARMv8) + . + [ Chunwei Chen ] + * Fix crash when using ZFS on Ceph rbd + . + [ Andrey Vesnovaty ] + * Evenly distribute the taskq threads across available CPUs + . + [ Chunwei Chen ] + * Linux 3.15 compat: NICE_TO_PRIO and PRIO_TO_NICE + * Linux 3.15: vfs_rename() added a flags argument + . + [ Brian Behlendorf ] + * Add KMC_SLAB cache type + * Add spl_kmem_cache_reclaim module option + * Restrict release number to META version + * Fix DKMS package upgrade and packager + . + [ Turbo Fredriksson ] + * Set LANG to a reasonable default (C) + . + [ Brian Behlendorf ] + * Tag spl-0.6.3 +Author: Darik Horn + +--- +The information above should follow the Patch Tagging Guidelines, please +checkout http://dep.debian.net/deps/dep3/ to learn about the format. Here +are templates for supplementary fields that you might want to add: + +Origin: , +Bug: +Bug-Debian: http://bugs.debian.org/ +Bug-Ubuntu: https://launchpad.net/bugs/ +Forwarded: +Reviewed-By: +Last-Update: + +--- spl-linux-0.6.3.orig/README.markdown ++++ spl-linux-0.6.3/README.markdown +@@ -1,26 +1,7 @@ +-The Solaris Porting Layer (SPL) is a Linux kernel module which provides +-many of the Solaris kernel APIs. This shim layer makes it possible to +-run Solaris kernel code in the Linux kernel with relatively minimal +-modification. This can be particularly useful when you want to track +-upstream Solaris development closely and do not want the overhead of +-maintaining a large patch which converts Solaris primitives to Linux +-primitives. ++The Solaris Porting Layer (SPL) for Debian and Ubuntu. Build packages ++from this source repository by running: + +-To build packages for your distribution: +- +- $ ./configure +- $ make pkg +- +-If you are building directly from the git tree and not an officially +-released tarball you will need to generate the configure script. +-This can be done by executing the autogen.sh script after installing +-the GNU autotools for your distribution. +- +-To copy the kernel code inside your kernel source tree for builtin +-compilation: +- +- $ ./configure --enable-linux-builtin --with-linux=/usr/src/linux-... +- $ ./copy-builtin /usr/src/linux-... ++ $ git-buildpackage -us -uc + + The SPL comes with an automated test suite called SPLAT. The test suite + is implemented in two parts. There is a kernel module which contains diff -Nru spl-linux-0.6.2/debian/patches/series spl-linux-0.6.3/debian/patches/series --- spl-linux-0.6.2/debian/patches/series 2013-08-24 00:01:29.000000000 +0000 +++ spl-linux-0.6.3/debian/patches/series 2014-06-13 00:51:14.000000000 +0000 @@ -1 +1,2 @@ 0001-Revert-Remove-etc-hostid-missing-warning.patch +debian-changes-0.6.3-1~precise diff -Nru spl-linux-0.6.2/include/linux/delay_compat.h spl-linux-0.6.3/include/linux/delay_compat.h --- spl-linux-0.6.2/include/linux/delay_compat.h 1970-01-01 00:00:00.000000000 +0000 +++ spl-linux-0.6.3/include/linux/delay_compat.h 2014-06-12 18:32:38.000000000 +0000 @@ -0,0 +1,47 @@ +/*****************************************************************************\ + * Copyright (C) 2007-2013 Lawrence Livermore National Security, LLC. + * Copyright (C) 2007 The Regents of the University of California. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf . + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see . + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see . +\*****************************************************************************/ + +#ifndef _SPL_DELAY_COMPAT_H +#define _SPL_DELAY_COMPAT_H + +#include +#include + +/* usleep_range() introduced in 2.6.36 */ +#ifndef HAVE_USLEEP_RANGE + +static inline void +usleep_range(unsigned long min, unsigned long max) +{ + unsigned int min_ms = min / USEC_PER_MSEC; + + if (min >= MAX_UDELAY_MS) + msleep(min_ms); + else + udelay(min); +} + +#endif /* HAVE_USLEEP_RANGE */ + +#endif /* _SPL_DELAY_COMPAT_H */ diff -Nru spl-linux-0.6.2/include/linux/Makefile.am spl-linux-0.6.3/include/linux/Makefile.am --- spl-linux-0.6.2/include/linux/Makefile.am 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/include/linux/Makefile.am 2014-06-12 18:32:38.000000000 +0000 @@ -3,6 +3,7 @@ KERNEL_H = \ $(top_srcdir)/include/linux/bitops_compat.h \ $(top_srcdir)/include/linux/compiler_compat.h \ + $(top_srcdir)/include/linux/delay_compat.h \ $(top_srcdir)/include/linux/file_compat.h \ $(top_srcdir)/include/linux/kallsyms_compat.h \ $(top_srcdir)/include/linux/list_compat.h \ diff -Nru spl-linux-0.6.2/include/linux/mm_compat.h spl-linux-0.6.3/include/linux/mm_compat.h --- spl-linux-0.6.2/include/linux/mm_compat.h 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/include/linux/mm_compat.h 2014-06-12 18:32:38.000000000 +0000 @@ -148,107 +148,167 @@ #endif /* HAVE_SHRINK_ICACHE_MEMORY */ /* - * Linux 2.6. - 2.6. Shrinker API Compatibility. + * Due to frequent changes in the shrinker API the following + * compatibility wrappers should be used. They are as follows: + * + * SPL_SHRINKER_DECLARE is used to declare the shrinker which is + * passed to spl_register_shrinker()/spl_unregister_shrinker(). Use + * shrinker_name to set the shrinker variable name, shrinker_callback + * to set the callback function, and seek_cost to define the cost of + * reclaiming an object. + * + * SPL_SHRINKER_DECLARE(shrinker_name, shrinker_callback, seek_cost); + * + * SPL_SHRINKER_CALLBACK_FWD_DECLARE is used when a forward declaration + * of the shrinker callback function is required. Only the callback + * function needs to be passed. + * + * SPL_SHRINKER_CALLBACK_FWD_DECLARE(shrinker_callback); + * + * SPL_SHRINKER_CALLBACK_WRAPPER is used to declare the callback function + * which is registered with the shrinker. This function will call your + * custom shrinker which must use the following prototype. Notice the + * leading __'s, these must be appended to the callback_function name. + * + * int __shrinker_callback(struct shrinker *, struct shrink_control *) + * SPL_SHRINKER_CALLBACK_WRAPPER(shrinker_callback);a + * + * + * Example: + * + * SPL_SHRINKER_CALLBACK_FWD_DECLARE(my_shrinker_fn); + * SPL_SHRINKER_DECLARE(my_shrinker, my_shrinker_fn, 1); + * + * static int + * __my_shrinker_fn(struct shrinker *shrink, struct shrink_control *sc) + * { + * if (sc->nr_to_scan) { + * ...scan objects in the cache and reclaim them... + * } + * + * ...calculate number of objects in the cache... + * + * return (number of objects in the cache); + * } + * SPL_SHRINKER_CALLBACK_WRAPPER(my_shrinker_fn); */ -#ifdef HAVE_SET_SHRINKER -typedef struct spl_shrinker { - struct shrinker *shrinker; - shrinker_t fn; - int seeks; -} spl_shrinker_t; - -static inline void -spl_register_shrinker(spl_shrinker_t *ss) -{ - ss->shrinker = set_shrinker(ss->seeks, ss->fn); -} - -static inline void -spl_unregister_shrinker(spl_shrinker_t *ss) -{ - remove_shrinker(ss->shrinker); -} - -# define SPL_SHRINKER_DECLARE(s, x, y) \ - static spl_shrinker_t s = { \ - .shrinker = NULL, \ - .fn = x, \ - .seeks = y \ - } - -# define SPL_SHRINKER_CALLBACK_FWD_DECLARE(fn) \ - static int fn(int, unsigned int) -# define SPL_SHRINKER_CALLBACK_WRAPPER(fn) \ -static int \ -fn(int nr_to_scan, unsigned int gfp_mask) \ -{ \ - struct shrink_control sc; \ - \ - sc.nr_to_scan = nr_to_scan; \ - sc.gfp_mask = gfp_mask; \ - \ - return __ ## fn(NULL, &sc); \ -} -#else +#define spl_register_shrinker(x) register_shrinker(x) +#define spl_unregister_shrinker(x) unregister_shrinker(x) -# define spl_register_shrinker(x) register_shrinker(x) -# define spl_unregister_shrinker(x) unregister_shrinker(x) -# define SPL_SHRINKER_DECLARE(s, x, y) \ - static struct shrinker s = { \ - .shrink = x, \ - .seeks = y \ - } - -/* - * Linux 2.6. - 2.6. Shrinker API Compatibility. - */ -# if defined(HAVE_SHRINK_CONTROL_STRUCT) -# define SPL_SHRINKER_CALLBACK_FWD_DECLARE(fn) \ - static int fn(struct shrinker *, struct shrink_control *) -# define SPL_SHRINKER_CALLBACK_WRAPPER(fn) \ -static int \ -fn(struct shrinker *shrink, struct shrink_control *sc) { \ - return __ ## fn(shrink, sc); \ +/* + * Linux 2.6.23 - 2.6.34 Shrinker API Compatibility. + */ +#if defined(HAVE_2ARGS_OLD_SHRINKER_CALLBACK) +#define SPL_SHRINKER_DECLARE(s, x, y) \ +static struct shrinker s = { \ + .shrink = x, \ + .seeks = y \ +} + +#define SPL_SHRINKER_CALLBACK_FWD_DECLARE(fn) \ +static int fn(int nr_to_scan, unsigned int gfp_mask) + +#define SPL_SHRINKER_CALLBACK_WRAPPER(fn) \ +static int \ +fn(int nr_to_scan, unsigned int gfp_mask) \ +{ \ + struct shrink_control sc; \ + \ + sc.nr_to_scan = nr_to_scan; \ + sc.gfp_mask = gfp_mask; \ + \ + return (__ ## fn(NULL, &sc)); \ } /* - * Linux 2.6. - 2.6. Shrinker API Compatibility. - */ -# elif defined(HAVE_3ARGS_SHRINKER_CALLBACK) -# define SPL_SHRINKER_CALLBACK_FWD_DECLARE(fn) \ - static int fn(struct shrinker *, int, unsigned int) -# define SPL_SHRINKER_CALLBACK_WRAPPER(fn) \ -static int \ -fn(struct shrinker *shrink, int nr_to_scan, unsigned int gfp_mask) \ -{ \ - struct shrink_control sc; \ - \ - sc.nr_to_scan = nr_to_scan; \ - sc.gfp_mask = gfp_mask; \ - \ - return __ ## fn(shrink, &sc); \ + * Linux 2.6.35 to 2.6.39 Shrinker API Compatibility. + */ +#elif defined(HAVE_3ARGS_SHRINKER_CALLBACK) +#define SPL_SHRINKER_DECLARE(s, x, y) \ +static struct shrinker s = { \ + .shrink = x, \ + .seeks = y \ +} + +#define SPL_SHRINKER_CALLBACK_FWD_DECLARE(fn) \ +static int fn(struct shrinker *, int, unsigned int) + +#define SPL_SHRINKER_CALLBACK_WRAPPER(fn) \ +static int \ +fn(struct shrinker *shrink, int nr_to_scan, unsigned int gfp_mask) \ +{ \ + struct shrink_control sc; \ + \ + sc.nr_to_scan = nr_to_scan; \ + sc.gfp_mask = gfp_mask; \ + \ + return (__ ## fn(shrink, &sc)); \ } /* - * Linux 2.6. - 2.6. Shrinker API Compatibility. - */ -# else -# define SPL_SHRINKER_CALLBACK_FWD_DECLARE(fn) \ - static int fn(int, unsigned int) -# define SPL_SHRINKER_CALLBACK_WRAPPER(fn) \ -static int \ -fn(int nr_to_scan, unsigned int gfp_mask) \ -{ \ - struct shrink_control sc; \ - \ - sc.nr_to_scan = nr_to_scan; \ - sc.gfp_mask = gfp_mask; \ - \ - return __ ## fn(NULL, &sc); \ + * Linux 3.0 to 3.11 Shrinker API Compatibility. + */ +#elif defined(HAVE_2ARGS_NEW_SHRINKER_CALLBACK) +#define SPL_SHRINKER_DECLARE(s, x, y) \ +static struct shrinker s = { \ + .shrink = x, \ + .seeks = y \ +} + +#define SPL_SHRINKER_CALLBACK_FWD_DECLARE(fn) \ +static int fn(struct shrinker *, struct shrink_control *) + +#define SPL_SHRINKER_CALLBACK_WRAPPER(fn) \ +static int \ +fn(struct shrinker *shrink, struct shrink_control *sc) \ +{ \ + return (__ ## fn(shrink, sc)); \ } -# endif -#endif /* HAVE_SET_SHRINKER */ +/* + * Linux 3.12 and later Shrinker API Compatibility. + */ +#elif defined(HAVE_SPLIT_SHRINKER_CALLBACK) +#define SPL_SHRINKER_DECLARE(s, x, y) \ +static struct shrinker s = { \ + .count_objects = x ## _count_objects, \ + .scan_objects = x ## _scan_objects, \ + .seeks = y \ +} + +#define SPL_SHRINKER_CALLBACK_FWD_DECLARE(fn) \ +static unsigned long fn ## _count_objects(struct shrinker *, \ + struct shrink_control *); \ +static unsigned long fn ## _scan_objects(struct shrinker *, \ + struct shrink_control *) + +#define SPL_SHRINKER_CALLBACK_WRAPPER(fn) \ +static unsigned long \ +fn ## _count_objects(struct shrinker *shrink, struct shrink_control *sc)\ +{ \ + int __ret__; \ + \ + sc->nr_to_scan = 0; \ + __ret__ = __ ## fn(NULL, sc); \ + \ + /* Errors may not be returned and must be converted to zeros */ \ + return ((__ret__ < 0) ? 0 : __ret__); \ +} \ + \ +static unsigned long \ +fn ## _scan_objects(struct shrinker *shrink, struct shrink_control *sc) \ +{ \ + int __ret__; \ + \ + __ret__ = __ ## fn(NULL, sc); \ + return ((__ret__ < 0) ? SHRINK_STOP : __ret__); \ +} +#else +/* + * Linux 2.x to 2.6.22, or a newer shrinker API has been introduced. + */ +#error "Unknown shrinker callback" +#endif #endif /* SPL_MM_COMPAT_H */ diff -Nru spl-linux-0.6.2/include/sys/callo.h spl-linux-0.6.3/include/sys/callo.h --- spl-linux-0.6.2/include/sys/callo.h 1970-01-01 00:00:00.000000000 +0000 +++ spl-linux-0.6.3/include/sys/callo.h 2014-06-12 18:32:38.000000000 +0000 @@ -0,0 +1,52 @@ +/*****************************************************************************\ + * Copyright (C) 2007-2013 Lawrence Livermore National Security, LLC. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf . + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * For details, see . + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see . +\*****************************************************************************/ + +#ifndef _SPL_CALLO_H +#define _SPL_CALLO_H + +/* + * Callout flags: + * + * CALLOUT_FLAG_ROUNDUP + * Roundup the expiration time to the next resolution boundary. + * If this flag is not specified, the expiration time is rounded down. + * CALLOUT_FLAG_ABSOLUTE + * Normally, the expiration passed to the timeout API functions is an + * expiration interval. If this flag is specified, then it is + * interpreted as the expiration time itself. + * CALLOUT_FLAG_HRESTIME + * Normally, callouts are not affected by changes to system time + * (hrestime). This flag is used to create a callout that is affected + * by system time. If system time changes, these timers must be + * handled in a special way (see callout.c). These are used by condition + * variables and LWP timers that need this behavior. + * CALLOUT_FLAG_32BIT + * Legacy interfaces timeout() and realtime_timeout() pass this flag + * to timeout_generic() to indicate that a 32-bit ID should be allocated. + */ +#define CALLOUT_FLAG_ROUNDUP 0x1 +#define CALLOUT_FLAG_ABSOLUTE 0x2 +#define CALLOUT_FLAG_HRESTIME 0x4 +#define CALLOUT_FLAG_32BIT 0x8 + +#endif /* _SPL_CALLB_H */ diff -Nru spl-linux-0.6.2/include/sys/condvar.h spl-linux-0.6.3/include/sys/condvar.h --- spl-linux-0.6.2/include/sys/condvar.h 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/include/sys/condvar.h 2014-06-12 18:32:38.000000000 +0000 @@ -27,8 +27,10 @@ #include #include +#include #include #include +#include /* * The kcondvar_t struct is protected by mutex taken externally before @@ -56,6 +58,8 @@ extern clock_t __cv_timedwait(kcondvar_t *cvp, kmutex_t *mp, clock_t exp_time); extern clock_t __cv_timedwait_interruptible(kcondvar_t *cvp, kmutex_t *mp, clock_t exp_time); +extern clock_t cv_timedwait_hires(kcondvar_t *cvp, kmutex_t *mp, + hrtime_t tim, hrtime_t res, int flag); extern void __cv_signal(kcondvar_t *cvp); extern void __cv_broadcast(kcondvar_t *cvp); diff -Nru spl-linux-0.6.2/include/sys/debug.h spl-linux-0.6.3/include/sys/debug.h --- spl-linux-0.6.2/include/sys/debug.h 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/include/sys/debug.h 2014-06-12 18:32:38.000000000 +0000 @@ -145,4 +145,15 @@ #define VERIFY(x) ASSERT(x) #endif /* NDEBUG */ + +/* + * Compile-time assertion. The condition 'x' must be constant. + */ +#define CTASSERT_GLOBAL(x) _CTASSERT(x, __LINE__) +#define CTASSERT(x) { _CTASSERT(x, __LINE__); } +#define _CTASSERT(x, y) __CTASSERT(x, y) +#define __CTASSERT(x, y) \ + typedef char __attribute__ ((unused)) \ + __compile_time_assertion__ ## y[(x) ? 1 : -1] + #endif /* SPL_DEBUG_H */ diff -Nru spl-linux-0.6.2/include/sys/disp.h spl-linux-0.6.3/include/sys/disp.h --- spl-linux-0.6.2/include/sys/disp.h 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/include/sys/disp.h 2014-06-12 18:32:38.000000000 +0000 @@ -27,6 +27,7 @@ #include +#define kpreempt(unused) schedule() #define kpreempt_disable() preempt_disable() #define kpreempt_enable() preempt_enable() diff -Nru spl-linux-0.6.2/include/sys/isa_defs.h spl-linux-0.6.3/include/sys/isa_defs.h --- spl-linux-0.6.2/include/sys/isa_defs.h 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/include/sys/isa_defs.h 2014-06-12 18:32:38.000000000 +0000 @@ -75,7 +75,7 @@ #endif /* arm arch specific defines */ -#elif defined(__arm) || defined(__arm__) +#elif defined(__arm) || defined(__arm__) || defined(__aarch64__) #if !defined(__arm) #define __arm @@ -85,13 +85,41 @@ #define __arm__ #endif -#if defined(__ARMEL__) +#if defined(__ARMEL__) || defined(__AARCH64EL__) #define _LITTLE_ENDIAN #else #define _BIG_ENDIAN #endif -#else /* Currently only x86_64, i386, arm, and powerpc arches supported */ +/* sparc arch specific defines */ +#elif defined(__sparc) || defined(__sparc__) + +#if !defined(__sparc) +#define __sparc +#endif + +#if !defined(__sparc__) +#define __sparc__ +#endif + +#define _BIG_ENDIAN +#define _SUNOS_VTOC_16 + +/* sparc64 arch specific defines */ +#elif defined(__sparc64) || defined(__sparc64__) + +#if !defined(__sparc64) +#define __sparc64 +#endif + +#if !defined(__sparc64__) +#define __sparc64__ +#endif + +#define _BIG_ENDIAN +#define _SUNOS_VTOC_16 + +#else /* Currently x86_64, i386, arm, powerpc, and sparc are supported */ #error "Unsupported ISA type" #endif diff -Nru spl-linux-0.6.2/include/sys/kmem.h spl-linux-0.6.3/include/sys/kmem.h --- spl-linux-0.6.2/include/sys/kmem.h 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/include/sys/kmem.h 2014-06-12 18:32:38.000000000 +0000 @@ -340,8 +340,9 @@ KMC_BIT_QCACHE = 4, /* XXX: Unsupported */ KMC_BIT_KMEM = 5, /* Use kmem cache */ KMC_BIT_VMEM = 6, /* Use vmem cache */ - KMC_BIT_OFFSLAB = 7, /* Objects not on slab */ - KMC_BIT_NOEMERGENCY = 8, /* Disable emergency objects */ + KMC_BIT_SLAB = 7, /* Use Linux slab cache */ + KMC_BIT_OFFSLAB = 8, /* Objects not on slab */ + KMC_BIT_NOEMERGENCY = 9, /* Disable emergency objects */ KMC_BIT_DEADLOCKED = 14, /* Deadlock detected */ KMC_BIT_GROWING = 15, /* Growing in progress */ KMC_BIT_REAPING = 16, /* Reaping in progress */ @@ -367,6 +368,7 @@ #define KMC_QCACHE (1 << KMC_BIT_QCACHE) #define KMC_KMEM (1 << KMC_BIT_KMEM) #define KMC_VMEM (1 << KMC_BIT_VMEM) +#define KMC_SLAB (1 << KMC_BIT_SLAB) #define KMC_OFFSLAB (1 << KMC_BIT_OFFSLAB) #define KMC_NOEMERGENCY (1 << KMC_BIT_NOEMERGENCY) #define KMC_DEADLOCKED (1 << KMC_BIT_DEADLOCKED) @@ -383,6 +385,8 @@ #define KMC_EXPIRE_AGE 0x1 /* Due to age */ #define KMC_EXPIRE_MEM 0x2 /* Due to low memory */ +#define KMC_RECLAIM_ONCE 0x1 /* Force a single shrinker pass */ + extern unsigned int spl_kmem_cache_expire; extern struct list_head spl_kmem_cache_list; extern struct rw_semaphore spl_kmem_cache_sem; @@ -456,6 +460,7 @@ spl_kmem_reclaim_t skc_reclaim; /* Reclaimator */ void *skc_private; /* Private data */ void *skc_vmp; /* Unused */ + struct kmem_cache *skc_linux_cache; /* Linux slab cache if used */ unsigned long skc_flags; /* Flags */ uint32_t skc_obj_size; /* Object size */ uint32_t skc_obj_align; /* Object alignment */ @@ -513,4 +518,24 @@ #define kmem_virt(ptr) (((ptr) >= (void *)VMALLOC_START) && \ ((ptr) < (void *)VMALLOC_END)) +/* + * Allow custom slab allocation flags to be set for KMC_SLAB based caches. + * One use for this function is to ensure the __GFP_COMP flag is part of + * the default allocation mask which ensures higher order allocations are + * properly refcounted. This flag was added to the default ->allocflags + * as of Linux 3.11. + */ +static inline void +kmem_cache_set_allocflags(spl_kmem_cache_t *skc, gfp_t flags) +{ + if (skc->skc_linux_cache == NULL) + return; + +#if defined(HAVE_KMEM_CACHE_ALLOCFLAGS) + skc->skc_linux_cache->allocflags |= flags; +#elif defined(HAVE_KMEM_CACHE_GFPFLAGS) + skc->skc_linux_cache->gfpflags |= flags; +#endif +} + #endif /* _SPL_KMEM_H */ diff -Nru spl-linux-0.6.2/include/sys/kstat.h spl-linux-0.6.3/include/sys/kstat.h --- spl-linux-0.6.2/include/sys/kstat.h 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/include/sys/kstat.h 2014-06-12 18:32:38.000000000 +0000 @@ -33,6 +33,7 @@ #include #define KSTAT_STRLEN 31 +#define KSTAT_RAW_MAX (128*1024) /* For reference valid classes are: * disk, tape, net, controller, vm, kvm, hat, streams, kstat, misc @@ -43,8 +44,7 @@ #define KSTAT_TYPE_INTR 2 /* interrupt stats; ks_ndata == 1 */ #define KSTAT_TYPE_IO 3 /* I/O stats; ks_ndata == 1 */ #define KSTAT_TYPE_TIMER 4 /* event timer; ks_ndata >= 1 */ -#define KSTAT_TYPE_TXG 5 /* txg sync; ks_ndata >= 1 */ -#define KSTAT_NUM_TYPES 6 +#define KSTAT_NUM_TYPES 5 #define KSTAT_DATA_CHAR 0 #define KSTAT_DATA_INT32 1 @@ -79,6 +79,7 @@ #define KSTAT_WRITE 1 struct kstat_s; +typedef struct kstat_s kstat_t; typedef int kid_t; /* unique kstat id */ typedef int kstat_update_t(struct kstat_s *, int); /* dynamic update cb */ @@ -90,7 +91,13 @@ struct proc_dir_entry *ksm_proc; /* proc entry */ } kstat_module_t; -typedef struct kstat_s { +typedef struct kstat_raw_ops { + int (*headers)(char *buf, size_t size); + int (*data)(char *buf, size_t size, void *data); + void *(*addr)(kstat_t *ksp, loff_t index); +} kstat_raw_ops_t; + +struct kstat_s { int ks_magic; /* magic value */ kid_t ks_kid; /* unique kstat ID */ hrtime_t ks_crtime; /* creation time */ @@ -107,10 +114,14 @@ struct proc_dir_entry *ks_proc; /* proc linkage */ kstat_update_t *ks_update; /* dynamic updates */ void *ks_private; /* private data */ - kmutex_t ks_lock; /* kstat data lock */ + kmutex_t ks_private_lock; /* kstat private data lock */ + kmutex_t *ks_lock; /* kstat data lock */ struct list_head ks_list; /* kstat linkage */ kstat_module_t *ks_owner; /* kstat module linkage */ -} kstat_t; + kstat_raw_ops_t ks_raw_ops; /* ops table for raw type */ + char *ks_raw_buf; /* buf used for raw ops */ + size_t ks_raw_bufsize; /* size of raw ops buffer */ +}; typedef struct kstat_named_s { char name[KSTAT_STRLEN]; /* name of counter */ @@ -165,36 +176,25 @@ hrtime_t stop_time; /* previous event stop time */ } kstat_timer_t; -typedef enum kstat_txg_state { - TXG_STATE_OPEN = 1, - TXG_STATE_QUIESCING = 2, - TXG_STATE_SYNCING = 3, - TXG_STATE_COMMITTED = 4, -} kstat_txg_state_t; - -typedef struct kstat_txg { - u_longlong_t txg; /* txg id */ - kstat_txg_state_t state; /* txg state */ - hrtime_t birth; /* birth time stamp */ - u_longlong_t nread; /* number of bytes read */ - u_longlong_t nwritten; /* number of bytes written */ - uint_t reads; /* number of read operations */ - uint_t writes; /* number of write operations */ - hrtime_t open_time; /* open time */ - hrtime_t quiesce_time;/* quiesce time */ - hrtime_t sync_time; /* sync time */ -} kstat_txg_t; - int spl_kstat_init(void); void spl_kstat_fini(void); +extern void __kstat_set_raw_ops(kstat_t *ksp, + int (*headers)(char *buf, size_t size), + int (*data)(char *buf, size_t size, void *data), + void* (*addr)(kstat_t *ksp, loff_t index)); extern kstat_t *__kstat_create(const char *ks_module, int ks_instance, const char *ks_name, const char *ks_class, uchar_t ks_type, uint_t ks_ndata, uchar_t ks_flags); extern void __kstat_install(kstat_t *ksp); extern void __kstat_delete(kstat_t *ksp); +extern void kstat_waitq_enter(kstat_io_t *); +extern void kstat_waitq_exit(kstat_io_t *); +extern void kstat_runq_enter(kstat_io_t *); +extern void kstat_runq_exit(kstat_io_t *); +#define kstat_set_raw_ops(k,h,d,a) __kstat_set_raw_ops(k,h,d,a) #define kstat_create(m,i,n,c,t,s,f) __kstat_create(m,i,n,c,t,s,f) #define kstat_install(k) __kstat_install(k) #define kstat_delete(k) __kstat_delete(k) diff -Nru spl-linux-0.6.2/include/sys/Makefile.am spl-linux-0.6.3/include/sys/Makefile.am --- spl-linux-0.6.2/include/sys/Makefile.am 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/include/sys/Makefile.am 2014-06-12 18:32:38.000000000 +0000 @@ -13,6 +13,7 @@ $(top_srcdir)/include/sys/buf.h \ $(top_srcdir)/include/sys/byteorder.h \ $(top_srcdir)/include/sys/callb.h \ + $(top_srcdir)/include/sys/callo.h \ $(top_srcdir)/include/sys/cmn_err.h \ $(top_srcdir)/include/sys/compress.h \ $(top_srcdir)/include/sys/condvar.h \ diff -Nru spl-linux-0.6.2/include/sys/sdt.h spl-linux-0.6.3/include/sys/sdt.h --- spl-linux-0.6.2/include/sys/sdt.h 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/include/sys/sdt.h 2014-06-12 18:32:38.000000000 +0000 @@ -25,4 +25,6 @@ #ifndef _SPL_SDT_H #define _SPL_SDT_H +#define SET_ERROR(x) (x) + #endif /* SPL_SDT_H */ diff -Nru spl-linux-0.6.2/include/sys/sysmacros.h spl-linux-0.6.3/include/sys/sysmacros.h --- spl-linux-0.6.2/include/sys/sysmacros.h 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/include/sys/sysmacros.h 2014-06-12 18:32:38.000000000 +0000 @@ -95,8 +95,12 @@ #define minclsyspri (MAX_RT_PRIO) #define maxclsyspri (MAX_PRIO-1) +#ifndef NICE_TO_PRIO #define NICE_TO_PRIO(nice) (MAX_RT_PRIO + (nice) + 20) +#endif +#ifndef PRIO_TO_NICE #define PRIO_TO_NICE(prio) ((prio) - MAX_RT_PRIO - 20) +#endif /* Missing macros */ @@ -143,7 +147,6 @@ /* Missing globals */ extern char spl_version[32]; extern unsigned long spl_hostid; -extern char hw_serial[11]; /* Missing misc functions */ extern int highbit(unsigned long i); diff -Nru spl-linux-0.6.2/include/sys/systeminfo.h spl-linux-0.6.3/include/sys/systeminfo.h --- spl-linux-0.6.2/include/sys/systeminfo.h 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/include/sys/systeminfo.h 2014-06-12 18:32:38.000000000 +0000 @@ -25,7 +25,6 @@ #ifndef _SPL_SYSTEMINFO_H #define _SPL_SYSTEMINFO_H -#define HW_INVALID_HOSTID 0xFFFFFFFF /* an invalid hostid */ #define HW_HOSTID_LEN 11 /* minimum buffer size needed */ /* to hold a decimal or hex */ /* hostid string */ diff -Nru spl-linux-0.6.2/include/sys/thread.h spl-linux-0.6.3/include/sys/thread.h --- spl-linux-0.6.2/include/sys/thread.h 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/include/sys/thread.h 2014-06-12 18:32:38.000000000 +0000 @@ -51,11 +51,15 @@ #define thread_exit() __thread_exit() #define thread_join(t) VERIFY(0) #define curthread current +#define getcomm() current->comm +#define getpid() current->pid extern kthread_t *__thread_create(caddr_t stk, size_t stksize, thread_func_t func, const char *name, void *args, size_t len, proc_t *pp, int state, pri_t pri); extern void __thread_exit(void); +extern struct task_struct *spl_kthread_create(int (*func)(void *), + void *data, const char namefmt[], ...); #endif /* _SPL_THREAD_H */ diff -Nru spl-linux-0.6.2/include/sys/time.h spl-linux-0.6.3/include/sys/time.h --- spl-linux-0.6.2/include/sys/time.h 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/include/sys/time.h 2014-06-12 18:32:38.000000000 +0000 @@ -47,6 +47,9 @@ #define MICROSEC 1000000 #define NANOSEC 1000000000 +#define MSEC2NSEC(m) ((hrtime_t)(m) * (NANOSEC / MILLISEC)) +#define NSEC2MSEC(n) ((n) / (NANOSEC / MILLISEC)) + /* Already defined in include/linux/time.h */ #undef CLOCK_THREAD_CPUTIME_ID #undef CLOCK_REALTIME diff -Nru spl-linux-0.6.2/include/sys/timer.h spl-linux-0.6.3/include/sys/timer.h --- spl-linux-0.6.2/include/sys/timer.h 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/include/sys/timer.h 2014-06-12 18:32:38.000000000 +0000 @@ -35,6 +35,20 @@ #define ddi_get_lbolt() ((clock_t)jiffies) #define ddi_get_lbolt64() ((int64_t)get_jiffies_64()) +#define ddi_time_before(a, b) (typecheck(clock_t, a) && \ + typecheck(clock_t, b) && \ + ((a) - (b) < 0)) +#define ddi_time_after(a, b) ddi_time_before(b, a) +#define ddi_time_before_eq(a, b) (!ddi_time_after(a, b)) +#define ddi_time_after_eq(a, b) ddi_time_before_eq(b, a) + +#define ddi_time_before64(a, b) (typecheck(int64_t, a) && \ + typecheck(int64_t, b) && \ + ((a) - (b) < 0)) +#define ddi_time_after64(a, b) ddi_time_before64(b, a) +#define ddi_time_before_eq64(a, b) (!ddi_time_after64(a, b)) +#define ddi_time_after_eq64(a, b) ddi_time_before_eq64(b, a) + #define delay(ticks) schedule_timeout_uninterruptible(ticks) #define SEC_TO_TICK(sec) ((sec) * HZ) diff -Nru spl-linux-0.6.2/include/sys/vmsystm.h spl-linux-0.6.3/include/sys/vmsystm.h --- spl-linux-0.6.2/include/sys/vmsystm.h 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/include/sys/vmsystm.h 2014-06-12 18:32:38.000000000 +0000 @@ -29,6 +29,7 @@ #include #include #include +#include #include #include diff -Nru spl-linux-0.6.2/man/Makefile.am spl-linux-0.6.3/man/Makefile.am --- spl-linux-0.6.2/man/Makefile.am 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/man/Makefile.am 2014-06-12 18:32:38.000000000 +0000 @@ -1 +1 @@ -SUBDIRS = man1 +SUBDIRS = man1 man5 diff -Nru spl-linux-0.6.2/man/man1/Makefile.am spl-linux-0.6.3/man/man1/Makefile.am --- spl-linux-0.6.2/man/man1/Makefile.am 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/man/man1/Makefile.am 2014-06-12 18:32:38.000000000 +0000 @@ -1,5 +1,4 @@ -man_MANS = splat.1 -EXTRA_DIST = $(man_MANS) +dist_man_MANS = splat.1 install-data-local: $(INSTALL) -d -m 0755 "$(DESTDIR)$(mandir)/man1" diff -Nru spl-linux-0.6.2/man/man5/Makefile.am spl-linux-0.6.3/man/man5/Makefile.am --- spl-linux-0.6.2/man/man5/Makefile.am 1970-01-01 00:00:00.000000000 +0000 +++ spl-linux-0.6.3/man/man5/Makefile.am 2014-06-12 18:32:38.000000000 +0000 @@ -0,0 +1,4 @@ +dist_man_MANS = spl-module-parameters.5 + +install-data-local: + $(INSTALL) -d -m 0755 "$(DESTDIR)$(mandir)/man5" diff -Nru spl-linux-0.6.2/man/man5/spl-module-parameters.5 spl-linux-0.6.3/man/man5/spl-module-parameters.5 --- spl-linux-0.6.2/man/man5/spl-module-parameters.5 1970-01-01 00:00:00.000000000 +0000 +++ spl-linux-0.6.3/man/man5/spl-module-parameters.5 2014-06-12 18:32:38.000000000 +0000 @@ -0,0 +1,138 @@ +'\" te +.\" +.\" Copyright 2013 Turbo Fredriksson . All rights reserved. +.\" +.TH SPL-MODULE-PARAMETERS 5 "Nov 18, 2013" +.SH NAME +spl\-module\-parameters \- SPL module parameters +.SH DESCRIPTION +.sp +.LP +Description of the different parameters to the SPL module. + +.SS "Module parameters" +.sp +.LP + +.sp +.ne 2 +.na +\fBspl_debug_subsys\fR (ulong) +.ad +.RS 12n +Subsystem debugging level mask. +.sp +Default value: \fB~0\fR. +.RE + +.sp +.ne 2 +.na +\fBspl_debug_mask\fR (ulong) +.ad +.RS 12n +Debugging level mask. +.sp +Default value: \fB8 | 10 | 4 | 20\fR (SD_ERROR | SD_EMERG | SD_WARNING | SD_CONSOLE). +.RE + +.sp +.ne 2 +.na +\fBspl_debug_printk\fR (ulong) +.ad +.RS 12n +Console printk level mask. +.sp +Default value: \fB8 | 10 | 4 | 20\fR (SD_ERROR | SD_EMERG | SD_WARNING | SD_CONSOLE). +.RE + +.sp +.ne 2 +.na +\fBspl_debug_mb\fR (int) +.ad +.RS 12n +Total debug buffer size. +.sp +Default value: \fB-1\fR. +.RE + +.sp +.ne 2 +.na +\fBspl_debug_panic_on_bug\fR (int) +.ad +.RS 12n +Panic on BUG +.sp +Use \fB1\fR for yes and \fB0\fR for no (default). +.RE + +.sp +.ne 2 +.na +\fBspl_kmem_cache_expire\fR (uint) +.ad +.RS 12n +By age (0x1) or low memory (0x2) +.sp +Default value: \fB0\fR. +.RE + +.sp +.ne 2 +.na +\fBspl_hostid\fR (ulong) +.ad +.RS 12n +The system hostid. +.sp +Default value: \fB0xFFFFFFFF\fR (an invalid hostid!) +.RE + +.sp +.ne 2 +.na +\fBspl_hostid_path\fR (charp) +.ad +.RS 12n +The system hostid file +.sp +Default value: \fB/etc/hostid\fR. +.RE + +.sp +.ne 2 +.na +\fBmutex_spin_max\fR (int) +.ad +.RS 12n +Spin a maximum of N times to acquire lock +.sp +.ne 2 +.na +\fBPossible values:\fR +.sp +.RS 12n + \fB0\fR Never spin when trying to acquire lock +.sp +\fB-1\fR Spin until acquired or holder yields without dropping lock +.sp +\fB1-MAX_INT\fR Spin for N attempts before sleeping for lock +.RE +.sp +.ne -4 +Default value: \fB0\fR. +.RE + +.sp +.ne 2 +.na +\fBspl_taskq_thread_bind\fR (int) +.ad +.RS 12n +Bind taskq thread to CPU +.sp +Default value: \fB0\fR. +.RE diff -Nru spl-linux-0.6.2/META spl-linux-0.6.3/META --- spl-linux-0.6.2/META 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/META 2014-06-12 18:32:38.000000000 +0000 @@ -1,6 +1,6 @@ Meta: 1 Name: spl Branch: 1.0 -Version: 0.6.2 +Version: 0.6.3 Release: 1 Release-Tags: relext diff -Nru spl-linux-0.6.2/module/spl/spl-condvar.c spl-linux-0.6.3/module/spl/spl-condvar.c --- spl-linux-0.6.2/module/spl/spl-condvar.c 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/module/spl/spl-condvar.c 2014-06-12 18:32:38.000000000 +0000 @@ -36,8 +36,6 @@ void __cv_init(kcondvar_t *cvp, char *name, kcv_type_t type, void *arg) { - int flags = KM_SLEEP; - SENTRY; ASSERT(cvp); ASSERT(name == NULL); @@ -51,12 +49,6 @@ atomic_set(&cvp->cv_refs, 1); cvp->cv_mutex = NULL; - /* We may be called when there is a non-zero preempt_count or - * interrupts are disabled is which case we must not sleep. - */ - if (current_thread_info()->preempt_count || irqs_disabled()) - flags = KM_NOSLEEP; - SEXIT; } EXPORT_SYMBOL(__cv_init); @@ -226,6 +218,87 @@ } EXPORT_SYMBOL(__cv_timedwait_interruptible); +/* + *'expire_time' argument is an absolute clock time in nanoseconds. + * Return value is time left (expire_time - now) or -1 if timeout occurred. + */ +static clock_t +__cv_timedwait_hires(kcondvar_t *cvp, kmutex_t *mp, + hrtime_t expire_time, int state) +{ + DEFINE_WAIT(wait); + hrtime_t time_left, now; + unsigned long time_left_us; + SENTRY; + + ASSERT(cvp); + ASSERT(mp); + ASSERT(cvp->cv_magic == CV_MAGIC); + ASSERT(mutex_owned(mp)); + atomic_inc(&cvp->cv_refs); + + if (cvp->cv_mutex == NULL) + cvp->cv_mutex = mp; + + /* Ensure the same mutex is used by all callers */ + ASSERT(cvp->cv_mutex == mp); + + now = gethrtime(); + time_left = expire_time - now; + if (time_left <= 0) { + atomic_dec(&cvp->cv_refs); + SRETURN(-1); + } + time_left_us = time_left / NSEC_PER_USEC; + + prepare_to_wait_exclusive(&cvp->cv_event, &wait, state); + atomic_inc(&cvp->cv_waiters); + + /* Mutex should be dropped after prepare_to_wait() this + * ensures we're linked in to the waiters list and avoids the + * race where 'cvp->cv_waiters > 0' but the list is empty. */ + mutex_exit(mp); + /* Allow a 100 us range to give kernel an opportunity to coalesce + * interrupts */ + usleep_range(time_left_us, time_left_us + 100); + mutex_enter(mp); + + /* No more waiters a different mutex could be used */ + if (atomic_dec_and_test(&cvp->cv_waiters)) { + cvp->cv_mutex = NULL; + wake_up(&cvp->cv_destroy); + } + + finish_wait(&cvp->cv_event, &wait); + atomic_dec(&cvp->cv_refs); + + time_left = expire_time - gethrtime(); + SRETURN(time_left > 0 ? time_left : -1); +} + +/* + * Compatibility wrapper for the cv_timedwait_hires() Illumos interface. + */ +clock_t +cv_timedwait_hires(kcondvar_t *cvp, kmutex_t *mp, hrtime_t tim, + hrtime_t res, int flag) +{ + if (res > 1) { + /* + * Align expiration to the specified resolution. + */ + if (flag & CALLOUT_FLAG_ROUNDUP) + tim += res - 1; + tim = (tim / res) * res; + } + + if (!(flag & CALLOUT_FLAG_ABSOLUTE)) + tim += gethrtime(); + + return __cv_timedwait_hires(cvp, mp, tim, TASK_UNINTERRUPTIBLE); +} +EXPORT_SYMBOL(cv_timedwait_hires); + void __cv_signal(kcondvar_t *cvp) { diff -Nru spl-linux-0.6.2/module/spl/spl-cred.c spl-linux-0.6.3/module/spl/spl-cred.c --- spl-linux-0.6.2/module/spl/spl-cred.c 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/module/spl/spl-cred.c 2014-06-12 18:32:38.000000000 +0000 @@ -44,7 +44,8 @@ cr_groups_search(const struct group_info *group_info, gid_t grp) #endif { - unsigned int left, right; + unsigned int left, right, mid; + int cmp; if (!group_info) return 0; @@ -52,8 +53,10 @@ left = 0; right = group_info->ngroups; while (left < right) { - unsigned int mid = (left+right)/2; - int cmp = KGID_TO_SGID(grp) - KGID_TO_SGID(GROUP_AT(group_info, mid)); + mid = (left + right) / 2; + cmp = KGID_TO_SGID(grp) - + KGID_TO_SGID(GROUP_AT(group_info, mid)); + if (cmp > 0) left = mid + 1; else if (cmp < 0) @@ -120,7 +123,7 @@ return gids; } -/* Check if the passed gid is available is in supplied credential. */ +/* Check if the passed gid is available in supplied credential. */ int groupmember(gid_t gid, const cred_t *cr) { @@ -128,7 +131,7 @@ int rc; gi = get_group_info(cr->group_info); - rc = cr_groups_search(cr->group_info, SGID_TO_KGID(gid)); + rc = cr_groups_search(gi, SGID_TO_KGID(gid)); put_group_info(gi); return rc; diff -Nru spl-linux-0.6.2/module/spl/spl-debug.c spl-linux-0.6.3/module/spl/spl-debug.c --- spl-linux-0.6.2/module/spl/spl-debug.c 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/module/spl/spl-debug.c 2014-06-12 18:32:38.000000000 +0000 @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -415,7 +416,7 @@ spl_debug_dumplog_internal(&dp); } else { - tsk = kthread_create(spl_debug_dumplog_thread,(void *)&dp,"spl_debug"); + tsk = spl_kthread_create(spl_debug_dumplog_thread,(void *)&dp,"spl_debug"); if (tsk == NULL) return -ENOMEM; diff -Nru spl-linux-0.6.2/module/spl/spl-generic.c spl-linux-0.6.3/module/spl/spl-generic.c --- spl-linux-0.6.2/module/spl/spl-generic.c 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/module/spl/spl-generic.c 2014-06-12 18:32:38.000000000 +0000 @@ -52,14 +52,11 @@ char spl_version[32] = "SPL v" SPL_META_VERSION "-" SPL_META_RELEASE; EXPORT_SYMBOL(spl_version); -unsigned long spl_hostid = HW_INVALID_HOSTID; +unsigned long spl_hostid = 0; EXPORT_SYMBOL(spl_hostid); module_param(spl_hostid, ulong, 0644); MODULE_PARM_DESC(spl_hostid, "The system hostid."); -char hw_serial[HW_HOSTID_LEN] = ""; -EXPORT_SYMBOL(hw_serial); - proc_t p0 = { 0 }; EXPORT_SYMBOL(p0); @@ -467,7 +464,7 @@ int result; uint64_t size; struct _buf *file; - unsigned long hostid = 0; + uint32_t hostid = 0; file = kobj_open_file(spl_hostid_path); @@ -511,45 +508,10 @@ return 0; } -#define GET_HOSTID_CMD \ - "exec 0/proc/sys/kernel/spl/hostid " \ - " 2>/dev/null; " \ - "hostid" - -static int -hostid_exec(void) -{ - char *argv[] = { "/bin/sh", - "-c", - GET_HOSTID_CMD, - NULL }; - char *envp[] = { "HOME=/", - "TERM=linux", - "PATH=/sbin:/usr/sbin:/bin:/usr/bin", - NULL }; - int rc; - - /* Doing address resolution in the kernel is tricky and just - * not a good idea in general. So to set the proper 'hw_serial' - * use the usermodehelper support to ask '/bin/sh' to run - * '/usr/bin/hostid' and redirect the result to /proc/sys/spl/hostid - * for us to use. It's a horrific solution but it will do for now. - */ - rc = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC); - if (rc) - printk("SPL: Failed user helper '%s %s %s', rc = %d\n", - argv[0], argv[1], argv[2], rc); - - return rc; -} - uint32_t zone_get_hostid(void *zone) { static int first = 1; - unsigned long hostid; - int rc; /* Only the global zone is supported */ ASSERT(zone == NULL); @@ -559,21 +521,16 @@ /* * Get the hostid if it was not passed as a module parameter. - * Try reading the /etc/hostid file directly, and then fall - * back to calling the /usr/bin/hostid utility. + * Try reading the /etc/hostid file directly. */ - if ((spl_hostid == HW_INVALID_HOSTID) && - (rc = hostid_read()) && (rc = hostid_exec())) - return HW_INVALID_HOSTID; + if (hostid_read()) + spl_hostid = 0; printk(KERN_NOTICE "SPL: using hostid 0x%08x\n", (unsigned int) spl_hostid); } - if (ddi_strtoul(hw_serial, NULL, HW_HOSTID_LEN-1, &hostid) != 0) - return HW_INVALID_HOSTID; - - return (uint32_t)hostid; + return spl_hostid; } EXPORT_SYMBOL(zone_get_hostid); @@ -759,3 +716,4 @@ MODULE_AUTHOR("Lawrence Livermore National Labs"); MODULE_DESCRIPTION("Solaris Porting Layer"); MODULE_LICENSE("GPL"); +MODULE_VERSION(SPL_META_VERSION "-" SPL_META_RELEASE); diff -Nru spl-linux-0.6.2/module/spl/spl-kmem.c spl-linux-0.6.3/module/spl/spl-kmem.c --- spl-linux-0.6.2/module/spl/spl-kmem.c 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/module/spl/spl-kmem.c 2014-06-12 18:32:38.000000000 +0000 @@ -34,19 +34,63 @@ #define SS_DEBUG_SUBSYS SS_KMEM /* + * Within the scope of spl-kmem.c file the kmem_cache_* definitions + * are removed to allow access to the real Linux slab allocator. + */ +#undef kmem_cache_destroy +#undef kmem_cache_create +#undef kmem_cache_alloc +#undef kmem_cache_free + + +/* * Cache expiration was implemented because it was part of the default Solaris * kmem_cache behavior. The idea is that per-cpu objects which haven't been * accessed in several seconds should be returned to the cache. On the other * hand Linux slabs never move objects back to the slabs unless there is - * memory pressure on the system. By default both methods are disabled, but - * may be enabled by setting KMC_EXPIRE_AGE or KMC_EXPIRE_MEM. + * memory pressure on the system. By default the Linux method is enabled + * because it has been shown to improve responsiveness on low memory systems. + * This policy may be changed by setting KMC_EXPIRE_AGE or KMC_EXPIRE_MEM. */ -unsigned int spl_kmem_cache_expire = 0; +unsigned int spl_kmem_cache_expire = KMC_EXPIRE_MEM; EXPORT_SYMBOL(spl_kmem_cache_expire); module_param(spl_kmem_cache_expire, uint, 0644); MODULE_PARM_DESC(spl_kmem_cache_expire, "By age (0x1) or low memory (0x2)"); /* + * KMC_RECLAIM_ONCE is set as the default until zfsonlinux/spl#268 is + * definitively resolved. Depending on the system configuration and + * workload this may increase the likelihood of out of memory events. + * For those cases it is advised that this option be set to zero. + */ +unsigned int spl_kmem_cache_reclaim = KMC_RECLAIM_ONCE; +module_param(spl_kmem_cache_reclaim, uint, 0644); +MODULE_PARM_DESC(spl_kmem_cache_reclaim, "Single reclaim pass (0x1)"); + +unsigned int spl_kmem_cache_obj_per_slab = SPL_KMEM_CACHE_OBJ_PER_SLAB; +module_param(spl_kmem_cache_obj_per_slab, uint, 0644); +MODULE_PARM_DESC(spl_kmem_cache_obj_per_slab, "Number of objects per slab"); + +unsigned int spl_kmem_cache_obj_per_slab_min = SPL_KMEM_CACHE_OBJ_PER_SLAB_MIN; +module_param(spl_kmem_cache_obj_per_slab_min, uint, 0644); +MODULE_PARM_DESC(spl_kmem_cache_obj_per_slab_min, + "Minimal number of objects per slab"); + +unsigned int spl_kmem_cache_max_size = 32; +module_param(spl_kmem_cache_max_size, uint, 0644); +MODULE_PARM_DESC(spl_kmem_cache_max_size, "Maximum size of slab in MB"); + +unsigned int spl_kmem_cache_slab_limit = 0; +module_param(spl_kmem_cache_slab_limit, uint, 0644); +MODULE_PARM_DESC(spl_kmem_cache_slab_limit, + "Objects less than N bytes use the Linux slab"); + +unsigned int spl_kmem_cache_kmem_limit = (PAGE_SIZE / 4); +module_param(spl_kmem_cache_kmem_limit, uint, 0644); +MODULE_PARM_DESC(spl_kmem_cache_kmem_limit, + "Objects less than N bytes use the kmalloc"); + +/* * The minimum amount of memory measured in pages to be free at all * times on the system. This is similar to Linux's zone->pages_min * multiplied by the number of zones and is sized based on that. @@ -850,7 +894,8 @@ ASSERT(ISP2(size)); if (skc->skc_flags & KMC_KMEM) - ptr = (void *)__get_free_pages(flags, get_order(size)); + ptr = (void *)__get_free_pages(flags | __GFP_COMP, + get_order(size)); else ptr = __vmalloc(size, flags | __GFP_HIGHMEM, PAGE_KERNEL); @@ -1333,7 +1378,10 @@ return; atomic_inc(&skc->skc_ref); - spl_on_each_cpu(spl_magazine_age, skc, 1); + + if (!(skc->skc_flags & KMC_NOMAGAZINE)) + spl_on_each_cpu(spl_magazine_age, skc, 1); + spl_slab_reclaim(skc, skc->skc_reap, 0); while (!test_bit(KMC_BIT_DESTROY, &skc->skc_flags) && !id) { @@ -1355,10 +1403,10 @@ /* * Size a slab based on the size of each aligned object plus spl_kmem_obj_t. - * When on-slab we want to target SPL_KMEM_CACHE_OBJ_PER_SLAB. However, + * When on-slab we want to target spl_kmem_cache_obj_per_slab. However, * for very small objects we may end up with more than this so as not * to waste space in the minimal allocation of a single page. Also for - * very large objects we may use as few as SPL_KMEM_CACHE_OBJ_PER_SLAB_MIN, + * very large objects we may use as few as spl_kmem_cache_obj_per_slab_min, * lower than this and we will fail. */ static int @@ -1367,7 +1415,7 @@ uint32_t sks_size, obj_size, max_size; if (skc->skc_flags & KMC_OFFSLAB) { - *objs = SPL_KMEM_CACHE_OBJ_PER_SLAB; + *objs = spl_kmem_cache_obj_per_slab; *size = P2ROUNDUP(sizeof(spl_kmem_slab_t), PAGE_SIZE); SRETURN(0); } else { @@ -1377,12 +1425,12 @@ if (skc->skc_flags & KMC_KMEM) max_size = ((uint32_t)1 << (MAX_ORDER-3)) * PAGE_SIZE; else - max_size = (32 * 1024 * 1024); + max_size = (spl_kmem_cache_max_size * 1024 * 1024); /* Power of two sized slab */ for (*size = PAGE_SIZE; *size <= max_size; *size *= 2) { *objs = (*size - sks_size) / obj_size; - if (*objs >= SPL_KMEM_CACHE_OBJ_PER_SLAB) + if (*objs >= spl_kmem_cache_obj_per_slab) SRETURN(0); } @@ -1393,7 +1441,7 @@ */ *size = max_size; *objs = (*size - sks_size) / obj_size; - if (*objs >= SPL_KMEM_CACHE_OBJ_PER_SLAB_MIN) + if (*objs >= (spl_kmem_cache_obj_per_slab_min)) SRETURN(0); } @@ -1478,6 +1526,9 @@ int i; SENTRY; + if (skc->skc_flags & KMC_NOMAGAZINE) + SRETURN(0); + skc->skc_mag_size = spl_magazine_size(skc); skc->skc_mag_refill = (skc->skc_mag_size + 1) / 2; @@ -1504,6 +1555,11 @@ int i; SENTRY; + if (skc->skc_flags & KMC_NOMAGAZINE) { + SEXIT; + return; + } + for_each_online_cpu(i) { skm = skc->skc_mag[i]; spl_cache_flush(skc, skm, skm->skm_avail); @@ -1526,11 +1582,12 @@ * flags * KMC_NOTOUCH Disable cache object aging (unsupported) * KMC_NODEBUG Disable debugging (unsupported) - * KMC_NOMAGAZINE Disable magazine (unsupported) * KMC_NOHASH Disable hashing (unsupported) * KMC_QCACHE Disable qcache (unsupported) + * KMC_NOMAGAZINE Enabled for kmem/vmem, Disabled for Linux slab * KMC_KMEM Force kmem backed cache * KMC_VMEM Force vmem backed cache + * KMC_SLAB Force Linux slab backed cache * KMC_OFFSLAB Locate objects off the slab */ spl_kmem_cache_t * @@ -1576,6 +1633,7 @@ skc->skc_reclaim = reclaim; skc->skc_private = priv; skc->skc_vmp = vmp; + skc->skc_linux_cache = NULL; skc->skc_flags = flags; skc->skc_obj_size = size; skc->skc_obj_align = SPL_KMEM_CACHE_ALIGN; @@ -1602,28 +1660,69 @@ skc->skc_obj_emergency = 0; skc->skc_obj_emergency_max = 0; + /* + * Verify the requested alignment restriction is sane. + */ if (align) { VERIFY(ISP2(align)); - VERIFY3U(align, >=, SPL_KMEM_CACHE_ALIGN); /* Min alignment */ - VERIFY3U(align, <=, PAGE_SIZE); /* Max alignment */ + VERIFY3U(align, >=, SPL_KMEM_CACHE_ALIGN); + VERIFY3U(align, <=, PAGE_SIZE); skc->skc_obj_align = align; } - /* If none passed select a cache type based on object size */ - if (!(skc->skc_flags & (KMC_KMEM | KMC_VMEM))) { - if (spl_obj_size(skc) < (PAGE_SIZE / 8)) + /* + * When no specific type of slab is requested (kmem, vmem, or + * linuxslab) then select a cache type based on the object size + * and default tunables. + */ + if (!(skc->skc_flags & (KMC_KMEM | KMC_VMEM | KMC_SLAB))) { + + /* + * Objects smaller than spl_kmem_cache_slab_limit can + * use the Linux slab for better space-efficiency. By + * default this functionality is disabled until its + * performance characters are fully understood. + */ + if (spl_kmem_cache_slab_limit && + size <= (size_t)spl_kmem_cache_slab_limit) + skc->skc_flags |= KMC_SLAB; + + /* + * Small objects, less than spl_kmem_cache_kmem_limit per + * object should use kmem because their slabs are small. + */ + else if (spl_obj_size(skc) <= spl_kmem_cache_kmem_limit) skc->skc_flags |= KMC_KMEM; + + /* + * All other objects are considered large and are placed + * on vmem backed slabs. + */ else skc->skc_flags |= KMC_VMEM; } - rc = spl_slab_size(skc, &skc->skc_slab_objs, &skc->skc_slab_size); - if (rc) - SGOTO(out, rc); - - rc = spl_magazine_create(skc); - if (rc) - SGOTO(out, rc); + /* + * Given the type of slab allocate the required resources. + */ + if (skc->skc_flags & (KMC_KMEM | KMC_VMEM)) { + rc = spl_slab_size(skc, + &skc->skc_slab_objs, &skc->skc_slab_size); + if (rc) + SGOTO(out, rc); + + rc = spl_magazine_create(skc); + if (rc) + SGOTO(out, rc); + } else { + skc->skc_linux_cache = kmem_cache_create( + skc->skc_name, size, align, 0, NULL); + if (skc->skc_linux_cache == NULL) + SGOTO(out, rc = ENOMEM); + + kmem_cache_set_allocflags(skc, __GFP_COMP); + skc->skc_flags |= KMC_NOMAGAZINE; + } if (spl_kmem_cache_expire & KMC_EXPIRE_AGE) skc->skc_taskqid = taskq_dispatch_delay(spl_kmem_cache_taskq, @@ -1665,6 +1764,7 @@ SENTRY; ASSERT(skc->skc_magic == SKC_MAGIC); + ASSERT(skc->skc_flags & (KMC_KMEM | KMC_VMEM | KMC_SLAB)); down_write(&spl_kmem_cache_sem); list_del_init(&skc->skc_list); @@ -1684,8 +1784,14 @@ * cache reaping action which races with this destroy. */ wait_event(wq, atomic_read(&skc->skc_ref) == 0); - spl_magazine_destroy(skc); - spl_slab_reclaim(skc, 0, 1); + if (skc->skc_flags & (KMC_KMEM | KMC_VMEM)) { + spl_magazine_destroy(skc); + spl_slab_reclaim(skc, 0, 1); + } else { + ASSERT(skc->skc_flags & KMC_SLAB); + kmem_cache_destroy(skc->skc_linux_cache); + } + spin_lock(&skc->skc_lock); /* Validate there are no objects in use and free all the @@ -1791,7 +1897,9 @@ } /* - * No available objects on any slabs, create a new slab. + * No available objects on any slabs, create a new slab. Note that this + * functionality is disabled for KMC_SLAB caches which are backed by the + * Linux slab. */ static int spl_cache_grow(spl_kmem_cache_t *skc, int flags, void **obj) @@ -1800,6 +1908,7 @@ SENTRY; ASSERT(skc->skc_magic == SKC_MAGIC); + ASSERT((skc->skc_flags & KMC_SLAB) == 0); might_sleep(); *obj = NULL; @@ -1995,15 +2104,35 @@ spl_kmem_cache_alloc(spl_kmem_cache_t *skc, int flags) { spl_kmem_magazine_t *skm; - unsigned long irq_flags; void *obj = NULL; SENTRY; ASSERT(skc->skc_magic == SKC_MAGIC); ASSERT(!test_bit(KMC_BIT_DESTROY, &skc->skc_flags)); ASSERT(flags & KM_SLEEP); + atomic_inc(&skc->skc_ref); - local_irq_save(irq_flags); + + /* + * Allocate directly from a Linux slab. All optimizations are left + * to the underlying cache we only need to guarantee that KM_SLEEP + * callers will never fail. + */ + if (skc->skc_flags & KMC_SLAB) { + struct kmem_cache *slc = skc->skc_linux_cache; + + do { + obj = kmem_cache_alloc(slc, flags | __GFP_COMP); + if (obj && skc->skc_ctor) + skc->skc_ctor(obj, skc->skc_private, flags); + + } while ((obj == NULL) && !(flags & KM_NOSLEEP)); + + atomic_dec(&skc->skc_ref); + SRETURN(obj); + } + + local_irq_disable(); restart: /* Safe to update per-cpu structure without lock, but @@ -2025,7 +2154,7 @@ SGOTO(restart, obj = NULL); } - local_irq_restore(irq_flags); + local_irq_enable(); ASSERT(obj); ASSERT(IS_P2ALIGNED(obj, skc->skc_obj_align)); @@ -2055,6 +2184,17 @@ atomic_inc(&skc->skc_ref); /* + * Free the object from the Linux underlying Linux slab. + */ + if (skc->skc_flags & KMC_SLAB) { + if (skc->skc_dtor) + skc->skc_dtor(obj, skc->skc_private); + + kmem_cache_free(skc->skc_linux_cache, obj); + goto out; + } + + /* * Only virtual slabs may have emergency objects and these objects * are guaranteed to have physical addresses. They must be removed * from the tree of emergency objects and the freed. @@ -2105,7 +2245,7 @@ struct shrink_control *sc) { spl_kmem_cache_t *skc; - int unused = 0; + int alloc = 0; down_read(&spl_kmem_cache_sem); list_for_each_entry(skc, &spl_kmem_cache_list, skc_list) { @@ -2114,24 +2254,25 @@ MAX(sc->nr_to_scan >> fls64(skc->skc_slab_objs), 1)); /* - * Presume everything alloc'ed in reclaimable, this ensures + * Presume everything alloc'ed is reclaimable, this ensures * we are called again with nr_to_scan > 0 so can try and * reclaim. The exact number is not important either so * we forgo taking this already highly contented lock. */ - unused += skc->skc_obj_alloc; + alloc += skc->skc_obj_alloc; } up_read(&spl_kmem_cache_sem); /* - * After performing reclaim always return -1 to indicate we cannot - * perform additional reclaim. This prevents shrink_slabs() from - * repeatedly invoking this generic shrinker and potentially spinning. + * When KMC_RECLAIM_ONCE is set allow only a single reclaim pass. + * This functionality only exists to work around a rare issue where + * shrink_slabs() is repeatedly invoked by many cores causing the + * system to thrash. */ - if (sc->nr_to_scan) - return -1; + if ((spl_kmem_cache_reclaim & KMC_RECLAIM_ONCE) && sc->nr_to_scan) + return (-1); - return unused; + return MAX((alloc * sysctl_vfs_cache_pressure) / 100, 0); } SPL_SHRINKER_CALLBACK_WRAPPER(spl_kmem_cache_generic_shrinker); @@ -2152,13 +2293,27 @@ ASSERT(skc->skc_magic == SKC_MAGIC); ASSERT(!test_bit(KMC_BIT_DESTROY, &skc->skc_flags)); - /* Prevent concurrent cache reaping when contended */ - if (test_and_set_bit(KMC_BIT_REAPING, &skc->skc_flags)) { - SEXIT; - return; + atomic_inc(&skc->skc_ref); + + /* + * Execute the registered reclaim callback if it exists. The + * per-cpu caches will be drained when is set KMC_EXPIRE_MEM. + */ + if (skc->skc_flags & KMC_SLAB) { + if (skc->skc_reclaim) + skc->skc_reclaim(skc->skc_private); + + if (spl_kmem_cache_expire & KMC_EXPIRE_MEM) + kmem_cache_shrink(skc->skc_linux_cache); + + SGOTO(out, 0); } - atomic_inc(&skc->skc_ref); + /* + * Prevent concurrent cache reaping when contended. + */ + if (test_and_set_bit(KMC_BIT_REAPING, &skc->skc_flags)) + SGOTO(out, 0); /* * When a reclaim function is available it may be invoked repeatedly @@ -2208,7 +2363,7 @@ clear_bit(KMC_BIT_REAPING, &skc->skc_flags); smp_mb__after_clear_bit(); wake_up_bit(&skc->skc_flags, KMC_BIT_REAPING); - +out: atomic_dec(&skc->skc_ref); SEXIT; diff -Nru spl-linux-0.6.2/module/spl/spl-kstat.c spl-linux-0.6.3/module/spl/spl-kstat.c --- spl-linux-0.6.2/module/spl/spl-kstat.c 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/module/spl/spl-kstat.c 2014-06-12 18:32:38.000000000 +0000 @@ -41,10 +41,91 @@ static struct list_head kstat_module_list; static kid_t kstat_id; -static void +static int +kstat_resize_raw(kstat_t *ksp) +{ + if (ksp->ks_raw_bufsize == KSTAT_RAW_MAX) + return ENOMEM; + + vmem_free(ksp->ks_raw_buf, ksp->ks_raw_bufsize); + ksp->ks_raw_bufsize = MIN(ksp->ks_raw_bufsize * 2, KSTAT_RAW_MAX); + ksp->ks_raw_buf = vmem_alloc(ksp->ks_raw_bufsize, KM_SLEEP); + + return 0; +} + +void +kstat_waitq_enter(kstat_io_t *kiop) +{ + hrtime_t new, delta; + ulong_t wcnt; + + new = gethrtime(); + delta = new - kiop->wlastupdate; + kiop->wlastupdate = new; + wcnt = kiop->wcnt++; + if (wcnt != 0) { + kiop->wlentime += delta * wcnt; + kiop->wtime += delta; + } +} +EXPORT_SYMBOL(kstat_waitq_enter); + +void +kstat_waitq_exit(kstat_io_t *kiop) +{ + hrtime_t new, delta; + ulong_t wcnt; + + new = gethrtime(); + delta = new - kiop->wlastupdate; + kiop->wlastupdate = new; + wcnt = kiop->wcnt--; + ASSERT((int)wcnt > 0); + kiop->wlentime += delta * wcnt; + kiop->wtime += delta; +} +EXPORT_SYMBOL(kstat_waitq_exit); + +void +kstat_runq_enter(kstat_io_t *kiop) +{ + hrtime_t new, delta; + ulong_t rcnt; + + new = gethrtime(); + delta = new - kiop->rlastupdate; + kiop->rlastupdate = new; + rcnt = kiop->rcnt++; + if (rcnt != 0) { + kiop->rlentime += delta * rcnt; + kiop->rtime += delta; + } +} +EXPORT_SYMBOL(kstat_runq_enter); + +void +kstat_runq_exit(kstat_io_t *kiop) +{ + hrtime_t new, delta; + ulong_t rcnt; + + new = gethrtime(); + delta = new - kiop->rlastupdate; + kiop->rlastupdate = new; + rcnt = kiop->rcnt--; + ASSERT((int)rcnt > 0); + kiop->rlentime += delta * rcnt; + kiop->rtime += delta; +} +EXPORT_SYMBOL(kstat_runq_exit); + +static int kstat_seq_show_headers(struct seq_file *f) { kstat_t *ksp = (kstat_t *)f->private; + int rc = 0; + ASSERT(ksp->ks_magic == KS_MAGIC); seq_printf(f, "%d %d 0x%02x %d %d %lld %lld\n", @@ -54,7 +135,17 @@ switch (ksp->ks_type) { case KSTAT_TYPE_RAW: - seq_printf(f, "raw data"); +restart: + if (ksp->ks_raw_ops.headers) { + rc = ksp->ks_raw_ops.headers( + ksp->ks_raw_buf, ksp->ks_raw_bufsize); + if (rc == ENOMEM && !kstat_resize_raw(ksp)) + goto restart; + if (!rc) + seq_puts(f, ksp->ks_raw_buf); + } else { + seq_printf(f, "raw data\n"); + } break; case KSTAT_TYPE_NAMED: seq_printf(f, "%-31s %-4s %s\n", @@ -81,17 +172,11 @@ "name", "events", "elapsed", "min", "max", "start", "stop"); break; - case KSTAT_TYPE_TXG: - seq_printf(f, - "%-8s %-5s %-13s %-12s %-12s %-8s %-8s " - "%-12s %-12s %-12s\n", - "txg", "state", "birth", - "nread", "nwritten", "reads", "writes", - "otime", "qtime", "stime"); - break; default: PANIC("Undefined kstat type %d\n", ksp->ks_type); } + + return -rc; } static int @@ -202,27 +287,6 @@ } static int -kstat_seq_show_txg(struct seq_file *f, kstat_txg_t *ktp) -{ - char state; - - switch (ktp->state) { - case TXG_STATE_OPEN: state = 'O'; break; - case TXG_STATE_QUIESCING: state = 'Q'; break; - case TXG_STATE_SYNCING: state = 'S'; break; - case TXG_STATE_COMMITTED: state = 'C'; break; - default: state = '?'; break; - } - - seq_printf(f, - "%-8llu %-5c %-13llu %-12llu %-12llu %-8u %-8u " - "%12lld %12lld %12lld\n", ktp->txg, state, ktp->birth, - ktp->nread, ktp->nwritten, ktp->reads, ktp->writes, - ktp->open_time, ktp->quiesce_time, ktp->sync_time); - return 0; -} - -static int kstat_seq_show(struct seq_file *f, void *p) { kstat_t *ksp = (kstat_t *)f->private; @@ -232,9 +296,19 @@ switch (ksp->ks_type) { case KSTAT_TYPE_RAW: - ASSERT(ksp->ks_ndata == 1); - rc = kstat_seq_show_raw(f, ksp->ks_data, - ksp->ks_data_size); +restart: + if (ksp->ks_raw_ops.data) { + rc = ksp->ks_raw_ops.data( + ksp->ks_raw_buf, ksp->ks_raw_bufsize, p); + if (rc == ENOMEM && !kstat_resize_raw(ksp)) + goto restart; + if (!rc) + seq_puts(f, ksp->ks_raw_buf); + } else { + ASSERT(ksp->ks_ndata == 1); + rc = kstat_seq_show_raw(f, ksp->ks_data, + ksp->ks_data_size); + } break; case KSTAT_TYPE_NAMED: rc = kstat_seq_show_named(f, (kstat_named_t *)p); @@ -248,20 +322,21 @@ case KSTAT_TYPE_TIMER: rc = kstat_seq_show_timer(f, (kstat_timer_t *)p); break; - case KSTAT_TYPE_TXG: - rc = kstat_seq_show_txg(f, (kstat_txg_t *)p); - break; default: PANIC("Undefined kstat type %d\n", ksp->ks_type); } - return rc; + return -rc; } int kstat_default_update(kstat_t *ksp, int rw) { ASSERT(ksp != NULL); + + if (rw == KSTAT_WRITE) + return (EACCES); + return 0; } @@ -273,7 +348,10 @@ switch (ksp->ks_type) { case KSTAT_TYPE_RAW: - rc = ksp->ks_data; + if (ksp->ks_raw_ops.addr) + rc = ksp->ks_raw_ops.addr(ksp, n); + else + rc = ksp->ks_data; break; case KSTAT_TYPE_NAMED: rc = ksp->ks_data + n * sizeof(kstat_named_t); @@ -287,9 +365,6 @@ case KSTAT_TYPE_TIMER: rc = ksp->ks_data + n * sizeof(kstat_timer_t); break; - case KSTAT_TYPE_TXG: - rc = ksp->ks_data + n * sizeof(kstat_txg_t); - break; default: PANIC("Undefined kstat type %d\n", ksp->ks_type); } @@ -305,15 +380,20 @@ ASSERT(ksp->ks_magic == KS_MAGIC); SENTRY; - mutex_enter(&ksp->ks_lock); + mutex_enter(ksp->ks_lock); + + if (ksp->ks_type == KSTAT_TYPE_RAW) { + ksp->ks_raw_bufsize = PAGE_SIZE; + ksp->ks_raw_buf = vmem_alloc(ksp->ks_raw_bufsize, KM_SLEEP); + } /* Dynamically update kstat, on error existing kstats are used */ (void) ksp->ks_update(ksp, KSTAT_READ); ksp->ks_snaptime = gethrtime(); - if (!n) - kstat_seq_show_headers(f); + if (!n && kstat_seq_show_headers(f)) + SRETURN(NULL); if (n >= ksp->ks_ndata) SRETURN(NULL); @@ -338,10 +418,13 @@ static void kstat_seq_stop(struct seq_file *f, void *v) { - kstat_t *ksp = (kstat_t *)f->private; - ASSERT(ksp->ks_magic == KS_MAGIC); + kstat_t *ksp = (kstat_t *)f->private; + ASSERT(ksp->ks_magic == KS_MAGIC); + + if (ksp->ks_type == KSTAT_TYPE_RAW) + vmem_free(ksp->ks_raw_buf, ksp->ks_raw_bufsize); - mutex_exit(&ksp->ks_lock); + mutex_exit(ksp->ks_lock); } static struct seq_operations kstat_seq_ops = { @@ -408,13 +491,47 @@ return rc; } +static ssize_t +proc_kstat_write(struct file *filp, const char __user *buf, + size_t len, loff_t *ppos) +{ + struct seq_file *f = filp->private_data; + kstat_t *ksp = f->private; + int rc; + + ASSERT(ksp->ks_magic == KS_MAGIC); + + mutex_enter(ksp->ks_lock); + rc = ksp->ks_update(ksp, KSTAT_WRITE); + mutex_exit(ksp->ks_lock); + + if (rc) + return (-rc); + + *ppos += len; + return (len); +} + static struct file_operations proc_kstat_operations = { - .open = proc_kstat_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, + .open = proc_kstat_open, + .write = proc_kstat_write, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, }; +void +__kstat_set_raw_ops(kstat_t *ksp, + int (*headers)(char *buf, size_t size), + int (*data)(char *buf, size_t size, void *data), + void *(*addr)(kstat_t *ksp, loff_t index)) +{ + ksp->ks_raw_ops.headers = headers; + ksp->ks_raw_ops.data = data; + ksp->ks_raw_ops.addr = addr; +} +EXPORT_SYMBOL(__kstat_set_raw_ops); + kstat_t * __kstat_create(const char *ks_module, int ks_instance, const char *ks_name, const char *ks_class, uchar_t ks_type, uint_t ks_ndata, @@ -440,7 +557,8 @@ mutex_exit(&kstat_module_lock); ksp->ks_magic = KS_MAGIC; - mutex_init(&ksp->ks_lock, NULL, MUTEX_DEFAULT, NULL); + mutex_init(&ksp->ks_private_lock, NULL, MUTEX_DEFAULT, NULL); + ksp->ks_lock = &ksp->ks_private_lock; INIT_LIST_HEAD(&ksp->ks_list); ksp->ks_crtime = gethrtime(); @@ -453,6 +571,11 @@ ksp->ks_flags = ks_flags; ksp->ks_update = kstat_default_update; ksp->ks_private = NULL; + ksp->ks_raw_ops.headers = NULL; + ksp->ks_raw_ops.data = NULL; + ksp->ks_raw_ops.addr = NULL; + ksp->ks_raw_buf = NULL; + ksp->ks_raw_bufsize = 0; switch (ksp->ks_type) { case KSTAT_TYPE_RAW: @@ -475,10 +598,6 @@ ksp->ks_ndata = ks_ndata; ksp->ks_data_size = ks_ndata * sizeof(kstat_timer_t); break; - case KSTAT_TYPE_TXG: - ksp->ks_ndata = ks_ndata; - ksp->ks_data_size = ks_ndata * sizeof(kstat_timer_t); - break; default: PANIC("Undefined kstat type %d\n", ksp->ks_type); } @@ -486,7 +605,7 @@ if (ksp->ks_flags & KSTAT_FLAG_VIRTUAL) { ksp->ks_data = NULL; } else { - ksp->ks_data = kmem_alloc(ksp->ks_data_size, KM_SLEEP); + ksp->ks_data = kmem_zalloc(ksp->ks_data_size, KM_SLEEP); if (ksp->ks_data == NULL) { kmem_free(ksp, sizeof(*ksp)); ksp = NULL; @@ -524,16 +643,16 @@ list_add_tail(&ksp->ks_list, &module->ksm_kstat_list); - mutex_enter(&ksp->ks_lock); + mutex_enter(ksp->ks_lock); ksp->ks_owner = module; - ksp->ks_proc = proc_create_data(ksp->ks_name, 0444, + ksp->ks_proc = proc_create_data(ksp->ks_name, 0644, module->ksm_proc, &proc_kstat_operations, (void *)ksp); if (ksp->ks_proc == NULL) { list_del_init(&ksp->ks_list); if (list_empty(&module->ksm_kstat_list)) kstat_delete_module(module); } - mutex_exit(&ksp->ks_lock); + mutex_exit(ksp->ks_lock); out: mutex_exit(&kstat_module_lock); } @@ -559,7 +678,8 @@ if (!(ksp->ks_flags & KSTAT_FLAG_VIRTUAL)) kmem_free(ksp->ks_data, ksp->ks_data_size); - mutex_destroy(&ksp->ks_lock); + ksp->ks_lock = NULL; + mutex_destroy(&ksp->ks_private_lock); kmem_free(ksp, sizeof(*ksp)); return; diff -Nru spl-linux-0.6.2/module/spl/spl-proc.c spl-linux-0.6.3/module/spl/spl-proc.c --- spl-linux-0.6.2/module/spl/spl-proc.c 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/module/spl/spl-proc.c 2014-06-12 18:32:38.000000000 +0000 @@ -72,7 +72,6 @@ #define CTL_VERSION CTL_UNNUMBERED /* Version */ #define CTL_HOSTID CTL_UNNUMBERED /* Host id by /usr/bin/hostid */ -#define CTL_HW_SERIAL CTL_UNNUMBERED /* HW serial number by hostid */ #define CTL_KALLSYMS CTL_UNNUMBERED /* kallsyms_lookup_name addr */ #define CTL_DEBUG_SUBSYS CTL_UNNUMBERED /* Debug subsystem */ @@ -129,7 +128,6 @@ enum { CTL_VERSION = 1, /* Version */ CTL_HOSTID, /* Host id reported by /usr/bin/hostid */ - CTL_HW_SERIAL, /* Hardware serial number from hostid */ CTL_KALLSYMS, /* Address of kallsyms_lookup_name */ #ifdef DEBUG_LOG @@ -513,9 +511,6 @@ if (str == end) SRETURN(-EINVAL); - (void) snprintf(hw_serial, HW_HOSTID_LEN, "%lu", spl_hostid); - hw_serial[HW_HOSTID_LEN - 1] = '\0'; - *ppos += *lenp; } else { len = snprintf(str, sizeof(str), "%lx", spl_hostid); if (*ppos >= len) @@ -651,6 +646,12 @@ ASSERT(skc->skc_magic == SKC_MAGIC); + /* + * Backed by Linux slab see /proc/slabinfo. + */ + if (skc->skc_flags & KMC_SLAB) + return (0); + spin_lock(&skc->skc_lock); seq_printf(f, "%-36s ", skc->skc_name); seq_printf(f, "0x%05lx %9lu %9lu %8u %8u " @@ -1058,14 +1059,6 @@ .mode = 0644, .proc_handler = &proc_dohostid, }, - { - CTL_NAME (CTL_HW_SERIAL) - .procname = "hw_serial", - .data = hw_serial, - .maxlen = sizeof(hw_serial), - .mode = 0444, - .proc_handler = &proc_dostring, - }, #ifndef HAVE_KALLSYMS_LOOKUP_NAME { CTL_NAME (CTL_KALLSYMS) diff -Nru spl-linux-0.6.2/module/spl/spl-taskq.c spl-linux-0.6.3/module/spl/spl-taskq.c --- spl-linux-0.6.2/module/spl/spl-taskq.c 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/module/spl/spl-taskq.c 2014-06-12 18:32:38.000000000 +0000 @@ -34,6 +34,10 @@ #define SS_DEBUG_SUBSYS SS_TASKQ +int spl_taskq_thread_bind = 0; +module_param(spl_taskq_thread_bind, int, 0644); +MODULE_PARM_DESC(spl_taskq_thread_bind, "Bind taskq thread to CPU by default"); + /* Global system-wide dynamic task queue available for all consumers */ taskq_t *system_taskq; EXPORT_SYMBOL(system_taskq); @@ -781,6 +785,7 @@ taskq_create(const char *name, int nthreads, pri_t pri, int minalloc, int maxalloc, uint_t flags) { + static int last_used_cpu = 0; taskq_t *tq; taskq_thread_t *tqt; int rc = 0, i, j = 0; @@ -839,11 +844,14 @@ tqt->tqt_tq = tq; tqt->tqt_id = 0; - tqt->tqt_thread = kthread_create(taskq_thread, tqt, + tqt->tqt_thread = spl_kthread_create(taskq_thread, tqt, "%s/%d", name, i); if (tqt->tqt_thread) { list_add(&tqt->tqt_thread_list, &tq->tq_thread_list); - kthread_bind(tqt->tqt_thread, i % num_online_cpus()); + if (spl_taskq_thread_bind) { + last_used_cpu = (last_used_cpu + 1) % num_online_cpus(); + kthread_bind(tqt->tqt_thread, last_used_cpu); + } set_user_nice(tqt->tqt_thread, PRIO_TO_NICE(pri)); wake_up_process(tqt->tqt_thread); j++; diff -Nru spl-linux-0.6.2/module/spl/spl-thread.c spl-linux-0.6.3/module/spl/spl-thread.c --- spl-linux-0.6.2/module/spl/spl-thread.c 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/module/spl/spl-thread.c 2014-06-12 18:32:38.000000000 +0000 @@ -126,7 +126,7 @@ tp->tp_state = state; tp->tp_pri = pri; - tsk = kthread_create(thread_generic_wrapper, (void *)tp, + tsk = spl_kthread_create(thread_generic_wrapper, (void *)tp, "%s", tp->tp_name); if (IS_ERR(tsk)) { SERROR("Failed to create thread: %ld\n", PTR_ERR(tsk)); @@ -137,3 +137,34 @@ SRETURN((kthread_t *)tsk); } EXPORT_SYMBOL(__thread_create); + +/* + * spl_kthread_create - Wrapper providing pre-3.13 semantics for + * kthread_create() in which it is not killable and less likely + * to return -ENOMEM. + */ +struct task_struct * +spl_kthread_create(int (*func)(void *), void *data, const char namefmt[], ...) +{ + struct task_struct *tsk; + va_list args; + char name[TASK_COMM_LEN]; + + va_start(args, namefmt); + vsnprintf(name, sizeof(name), namefmt, args); + va_end(args); + do { + tsk = kthread_create(func, data, "%s", name); + if (IS_ERR(tsk)) { + if (signal_pending(current)) { + clear_thread_flag(TIF_SIGPENDING); + continue; + } + if (PTR_ERR(tsk) == -ENOMEM) + continue; + return (NULL); + } else + return (tsk); + } while (1); +} +EXPORT_SYMBOL(spl_kthread_create); diff -Nru spl-linux-0.6.2/module/spl/spl-time.c spl-linux-0.6.3/module/spl/spl-time.c --- spl-linux-0.6.2/module/spl/spl-time.c 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/module/spl/spl-time.c 2014-06-12 18:32:38.000000000 +0000 @@ -40,7 +40,9 @@ void __gethrestime(timestruc_t *ts) { - struct timespec tspec = current_kernel_time(); + struct timespec tspec; + + getnstimeofday(&tspec); ts->tv_sec = tspec.tv_sec; ts->tv_nsec = tspec.tv_nsec; diff -Nru spl-linux-0.6.2/module/spl/spl-vnode.c spl-linux-0.6.3/module/spl/spl-vnode.c --- spl-linux-0.6.2/module/spl/spl-vnode.c 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/module/spl/spl-vnode.c 2014-06-12 18:32:38.000000000 +0000 @@ -334,7 +334,11 @@ if (inode) ihold(inode); +#ifdef HAVE_2ARGS_VFS_UNLINK rc = vfs_unlink(parent.dentry->d_inode, dentry); +#else + rc = vfs_unlink(parent.dentry->d_inode, dentry, NULL); +#endif /* HAVE_2ARGS_VFS_UNLINK */ exit1: dput(dentry); } else { @@ -410,13 +414,16 @@ SGOTO(exit4, rc); } -#ifdef HAVE_4ARGS_VFS_RENAME +#if defined(HAVE_4ARGS_VFS_RENAME) + rc = vfs_rename(old_dir->d_inode, old_dentry, + new_dir->d_inode, new_dentry); +#elif defined(HAVE_5ARGS_VFS_RENAME) rc = vfs_rename(old_dir->d_inode, old_dentry, - new_dir->d_inode, new_dentry); + new_dir->d_inode, new_dentry, NULL); #else - rc = vfs_rename(old_dir->d_inode, old_dentry, oldnd.nd_mnt, - new_dir->d_inode, new_dentry, newnd.nd_mnt); -#endif /* HAVE_4ARGS_VFS_RENAME */ + rc = vfs_rename(old_dir->d_inode, old_dentry, + new_dir->d_inode, new_dentry, NULL, 0); +#endif exit4: unlock_rename(new_dir, old_dir); exit3: @@ -478,9 +485,9 @@ if (inode) atomic_inc(&inode->i_count); #ifdef HAVE_2ARGS_VFS_UNLINK - rc = vfs_unlink(nd.nd_dentry->d_inode, dentry); + rc = vfs_unlink(nd.nd_dentry->d_inode, dentry); #else - rc = vfs_unlink(nd.nd_dentry->d_inode, dentry, nd.nd_mnt); + rc = vfs_unlink(nd.nd_dentry->d_inode, dentry, NULL); #endif /* HAVE_2ARGS_VFS_UNLINK */ exit2: dput(dentry); @@ -570,13 +577,16 @@ if (new_dentry == trap) SGOTO(exit5, rc); -#ifdef HAVE_4ARGS_VFS_RENAME - rc = vfs_rename(old_dir->d_inode, old_dentry, - new_dir->d_inode, new_dentry); +#if defined(HAVE_4ARGS_VFS_RENAME) + rc = vfs_rename(old_dir->d_inode, old_dentry, + new_dir->d_inode, new_dentry); +#elif defined(HAVE_5ARGS_VFS_RENAME) + rc = vfs_rename(old_dir->d_inode, old_dentry, + new_dir->d_inode, new_dentry, NULL); #else - rc = vfs_rename(old_dir->d_inode, old_dentry, oldnd.nd_mnt, - new_dir->d_inode, new_dentry, newnd.nd_mnt); -#endif /* HAVE_4ARGS_VFS_RENAME */ + rc = vfs_rename(old_dir->d_inode, old_dentry, + new_dir->d_inode, new_dentry, NULL, 0); +#endif exit5: dput(new_dentry); exit4: diff -Nru spl-linux-0.6.2/module/splat/splat-condvar.c spl-linux-0.6.3/module/splat/splat-condvar.c --- spl-linux-0.6.2/module/splat/splat-condvar.c 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/module/splat/splat-condvar.c 2014-06-12 18:32:38.000000000 +0000 @@ -108,7 +108,7 @@ ct[i].ct_cvp = &cv; ct[i].ct_name = SPLAT_CONDVAR_TEST1_NAME; ct[i].ct_rc = 0; - ct[i].ct_thread = kthread_create(splat_condvar_test12_thread, + ct[i].ct_thread = spl_kthread_create(splat_condvar_test12_thread, &ct[i], "%s/%d", SPLAT_CONDVAR_TEST_NAME, i); if (!IS_ERR(ct[i].ct_thread)) { @@ -173,7 +173,7 @@ ct[i].ct_cvp = &cv; ct[i].ct_name = SPLAT_CONDVAR_TEST2_NAME; ct[i].ct_rc = 0; - ct[i].ct_thread = kthread_create(splat_condvar_test12_thread, + ct[i].ct_thread = spl_kthread_create(splat_condvar_test12_thread, &ct[i], "%s/%d", SPLAT_CONDVAR_TEST_NAME, i); if (!IS_ERR(ct[i].ct_thread)) { @@ -254,7 +254,7 @@ ct[i].ct_cvp = &cv; ct[i].ct_name = SPLAT_CONDVAR_TEST3_NAME; ct[i].ct_rc = 0; - ct[i].ct_thread = kthread_create(splat_condvar_test34_thread, + ct[i].ct_thread = spl_kthread_create(splat_condvar_test34_thread, &ct[i], "%s/%d", SPLAT_CONDVAR_TEST_NAME, i); if (!IS_ERR(ct[i].ct_thread)) { @@ -324,7 +324,7 @@ ct[i].ct_cvp = &cv; ct[i].ct_name = SPLAT_CONDVAR_TEST3_NAME; ct[i].ct_rc = 0; - ct[i].ct_thread = kthread_create(splat_condvar_test34_thread, + ct[i].ct_thread = spl_kthread_create(splat_condvar_test34_thread, &ct[i], "%s/%d", SPLAT_CONDVAR_TEST_NAME, i); if (!IS_ERR(ct[i].ct_thread)) { diff -Nru spl-linux-0.6.2/module/splat/splat-cred.c spl-linux-0.6.3/module/splat/splat-cred.c --- spl-linux-0.6.2/module/splat/splat-cred.c 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/module/splat/splat-cred.c 2014-06-12 18:32:38.000000000 +0000 @@ -25,6 +25,7 @@ \*****************************************************************************/ #include +#include #include "splat-internal.h" #define SPLAT_CRED_NAME "cred" @@ -166,42 +167,89 @@ } /* splat_cred_test2() */ /* - * On most/all systems it can be expected that a task with root - * permissions also is a member of the root group, Since the - * test suite is always run as root we check first that CRED() is - * a member of the root group, and secondly that it is not a member - * of our fake group. This test will break is someone happens to - * create group number NGROUPS_MAX-1 and then added root to it. + * Verify the groupmember() works correctly by constructing an interesting + * CRED() and checking that the expected gids are part of it. */ static int splat_cred_test3(struct file *file, void *arg) { - gid_t root_gid, fake_gid; - int rc; + gid_t known_gid, missing_gid, tmp_gid; + unsigned char rnd; + struct group_info *gi; + int i, rc; + + get_random_bytes((void *)&rnd, 1); + known_gid = (rnd > 0) ? rnd : 1; + missing_gid = 0; + + /* + * Create an interesting known set of gids for test purposes. The + * gids are pseudo randomly selected are will be in the range of + * 1:(NGROUPS_MAX-1). Gid 0 is explicitly avoided so we can reliably + * test for its absence in the test cases. + */ + gi = groups_alloc(NGROUPS_SMALL); + if (gi == NULL) { + splat_vprint(file, SPLAT_CRED_TEST3_NAME, "Failed create " + "group_info for known gids: %d\n", -ENOMEM); + rc = -ENOMEM; + goto show_groups; + } + + for (i = 0, tmp_gid = known_gid; i < NGROUPS_SMALL; i++) { + splat_vprint(file, SPLAT_CRED_TEST3_NAME, "Adding gid %d " + "to current CRED() (%d/%d)\n", tmp_gid, i, gi->ngroups); +#ifdef HAVE_KUIDGID_T + GROUP_AT(gi, i) = make_kgid(current_user_ns(), tmp_gid); +#else + GROUP_AT(gi, i) = tmp_gid; +#endif /* HAVE_KUIDGID_T */ + tmp_gid = ((tmp_gid * 17) % (NGROUPS_MAX - 1)) + 1; + } + + /* Set the new groups in the CRED() and release our reference. */ + rc = set_current_groups(gi); + put_group_info(gi); - root_gid = 0; - fake_gid = NGROUPS_MAX-1; + if (rc) { + splat_vprint(file, SPLAT_CRED_TEST3_NAME, "Failed to add " + "gid %d to current group: %d\n", known_gid, rc); + goto show_groups; + } - rc = groupmember(root_gid, CRED()); + /* Verify groupmember() finds the known_gid in the CRED() */ + rc = groupmember(known_gid, CRED()); if (!rc) { - splat_vprint(file, SPLAT_CRED_TEST3_NAME, - "Failed root git %d expected to be member " - "of CRED() groups: %d\n", root_gid, rc); - return -EIDRM; + splat_vprint(file, SPLAT_CRED_TEST3_NAME, "Failed to find " + "known gid %d in CRED()'s groups.\n", known_gid); + rc = -EIDRM; + goto show_groups; } - rc = groupmember(fake_gid, CRED()); + /* Verify groupmember() does NOT finds the missing gid in the CRED() */ + rc = groupmember(missing_gid, CRED()); if (rc) { - splat_vprint(file, SPLAT_CRED_TEST3_NAME, - "Failed fake git %d expected not to be member " - "of CRED() groups: %d\n", fake_gid, rc); - return -EIDRM; + splat_vprint(file, SPLAT_CRED_TEST3_NAME, "Failed missing " + "gid %d was found in CRED()'s groups.\n", missing_gid); + rc = -EIDRM; + goto show_groups; + } + + splat_vprint(file, SPLAT_CRED_TEST3_NAME, "Success groupmember() " + "correctly detects expected gids in CRED(): %d\n", rc); + +show_groups: + if (rc) { + int i, grps = crgetngroups(CRED()); + + splat_vprint(file, SPLAT_CRED_TEST3_NAME, "%d groups: ", grps); + for (i = 0; i < grps; i++) + splat_print(file, "%d ", crgetgroups(CRED())[i]); + splat_print(file, "%s", "\n"); } - splat_vprint(file, SPLAT_CRED_TEST3_NAME, "Success root gid " - "is a member of the expected groups: %d\n", rc); - return rc; + return (rc); } /* splat_cred_test3() */ splat_subsystem_t * diff -Nru spl-linux-0.6.2/module/splat/splat-ctl.c spl-linux-0.6.3/module/splat/splat-ctl.c --- spl-linux-0.6.2/module/splat/splat-ctl.c 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/module/splat/splat-ctl.c 2014-06-12 18:32:38.000000000 +0000 @@ -721,3 +721,4 @@ MODULE_AUTHOR("Lawrence Livermore National Labs"); MODULE_DESCRIPTION("Solaris Porting LAyer Tests"); MODULE_LICENSE("GPL"); +MODULE_VERSION(SPL_META_VERSION "-" SPL_META_RELEASE); diff -Nru spl-linux-0.6.2/module/splat/splat-kmem.c spl-linux-0.6.3/module/splat/splat-kmem.c --- spl-linux-0.6.2/module/splat/splat-kmem.c 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/module/splat/splat-kmem.c 2014-06-12 18:32:38.000000000 +0000 @@ -244,7 +244,7 @@ #define SPLAT_KMEM_TEST_MAGIC 0x004488CCUL #define SPLAT_KMEM_CACHE_NAME "kmem_test" #define SPLAT_KMEM_OBJ_COUNT 1024 -#define SPLAT_KMEM_OBJ_RECLAIM 1000 /* objects */ +#define SPLAT_KMEM_OBJ_RECLAIM 32 /* objects */ #define SPLAT_KMEM_THREADS 32 #define KCP_FLAG_READY 0x01 @@ -394,18 +394,25 @@ { int j; - splat_vprint(file, name, - "%s cache objects %d, slabs %u/%u objs %u/%u mags ", - kcp->kcp_cache->skc_name, kcp->kcp_count, + splat_vprint(file, name, "%s cache objects %d", + kcp->kcp_cache->skc_name, kcp->kcp_count); + + if (kcp->kcp_cache->skc_flags & (KMC_KMEM | KMC_VMEM)) { + splat_vprint(file, name, ", slabs %u/%u objs %u/%u", (unsigned)kcp->kcp_cache->skc_slab_alloc, (unsigned)kcp->kcp_cache->skc_slab_total, (unsigned)kcp->kcp_cache->skc_obj_alloc, (unsigned)kcp->kcp_cache->skc_obj_total); - for_each_online_cpu(j) - splat_print(file, "%u/%u ", - kcp->kcp_cache->skc_mag[j]->skm_avail, - kcp->kcp_cache->skc_mag[j]->skm_size); + if (!(kcp->kcp_cache->skc_flags & KMC_NOMAGAZINE)) { + splat_vprint(file, name, "%s", "mags"); + + for_each_online_cpu(j) + splat_print(file, "%u/%u ", + kcp->kcp_cache->skc_mag[j]->skm_avail, + kcp->kcp_cache->skc_mag[j]->skm_size); + } + } splat_print(file, "%s\n", ""); } @@ -682,7 +689,7 @@ goto out_kcp; } - start = current_kernel_time(); + getnstimeofday(&start); for (i = 0; i < SPLAT_KMEM_THREADS; i++) { thr = thread_create(NULL, 0, @@ -707,7 +714,7 @@ /* Sleep until all thread have finished */ wait_event(kcp->kcp_ctl_waitq, splat_kmem_cache_test_threads(kcp, 0)); - stop = current_kernel_time(); + getnstimeofday(&stop); delta = timespec_sub(stop, start); splat_vprint(file, name, @@ -895,18 +902,19 @@ goto out_kct; } - for (i = 0; i < 60; i++) { + /* Force reclaim every 1/10 a second for 60 seconds. */ + for (i = 0; i < 600; i++) { kmem_cache_reap_now(kcp->kcp_cache); splat_kmem_cache_test_debug(file, SPLAT_KMEM_TEST8_NAME, kcp); - if (kcp->kcp_cache->skc_obj_total == 0) + if (kcp->kcp_count == 0) break; set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ); + schedule_timeout(HZ / 10); } - if (kcp->kcp_cache->skc_obj_total == 0) { + if (kcp->kcp_count == 0) { splat_vprint(file, SPLAT_KMEM_TEST8_NAME, "Successfully created %d objects " "in cache %s and reclaimed them\n", @@ -914,7 +922,7 @@ } else { splat_vprint(file, SPLAT_KMEM_TEST8_NAME, "Failed to reclaim %u/%d objects from cache %s\n", - (unsigned)kcp->kcp_cache->skc_obj_total, + (unsigned)kcp->kcp_count, SPLAT_KMEM_OBJ_COUNT, SPLAT_KMEM_CACHE_NAME); rc = -ENOMEM; } @@ -994,14 +1002,14 @@ for (i = 0; i < 60; i++) { splat_kmem_cache_test_debug(file, SPLAT_KMEM_TEST9_NAME, kcp); - if (kcp->kcp_cache->skc_obj_total == 0) + if (kcp->kcp_count == 0) break; set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ); } - if (kcp->kcp_cache->skc_obj_total == 0) { + if (kcp->kcp_count == 0) { splat_vprint(file, SPLAT_KMEM_TEST9_NAME, "Successfully created %d objects " "in cache %s and reclaimed them\n", @@ -1009,7 +1017,7 @@ } else { splat_vprint(file, SPLAT_KMEM_TEST9_NAME, "Failed to reclaim %u/%d objects from cache %s\n", - (unsigned)kcp->kcp_cache->skc_obj_total, count, + (unsigned)kcp->kcp_count, count, SPLAT_KMEM_CACHE_NAME); rc = -ENOMEM; } @@ -1203,7 +1211,7 @@ kmem_cache_thread_t *kct; dummy_page_t *dp; struct list_head list; - struct timespec start, delta = { 0, 0 }; + struct timespec start, stop, delta = { 0, 0 }; int size, count, slabs, fails = 0; int i, rc = 0, max_time = 10; @@ -1250,7 +1258,7 @@ i = 0; slabs = kcp->kcp_cache->skc_slab_total; INIT_LIST_HEAD(&list); - start = current_kernel_time(); + getnstimeofday(&start); /* Apply memory pressure */ while (kcp->kcp_cache->skc_slab_total > (slabs >> 2)) { @@ -1259,7 +1267,8 @@ splat_kmem_cache_test_debug( file, SPLAT_KMEM_TEST13_NAME, kcp); - delta = timespec_sub(current_kernel_time(), start); + getnstimeofday(&stop); + delta = timespec_sub(stop, start); if (delta.tv_sec >= max_time) { splat_vprint(file, SPLAT_KMEM_TEST13_NAME, "Failed to reclaim 3/4 of cache in %ds, " @@ -1270,7 +1279,7 @@ break; } - dp = (dummy_page_t *)__get_free_page(GFP_KERNEL | __GFP_NORETRY); + dp = (dummy_page_t *)__get_free_page(GFP_KERNEL); if (!dp) { fails++; splat_vprint(file, SPLAT_KMEM_TEST13_NAME, diff -Nru spl-linux-0.6.2/module/splat/splat-rwlock.c spl-linux-0.6.3/module/splat/splat-rwlock.c --- spl-linux-0.6.2/module/splat/splat-rwlock.c 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/module/splat/splat-rwlock.c 2014-06-12 18:32:38.000000000 +0000 @@ -215,10 +215,10 @@ /* The first thread will be the writer */ if (i == 0) - rwt[i].rwt_thread = kthread_create(splat_rwlock_wr_thr, + rwt[i].rwt_thread = spl_kthread_create(splat_rwlock_wr_thr, &rwt[i], "%s/%d", SPLAT_RWLOCK_TEST_NAME, i); else - rwt[i].rwt_thread = kthread_create(splat_rwlock_rd_thr, + rwt[i].rwt_thread = spl_kthread_create(splat_rwlock_rd_thr, &rwt[i], "%s/%d", SPLAT_RWLOCK_TEST_NAME, i); if (!IS_ERR(rwt[i].rwt_thread)) { diff -Nru spl-linux-0.6.2/module/splat/splat-taskq.c spl-linux-0.6.3/module/splat/splat-taskq.c --- spl-linux-0.6.2/module/splat/splat-taskq.c 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/module/splat/splat-taskq.c 2014-06-12 18:32:38.000000000 +0000 @@ -82,7 +82,7 @@ atomic_t *count; int order[SPLAT_TASKQ_ORDER_MAX]; unsigned int depth; - unsigned long expire; + clock_t expire; taskq_t *tq; taskq_ent_t *tqe; spinlock_t lock; @@ -1140,7 +1140,7 @@ splat_taskq_arg_t *tq_arg = (splat_taskq_arg_t *)arg; ASSERT(tq_arg); - if (ddi_get_lbolt() >= tq_arg->expire) + if (ddi_time_after_eq(ddi_get_lbolt(), tq_arg->expire)) atomic_inc(tq_arg->count); kmem_free(tq_arg, sizeof(splat_taskq_arg_t)); @@ -1228,7 +1228,7 @@ splat_taskq_arg_t *tq_arg = (splat_taskq_arg_t *)arg; uint8_t rnd; - if (ddi_get_lbolt() >= tq_arg->expire) + if (ddi_time_after_eq(ddi_get_lbolt(), tq_arg->expire)) atomic_inc(tq_arg->count); /* Randomly sleep to further perturb the system */ @@ -1249,7 +1249,7 @@ int canceled = 0; int completed = 0; int blocked = 0; - unsigned long start, cancel; + clock_t start, cancel; tqas = vmalloc(sizeof(*tqas) * nr_tasks); if (tqas == NULL) @@ -1327,7 +1327,7 @@ start = ddi_get_lbolt(); i = 0; - while (ddi_get_lbolt() < start + 5 * HZ) { + while (ddi_time_before(ddi_get_lbolt(), start + 5 * HZ)) { taskqid_t id; uint32_t rnd; diff -Nru spl-linux-0.6.2/README.markdown spl-linux-0.6.3/README.markdown --- spl-linux-0.6.2/README.markdown 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/README.markdown 2014-06-12 18:32:38.000000000 +0000 @@ -22,5 +22,13 @@ $ ./configure --enable-linux-builtin --with-linux=/usr/src/linux-... $ ./copy-builtin /usr/src/linux-... -Full documentation for building, configuring, and using the SPL can -be found at: +The SPL comes with an automated test suite called SPLAT. The test suite +is implemented in two parts. There is a kernel module which contains +the tests and a user space utility which controls which tests are run. +To run the full test suite: + + $ sudo insmod ./module/splat/splat.ko + $ sudo ./cmd/splat --all + +Full documentation for building, configuring, testing, and using the +SPL can be found at: diff -Nru spl-linux-0.6.2/rpm/fedora/spl-dkms.spec.in spl-linux-0.6.3/rpm/fedora/spl-dkms.spec.in --- spl-linux-0.6.2/rpm/fedora/spl-dkms.spec.in 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/rpm/fedora/spl-dkms.spec.in 2014-06-12 18:32:38.000000000 +0000 @@ -1,3 +1,5 @@ +%{?!packager: %define packager Brian Behlendorf } + %define module @PACKAGE@ %define mkconf scripts/dkms.mkconf @@ -60,11 +62,16 @@ exit 1 %preun -dkms remove -m %{module} -v %{version} --all --rpm_safe_upgrade +# Only remove the modules if they are for this %{version}-%{release}. A +# package upgrade can replace them if only the %{release} is changed. +RELEASE="/var/lib/dkms/%{module}/%{version}/build/%{module}.release" +if [ -f $RELEASE ] && [ `cat $RELEASE`%{?dist} = "%{version}-%{release}" ]; then + echo -e + echo -e "Uninstall of %{module} module (version %{version}) beginning:" + dkms remove -m %{module} -v %{version} --all --rpm_safe_upgrade +fi exit 0 %changelog -* Wed Aug 21 2013 Brian Behlendorf - 0.6.2-1 -- Released 0.6.2-1 -* Fri Mar 22 2013 Brian Behlendorf - 0.6.1-1 -- First official stable release. +* %(date "+%a %b %d %Y") %packager %{version}-%{release} +- Automatic build by DKMS diff -Nru spl-linux-0.6.2/rpm/fedora/spl-kmod.spec.in spl-linux-0.6.3/rpm/fedora/spl-kmod.spec.in --- spl-linux-0.6.2/rpm/fedora/spl-kmod.spec.in 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/rpm/fedora/spl-kmod.spec.in 2014-06-12 18:32:38.000000000 +0000 @@ -160,7 +160,9 @@ rm -rf $RPM_BUILD_ROOT %changelog +* Thu Jun 12 2014 Brian Behlendorf - 0.6.3-1 +- Released 0.6.3-1 * Wed Aug 21 2013 Brian Behlendorf - 0.6.2-1 - Released 0.6.2-1 -* Tue Mar 22 2013 Brian Behlendorf - 0.6.1-1 +* Fri Mar 22 2013 Brian Behlendorf - 0.6.1-1 - First official stable release. diff -Nru spl-linux-0.6.2/rpm/fedora/spl.spec.in spl-linux-0.6.3/rpm/fedora/spl.spec.in --- spl-linux-0.6.2/rpm/fedora/spl.spec.in 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/rpm/fedora/spl.spec.in 2014-06-12 18:32:38.000000000 +0000 @@ -13,7 +13,7 @@ # May build but untested on ppc/ppc64 ExcludeArch: ppc ppc64 -Requires: %{name}-kmod >= %{version} +Requires: %{name}-kmod = %{version} Provides: %{name}-kmod-common = %{version} %description @@ -35,8 +35,11 @@ %doc AUTHORS COPYING DISCLAIMER %{_sbindir}/* %{_mandir}/man1/* +%{_mandir}/man5/* %changelog +* Thu Jun 12 2014 Brian Behlendorf - 0.6.3-1 +- Released 0.6.3-1 * Wed Aug 21 2013 Brian Behlendorf - 0.6.2-1 - Released 0.6.2-1 * Fri Mar 22 2013 Brian Behlendorf - 0.6.1-1 diff -Nru spl-linux-0.6.2/rpm/generic/spl-dkms.spec.in spl-linux-0.6.3/rpm/generic/spl-dkms.spec.in --- spl-linux-0.6.2/rpm/generic/spl-dkms.spec.in 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/rpm/generic/spl-dkms.spec.in 2014-06-12 18:32:38.000000000 +0000 @@ -1,3 +1,5 @@ +%{?!packager: %define packager Brian Behlendorf } + %define module @PACKAGE@ %define mkconf scripts/dkms.mkconf @@ -60,11 +62,16 @@ exit 1 %preun -dkms remove -m %{module} -v %{version} --all --rpm_safe_upgrade +# Only remove the modules if they are for this %{version}-%{release}. A +# package upgrade can replace them if only the %{release} is changed. +RELEASE="/var/lib/dkms/%{module}/%{version}/build/%{module}.release" +if [ -f $RELEASE ] && [ `cat $RELEASE`%{?dist} = "%{version}-%{release}" ]; then + echo -e + echo -e "Uninstall of %{module} module (version %{version}) beginning:" + dkms remove -m %{module} -v %{version} --all --rpm_safe_upgrade +fi exit 0 %changelog -* Wed Aug 21 2013 Brian Behlendorf - 0.6.2-1 -- Released 0.6.2-1 -* Fri Mar 22 2013 Brian Behlendorf - 0.6.1-1 -- First official stable release. +* %(date "+%a %b %d %Y") %packager %{version}-%{release} +- Automatic build by DKMS diff -Nru spl-linux-0.6.2/rpm/generic/spl-kmod.spec.in spl-linux-0.6.3/rpm/generic/spl-kmod.spec.in --- spl-linux-0.6.2/rpm/generic/spl-kmod.spec.in 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/rpm/generic/spl-kmod.spec.in 2014-06-12 18:32:38.000000000 +0000 @@ -160,7 +160,9 @@ rm -rf $RPM_BUILD_ROOT %changelog +* Thu Jun 12 2014 Brian Behlendorf - 0.6.3-1 +- Released 0.6.3-1 * Wed Aug 21 2013 Brian Behlendorf - 0.6.2-1 - Released 0.6.2-1 -* Tue Mar 22 2013 Brian Behlendorf - 0.6.1-1 +* Fri Mar 22 2013 Brian Behlendorf - 0.6.1-1 - First official stable release. diff -Nru spl-linux-0.6.2/rpm/generic/spl.spec.in spl-linux-0.6.3/rpm/generic/spl.spec.in --- spl-linux-0.6.2/rpm/generic/spl.spec.in 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/rpm/generic/spl.spec.in 2014-06-12 18:32:38.000000000 +0000 @@ -13,7 +13,7 @@ # May build but untested on ppc/ppc64 ExcludeArch: ppc ppc64 -Requires: %{name}-kmod >= %{version} +Requires: %{name}-kmod = %{version} Provides: %{name}-kmod-common = %{version} %description @@ -35,8 +35,11 @@ %doc AUTHORS COPYING DISCLAIMER %{_sbindir}/* %{_mandir}/man1/* +%{_mandir}/man5/* %changelog +* Thu Jun 12 2014 Brian Behlendorf - 0.6.3-1 +- Released 0.6.3-1 * Wed Aug 21 2013 Brian Behlendorf - 0.6.2-1 - Released 0.6.2-1 * Fri Mar 22 2013 Brian Behlendorf - 0.6.1-1 diff -Nru spl-linux-0.6.2/scripts/kmodtool spl-linux-0.6.3/scripts/kmodtool --- spl-linux-0.6.2/scripts/kmodtool 2013-08-16 22:17:35.000000000 +0000 +++ spl-linux-0.6.3/scripts/kmodtool 2014-06-12 18:32:38.000000000 +0000 @@ -64,7 +64,7 @@ cat <