diff -Nru spl-linux-0.6.2/debian/changelog spl-linux-0.6.2/debian/changelog --- spl-linux-0.6.2/debian/changelog 2014-04-16 02:41:53.000000000 +0000 +++ spl-linux-0.6.2/debian/changelog 2014-04-16 14:57:13.000000000 +0000 @@ -1,3 +1,11 @@ +spl-linux (0.6.2-2.1~trusty~10.gbpedccf5) trusty; urgency=low + + ** SNAPSHOT build @edccf5d838b707ea195ac4f4638ab7c4cbd77b06 ** + + * No changes; a full upload is required to unwedge the builders. + + -- Darik Horn Wed, 16 Apr 2014 10:55:08 -0400 + spl-linux (0.6.2-2.1~trusty~5.gbpb54f2d) trusty; urgency=low ** SNAPSHOT build @b54f2df0d315085519919f5c43d86df500fa80e2 ** diff -Nru spl-linux-0.6.2/debian/patches/debian-changes-0.6.2-2.1~trusty~10.gbpedccf5 spl-linux-0.6.2/debian/patches/debian-changes-0.6.2-2.1~trusty~10.gbpedccf5 --- spl-linux-0.6.2/debian/patches/debian-changes-0.6.2-2.1~trusty~10.gbpedccf5 1970-01-01 00:00:00.000000000 +0000 +++ spl-linux-0.6.2/debian/patches/debian-changes-0.6.2-2.1~trusty~10.gbpedccf5 2014-04-16 14:57:33.000000000 +0000 @@ -0,0 +1,2440 @@ +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.2-2.1~trusty~10.gbpedccf5) trusty; urgency=low + . + ** SNAPSHOT build @edccf5d838b707ea195ac4f4638ab7c4cbd77b06 ** + . + * No changes; a full upload is required to unwedge the builders. +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.2.orig/README.markdown ++++ spl-linux-0.6.2/README.markdown +@@ -22,5 +22,13 @@ compilation: + $ ./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: +--- spl-linux-0.6.2.orig/config/spl-build.m4 ++++ spl-linux-0.6.2/config/spl-build.m4 +@@ -27,8 +27,7 @@ AC_DEFUN([SPL_AC_CONFIG_KERNEL], [ + 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,7 @@ AC_DEFUN([SPL_AC_CONFIG_KERNEL], [ + SPL_AC_RWSEM_SPINLOCK_IS_RAW + SPL_AC_SCHED_RT_HEADER + SPL_AC_2ARGS_VFS_GETATTR ++ SPL_AC_USLEEP_RANGE + ]) + + AC_DEFUN([SPL_AC_MODULE_SYMVERS], [ +@@ -884,37 +884,18 @@ AC_DEFUN([SPL_AC_2ARGS_REGISTER_SYSCTL], + ]) + ]) + +-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 +904,86 @@ AC_DEFUN([SPL_AC_3ARGS_SHRINKER_CALLBACK + 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 +1842,73 @@ AC_DEFUN([SPL_AC_SET_FS_PWD_WITH_CONST], + 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_ERROR(no) ++ ]) + ]) + ]) + +@@ -2400,3 +2489,25 @@ AC_DEFUN([SPL_AC_2ARGS_VFS_GETATTR], [ + ]) + ]) + ]) ++ ++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) ++ ]) ++]) +--- spl-linux-0.6.2.orig/configure.ac ++++ spl-linux-0.6.2/configure.ac +@@ -50,6 +50,7 @@ AC_CONFIG_FILES([ + Makefile + man/Makefile + man/man1/Makefile ++ man/man5/Makefile + lib/Makefile + cmd/Makefile + module/Makefile +--- spl-linux-0.6.2.orig/include/linux/Makefile.am ++++ spl-linux-0.6.2/include/linux/Makefile.am +@@ -3,6 +3,7 @@ COMMON_H = + 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 \ +--- /dev/null ++++ spl-linux-0.6.2/include/linux/delay_compat.h +@@ -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 */ +--- spl-linux-0.6.2.orig/include/linux/mm_compat.h ++++ spl-linux-0.6.2/include/linux/mm_compat.h +@@ -148,107 +148,167 @@ extern shrink_icache_memory_t shrink_ica + #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 */ +--- spl-linux-0.6.2.orig/include/sys/Makefile.am ++++ spl-linux-0.6.2/include/sys/Makefile.am +@@ -13,6 +13,7 @@ KERNEL_H = \ + $(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 \ +--- /dev/null ++++ spl-linux-0.6.2/include/sys/callo.h +@@ -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 */ +--- spl-linux-0.6.2.orig/include/sys/condvar.h ++++ spl-linux-0.6.2/include/sys/condvar.h +@@ -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 void __cv_wait_interruptible(kcon + 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); + +--- spl-linux-0.6.2.orig/include/sys/debug.h ++++ spl-linux-0.6.2/include/sys/debug.h +@@ -145,4 +145,15 @@ do { \ + #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 */ +--- spl-linux-0.6.2.orig/include/sys/disp.h ++++ spl-linux-0.6.2/include/sys/disp.h +@@ -27,6 +27,7 @@ + + #include + ++#define kpreempt(unused) schedule() + #define kpreempt_disable() preempt_disable() + #define kpreempt_enable() preempt_enable() + +--- spl-linux-0.6.2.orig/include/sys/isa_defs.h ++++ spl-linux-0.6.2/include/sys/isa_defs.h +@@ -91,7 +91,35 @@ + #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 + +--- spl-linux-0.6.2.orig/include/sys/kstat.h ++++ spl-linux-0.6.2/include/sys/kstat.h +@@ -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 @@ typedef struct kstat_module { + 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 @@ typedef struct kstat_s { + 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 @@ typedef struct kstat_timer { + 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) +--- spl-linux-0.6.2.orig/include/sys/sdt.h ++++ spl-linux-0.6.2/include/sys/sdt.h +@@ -25,4 +25,6 @@ + #ifndef _SPL_SDT_H + #define _SPL_SDT_H + ++#define SET_ERROR(x) (x) ++ + #endif /* SPL_SDT_H */ +--- spl-linux-0.6.2.orig/include/sys/sysmacros.h ++++ spl-linux-0.6.2/include/sys/sysmacros.h +@@ -143,7 +143,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); +--- spl-linux-0.6.2.orig/include/sys/systeminfo.h ++++ spl-linux-0.6.2/include/sys/systeminfo.h +@@ -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 */ +--- spl-linux-0.6.2.orig/include/sys/thread.h ++++ spl-linux-0.6.2/include/sys/thread.h +@@ -51,11 +51,15 @@ typedef void (*thread_func_t)(void *); + #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 */ +--- spl-linux-0.6.2.orig/include/sys/time.h ++++ spl-linux-0.6.2/include/sys/time.h +@@ -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 +--- spl-linux-0.6.2.orig/include/sys/timer.h ++++ spl-linux-0.6.2/include/sys/timer.h +@@ -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) +--- spl-linux-0.6.2.orig/include/sys/vmsystm.h ++++ spl-linux-0.6.2/include/sys/vmsystm.h +@@ -29,6 +29,7 @@ + #include + #include + #include ++#include + #include + #include + +--- spl-linux-0.6.2.orig/man/Makefile.am ++++ spl-linux-0.6.2/man/Makefile.am +@@ -1 +1 @@ +-SUBDIRS = man1 ++SUBDIRS = man1 man5 +--- spl-linux-0.6.2.orig/man/man1/Makefile.am ++++ spl-linux-0.6.2/man/man1/Makefile.am +@@ -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" +--- /dev/null ++++ spl-linux-0.6.2/man/man5/Makefile.am +@@ -0,0 +1,4 @@ ++dist_man_MANS = spl-module-parameters.5 ++ ++install-data-local: ++ $(INSTALL) -d -m 0755 "$(DESTDIR)$(mandir)/man5" +--- /dev/null ++++ spl-linux-0.6.2/man/man5/spl-module-parameters.5 +@@ -0,0 +1,126 @@ ++'\" 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. +--- spl-linux-0.6.2.orig/module/spl/spl-condvar.c ++++ spl-linux-0.6.2/module/spl/spl-condvar.c +@@ -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 @@ __cv_init(kcondvar_t *cvp, char *name, k + 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 @@ __cv_timedwait_interruptible(kcondvar_t + } + 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) + { +--- spl-linux-0.6.2.orig/module/spl/spl-cred.c ++++ spl-linux-0.6.2/module/spl/spl-cred.c +@@ -44,7 +44,8 @@ cr_groups_search(const struct group_info + 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 @@ cr_groups_search(const struct group_info + 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 @@ crgetgroups(const cred_t *cr) + 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 @@ groupmember(gid_t gid, const cred_t *cr) + 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; +--- spl-linux-0.6.2.orig/module/spl/spl-debug.c ++++ spl-linux-0.6.2/module/spl/spl-debug.c +@@ -38,6 +38,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -415,7 +416,7 @@ spl_debug_dumplog(int flags) + 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; + +--- spl-linux-0.6.2.orig/module/spl/spl-generic.c ++++ spl-linux-0.6.2/module/spl/spl-generic.c +@@ -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 @@ hostid_read(void) + int result; + uint64_t size; + struct _buf *file; +- unsigned long hostid = 0; ++ uint32_t hostid = 0; + + file = kobj_open_file(spl_hostid_path); + +@@ -515,45 +512,10 @@ hostid_read(void) + 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); +@@ -563,21 +525,16 @@ zone_get_hostid(void *zone) + + /* + * 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); + +@@ -763,3 +720,4 @@ module_exit(spl_fini); + MODULE_AUTHOR("Lawrence Livermore National Labs"); + MODULE_DESCRIPTION("Solaris Porting Layer"); + MODULE_LICENSE("GPL"); ++MODULE_VERSION(SPL_META_VERSION "-" SPL_META_RELEASE); +--- spl-linux-0.6.2.orig/module/spl/spl-kmem.c ++++ spl-linux-0.6.2/module/spl/spl-kmem.c +@@ -38,14 +38,28 @@ + * 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)"); + ++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"); ++ + /* + * 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 +@@ -1355,10 +1369,10 @@ spl_cache_age(void *data) + + /* + * 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 +1381,7 @@ spl_slab_size(spl_kmem_cache_t *skc, uin + 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 +1391,12 @@ spl_slab_size(spl_kmem_cache_t *skc, uin + 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 +1407,7 @@ spl_slab_size(spl_kmem_cache_t *skc, uin + */ + *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); + } + +@@ -1995,7 +2009,6 @@ void * + spl_kmem_cache_alloc(spl_kmem_cache_t *skc, int flags) + { + spl_kmem_magazine_t *skm; +- unsigned long irq_flags; + void *obj = NULL; + SENTRY; + +@@ -2003,7 +2016,7 @@ spl_kmem_cache_alloc(spl_kmem_cache_t *s + ASSERT(!test_bit(KMC_BIT_DESTROY, &skc->skc_flags)); + ASSERT(flags & KM_SLEEP); + atomic_inc(&skc->skc_ref); +- local_irq_save(irq_flags); ++ local_irq_disable(); + + restart: + /* Safe to update per-cpu structure without lock, but +@@ -2025,7 +2038,7 @@ restart: + SGOTO(restart, obj = NULL); + } + +- local_irq_restore(irq_flags); ++ local_irq_enable(); + ASSERT(obj); + ASSERT(IS_P2ALIGNED(obj, skc->skc_obj_align)); + +--- spl-linux-0.6.2.orig/module/spl/spl-kstat.c ++++ spl-linux-0.6.2/module/spl/spl-kstat.c +@@ -41,10 +41,91 @@ static kmutex_t kstat_module_lock; + 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 @@ kstat_seq_show_headers(struct seq_file * + + 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 @@ kstat_seq_show_headers(struct seq_file * + "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 @@ kstat_seq_show_timer(struct seq_file *f, + } + + 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 @@ kstat_seq_show(struct seq_file *f, void + + 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 @@ kstat_seq_show(struct seq_file *f, void + 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 @@ kstat_seq_data_addr(kstat_t *ksp, loff_t + + 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 @@ kstat_seq_data_addr(kstat_t *ksp, loff_t + 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 @@ kstat_seq_start(struct seq_file *f, loff + 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 @@ kstat_seq_next(struct seq_file *f, void + 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 @@ proc_kstat_open(struct inode *inode, str + 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 @@ __kstat_create(const char *ks_module, in + 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 @@ __kstat_create(const char *ks_module, in + 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 @@ __kstat_create(const char *ks_module, in + 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 @@ __kstat_create(const char *ks_module, in + 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 @@ __kstat_install(kstat_t *ksp) + + 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 @@ __kstat_delete(kstat_t *ksp) + 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; +--- spl-linux-0.6.2.orig/module/spl/spl-proc.c ++++ spl-linux-0.6.2/module/spl/spl-proc.c +@@ -72,7 +72,6 @@ struct proc_dir_entry *proc_spl_kstat = + + #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 { + 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 @@ SPL_PROC_HANDLER(proc_dohostid) + 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) +@@ -1058,14 +1053,6 @@ static struct ctl_table spl_table[] = { + .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) +--- spl-linux-0.6.2.orig/module/spl/spl-taskq.c ++++ spl-linux-0.6.2/module/spl/spl-taskq.c +@@ -839,11 +839,10 @@ taskq_create(const char *name, int nthre + 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()); + set_user_nice(tqt->tqt_thread, PRIO_TO_NICE(pri)); + wake_up_process(tqt->tqt_thread); + j++; +--- spl-linux-0.6.2.orig/module/spl/spl-thread.c ++++ spl-linux-0.6.2/module/spl/spl-thread.c +@@ -126,7 +126,7 @@ __thread_create(caddr_t stk, size_t stk + 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 @@ __thread_create(caddr_t stk, size_t stk + 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); +--- spl-linux-0.6.2.orig/module/spl/spl-time.c ++++ spl-linux-0.6.2/module/spl/spl-time.c +@@ -40,7 +40,9 @@ extern unsigned long long monotonic_cloc + 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; +--- spl-linux-0.6.2.orig/module/spl/spl-vnode.c ++++ spl-linux-0.6.2/module/spl/spl-vnode.c +@@ -334,7 +334,11 @@ vn_remove(const char *path, uio_seg_t se + 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 { +@@ -412,10 +416,10 @@ vn_rename(const char *oldname, const cha + + #ifdef HAVE_4ARGS_VFS_RENAME + rc = vfs_rename(old_dir->d_inode, old_dentry, +- new_dir->d_inode, new_dentry); ++ new_dir->d_inode, new_dentry); + #else +- rc = vfs_rename(old_dir->d_inode, old_dentry, oldnd.nd_mnt, +- new_dir->d_inode, new_dentry, newnd.nd_mnt); ++ rc = vfs_rename(old_dir->d_inode, old_dentry, ++ new_dir->d_inode, new_dentry, NULL); + #endif /* HAVE_4ARGS_VFS_RENAME */ + exit4: + unlock_rename(new_dir, old_dir); +@@ -478,9 +482,9 @@ vn_remove(const char *path, uio_seg_t se + 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); +@@ -571,11 +575,11 @@ vn_rename(const char *oldname, const cha + SGOTO(exit5, rc); + + #ifdef HAVE_4ARGS_VFS_RENAME +- rc = vfs_rename(old_dir->d_inode, old_dentry, +- new_dir->d_inode, new_dentry); ++ rc = vfs_rename(old_dir->d_inode, old_dentry, ++ new_dir->d_inode, new_dentry); + #else +- rc = vfs_rename(old_dir->d_inode, old_dentry, oldnd.nd_mnt, +- new_dir->d_inode, new_dentry, newnd.nd_mnt); ++ rc = vfs_rename(old_dir->d_inode, old_dentry, ++ new_dir->d_inode, new_dentry, NULL); + #endif /* HAVE_4ARGS_VFS_RENAME */ + exit5: + dput(new_dentry); +--- spl-linux-0.6.2.orig/module/splat/splat-condvar.c ++++ spl-linux-0.6.2/module/splat/splat-condvar.c +@@ -108,7 +108,7 @@ splat_condvar_test1(struct file *file, v + 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 @@ splat_condvar_test2(struct file *file, v + 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 @@ splat_condvar_test3(struct file *file, v + 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 @@ splat_condvar_test4(struct file *file, v + 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)) { +--- spl-linux-0.6.2.orig/module/splat/splat-cred.c ++++ spl-linux-0.6.2/module/splat/splat-cred.c +@@ -25,6 +25,7 @@ + \*****************************************************************************/ + + #include ++#include + #include "splat-internal.h" + + #define SPLAT_CRED_NAME "cred" +@@ -166,42 +167,89 @@ splat_cred_test2(struct file *file, void + } /* 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 * +--- spl-linux-0.6.2.orig/module/splat/splat-ctl.c ++++ spl-linux-0.6.2/module/splat/splat-ctl.c +@@ -721,3 +721,4 @@ spl_module_exit(splat_fini); + MODULE_AUTHOR("Lawrence Livermore National Labs"); + MODULE_DESCRIPTION("Solaris Porting LAyer Tests"); + MODULE_LICENSE("GPL"); ++MODULE_VERSION(SPL_META_VERSION "-" SPL_META_RELEASE); +--- spl-linux-0.6.2.orig/module/splat/splat-kmem.c ++++ spl-linux-0.6.2/module/splat/splat-kmem.c +@@ -244,7 +244,7 @@ splat_kmem_test4(struct file *file, void + #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 +@@ -682,7 +682,7 @@ splat_kmem_cache_thread_test(struct file + goto out_kcp; + } + +- start = current_kernel_time(); ++ getnstimeofday(&start); + + for (i = 0; i < SPLAT_KMEM_THREADS; i++) { + thr = thread_create(NULL, 0, +@@ -707,7 +707,7 @@ splat_kmem_cache_thread_test(struct file + /* 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,7 +895,8 @@ splat_kmem_test8(struct file *file, void + 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); + +@@ -903,7 +904,7 @@ splat_kmem_test8(struct file *file, void + break; + + set_current_state(TASK_INTERRUPTIBLE); +- schedule_timeout(HZ); ++ schedule_timeout(HZ / 10); + } + + if (kcp->kcp_cache->skc_obj_total == 0) { +@@ -1203,7 +1204,7 @@ splat_kmem_test13(struct file *file, voi + 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 +1251,7 @@ splat_kmem_test13(struct file *file, voi + 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 +1260,8 @@ splat_kmem_test13(struct file *file, voi + 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 +1272,7 @@ splat_kmem_test13(struct file *file, voi + 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, +--- spl-linux-0.6.2.orig/module/splat/splat-rwlock.c ++++ spl-linux-0.6.2/module/splat/splat-rwlock.c +@@ -215,10 +215,10 @@ splat_rwlock_test1(struct file *file, vo + + /* 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)) { +--- spl-linux-0.6.2.orig/module/splat/splat-taskq.c ++++ spl-linux-0.6.2/module/splat/splat-taskq.c +@@ -82,7 +82,7 @@ typedef struct splat_taskq_arg { + 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_test9_func(void *arg) + 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_test10_func(void *arg) + 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 @@ splat_taskq_test10(struct file *file, vo + 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 @@ splat_taskq_test10(struct file *file, vo + 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; + +--- spl-linux-0.6.2.orig/rpm/generic/spl-kmod.spec.in ++++ spl-linux-0.6.2/rpm/generic/spl-kmod.spec.in +@@ -162,5 +162,5 @@ rm -rf $RPM_BUILD_ROOT + %changelog + * 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. +--- spl-linux-0.6.2.orig/rpm/generic/spl.spec.in ++++ spl-linux-0.6.2/rpm/generic/spl.spec.in +@@ -13,7 +13,7 @@ ExclusiveArch: i386 i686 x86_64 + # 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,6 +35,7 @@ make install DESTDIR=%{?buildroot} + %doc AUTHORS COPYING DISCLAIMER + %{_sbindir}/* + %{_mandir}/man1/* ++%{_mandir}/man5/* + + %changelog + * Wed Aug 21 2013 Brian Behlendorf - 0.6.2-1 diff -Nru spl-linux-0.6.2/debian/patches/debian-changes-0.6.2-2.1~trusty~5.gbpb54f2d spl-linux-0.6.2/debian/patches/debian-changes-0.6.2-2.1~trusty~5.gbpb54f2d --- spl-linux-0.6.2/debian/patches/debian-changes-0.6.2-2.1~trusty~5.gbpb54f2d 2014-04-16 13:49:08.000000000 +0000 +++ spl-linux-0.6.2/debian/patches/debian-changes-0.6.2-2.1~trusty~5.gbpb54f2d 1970-01-01 00:00:00.000000000 +0000 @@ -1,2456 +0,0 @@ -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.2-2.1~trusty~5.gbpb54f2d) trusty; urgency=low - . - ** SNAPSHOT build @b54f2df0d315085519919f5c43d86df500fa80e2 ** - . - [ Tim Chase ] - * 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 -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.2.orig/README.markdown -+++ spl-linux-0.6.2/README.markdown -@@ -22,5 +22,13 @@ compilation: - $ ./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: ---- spl-linux-0.6.2.orig/config/spl-build.m4 -+++ spl-linux-0.6.2/config/spl-build.m4 -@@ -27,8 +27,7 @@ AC_DEFUN([SPL_AC_CONFIG_KERNEL], [ - 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,7 @@ AC_DEFUN([SPL_AC_CONFIG_KERNEL], [ - SPL_AC_RWSEM_SPINLOCK_IS_RAW - SPL_AC_SCHED_RT_HEADER - SPL_AC_2ARGS_VFS_GETATTR -+ SPL_AC_USLEEP_RANGE - ]) - - AC_DEFUN([SPL_AC_MODULE_SYMVERS], [ -@@ -884,37 +884,18 @@ AC_DEFUN([SPL_AC_2ARGS_REGISTER_SYSCTL], - ]) - ]) - --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 +904,86 @@ AC_DEFUN([SPL_AC_3ARGS_SHRINKER_CALLBACK - 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 +1842,73 @@ AC_DEFUN([SPL_AC_SET_FS_PWD_WITH_CONST], - 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_ERROR(no) -+ ]) - ]) - ]) - -@@ -2400,3 +2489,25 @@ AC_DEFUN([SPL_AC_2ARGS_VFS_GETATTR], [ - ]) - ]) - ]) -+ -+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) -+ ]) -+]) ---- spl-linux-0.6.2.orig/configure.ac -+++ spl-linux-0.6.2/configure.ac -@@ -50,6 +50,7 @@ AC_CONFIG_FILES([ - Makefile - man/Makefile - man/man1/Makefile -+ man/man5/Makefile - lib/Makefile - cmd/Makefile - module/Makefile ---- spl-linux-0.6.2.orig/include/linux/Makefile.am -+++ spl-linux-0.6.2/include/linux/Makefile.am -@@ -3,6 +3,7 @@ COMMON_H = - 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 \ ---- /dev/null -+++ spl-linux-0.6.2/include/linux/delay_compat.h -@@ -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 */ ---- spl-linux-0.6.2.orig/include/linux/mm_compat.h -+++ spl-linux-0.6.2/include/linux/mm_compat.h -@@ -148,107 +148,167 @@ extern shrink_icache_memory_t shrink_ica - #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 */ ---- spl-linux-0.6.2.orig/include/sys/Makefile.am -+++ spl-linux-0.6.2/include/sys/Makefile.am -@@ -13,6 +13,7 @@ KERNEL_H = \ - $(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 \ ---- /dev/null -+++ spl-linux-0.6.2/include/sys/callo.h -@@ -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 */ ---- spl-linux-0.6.2.orig/include/sys/condvar.h -+++ spl-linux-0.6.2/include/sys/condvar.h -@@ -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 void __cv_wait_interruptible(kcon - 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); - ---- spl-linux-0.6.2.orig/include/sys/debug.h -+++ spl-linux-0.6.2/include/sys/debug.h -@@ -145,4 +145,15 @@ do { \ - #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 */ ---- spl-linux-0.6.2.orig/include/sys/disp.h -+++ spl-linux-0.6.2/include/sys/disp.h -@@ -27,6 +27,7 @@ - - #include - -+#define kpreempt(unused) schedule() - #define kpreempt_disable() preempt_disable() - #define kpreempt_enable() preempt_enable() - ---- spl-linux-0.6.2.orig/include/sys/isa_defs.h -+++ spl-linux-0.6.2/include/sys/isa_defs.h -@@ -91,7 +91,35 @@ - #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 - ---- spl-linux-0.6.2.orig/include/sys/kstat.h -+++ spl-linux-0.6.2/include/sys/kstat.h -@@ -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 @@ typedef struct kstat_module { - 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 @@ typedef struct kstat_s { - 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 @@ typedef struct kstat_timer { - 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) ---- spl-linux-0.6.2.orig/include/sys/sdt.h -+++ spl-linux-0.6.2/include/sys/sdt.h -@@ -25,4 +25,6 @@ - #ifndef _SPL_SDT_H - #define _SPL_SDT_H - -+#define SET_ERROR(x) (x) -+ - #endif /* SPL_SDT_H */ ---- spl-linux-0.6.2.orig/include/sys/sysmacros.h -+++ spl-linux-0.6.2/include/sys/sysmacros.h -@@ -143,7 +143,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); ---- spl-linux-0.6.2.orig/include/sys/systeminfo.h -+++ spl-linux-0.6.2/include/sys/systeminfo.h -@@ -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 */ ---- spl-linux-0.6.2.orig/include/sys/thread.h -+++ spl-linux-0.6.2/include/sys/thread.h -@@ -51,11 +51,15 @@ typedef void (*thread_func_t)(void *); - #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 */ ---- spl-linux-0.6.2.orig/include/sys/time.h -+++ spl-linux-0.6.2/include/sys/time.h -@@ -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 ---- spl-linux-0.6.2.orig/include/sys/timer.h -+++ spl-linux-0.6.2/include/sys/timer.h -@@ -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) ---- spl-linux-0.6.2.orig/include/sys/vmsystm.h -+++ spl-linux-0.6.2/include/sys/vmsystm.h -@@ -29,6 +29,7 @@ - #include - #include - #include -+#include - #include - #include - ---- spl-linux-0.6.2.orig/man/Makefile.am -+++ spl-linux-0.6.2/man/Makefile.am -@@ -1 +1 @@ --SUBDIRS = man1 -+SUBDIRS = man1 man5 ---- spl-linux-0.6.2.orig/man/man1/Makefile.am -+++ spl-linux-0.6.2/man/man1/Makefile.am -@@ -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" ---- /dev/null -+++ spl-linux-0.6.2/man/man5/Makefile.am -@@ -0,0 +1,4 @@ -+dist_man_MANS = spl-module-parameters.5 -+ -+install-data-local: -+ $(INSTALL) -d -m 0755 "$(DESTDIR)$(mandir)/man5" ---- /dev/null -+++ spl-linux-0.6.2/man/man5/spl-module-parameters.5 -@@ -0,0 +1,126 @@ -+'\" 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. ---- spl-linux-0.6.2.orig/module/spl/spl-condvar.c -+++ spl-linux-0.6.2/module/spl/spl-condvar.c -@@ -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 @@ __cv_init(kcondvar_t *cvp, char *name, k - 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 @@ __cv_timedwait_interruptible(kcondvar_t - } - 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) - { ---- spl-linux-0.6.2.orig/module/spl/spl-cred.c -+++ spl-linux-0.6.2/module/spl/spl-cred.c -@@ -44,7 +44,8 @@ cr_groups_search(const struct group_info - 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 @@ cr_groups_search(const struct group_info - 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 @@ crgetgroups(const cred_t *cr) - 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 @@ groupmember(gid_t gid, const cred_t *cr) - 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; ---- spl-linux-0.6.2.orig/module/spl/spl-debug.c -+++ spl-linux-0.6.2/module/spl/spl-debug.c -@@ -38,6 +38,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -415,7 +416,7 @@ spl_debug_dumplog(int flags) - 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; - ---- spl-linux-0.6.2.orig/module/spl/spl-generic.c -+++ spl-linux-0.6.2/module/spl/spl-generic.c -@@ -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 @@ hostid_read(void) - int result; - uint64_t size; - struct _buf *file; -- unsigned long hostid = 0; -+ uint32_t hostid = 0; - - file = kobj_open_file(spl_hostid_path); - -@@ -515,45 +512,10 @@ hostid_read(void) - 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); -@@ -563,21 +525,16 @@ zone_get_hostid(void *zone) - - /* - * 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); - -@@ -763,3 +720,4 @@ module_exit(spl_fini); - MODULE_AUTHOR("Lawrence Livermore National Labs"); - MODULE_DESCRIPTION("Solaris Porting Layer"); - MODULE_LICENSE("GPL"); -+MODULE_VERSION(SPL_META_VERSION "-" SPL_META_RELEASE); ---- spl-linux-0.6.2.orig/module/spl/spl-kmem.c -+++ spl-linux-0.6.2/module/spl/spl-kmem.c -@@ -38,14 +38,28 @@ - * 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)"); - -+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"); -+ - /* - * 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 -@@ -1355,10 +1369,10 @@ spl_cache_age(void *data) - - /* - * 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 +1381,7 @@ spl_slab_size(spl_kmem_cache_t *skc, uin - 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 +1391,12 @@ spl_slab_size(spl_kmem_cache_t *skc, uin - 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 +1407,7 @@ spl_slab_size(spl_kmem_cache_t *skc, uin - */ - *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); - } - -@@ -1995,7 +2009,6 @@ void * - spl_kmem_cache_alloc(spl_kmem_cache_t *skc, int flags) - { - spl_kmem_magazine_t *skm; -- unsigned long irq_flags; - void *obj = NULL; - SENTRY; - -@@ -2003,7 +2016,7 @@ spl_kmem_cache_alloc(spl_kmem_cache_t *s - ASSERT(!test_bit(KMC_BIT_DESTROY, &skc->skc_flags)); - ASSERT(flags & KM_SLEEP); - atomic_inc(&skc->skc_ref); -- local_irq_save(irq_flags); -+ local_irq_disable(); - - restart: - /* Safe to update per-cpu structure without lock, but -@@ -2025,7 +2038,7 @@ restart: - SGOTO(restart, obj = NULL); - } - -- local_irq_restore(irq_flags); -+ local_irq_enable(); - ASSERT(obj); - ASSERT(IS_P2ALIGNED(obj, skc->skc_obj_align)); - ---- spl-linux-0.6.2.orig/module/spl/spl-kstat.c -+++ spl-linux-0.6.2/module/spl/spl-kstat.c -@@ -41,10 +41,91 @@ static kmutex_t kstat_module_lock; - 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 @@ kstat_seq_show_headers(struct seq_file * - - 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 @@ kstat_seq_show_headers(struct seq_file * - "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 @@ kstat_seq_show_timer(struct seq_file *f, - } - - 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 @@ kstat_seq_show(struct seq_file *f, void - - 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 @@ kstat_seq_show(struct seq_file *f, void - 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 @@ kstat_seq_data_addr(kstat_t *ksp, loff_t - - 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 @@ kstat_seq_data_addr(kstat_t *ksp, loff_t - 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 @@ kstat_seq_start(struct seq_file *f, loff - 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 @@ kstat_seq_next(struct seq_file *f, void - 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 @@ proc_kstat_open(struct inode *inode, str - 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 @@ __kstat_create(const char *ks_module, in - 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 @@ __kstat_create(const char *ks_module, in - 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 @@ __kstat_create(const char *ks_module, in - 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 @@ __kstat_create(const char *ks_module, in - 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 @@ __kstat_install(kstat_t *ksp) - - 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 @@ __kstat_delete(kstat_t *ksp) - 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; ---- spl-linux-0.6.2.orig/module/spl/spl-proc.c -+++ spl-linux-0.6.2/module/spl/spl-proc.c -@@ -72,7 +72,6 @@ struct proc_dir_entry *proc_spl_kstat = - - #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 { - 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 @@ SPL_PROC_HANDLER(proc_dohostid) - 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) -@@ -1058,14 +1053,6 @@ static struct ctl_table spl_table[] = { - .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) ---- spl-linux-0.6.2.orig/module/spl/spl-taskq.c -+++ spl-linux-0.6.2/module/spl/spl-taskq.c -@@ -839,11 +839,10 @@ taskq_create(const char *name, int nthre - 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()); - set_user_nice(tqt->tqt_thread, PRIO_TO_NICE(pri)); - wake_up_process(tqt->tqt_thread); - j++; ---- spl-linux-0.6.2.orig/module/spl/spl-thread.c -+++ spl-linux-0.6.2/module/spl/spl-thread.c -@@ -126,7 +126,7 @@ __thread_create(caddr_t stk, size_t stk - 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 @@ __thread_create(caddr_t stk, size_t stk - 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); ---- spl-linux-0.6.2.orig/module/spl/spl-time.c -+++ spl-linux-0.6.2/module/spl/spl-time.c -@@ -40,7 +40,9 @@ extern unsigned long long monotonic_cloc - 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; ---- spl-linux-0.6.2.orig/module/spl/spl-vnode.c -+++ spl-linux-0.6.2/module/spl/spl-vnode.c -@@ -334,7 +334,11 @@ vn_remove(const char *path, uio_seg_t se - 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 { -@@ -412,10 +416,10 @@ vn_rename(const char *oldname, const cha - - #ifdef HAVE_4ARGS_VFS_RENAME - rc = vfs_rename(old_dir->d_inode, old_dentry, -- new_dir->d_inode, new_dentry); -+ new_dir->d_inode, new_dentry); - #else -- rc = vfs_rename(old_dir->d_inode, old_dentry, oldnd.nd_mnt, -- new_dir->d_inode, new_dentry, newnd.nd_mnt); -+ rc = vfs_rename(old_dir->d_inode, old_dentry, -+ new_dir->d_inode, new_dentry, NULL); - #endif /* HAVE_4ARGS_VFS_RENAME */ - exit4: - unlock_rename(new_dir, old_dir); -@@ -478,9 +482,9 @@ vn_remove(const char *path, uio_seg_t se - 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); -@@ -571,11 +575,11 @@ vn_rename(const char *oldname, const cha - SGOTO(exit5, rc); - - #ifdef HAVE_4ARGS_VFS_RENAME -- rc = vfs_rename(old_dir->d_inode, old_dentry, -- new_dir->d_inode, new_dentry); -+ rc = vfs_rename(old_dir->d_inode, old_dentry, -+ new_dir->d_inode, new_dentry); - #else -- rc = vfs_rename(old_dir->d_inode, old_dentry, oldnd.nd_mnt, -- new_dir->d_inode, new_dentry, newnd.nd_mnt); -+ rc = vfs_rename(old_dir->d_inode, old_dentry, -+ new_dir->d_inode, new_dentry, NULL); - #endif /* HAVE_4ARGS_VFS_RENAME */ - exit5: - dput(new_dentry); ---- spl-linux-0.6.2.orig/module/splat/splat-condvar.c -+++ spl-linux-0.6.2/module/splat/splat-condvar.c -@@ -108,7 +108,7 @@ splat_condvar_test1(struct file *file, v - 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 @@ splat_condvar_test2(struct file *file, v - 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 @@ splat_condvar_test3(struct file *file, v - 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 @@ splat_condvar_test4(struct file *file, v - 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)) { ---- spl-linux-0.6.2.orig/module/splat/splat-cred.c -+++ spl-linux-0.6.2/module/splat/splat-cred.c -@@ -25,6 +25,7 @@ - \*****************************************************************************/ - - #include -+#include - #include "splat-internal.h" - - #define SPLAT_CRED_NAME "cred" -@@ -166,42 +167,89 @@ splat_cred_test2(struct file *file, void - } /* 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 * ---- spl-linux-0.6.2.orig/module/splat/splat-ctl.c -+++ spl-linux-0.6.2/module/splat/splat-ctl.c -@@ -721,3 +721,4 @@ spl_module_exit(splat_fini); - MODULE_AUTHOR("Lawrence Livermore National Labs"); - MODULE_DESCRIPTION("Solaris Porting LAyer Tests"); - MODULE_LICENSE("GPL"); -+MODULE_VERSION(SPL_META_VERSION "-" SPL_META_RELEASE); ---- spl-linux-0.6.2.orig/module/splat/splat-kmem.c -+++ spl-linux-0.6.2/module/splat/splat-kmem.c -@@ -244,7 +244,7 @@ splat_kmem_test4(struct file *file, void - #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 -@@ -682,7 +682,7 @@ splat_kmem_cache_thread_test(struct file - goto out_kcp; - } - -- start = current_kernel_time(); -+ getnstimeofday(&start); - - for (i = 0; i < SPLAT_KMEM_THREADS; i++) { - thr = thread_create(NULL, 0, -@@ -707,7 +707,7 @@ splat_kmem_cache_thread_test(struct file - /* 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,7 +895,8 @@ splat_kmem_test8(struct file *file, void - 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); - -@@ -903,7 +904,7 @@ splat_kmem_test8(struct file *file, void - break; - - set_current_state(TASK_INTERRUPTIBLE); -- schedule_timeout(HZ); -+ schedule_timeout(HZ / 10); - } - - if (kcp->kcp_cache->skc_obj_total == 0) { -@@ -1203,7 +1204,7 @@ splat_kmem_test13(struct file *file, voi - 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 +1251,7 @@ splat_kmem_test13(struct file *file, voi - 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 +1260,8 @@ splat_kmem_test13(struct file *file, voi - 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 +1272,7 @@ splat_kmem_test13(struct file *file, voi - 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, ---- spl-linux-0.6.2.orig/module/splat/splat-rwlock.c -+++ spl-linux-0.6.2/module/splat/splat-rwlock.c -@@ -215,10 +215,10 @@ splat_rwlock_test1(struct file *file, vo - - /* 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)) { ---- spl-linux-0.6.2.orig/module/splat/splat-taskq.c -+++ spl-linux-0.6.2/module/splat/splat-taskq.c -@@ -82,7 +82,7 @@ typedef struct splat_taskq_arg { - 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_test9_func(void *arg) - 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_test10_func(void *arg) - 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 @@ splat_taskq_test10(struct file *file, vo - 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 @@ splat_taskq_test10(struct file *file, vo - 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; - ---- spl-linux-0.6.2.orig/rpm/generic/spl-kmod.spec.in -+++ spl-linux-0.6.2/rpm/generic/spl-kmod.spec.in -@@ -162,5 +162,5 @@ rm -rf $RPM_BUILD_ROOT - %changelog - * 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. ---- spl-linux-0.6.2.orig/rpm/generic/spl.spec.in -+++ spl-linux-0.6.2/rpm/generic/spl.spec.in -@@ -13,7 +13,7 @@ ExclusiveArch: i386 i686 x86_64 - # 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,6 +35,7 @@ make install DESTDIR=%{?buildroot} - %doc AUTHORS COPYING DISCLAIMER - %{_sbindir}/* - %{_mandir}/man1/* -+%{_mandir}/man5/* - - %changelog - * Wed Aug 21 2013 Brian Behlendorf - 0.6.2-1 diff -Nru spl-linux-0.6.2/debian/patches/series spl-linux-0.6.2/debian/patches/series --- spl-linux-0.6.2/debian/patches/series 2014-04-16 13:49:08.000000000 +0000 +++ spl-linux-0.6.2/debian/patches/series 2014-04-16 14:57:33.000000000 +0000 @@ -1,2 +1,2 @@ 0001-Revert-Remove-etc-hostid-missing-warning.patch -debian-changes-0.6.2-2.1~trusty~5.gbpb54f2d +debian-changes-0.6.2-2.1~trusty~10.gbpedccf5