Compare commits

...

15 Commits

Author SHA1 Message Date
Ned Bass 44b5ec8fd1 Tag zfs-0.6.4.2
META file and release log updated.

Signed-off-by: Ned Bass <bass6@llnl.gov>
2015-06-25 12:13:29 -07:00
Ned Bass 464c506e3d Serialize access to spa->spa_feat_stats nvlist
The function spa_add_feature_stats() manipulates the shared nvlist
spa->spa_feat_stats in an unsafe concurrent manner. Add a mutex to
protect the list.

Signed-off-by: Ned Bass <bass6@llnl.gov>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #3335
2015-06-22 18:14:46 -07:00
tuxoko 71fa174225 Add cond_resched to zfs_zget to prevent infinite loop
It's been reported that threads would loop infinitely inside zfs_zget. The
speculated cause for this is that if an inode is marked for evict, zfs_zget
would see that and loop. However, if the looping thread doesn't yield, the
inode may not have a chance to finish evict, thus causing a infinite loop.

This patch solve this issue by add cond_resched to zfs_zget, making the
looping thread to yield when needed.

Tested-by: jlavoy <jalavoy@gmail.com>
Signed-off-by: Chunwei Chen <tuxoko@gmail.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #3349
2015-06-22 18:14:41 -07:00
Chris Dunlop 3a25380b5e Wait for all znodes to be released before tearing down the superblock
By the time we're tearing down our superblock the VFS has started releasing
all our inodes/znodes. Some of this work may have been handed off to our
iput taskq so we need to wait for that work to complete. However the iput
from the taskq can itself result in additional work being added to the
taskq:

dsl_pool_iput_taskq
 iput
  iput_final
   evict
    destroy_inode
     zpl_inode_destroy
      zfs_inode_destroy
       zfs_iput_async(ZTOI(zp->z_xattr_parent))
        taskq_dispatch(dsl_pool_iput_taskq..., iput, ...)

Let's wait until all our znodes have been released.

Signed-off-by: Chris Dunlop <chris@onthe.net.au>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #3281
2015-06-22 14:29:18 -07:00
Brian Behlendorf c4dd92ad0d Add zfs_sb_prune_aliases() function
For kernels which do not implement a per-suberblock shrinker,
those older than Linux 3.1, the shrink_dcache_parent() function
was used to attempt to reclaim dentries.  This was found not be
entirely reliable and could lead to performance issues on older
kernels running meta-data heavy workloads.

To address this issue a zfs_sb_prune_aliases() function has been
added to implement this functionality.  It relies on traversing
the list of znodes for a filesystem and adding them to a private
list with a reference held.  The private list can then be safely
walked outside the z_znodes_lock to prune dentires and drop the
last reference so the inode can be freed.

This provides the same synchronous behavior as the per-filesystem
shrinker and has the advantage of depending on only long standing
interfaces.

Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Tim Chase <tim@chase2k.com>
Closes #3501
2015-06-22 13:14:51 -07:00
Matus Kral 4aa9d97f45 Linux 4.1 compat: use read_iter() / write_iter()
Linux 3.15 commit torvalds/linux@293bc98 introduced two new methods.
The ->read_iter() and ->write_iter() methods were designed to replace
the ->aio_read() and ->aio_write() interfaces.  Both interfaces were
preserved for several kernel releases in order to migrate all existing
consumers to the new interfaces.  But as of Linux 4.1 the legacy
interface has been retired and the ZFS code must be updated to use
the new interfaces.

Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #3352
2015-06-22 13:14:51 -07:00
Tim Chase aa5f4beb84 Linux 3.12 compat: NUMA-aware per-superblock shrinker
Kernels >= 3.12 have a NUMA-aware superblock shrinker which is used in
ZoL by zfs_sb_prune().  This patch calls the shrinker for each on-line
NUMA node in order that memory be freed for each one.

Signed-off-by: Tim Chase <tim@chase2k.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #3495
2015-06-22 13:14:42 -07:00
Brian Behlendorf 04faa11e95 Wait interruptibly in prefetch thread
The Linux kernel watchdog will automatically dump a backtrace for
any process while sleeps for over 120s in an uninterruptible state.

The solution is for the prefetch thread to sleep in an interruptible
state.  The way the existing code was written this is safe because
when woken it will always reevaluate its conditional.  As a general
rule it is preferable to sleep in an interruptible when possible.

Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #3450
Closes #3402
2015-06-22 13:12:27 -07:00
Brian Behlendorf 4c05965578 Use ExecStartPre to load zfs modules
Commit 87abfcb broke the systemd import service by treating the
ExecStart line as if it were a shell command that could be executed.
This isn't the way systemd works and the correct way to handle this
case is with ExecStartPre.  This patch updates the zfs import service
files accordingly,

Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Steven Noonan <steven@uplinklabs.net>
Signed-off-by: Chris Siebenmann <cks.git01@cs.toronto.edu>
Closes #3440
2015-05-27 09:06:36 -07:00
Brian Behlendorf d1b9bc7a78 Wait in libzfs_init() for the /dev/zfs device
While module loading itself is synchronous the creation of the /dev/zfs
device is not.  This is because /dev/zfs is typically created by a udev
rule after the module is registered and presented to user space through
sysfs.  This small window between module loading and device creation
can result in spurious failures of libzfs_init().

This patch closes that race by extending libzfs_init() so it can detect
that the modules are loaded and only if required wait for the /dev/zfs
device to be created.  This allows scripts to reliably use the following
shell construct without the need for additional error handling.

$ /sbin/modprobe zfs && /sbin/zpool import -a

To minimize the potential time waiting in libzfs_init() a strategy
similar to adaptive mutexes is employed.  The function will busy-wait
for up to 10ms based on the expectation that the modules were just
loaded and therefore the /dev/zfs will be created imminently.  If it
takes longer than this it will fall back to polling for up to 10 seconds.

This behavior can be customized to some degree by setting the following
new environment variables.  This functionality is provided for backwards
compatibility with existing scripts which depend on the module auto-load
behavior.  By default module auto-loading is now disabled.

* ZFS_MODULE_LOADING="YES|yes|ON|on" - Attempt to load modules.
* ZFS_MODULE_TIMEOUT="<seconds>"     - Seconds to wait for /dev/zfs

The zfs-import-* systemd service files have been updated to call
'/sbin/modprobe zfs' so they no longer rely on the legacy auto-loading
behavior.

NOTE: Unlike the version of this patch which was merged to master the
default behavior is to auto-load the modules.  The default behavior
should not be changes for a point release.

Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Chris Dunlap <cdunlap@llnl.gov>
Signed-off-by: Richard Yao <ryao@gentoo.org>
Closes #2556
2015-05-22 13:38:57 -07:00
Brian Behlendorf 7065e2dac6 Tag zfs-0.6.4.1
META file and release log updated.

Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
2015-04-23 14:04:08 -07:00
Brian Behlendorf 320e58d5a6 Extend PF_FSTRANS critical regions
Additional testing has shown that the region covered by PF_FSTRANS
needs to be extended to cover the  zpl_xattr_security_init() and
init_acl() functions.  The zpl_mark_dirty() function can also recurse
and therefore must always be protected.

Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Chunwei Chen <tuxoko@gmail.com>
Closes #3331
2015-04-23 14:02:20 -07:00
Chris Dunlap 4ec7b857a9 Fix io-spare.sh to work with disk vdevs
The "zpool status" output shows the full pathname for file-type vdevs,
but only the basename component for disk-type vdevs.  In commit
bee6665, the "basename" command was dropped from altering the vdev
name used when searching the "zpool status" output.  Consequently,
hot-disk sparing for disk vdevs broke since "zpool status" output
was now being searched for the full pathname to the disk vdev.

Parsing the "zpool status" output in this manner is rather brittle.
It would be preferable to search for the vdev based on its guid.
But until that happens, this commit adds back the "basename" command
to fix the vdev name breakage.

Signed-off-by: Chris Dunlap <cdunlap@llnl.gov>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #3310
2015-04-17 14:15:15 -07:00
Brian Behlendorf e548a597d0 Mark additional functions as PF_FSTRANS
Prevent deadlocks by disabling direct reclaim during all NFS, xattr,
ctldir, and super function calls.  This is related to 40d06e3.

Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Tim Chase <tim@chase2k.com>
Issue #3225
2015-04-17 09:47:07 -07:00
Tim Chase 7af63221dc Allocate zfs_znode_cache on the Linux slab
The Linux slab, in general, performs better than the SPl slab in cases
where a lot of objects are allocated and fragmentation is likely present.

This patch fixes pathologically bad behavior in cases where the ARC is
filled with mostly metadata and a user program needs to allocate and
dirty enough memory which would require an insignificant amount of the
ARC to be reclaimed.

If zfs_znode_cache is on the SPL slab, the system may spin for a very
long time trying to reclaim sufficient memory.  If it is on the Linux
slab, the behavior has been observed to be much more predictible; the
memory is reclaimed more efficiently.

Signed-off-by: Tim Chase <tim@chase2k.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Issue #3283
2015-04-17 09:46:51 -07:00
23 changed files with 400 additions and 51 deletions

2
META
View File

@ -1,7 +1,7 @@
Meta: 1
Name: zfs
Branch: 1.0
Version: 0.6.4
Version: 0.6.4.2
Release: 1
Release-Tags: relext
License: CDDL

View File

@ -54,7 +54,7 @@ flock -x 8
# Given a <pool> and <device> return the status, (ONLINE, FAULTED, etc...).
vdev_status() {
local POOL=$1
local VDEV=$2
local VDEV=`basename $2`
local T=' ' # tab character since '\t' isn't portable
${ZPOOL} status ${POOL} | sed -n -e \

View File

@ -0,0 +1,19 @@
dnl #
dnl # 2.6.12 API change
dnl # d_prune_aliases() helper function available.
dnl #
AC_DEFUN([ZFS_AC_KERNEL_D_PRUNE_ALIASES],
[AC_MSG_CHECKING([whether d_prune_aliases() is available])
ZFS_LINUX_TRY_COMPILE_SYMBOL([
#include <linux/dcache.h>
], [
struct inode *ip = NULL;
d_prune_aliases(ip);
], [d_prune_aliases], [fs/dcache.c], [
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_D_PRUNE_ALIASES, 1,
[d_prune_aliases() is available])
], [
AC_MSG_RESULT(no)
])
])

View File

@ -109,3 +109,25 @@ AC_DEFUN([ZFS_AC_KERNEL_FREE_CACHED_OBJECTS], [
AC_MSG_RESULT(no)
])
])
dnl #
dnl # 3.12 API change
dnl # The nid member was added to struct shrink_control to support
dnl # NUMA-aware shrinkers.
dnl #
AC_DEFUN([ZFS_AC_KERNEL_SHRINK_CONTROL_HAS_NID], [
AC_MSG_CHECKING([whether shrink_control has nid])
ZFS_LINUX_TRY_COMPILE([
#include <linux/fs.h>
],[
struct shrink_control sc __attribute__ ((unused));
unsigned long scnidsize __attribute__ ((unused)) =
sizeof(sc.nid);
],[
AC_MSG_RESULT(yes)
AC_DEFINE(SHRINK_CONTROL_HAS_NID, 1,
[struct shrink_control has nid])
],[
AC_MSG_RESULT(no)
])
])

View File

@ -0,0 +1,27 @@
dnl #
dnl # Linux 4.1.x API
dnl #
AC_DEFUN([ZFS_AC_KERNEL_VFS_RW_ITERATE],
[AC_MSG_CHECKING([whether fops->read/write_iter() are available])
ZFS_LINUX_TRY_COMPILE([
#include <linux/fs.h>
ssize_t test_read(struct kiocb *kiocb, struct iov_iter *to)
{ return 0; }
ssize_t test_write(struct kiocb *kiocb, struct iov_iter *from)
{ return 0; }
static const struct file_operations
fops __attribute__ ((unused)) = {
.read_iter = test_read,
.write_iter = test_write,
};
],[
],[
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_VFS_RW_ITERATE, 1,
[fops->read/write_iter() are available])
],[
AC_MSG_RESULT(no)
])
])

View File

@ -79,6 +79,7 @@ AC_DEFUN([ZFS_AC_CONFIG_KERNEL], [
ZFS_AC_KERNEL_INSERT_INODE_LOCKED
ZFS_AC_KERNEL_D_MAKE_ROOT
ZFS_AC_KERNEL_D_OBTAIN_ALIAS
ZFS_AC_KERNEL_D_PRUNE_ALIASES
ZFS_AC_KERNEL_D_SET_D_OP
ZFS_AC_KERNEL_D_REVALIDATE_NAMEIDATA
ZFS_AC_KERNEL_CONST_DENTRY_OPERATIONS
@ -88,6 +89,7 @@ AC_DEFUN([ZFS_AC_CONFIG_KERNEL], [
ZFS_AC_KERNEL_CALLBACK_SECURITY_INODE_INIT_SECURITY
ZFS_AC_KERNEL_MOUNT_NODEV
ZFS_AC_KERNEL_SHRINK
ZFS_AC_KERNEL_SHRINK_CONTROL_HAS_NID
ZFS_AC_KERNEL_S_INSTANCES_LIST_HEAD
ZFS_AC_KERNEL_S_D_OP
ZFS_AC_KERNEL_BDI_SETUP_AND_REGISTER
@ -96,6 +98,7 @@ AC_DEFUN([ZFS_AC_CONFIG_KERNEL], [
ZFS_AC_KERNEL_5ARG_SGET
ZFS_AC_KERNEL_LSEEK_EXECUTE
ZFS_AC_KERNEL_VFS_ITERATE
ZFS_AC_KERNEL_VFS_RW_ITERATE
AS_IF([test "$LINUX_OBJ" != "$LINUX"], [
KERNELMAKE_PARAMS="$KERNELMAKE_PARAMS O=$LINUX_OBJ"

View File

@ -9,4 +9,5 @@ ConditionPathExists=@sysconfdir@/zfs/zpool.cache
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStartPre=/sbin/modprobe zfs
ExecStart=@sbindir@/zpool import -c @sysconfdir@/zfs/zpool.cache -aN

View File

@ -9,4 +9,5 @@ ConditionPathExists=!@sysconfdir@/zfs/zpool.cache
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStartPre=/sbin/modprobe zfs
ExecStart=@sbindir@/zpool import -d /dev/disk/by-id -aN

View File

@ -236,6 +236,7 @@ struct spa {
uint64_t spa_feat_for_read_obj; /* required to read from pool */
uint64_t spa_feat_desc_obj; /* Feature descriptions */
uint64_t spa_feat_enabled_txg_obj; /* Feature enabled txg */
kmutex_t spa_feat_stats_lock; /* protects spa_feat_stats */
nvlist_t *spa_feat_stats; /* Cache of enabled features */
/* cache feature refcounts */
uint64_t spa_feat_refcount_cache[SPA_FEATURES];

View File

@ -660,23 +660,84 @@ libzfs_run_process(const char *path, char *argv[], int flags)
return (-1);
}
/*
* Verify the required ZFS_DEV device is available and optionally attempt
* to load the ZFS modules. Under normal circumstances the modules
* should already have been loaded by some external mechanism.
*
* Environment variables:
* - ZFS_MODULE_LOADING="YES|yes|ON|on" - Attempt to load modules.
* - ZFS_MODULE_TIMEOUT="<seconds>" - Seconds to wait for ZFS_DEV
*/
int
libzfs_load_module(const char *module)
{
char *argv[4] = {"/sbin/modprobe", "-q", (char *)module, (char *)0};
char *load_str, *timeout_str;
long timeout = 10; /* seconds */
long busy_timeout = 10; /* milliseconds */
int load = 1, fd;
hrtime_t start;
if (libzfs_module_loaded(module))
return (0);
/* Optionally request module loading */
if (!libzfs_module_loaded(module)) {
load_str = getenv("ZFS_MODULE_LOADING");
if (load_str) {
if (!strncasecmp(load_str, "YES", strlen("YES")) ||
!strncasecmp(load_str, "ON", strlen("ON")))
load = 1;
else
load = 0;
}
return (libzfs_run_process("/sbin/modprobe", argv, 0));
if (load && libzfs_run_process("/sbin/modprobe", argv, 0))
return (ENOEXEC);
}
/* Module loading is synchronous it must be available */
if (!libzfs_module_loaded(module))
return (ENXIO);
/*
* Device creation by udev is asynchronous and waiting may be
* required. Busy wait for 10ms and then fall back to polling every
* 10ms for the allowed timeout (default 10s, max 10m). This is
* done to optimize for the common case where the device is
* immediately available and to avoid penalizing the possible
* case where udev is slow or unable to create the device.
*/
timeout_str = getenv("ZFS_MODULE_TIMEOUT");
if (timeout_str) {
timeout = strtol(timeout_str, NULL, 0);
timeout = MAX(MIN(timeout, (10 * 60)), 0); /* 0 <= N <= 600 */
}
start = gethrtime();
do {
fd = open(ZFS_DEV, O_RDWR);
if (fd >= 0) {
(void) close(fd);
return (0);
} else if (errno != ENOENT) {
return (errno);
} else if (NSEC2MSEC(gethrtime() - start) < busy_timeout) {
sched_yield();
} else {
usleep(10 * MILLISEC);
}
} while (NSEC2MSEC(gethrtime() - start) < (timeout * MILLISEC));
return (ENOENT);
}
libzfs_handle_t *
libzfs_init(void)
{
libzfs_handle_t *hdl;
int error;
if (libzfs_load_module("zfs") != 0) {
error = libzfs_load_module(ZFS_DRIVER);
if (error) {
(void) fprintf(stderr, gettext("Failed to load ZFS module "
"stack.\nLoad the module manually by running "
"'insmod <location>/zfs.ko' as root.\n"));

View File

@ -254,7 +254,7 @@ traverse_visitbp(traverse_data_t *td, const dnode_phys_t *dnp,
mutex_enter(&pd->pd_mtx);
ASSERT(pd->pd_bytes_fetched >= 0);
while (pd->pd_bytes_fetched < size && !pd->pd_exited)
cv_wait(&pd->pd_cv, &pd->pd_mtx);
cv_wait_interruptible(&pd->pd_cv, &pd->pd_mtx);
pd->pd_bytes_fetched -= size;
cv_broadcast(&pd->pd_cv);
mutex_exit(&pd->pd_mtx);
@ -461,7 +461,7 @@ traverse_prefetcher(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
mutex_enter(&pfd->pd_mtx);
while (!pfd->pd_cancel && pfd->pd_bytes_fetched >= zfs_pd_bytes_max)
cv_wait(&pfd->pd_cv, &pfd->pd_mtx);
cv_wait_interruptible(&pfd->pd_cv, &pfd->pd_mtx);
pfd->pd_bytes_fetched += BP_GET_LSIZE(bp);
cv_broadcast(&pfd->pd_cv);
mutex_exit(&pfd->pd_mtx);
@ -566,7 +566,7 @@ traverse_impl(spa_t *spa, dsl_dataset_t *ds, uint64_t objset, blkptr_t *rootbp,
pd->pd_cancel = B_TRUE;
cv_broadcast(&pd->pd_cv);
while (!pd->pd_exited)
cv_wait(&pd->pd_cv, &pd->pd_mtx);
cv_wait_interruptible(&pd->pd_cv, &pd->pd_mtx);
mutex_exit(&pd->pd_mtx);
mutex_destroy(&pd->pd_mtx);

View File

@ -3264,10 +3264,13 @@ spa_feature_stats_from_cache(spa_t *spa, nvlist_t *features)
static void
spa_add_feature_stats(spa_t *spa, nvlist_t *config)
{
nvlist_t *features = spa->spa_feat_stats;
nvlist_t *features;
ASSERT(spa_config_held(spa, SCL_CONFIG, RW_READER));
mutex_enter(&spa->spa_feat_stats_lock);
features = spa->spa_feat_stats;
if (features != NULL) {
spa_feature_stats_from_cache(spa, features);
} else {
@ -3278,6 +3281,8 @@ spa_add_feature_stats(spa_t *spa, nvlist_t *config)
VERIFY0(nvlist_add_nvlist(config, ZPOOL_CONFIG_FEATURE_STATS,
features));
mutex_exit(&spa->spa_feat_stats_lock);
}
int

View File

@ -531,6 +531,7 @@ spa_add(const char *name, nvlist_t *config, const char *altroot)
mutex_init(&spa->spa_scrub_lock, NULL, MUTEX_DEFAULT, NULL);
mutex_init(&spa->spa_suspend_lock, NULL, MUTEX_DEFAULT, NULL);
mutex_init(&spa->spa_vdev_top_lock, NULL, MUTEX_DEFAULT, NULL);
mutex_init(&spa->spa_feat_stats_lock, NULL, MUTEX_DEFAULT, NULL);
cv_init(&spa->spa_async_cv, NULL, CV_DEFAULT, NULL);
cv_init(&spa->spa_proc_cv, NULL, CV_DEFAULT, NULL);
@ -668,6 +669,7 @@ spa_remove(spa_t *spa)
mutex_destroy(&spa->spa_scrub_lock);
mutex_destroy(&spa->spa_suspend_lock);
mutex_destroy(&spa->spa_vdev_top_lock);
mutex_destroy(&spa->spa_feat_stats_lock);
kmem_free(spa, sizeof (spa_t));
}

View File

@ -68,7 +68,6 @@
#include <sys/zpl.h>
#include "zfs_comutil.h"
/*ARGSUSED*/
int
zfs_sync(struct super_block *sb, int wait, cred_t *cr)
@ -1074,6 +1073,67 @@ zfs_root(zfs_sb_t *zsb, struct inode **ipp)
}
EXPORT_SYMBOL(zfs_root);
#if !defined(HAVE_SPLIT_SHRINKER_CALLBACK) && !defined(HAVE_SHRINK) && \
defined(HAVE_D_PRUNE_ALIASES)
/*
* Linux kernels older than 3.1 do not support a per-filesystem shrinker.
* To accommodate this we must improvise and manually walk the list of znodes
* attempting to prune dentries in order to be able to drop the inodes.
*
* To avoid scanning the same znodes multiple times they are always rotated
* to the end of the z_all_znodes list. New znodes are inserted at the
* end of the list so we're always scanning the oldest znodes first.
*/
static int
zfs_sb_prune_aliases(zfs_sb_t *zsb, unsigned long nr_to_scan)
{
znode_t **zp_array, *zp;
int max_array = MIN(nr_to_scan, PAGE_SIZE * 8 / sizeof (znode_t *));
int objects = 0;
int i = 0, j = 0;
zp_array = kmem_zalloc(max_array * sizeof (znode_t *), KM_SLEEP);
mutex_enter(&zsb->z_znodes_lock);
while ((zp = list_head(&zsb->z_all_znodes)) != NULL) {
if ((i++ > nr_to_scan) || (j >= max_array))
break;
ASSERT(list_link_active(&zp->z_link_node));
list_remove(&zsb->z_all_znodes, zp);
list_insert_tail(&zsb->z_all_znodes, zp);
/* Skip active znodes and .zfs entries */
if (MUTEX_HELD(&zp->z_lock) || zp->z_is_ctldir)
continue;
if (igrab(ZTOI(zp)) == NULL)
continue;
zp_array[j] = zp;
j++;
}
mutex_exit(&zsb->z_znodes_lock);
for (i = 0; i < j; i++) {
zp = zp_array[i];
ASSERT3P(zp, !=, NULL);
d_prune_aliases(ZTOI(zp));
if (atomic_read(&ZTOI(zp)->i_count) == 1)
objects++;
iput(ZTOI(zp));
}
kmem_free(zp_array, max_array * sizeof (znode_t *));
return (objects);
}
#endif /* HAVE_D_PRUNE_ALIASES */
/*
* The ARC has requested that the filesystem drop entries from the dentry
* and inode caches. This can occur when the ARC needs to free meta data
@ -1094,22 +1154,24 @@ zfs_sb_prune(struct super_block *sb, unsigned long nr_to_scan, int *objects)
ZFS_ENTER(zsb);
#if defined(HAVE_SPLIT_SHRINKER_CALLBACK)
#if defined(HAVE_SPLIT_SHRINKER_CALLBACK) && \
defined(SHRINK_CONTROL_HAS_NID) && \
defined(SHRINKER_NUMA_AWARE)
if (sb->s_shrink.flags & SHRINKER_NUMA_AWARE) {
*objects = 0;
for_each_online_node(sc.nid)
*objects += (*shrinker->scan_objects)(shrinker, &sc);
} else {
*objects = (*shrinker->scan_objects)(shrinker, &sc);
}
#elif defined(HAVE_SPLIT_SHRINKER_CALLBACK)
*objects = (*shrinker->scan_objects)(shrinker, &sc);
#elif defined(HAVE_SHRINK)
*objects = (*shrinker->shrink)(shrinker, &sc);
#elif defined(HAVE_D_PRUNE_ALIASES)
*objects = zfs_sb_prune_aliases(zsb, nr_to_scan);
#else
/*
* Linux kernels older than 3.1 do not support a per-filesystem
* shrinker. Therefore, we must fall back to the only available
* interface which is to discard all unused dentries and inodes.
* This behavior clearly isn't ideal but it's required so the ARC
* may free memory. The performance impact is mitigated by the
* fact that the frequently accessed dentry and inode buffers will
* still be in the ARC making them relatively cheap to recreate.
*/
*objects = 0;
shrink_dcache_parent(sb->s_root);
#error "No available dentry and inode cache pruning mechanism."
#endif
ZFS_EXIT(zsb);
@ -1137,8 +1199,28 @@ zfs_sb_teardown(zfs_sb_t *zsb, boolean_t unmounting)
* drain the iput_taskq to ensure all active references to the
* zfs_sb_t have been handled only then can it be safely destroyed.
*/
if (zsb->z_os)
taskq_wait(dsl_pool_iput_taskq(dmu_objset_pool(zsb->z_os)));
if (zsb->z_os) {
/*
* If we're unmounting we have to wait for the list to
* drain completely.
*
* If we're not unmounting there's no guarantee the list
* will drain completely, but iputs run from the taskq
* may add the parents of dir-based xattrs to the taskq
* so we want to wait for these.
*
* We can safely read z_nr_znodes without locking because the
* VFS has already blocked operations which add to the
* z_all_znodes list and thus increment z_nr_znodes.
*/
int round = 0;
while (zsb->z_nr_znodes > 0) {
taskq_wait(dsl_pool_iput_taskq(dmu_objset_pool(
zsb->z_os)));
if (++round > 1 && !unmounting)
break;
}
}
rrw_enter(&zsb->z_teardown_lock, RW_WRITER, FTAG);
@ -1182,13 +1264,15 @@ zfs_sb_teardown(zfs_sb_t *zsb, boolean_t unmounting)
*
* Release all holds on dbufs.
*/
mutex_enter(&zsb->z_znodes_lock);
for (zp = list_head(&zsb->z_all_znodes); zp != NULL;
zp = list_next(&zsb->z_all_znodes, zp)) {
if (zp->z_sa_hdl)
zfs_znode_dmu_fini(zp);
if (!unmounting) {
mutex_enter(&zsb->z_znodes_lock);
for (zp = list_head(&zsb->z_all_znodes); zp != NULL;
zp = list_next(&zsb->z_all_znodes, zp)) {
if (zp->z_sa_hdl)
zfs_znode_dmu_fini(zp);
}
mutex_exit(&zsb->z_znodes_lock);
}
mutex_exit(&zsb->z_znodes_lock);
/*
* If we are unmounting, set the unmounted flag and let new VFS ops

View File

@ -147,12 +147,14 @@ void
zfs_znode_init(void)
{
/*
* Initialize zcache
* Initialize zcache. The KMC_SLAB hint is used in order that it be
* backed by kmalloc() when on the Linux slab in order that any
* wait_on_bit() operations on the related inode operate properly.
*/
ASSERT(znode_cache == NULL);
znode_cache = kmem_cache_create("zfs_znode_cache",
sizeof (znode_t), 0, zfs_znode_cache_constructor,
zfs_znode_cache_destructor, NULL, NULL, NULL, KMC_KMEM);
zfs_znode_cache_destructor, NULL, NULL, NULL, KMC_SLAB);
}
void
@ -948,6 +950,8 @@ again:
mutex_exit(&zp->z_lock);
sa_buf_rele(db, NULL);
ZFS_OBJ_HOLD_EXIT(zsb, obj_num);
/* inode might need this to finish evict */
cond_resched();
goto again;
}
*zpp = zp;

View File

@ -226,14 +226,17 @@ zpl_snapdir_lookup(struct inode *dip, struct dentry *dentry,
#endif
{
fstrans_cookie_t cookie;
cred_t *cr = CRED();
struct inode *ip = NULL;
int error;
crhold(cr);
cookie = spl_fstrans_mark();
error = -zfsctl_snapdir_lookup(dip, dname(dentry), &ip,
0, cr, NULL, NULL);
ASSERT3S(error, <=, 0);
spl_fstrans_unmark(cookie);
crfree(cr);
if (error && error != -ENOENT)
@ -250,21 +253,23 @@ static int
zpl_snapdir_iterate(struct file *filp, struct dir_context *ctx)
{
zfs_sb_t *zsb = ITOZSB(filp->f_path.dentry->d_inode);
fstrans_cookie_t cookie;
char snapname[MAXNAMELEN];
boolean_t case_conflict;
uint64_t id, cookie;
uint64_t id, pos;
int error = 0;
ZFS_ENTER(zsb);
cookie = spl_fstrans_mark();
if (!dir_emit_dots(filp, ctx))
goto out;
cookie = ctx->pos;
pos = ctx->pos;
while (error == 0) {
dsl_pool_config_enter(dmu_objset_pool(zsb->z_os), FTAG);
error = -dmu_snapshot_list_next(zsb->z_os, MAXNAMELEN,
snapname, &id, &cookie, &case_conflict);
snapname, &id, &pos, &case_conflict);
dsl_pool_config_exit(dmu_objset_pool(zsb->z_os), FTAG);
if (error)
goto out;
@ -273,9 +278,10 @@ zpl_snapdir_iterate(struct file *filp, struct dir_context *ctx)
ZFSCTL_INO_SHARES - id, DT_DIR))
goto out;
ctx->pos = cookie;
ctx->pos = pos;
}
out:
spl_fstrans_unmark(cookie);
ZFS_EXIT(zsb);
if (error == -ENOENT)
@ -414,14 +420,17 @@ zpl_shares_lookup(struct inode *dip, struct dentry *dentry,
unsigned int flags)
#endif
{
fstrans_cookie_t cookie;
cred_t *cr = CRED();
struct inode *ip = NULL;
int error;
crhold(cr);
cookie = spl_fstrans_mark();
error = -zfsctl_shares_lookup(dip, dname(dentry), &ip,
0, cr, NULL, NULL);
ASSERT3S(error, <=, 0);
spl_fstrans_unmark(cookie);
crfree(cr);
if (error) {
@ -437,12 +446,14 @@ zpl_shares_lookup(struct inode *dip, struct dentry *dentry,
static int
zpl_shares_iterate(struct file *filp, struct dir_context *ctx)
{
fstrans_cookie_t cookie;
cred_t *cr = CRED();
zfs_sb_t *zsb = ITOZSB(filp->f_path.dentry->d_inode);
znode_t *dzp;
int error = 0;
ZFS_ENTER(zsb);
cookie = spl_fstrans_mark();
if (zsb->z_shares_dir == 0) {
dir_emit_dots(filp, ctx);
@ -459,6 +470,7 @@ zpl_shares_iterate(struct file *filp, struct dir_context *ctx)
iput(ZTOI(dzp));
out:
spl_fstrans_unmark(cookie);
ZFS_EXIT(zsb);
ASSERT3S(error, <=, 0);

View File

@ -39,6 +39,7 @@ zpl_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len, int connectable)
{
struct inode *ip = dentry->d_inode;
#endif /* HAVE_ENCODE_FH_WITH_INODE */
fstrans_cookie_t cookie;
fid_t *fid = (fid_t *)fh;
int len_bytes, rc;
@ -48,12 +49,14 @@ zpl_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len, int connectable)
return (255);
fid->fid_len = len_bytes - offsetof(fid_t, fid_data);
cookie = spl_fstrans_mark();
if (zfsctl_is_node(ip))
rc = zfsctl_fid(ip, fid);
else
rc = zfs_fid(ip, fid);
spl_fstrans_unmark(cookie);
len_bytes = offsetof(fid_t, fid_data) + fid->fid_len;
*max_len = roundup(len_bytes, sizeof (__u32)) / sizeof (__u32);
@ -84,6 +87,7 @@ zpl_fh_to_dentry(struct super_block *sb, struct fid *fh,
int fh_len, int fh_type)
{
fid_t *fid = (fid_t *)fh;
fstrans_cookie_t cookie;
struct inode *ip;
int len_bytes, rc;
@ -94,7 +98,9 @@ zpl_fh_to_dentry(struct super_block *sb, struct fid *fh,
len_bytes < offsetof(fid_t, fid_data) + fid->fid_len)
return (ERR_PTR(-EINVAL));
cookie = spl_fstrans_mark();
rc = zfs_vget(sb, &ip, fid);
spl_fstrans_unmark(cookie);
if (rc != 0)
return (ERR_PTR(-rc));
@ -108,11 +114,14 @@ static struct dentry *
zpl_get_parent(struct dentry *child)
{
cred_t *cr = CRED();
fstrans_cookie_t cookie;
struct inode *ip;
int error;
crhold(cr);
cookie = spl_fstrans_mark();
error = -zfs_lookup(child->d_inode, "..", &ip, 0, cr, NULL, NULL);
spl_fstrans_unmark(cookie);
crfree(cr);
ASSERT3S(error, <=, 0);
@ -127,10 +136,13 @@ static int
zpl_commit_metadata(struct inode *inode)
{
cred_t *cr = CRED();
fstrans_cookie_t cookie;
int error;
crhold(cr);
cookie = spl_fstrans_mark();
error = -zfs_fsync(inode, 0, cr);
spl_fstrans_unmark(cookie);
crfree(cr);
ASSERT3S(error, <=, 0);

View File

@ -196,8 +196,7 @@ zpl_fsync(struct file *filp, loff_t start, loff_t end, int datasync)
static int
zpl_aio_fsync(struct kiocb *kiocb, int datasync)
{
return (zpl_fsync(kiocb->ki_filp, kiocb->ki_pos,
kiocb->ki_pos + kiocb->ki_nbytes, datasync));
return (zpl_fsync(kiocb->ki_filp, kiocb->ki_pos, -1, datasync));
}
#else
#error "Unsupported fops->fsync() implementation"
@ -261,12 +260,11 @@ zpl_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos)
}
static ssize_t
zpl_aio_read(struct kiocb *kiocb, const struct iovec *iovp,
unsigned long nr_segs, loff_t pos)
zpl_iter_read_common(struct kiocb *kiocb, const struct iovec *iovp,
unsigned long nr_segs, size_t count)
{
cred_t *cr = CRED();
struct file *filp = kiocb->ki_filp;
size_t count = kiocb->ki_nbytes;
ssize_t read;
size_t alloc_size = sizeof (struct iovec) * nr_segs;
struct iovec *iov_tmp = kmem_alloc(alloc_size, KM_SLEEP);
@ -284,6 +282,22 @@ zpl_aio_read(struct kiocb *kiocb, const struct iovec *iovp,
return (read);
}
#if defined(HAVE_VFS_RW_ITERATE)
static ssize_t
zpl_iter_read(struct kiocb *kiocb, struct iov_iter *to)
{
return (zpl_iter_read_common(kiocb, to->iov, to->nr_segs,
iov_iter_count(to)));
}
#else
static ssize_t
zpl_aio_read(struct kiocb *kiocb, const struct iovec *iovp,
unsigned long nr_segs, loff_t pos)
{
return (zpl_iter_read_common(kiocb, iovp, nr_segs, kiocb->ki_nbytes));
}
#endif /* HAVE_VFS_RW_ITERATE */
static inline ssize_t
zpl_write_common_iovec(struct inode *ip, const struct iovec *iovp, size_t count,
unsigned long nr_segs, loff_t *ppos, uio_seg_t segment,
@ -344,12 +358,11 @@ zpl_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos)
}
static ssize_t
zpl_aio_write(struct kiocb *kiocb, const struct iovec *iovp,
unsigned long nr_segs, loff_t pos)
zpl_iter_write_common(struct kiocb *kiocb, const struct iovec *iovp,
unsigned long nr_segs, size_t count)
{
cred_t *cr = CRED();
struct file *filp = kiocb->ki_filp;
size_t count = kiocb->ki_nbytes;
ssize_t wrote;
size_t alloc_size = sizeof (struct iovec) * nr_segs;
struct iovec *iov_tmp = kmem_alloc(alloc_size, KM_SLEEP);
@ -367,6 +380,22 @@ zpl_aio_write(struct kiocb *kiocb, const struct iovec *iovp,
return (wrote);
}
#if defined(HAVE_VFS_RW_ITERATE)
static ssize_t
zpl_iter_write(struct kiocb *kiocb, struct iov_iter *from)
{
return (zpl_iter_write_common(kiocb, from->iov, from->nr_segs,
iov_iter_count(from)));
}
#else
static ssize_t
zpl_aio_write(struct kiocb *kiocb, const struct iovec *iovp,
unsigned long nr_segs, loff_t pos)
{
return (zpl_iter_write_common(kiocb, iovp, nr_segs, kiocb->ki_nbytes));
}
#endif /* HAVE_VFS_RW_ITERATE */
static loff_t
zpl_llseek(struct file *filp, loff_t offset, int whence)
{
@ -778,8 +807,13 @@ const struct file_operations zpl_file_operations = {
.llseek = zpl_llseek,
.read = zpl_read,
.write = zpl_write,
#ifdef HAVE_VFS_RW_ITERATE
.read_iter = zpl_iter_read,
.write_iter = zpl_iter_write,
#else
.aio_read = zpl_aio_read,
.aio_write = zpl_aio_write,
#endif
.mmap = zpl_mmap,
.fsync = zpl_fsync,
.aio_fsync = zpl_aio_fsync,

View File

@ -106,13 +106,13 @@ zpl_create(struct inode *dir, struct dentry *dentry, zpl_umode_t mode,
cookie = spl_fstrans_mark();
error = -zfs_create(dir, dname(dentry), vap, 0, mode, &ip, cr, 0, NULL);
spl_fstrans_unmark(cookie);
if (error == 0) {
VERIFY0(zpl_xattr_security_init(ip, dir, &dentry->d_name));
VERIFY0(zpl_init_acl(ip, dir));
d_instantiate(dentry, ip);
}
spl_fstrans_unmark(cookie);
kmem_free(vap, sizeof (vattr_t));
crfree(cr);
ASSERT3S(error, <=, 0);
@ -144,13 +144,13 @@ zpl_mknod(struct inode *dir, struct dentry *dentry, zpl_umode_t mode,
cookie = spl_fstrans_mark();
error = -zfs_create(dir, dname(dentry), vap, 0, mode, &ip, cr, 0, NULL);
spl_fstrans_unmark(cookie);
if (error == 0) {
VERIFY0(zpl_xattr_security_init(ip, dir, &dentry->d_name));
VERIFY0(zpl_init_acl(ip, dir));
d_instantiate(dentry, ip);
}
spl_fstrans_unmark(cookie);
kmem_free(vap, sizeof (vattr_t));
crfree(cr);
ASSERT3S(error, <=, 0);
@ -190,13 +190,13 @@ zpl_mkdir(struct inode *dir, struct dentry *dentry, zpl_umode_t mode)
cookie = spl_fstrans_mark();
error = -zfs_mkdir(dir, dname(dentry), vap, &ip, cr, 0, NULL);
spl_fstrans_unmark(cookie);
if (error == 0) {
VERIFY0(zpl_xattr_security_init(ip, dir, &dentry->d_name));
VERIFY0(zpl_init_acl(ip, dir));
d_instantiate(dentry, ip);
}
spl_fstrans_unmark(cookie);
kmem_free(vap, sizeof (vattr_t));
crfree(cr);
ASSERT3S(error, <=, 0);
@ -273,10 +273,10 @@ zpl_setattr(struct dentry *dentry, struct iattr *ia)
cookie = spl_fstrans_mark();
error = -zfs_setattr(ip, vap, 0, cr);
spl_fstrans_unmark(cookie);
if (!error && (ia->ia_valid & ATTR_MODE))
error = zpl_chmod_acl(ip);
spl_fstrans_unmark(cookie);
kmem_free(vap, sizeof (vattr_t));
crfree(cr);
ASSERT3S(error, <=, 0);
@ -317,12 +317,12 @@ zpl_symlink(struct inode *dir, struct dentry *dentry, const char *name)
cookie = spl_fstrans_mark();
error = -zfs_symlink(dir, dname(dentry), vap, (char *)name, &ip, cr, 0);
spl_fstrans_unmark(cookie);
if (error == 0) {
VERIFY0(zpl_xattr_security_init(ip, dir, &dentry->d_name));
d_instantiate(dentry, ip);
}
spl_fstrans_unmark(cookie);
kmem_free(vap, sizeof (vattr_t));
crfree(cr);
ASSERT3S(error, <=, 0);
@ -391,7 +391,6 @@ zpl_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
cookie = spl_fstrans_mark();
error = -zfs_link(dir, ip, dname(dentry), cr);
spl_fstrans_unmark(cookie);
if (error) {
iput(ip);
goto out;
@ -399,6 +398,7 @@ zpl_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
d_instantiate(dentry, ip);
out:
spl_fstrans_unmark(cookie);
crfree(cr);
ASSERT3S(error, <=, 0);

View File

@ -57,13 +57,21 @@ zpl_inode_destroy(struct inode *ip)
static void
zpl_dirty_inode(struct inode *ip, int flags)
{
fstrans_cookie_t cookie;
cookie = spl_fstrans_mark();
zfs_dirty_inode(ip, flags);
spl_fstrans_unmark(cookie);
}
#else
static void
zpl_dirty_inode(struct inode *ip)
{
fstrans_cookie_t cookie;
cookie = spl_fstrans_mark();
zfs_dirty_inode(ip, 0);
spl_fstrans_unmark(cookie);
}
#endif /* HAVE_DIRTY_INODE_WITH_FLAGS */
@ -136,20 +144,26 @@ zpl_inode_delete(struct inode *ip)
static void
zpl_put_super(struct super_block *sb)
{
fstrans_cookie_t cookie;
int error;
cookie = spl_fstrans_mark();
error = -zfs_umount(sb);
spl_fstrans_unmark(cookie);
ASSERT3S(error, <=, 0);
}
static int
zpl_sync_fs(struct super_block *sb, int wait)
{
fstrans_cookie_t cookie;
cred_t *cr = CRED();
int error;
crhold(cr);
cookie = spl_fstrans_mark();
error = -zfs_sync(sb, wait, cr);
spl_fstrans_unmark(cookie);
crfree(cr);
ASSERT3S(error, <=, 0);
@ -159,9 +173,12 @@ zpl_sync_fs(struct super_block *sb, int wait)
static int
zpl_statfs(struct dentry *dentry, struct kstatfs *statp)
{
fstrans_cookie_t cookie;
int error;
cookie = spl_fstrans_mark();
error = -zfs_statvfs(dentry, statp);
spl_fstrans_unmark(cookie);
ASSERT3S(error, <=, 0);
return (error);
@ -170,8 +187,12 @@ zpl_statfs(struct dentry *dentry, struct kstatfs *statp)
static int
zpl_remount_fs(struct super_block *sb, int *flags, char *data)
{
fstrans_cookie_t cookie;
int error;
cookie = spl_fstrans_mark();
error = -zfs_remount(sb, flags, data);
spl_fstrans_unmark(cookie);
ASSERT3S(error, <=, 0);
return (error);
@ -242,9 +263,12 @@ zpl_show_options(struct seq_file *seq, struct vfsmount *vfsp)
static int
zpl_fill_super(struct super_block *sb, void *data, int silent)
{
fstrans_cookie_t cookie;
int error;
cookie = spl_fstrans_mark();
error = -zfs_domount(sb, data, silent);
spl_fstrans_unmark(cookie);
ASSERT3S(error, <=, 0);
return (error);

View File

@ -209,9 +209,11 @@ zpl_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size)
zfs_sb_t *zsb = ZTOZSB(zp);
xattr_filldir_t xf = { buffer_size, 0, buffer, dentry->d_inode };
cred_t *cr = CRED();
fstrans_cookie_t cookie;
int error = 0;
crhold(cr);
cookie = spl_fstrans_mark();
rw_enter(&zp->z_xattr_lock, RW_READER);
if (zsb->z_use_sa && zp->z_is_sa) {
@ -228,6 +230,7 @@ zpl_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size)
out:
rw_exit(&zp->z_xattr_lock);
spl_fstrans_unmark(cookie);
crfree(cr);
return (error);
@ -337,12 +340,15 @@ zpl_xattr_get(struct inode *ip, const char *name, void *value, size_t size)
{
znode_t *zp = ITOZ(ip);
cred_t *cr = CRED();
fstrans_cookie_t cookie;
int error;
crhold(cr);
cookie = spl_fstrans_mark();
rw_enter(&zp->z_xattr_lock, RW_READER);
error = __zpl_xattr_get(ip, name, value, size, cr);
rw_exit(&zp->z_xattr_lock);
spl_fstrans_unmark(cookie);
crfree(cr);
return (error);
@ -482,9 +488,11 @@ zpl_xattr_set(struct inode *ip, const char *name, const void *value,
znode_t *zp = ITOZ(ip);
zfs_sb_t *zsb = ZTOZSB(zp);
cred_t *cr = CRED();
fstrans_cookie_t cookie;
int error;
crhold(cr);
cookie = spl_fstrans_mark();
rw_enter(&ITOZ(ip)->z_xattr_lock, RW_WRITER);
/*
@ -522,6 +530,7 @@ zpl_xattr_set(struct inode *ip, const char *name, const void *value,
error = zpl_xattr_set_dir(ip, name, value, size, flags, cr);
out:
rw_exit(&ITOZ(ip)->z_xattr_lock);
spl_fstrans_unmark(cookie);
crfree(cr);
ASSERT3S(error, <=, 0);

View File

@ -185,6 +185,20 @@ chmod u+x ${RPM_BUILD_ROOT}%{kmodinstdir_prefix}/*/extra/*/*/*
rm -rf $RPM_BUILD_ROOT
%changelog
* Wed Jun 24 2015 Ned Bass <bass6@llnl.gov> - 0.6.4.2-1
- Fix panic due to corrupt nvlist when running utilities zfsonlinux/zfs#3335
- Fix hard lockup due to infinite loop in zfs_zget() zfsonlinux/zfs#3349
- Fix panic on unmount due to iput taskq zfsonlinux/zfs#3281
- Improve metadata shrinker performance on pre-3.1 kernels zfsonlinux/zfs#3501
- Linux 4.1 compat: use read_iter() / write_iter()
- Linux 3.12 compat: NUMA-aware per-superblock shrinker
- Fix spurious hung task watchdog stack traces zfsonlinux/zfs#3402
- Fix module loading in zfs import systemd service zfsonlinux/zfs#3440
- Fix intermittent libzfs_init() failure to open /dev/zfs zfsonlinux/zfs#2556
* Thu Apr 23 2015 Brian Behlendorf <behlendorf1@llnl.gov> - 0.6.4.1-1
- Fix direct memory reclaim deadlocks zfsonlinux/zfs#3331 zfsonlinux/zfs#3225
- Fix hot-disk sparing for disk vdevs zfsonlinux/zfs#3310
- Fix system spinning during ARC reclaim zfsonlinux/zfs#3283
* Wed Apr 8 2015 Brian Behlendorf <behlendorf1@llnl.gov> - 0.6.4-1
- Released 0.6.4-1
* Thu Jun 12 2014 Brian Behlendorf <behlendorf1@llnl.gov> - 0.6.3-1

View File

@ -295,6 +295,20 @@ exit 0
%{_dracutdir}/modules.d/*
%changelog
* Wed Jun 24 2015 Ned Bass <bass6@llnl.gov> - 0.6.4.2-1
- Fix panic due to corrupt nvlist when running utilities zfsonlinux/zfs#3335
- Fix hard lockup due to infinite loop in zfs_zget() zfsonlinux/zfs#3349
- Fix panic on unmount due to iput taskq zfsonlinux/zfs#3281
- Improve metadata shrinker performance on pre-3.1 kernels zfsonlinux/zfs#3501
- Linux 4.1 compat: use read_iter() / write_iter()
- Linux 3.12 compat: NUMA-aware per-superblock shrinker
- Fix spurious hung task watchdog stack traces zfsonlinux/zfs#3402
- Fix module loading in zfs import systemd service zfsonlinux/zfs#3440
- Fix intermittent libzfs_init() failure to open /dev/zfs zfsonlinux/zfs#2556
* Thu Apr 23 2015 Brian Behlendorf <behlendorf1@llnl.gov> - 0.6.4.1-1
- Fix direct memory reclaim deadlocks zfsonlinux/zfs#3331 zfsonlinux/zfs#3225
- Fix hot-disk sparing for disk vdevs zfsonlinux/zfs#3310
- Fix system spinning during ARC reclaim zfsonlinux/zfs#3283
* Wed Apr 8 2015 Brian Behlendorf <behlendorf1@llnl.gov> - 0.6.4-1
- Released 0.6.4-1
* Thu Jun 12 2014 Brian Behlendorf <behlendorf1@llnl.gov> - 0.6.3-1