[Midnightbsd-cvs] src [9155] trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs: sync with freebsd 9.2
laffer1 at midnightbsd.org
laffer1 at midnightbsd.org
Thu Oct 13 22:04:39 EDT 2016
Revision: 9155
http://svnweb.midnightbsd.org/src/?rev=9155
Author: laffer1
Date: 2016-10-13 22:04:39 -0400 (Thu, 13 Oct 2016)
Log Message:
-----------
sync with freebsd 9.2
Modified Paths:
--------------
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/bplist.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/bpobj.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/bptree.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt_zap.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_diff.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_object.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_objset.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_traverse.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_tx.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_zfetch.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode_sync.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_deadlist.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_deleg.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_destroy.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dir.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_prop.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_scan.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_synctask.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_userhold.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/gzip.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/lz4.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/lzjb.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/metaslab.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/refcount.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/rrwlock.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sa.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sha256.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_config.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_errlog.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_history.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/space_map.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/arc.h
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dbuf.h
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/ddt.h
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu_objset.h
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dnode.h
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dataset.h
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_pool.h
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_scan.h
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_userhold.h
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/sa_impl.h
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa_impl.h
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/space_map.h
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/txg_impl.h
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/unique.h
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/vdev_impl.h
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zap.h
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zap_leaf.h
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_acl.h
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_ioctl.h
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_rlock.h
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_znode.h
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zil.h
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio_impl.h
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/trim_map.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/txg.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/uberblock.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/unique.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_cache.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_disk.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_file.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_label.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_mirror.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_missing.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_queue.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_raidz.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_root.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap_leaf.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap_micro.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfeature.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_acl.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_byteswap.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_debug.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_dir.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_fm.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_fuid.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_log.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_onexit.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_replay.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_rlock.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_sa.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio_checksum.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio_compress.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio_inject.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zle.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zrlock.c
trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -22,6 +23,7 @@
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
*/
/*
@@ -57,11 +59,11 @@
* tight.
*
* 3. The Megiddo and Modha model assumes a fixed page size. All
- * elements of the cache are therefor exactly the same size. So
+ * elements of the cache are therefore exactly the same size. So
* when adjusting the cache size following a cache miss, its simply
* a matter of choosing a single page to evict. In our model, we
* have variable sized cache blocks (rangeing from 512 bytes to
- * 128K bytes). We therefor choose a set of blocks to evict to make
+ * 128K bytes). We therefore choose a set of blocks to evict to make
* space for a cache miss that approximates as closely as possible
* the space used by the new block.
*
@@ -76,7 +78,7 @@
* ways: 1) via a hash table lookup using the DVA as a key,
* or 2) via one of the ARC lists. The arc_read() interface
* uses method 1, while the internal arc algorithms for
- * adjusting the cache use method 2. We therefor provide two
+ * adjusting the cache use method 2. We therefore provide two
* types of locks: 1) the hash table lock array, and 2) the
* arc list locks.
*
@@ -120,6 +122,7 @@
#include <sys/spa.h>
#include <sys/zio.h>
+#include <sys/zio_compress.h>
#include <sys/zfs_context.h>
#include <sys/arc.h>
#include <sys/refcount.h>
@@ -287,7 +290,18 @@
kstat_named_t arcstat_deleted;
kstat_named_t arcstat_stolen;
kstat_named_t arcstat_recycle_miss;
+ /*
+ * Number of buffers that could not be evicted because the hash lock
+ * was held by another thread. The lock may not necessarily be held
+ * by something using the same buffer, since hash locks are shared
+ * by multiple buffers.
+ */
kstat_named_t arcstat_mutex_miss;
+ /*
+ * Number of buffers skipped because they have I/O in progress, are
+ * indrect prefetch buffers that have not lived long enough, or are
+ * not from the spa we're trying to evict from.
+ */
kstat_named_t arcstat_evict_skip;
kstat_named_t arcstat_evict_l2_cached;
kstat_named_t arcstat_evict_l2_eligible;
@@ -322,7 +336,11 @@
kstat_named_t arcstat_l2_cksum_bad;
kstat_named_t arcstat_l2_io_error;
kstat_named_t arcstat_l2_size;
+ kstat_named_t arcstat_l2_asize;
kstat_named_t arcstat_l2_hdr_size;
+ kstat_named_t arcstat_l2_compress_successes;
+ kstat_named_t arcstat_l2_compress_zeros;
+ kstat_named_t arcstat_l2_compress_failures;
kstat_named_t arcstat_l2_write_trylock_fail;
kstat_named_t arcstat_l2_write_passed_headroom;
kstat_named_t arcstat_l2_write_spa_mismatch;
@@ -395,7 +413,11 @@
{ "l2_cksum_bad", KSTAT_DATA_UINT64 },
{ "l2_io_error", KSTAT_DATA_UINT64 },
{ "l2_size", KSTAT_DATA_UINT64 },
+ { "l2_asize", KSTAT_DATA_UINT64 },
{ "l2_hdr_size", KSTAT_DATA_UINT64 },
+ { "l2_compress_successes", KSTAT_DATA_UINT64 },
+ { "l2_compress_zeros", KSTAT_DATA_UINT64 },
+ { "l2_compress_failures", KSTAT_DATA_UINT64 },
{ "l2_write_trylock_fail", KSTAT_DATA_UINT64 },
{ "l2_write_passed_headroom", KSTAT_DATA_UINT64 },
{ "l2_write_spa_mismatch", KSTAT_DATA_UINT64 },
@@ -417,7 +439,7 @@
#define ARCSTAT(stat) (arc_stats.stat.value.ui64)
#define ARCSTAT_INCR(stat, val) \
- atomic_add_64(&arc_stats.stat.value.ui64, (val));
+ atomic_add_64(&arc_stats.stat.value.ui64, (val))
#define ARCSTAT_BUMP(stat) ARCSTAT_INCR(stat, 1)
#define ARCSTAT_BUMPDOWN(stat) ARCSTAT_INCR(stat, -1)
@@ -474,6 +496,9 @@
#define arc_c_min ARCSTAT(arcstat_c_min) /* min target cache size */
#define arc_c_max ARCSTAT(arcstat_c_max) /* max target cache size */
+#define L2ARC_IS_VALID_COMPRESS(_c_) \
+ ((_c_) == ZIO_COMPRESS_LZ4 || (_c_) == ZIO_COMPRESS_EMPTY)
+
static int arc_no_grow; /* Don't try to grow cache size */
static uint64_t arc_tempreserve;
static uint64_t arc_loaned_bytes;
@@ -636,7 +661,12 @@
*/
#define L2ARC_WRITE_SIZE (8 * 1024 * 1024) /* initial write max */
-#define L2ARC_HEADROOM 2 /* num of writes */
+#define L2ARC_HEADROOM 2 /* num of writes */
+/*
+ * If we discover during ARC scan any buffers to be compressed, we boost
+ * our headroom for the next scanning cycle by this percentage multiple.
+ */
+#define L2ARC_HEADROOM_BOOST 200
#define L2ARC_FEED_SECS 1 /* caching interval secs */
#define L2ARC_FEED_MIN_MS 200 /* min caching interval ms */
@@ -643,12 +673,11 @@
#define l2arc_writes_sent ARCSTAT(arcstat_l2_writes_sent)
#define l2arc_writes_done ARCSTAT(arcstat_l2_writes_done)
-/*
- * L2ARC Performance Tunables
- */
+/* L2ARC Performance Tunables */
uint64_t l2arc_write_max = L2ARC_WRITE_SIZE; /* default max write size */
uint64_t l2arc_write_boost = L2ARC_WRITE_SIZE; /* extra write during warmup */
uint64_t l2arc_headroom = L2ARC_HEADROOM; /* number of dev writes */
+uint64_t l2arc_headroom_boost = L2ARC_HEADROOM_BOOST;
uint64_t l2arc_feed_secs = L2ARC_FEED_SECS; /* interval seconds */
uint64_t l2arc_feed_min_ms = L2ARC_FEED_MIN_MS; /* min interval milliseconds */
boolean_t l2arc_noprefetch = B_TRUE; /* don't cache prefetch bufs */
@@ -722,8 +751,6 @@
vdev_t *l2ad_vdev; /* vdev */
spa_t *l2ad_spa; /* spa */
uint64_t l2ad_hand; /* next write location */
- uint64_t l2ad_write; /* desired write size, bytes */
- uint64_t l2ad_boost; /* warmup write boost, bytes */
uint64_t l2ad_start; /* first addr on device */
uint64_t l2ad_end; /* last addr on device */
uint64_t l2ad_evict; /* last addr eviction reached */
@@ -744,11 +771,12 @@
static uint64_t l2arc_ndev; /* number of devices */
typedef struct l2arc_read_callback {
- arc_buf_t *l2rcb_buf; /* read buffer */
- spa_t *l2rcb_spa; /* spa */
- blkptr_t l2rcb_bp; /* original blkptr */
- zbookmark_t l2rcb_zb; /* original bookmark */
- int l2rcb_flags; /* original flags */
+ arc_buf_t *l2rcb_buf; /* read buffer */
+ spa_t *l2rcb_spa; /* spa */
+ blkptr_t l2rcb_bp; /* original blkptr */
+ zbookmark_t l2rcb_zb; /* original bookmark */
+ int l2rcb_flags; /* original flags */
+ enum zio_compress l2rcb_compress; /* applied compress */
} l2arc_read_callback_t;
typedef struct l2arc_write_callback {
@@ -758,8 +786,14 @@
struct l2arc_buf_hdr {
/* protected by arc_buf_hdr mutex */
- l2arc_dev_t *b_dev; /* L2ARC device */
- uint64_t b_daddr; /* disk address, offset byte */
+ l2arc_dev_t *b_dev; /* L2ARC device */
+ uint64_t b_daddr; /* disk address, offset byte */
+ /* compression applied to buffer data */
+ enum zio_compress b_compress;
+ /* real alloc'd buffer size depending on b_compress applied */
+ int b_asize;
+ /* temporary buffer holder for in-flight compressed data */
+ void *b_tmp_cdata;
};
typedef struct l2arc_data_free {
@@ -778,6 +812,11 @@
static void l2arc_hdr_stat_add(void);
static void l2arc_hdr_stat_remove(void);
+static boolean_t l2arc_compress_buf(l2arc_buf_hdr_t *l2hdr);
+static void l2arc_decompress_zio(zio_t *zio, arc_buf_hdr_t *hdr,
+ enum zio_compress c);
+static void l2arc_release_cdata_buf(arc_buf_hdr_t *ab);
+
static uint64_t
buf_hash(uint64_t spa, const dva_t *dva, uint64_t birth)
{
@@ -1696,6 +1735,7 @@
hdr->b_size, 0);
list_remove(l2hdr->b_dev->l2ad_buflist, hdr);
ARCSTAT_INCR(arcstat_l2_size, -hdr->b_size);
+ ARCSTAT_INCR(arcstat_l2_asize, -l2hdr->b_asize);
kmem_free(l2hdr, sizeof (l2arc_buf_hdr_t));
if (hdr->b_state == arc_l2c_only)
l2arc_hdr_stat_remove();
@@ -3118,6 +3158,8 @@
arc_access(hdr, hash_lock);
if (*arc_flags & ARC_L2CACHE)
hdr->b_flags |= ARC_L2CACHE;
+ if (*arc_flags & ARC_L2COMPRESS)
+ hdr->b_flags |= ARC_L2COMPRESS;
mutex_exit(hash_lock);
ARCSTAT_BUMP(arcstat_hits);
ARCSTAT_CONDSTAT(!(hdr->b_flags & ARC_PREFETCH),
@@ -3158,6 +3200,8 @@
}
if (*arc_flags & ARC_L2CACHE)
hdr->b_flags |= ARC_L2CACHE;
+ if (*arc_flags & ARC_L2COMPRESS)
+ hdr->b_flags |= ARC_L2COMPRESS;
if (BP_GET_LEVEL(bp) > 0)
hdr->b_flags |= ARC_INDIRECT;
} else {
@@ -3174,6 +3218,8 @@
add_reference(hdr, hash_lock, private);
if (*arc_flags & ARC_L2CACHE)
hdr->b_flags |= ARC_L2CACHE;
+ if (*arc_flags & ARC_L2COMPRESS)
+ hdr->b_flags |= ARC_L2COMPRESS;
buf = kmem_cache_alloc(buf_cache, KM_PUSHPAGE);
buf->b_hdr = hdr;
buf->b_data = NULL;
@@ -3211,6 +3257,10 @@
mutex_exit(hash_lock);
+ /*
+ * At this point, we have a level 1 cache miss. Try again in
+ * L2ARC if possible.
+ */
ASSERT3U(hdr->b_size, ==, size);
DTRACE_PROBE4(arc__miss, arc_buf_hdr_t *, hdr, blkptr_t *, bp,
uint64_t, size, zbookmark_t *, zb);
@@ -3247,6 +3297,7 @@
cb->l2rcb_bp = *bp;
cb->l2rcb_zb = *zb;
cb->l2rcb_flags = zio_flags;
+ cb->l2rcb_compress = hdr->b_l2hdr->b_compress;
ASSERT(addr >= VDEV_LABEL_START_SIZE &&
addr + size < vd->vdev_psize -
@@ -3255,16 +3306,31 @@
/*
* l2arc read. The SCL_L2ARC lock will be
* released by l2arc_read_done().
+ * Issue a null zio if the underlying buffer
+ * was squashed to zero size by compression.
*/
- rzio = zio_read_phys(pio, vd, addr, size,
- buf->b_data, ZIO_CHECKSUM_OFF,
- l2arc_read_done, cb, priority, zio_flags |
- ZIO_FLAG_DONT_CACHE | ZIO_FLAG_CANFAIL |
- ZIO_FLAG_DONT_PROPAGATE |
- ZIO_FLAG_DONT_RETRY, B_FALSE);
+ if (hdr->b_l2hdr->b_compress ==
+ ZIO_COMPRESS_EMPTY) {
+ rzio = zio_null(pio, spa, vd,
+ l2arc_read_done, cb,
+ zio_flags | ZIO_FLAG_DONT_CACHE |
+ ZIO_FLAG_CANFAIL |
+ ZIO_FLAG_DONT_PROPAGATE |
+ ZIO_FLAG_DONT_RETRY);
+ } else {
+ rzio = zio_read_phys(pio, vd, addr,
+ hdr->b_l2hdr->b_asize,
+ buf->b_data, ZIO_CHECKSUM_OFF,
+ l2arc_read_done, cb, priority,
+ zio_flags | ZIO_FLAG_DONT_CACHE |
+ ZIO_FLAG_CANFAIL |
+ ZIO_FLAG_DONT_PROPAGATE |
+ ZIO_FLAG_DONT_RETRY, B_FALSE);
+ }
DTRACE_PROBE2(l2arc__read, vdev_t *, vd,
zio_t *, rzio);
- ARCSTAT_INCR(arcstat_l2_read_bytes, size);
+ ARCSTAT_INCR(arcstat_l2_read_bytes,
+ hdr->b_l2hdr->b_asize);
if (*arc_flags & ARC_NOWAIT) {
zio_nowait(rzio);
@@ -3320,6 +3386,34 @@
}
/*
+ * Notify the arc that a block was freed, and thus will never be used again.
+ */
+void
+arc_freed(spa_t *spa, const blkptr_t *bp)
+{
+ arc_buf_hdr_t *hdr;
+ kmutex_t *hash_lock;
+ uint64_t guid = spa_load_guid(spa);
+
+ hdr = buf_hash_find(guid, BP_IDENTITY(bp), BP_PHYSICAL_BIRTH(bp),
+ &hash_lock);
+ if (hdr == NULL)
+ return;
+ if (HDR_BUF_AVAILABLE(hdr)) {
+ arc_buf_t *buf = hdr->b_buf;
+ add_reference(hdr, hash_lock, FTAG);
+ hdr->b_flags &= ~ARC_BUF_AVAILABLE;
+ mutex_exit(hash_lock);
+
+ arc_release(buf, FTAG);
+ (void) arc_buf_remove_ref(buf, FTAG);
+ } else {
+ mutex_exit(hash_lock);
+ }
+
+}
+
+/*
* This is used by the DMU to let the ARC know that a buffer is
* being evicted, so the ARC should clean up. If this arc buf
* is not yet in the evicted state, it will be put there.
@@ -3408,8 +3502,8 @@
}
/*
- * Release this buffer from the cache. This must be done
- * after a read and prior to modifying the buffer contents.
+ * Release this buffer from the cache, making it an anonymous buffer. This
+ * must be done after a read and prior to modifying the buffer contents.
* If the buffer has more than one reference, we must make
* a new hdr for the buffer.
*/
@@ -3531,6 +3625,7 @@
buf->b_private = NULL;
if (l2hdr) {
+ ARCSTAT_INCR(arcstat_l2_asize, -l2hdr->b_asize);
trim_map_free(l2hdr->b_dev->l2ad_vdev, l2hdr->b_daddr,
hdr->b_size, 0);
list_remove(l2hdr->b_dev->l2ad_buflist, hdr);
@@ -3682,9 +3777,9 @@
zio_t *
arc_write(zio_t *pio, spa_t *spa, uint64_t txg,
- blkptr_t *bp, arc_buf_t *buf, boolean_t l2arc, const zio_prop_t *zp,
- arc_done_func_t *ready, arc_done_func_t *done, void *private,
- int priority, int zio_flags, const zbookmark_t *zb)
+ blkptr_t *bp, arc_buf_t *buf, boolean_t l2arc, boolean_t l2arc_compress,
+ const zio_prop_t *zp, arc_done_func_t *ready, arc_done_func_t *done,
+ void *private, int priority, int zio_flags, const zbookmark_t *zb)
{
arc_buf_hdr_t *hdr = buf->b_hdr;
arc_write_callback_t *callback;
@@ -3697,6 +3792,8 @@
ASSERT(hdr->b_acb == NULL);
if (l2arc)
hdr->b_flags |= ARC_L2CACHE;
+ if (l2arc_compress)
+ hdr->b_flags |= ARC_L2COMPRESS;
callback = kmem_zalloc(sizeof (arc_write_callback_t), KM_SLEEP);
callback->awcb_ready = ready;
callback->awcb_done = done;
@@ -3802,7 +3899,7 @@
/*
* Writes will, almost always, require additional memory allocations
- * in order to compress/encrypt/etc the data. We therefor need to
+ * in order to compress/encrypt/etc the data. We therefore need to
* make sure that there is sufficient available memory for this.
*/
if (error = arc_memory_throttle(reserve, anon_size, txg))
@@ -4147,8 +4244,12 @@
* 2. The L2ARC attempts to cache data from the ARC before it is evicted.
* It does this by periodically scanning buffers from the eviction-end of
* the MFU and MRU ARC lists, copying them to the L2ARC devices if they are
- * not already there. It scans until a headroom of buffers is satisfied,
- * which itself is a buffer for ARC eviction. The thread that does this is
+ * not already there. It scans until a headroom of buffers is satisfied,
+ * which itself is a buffer for ARC eviction. If a compressible buffer is
+ * found during scanning and selected for writing to an L2ARC device, we
+ * temporarily boost scanning headroom during the next scan cycle to make
+ * sure we adapt to compression effects (which might significantly reduce
+ * the data volume we write to L2ARC). The thread that does this is
* l2arc_feed_thread(), illustrated below; example sizes are included to
* provide a better sense of ratio than this diagram:
*
@@ -4213,6 +4314,11 @@
* l2arc_write_boost extra write bytes during device warmup
* l2arc_noprefetch skip caching prefetched buffers
* l2arc_headroom number of max device writes to precache
+ * l2arc_headroom_boost when we find compressed buffers during ARC
+ * scanning, we multiply headroom by this
+ * percentage factor for the next scan cycle,
+ * since more compressed buffers are likely to
+ * be present
* l2arc_feed_secs seconds between L2ARC writing
*
* Tunables may be removed or added as future performance improvements are
@@ -4259,14 +4365,24 @@
}
static uint64_t
-l2arc_write_size(l2arc_dev_t *dev)
+l2arc_write_size(void)
{
uint64_t size;
- size = dev->l2ad_write;
+ /*
+ * Make sure our globals have meaningful values in case the user
+ * altered them.
+ */
+ size = l2arc_write_max;
+ if (size == 0) {
+ cmn_err(CE_NOTE, "Bad value for l2arc_write_max, value must "
+ "be greater than zero, resetting it to the default (%d)",
+ L2ARC_WRITE_SIZE);
+ size = l2arc_write_max = L2ARC_WRITE_SIZE;
+ }
if (arc_warm == B_FALSE)
- size += dev->l2ad_boost;
+ size += l2arc_write_boost;
return (size);
@@ -4440,12 +4556,20 @@
continue;
}
+ abl2 = ab->b_l2hdr;
+
+ /*
+ * Release the temporary compressed buffer as soon as possible.
+ */
+ if (abl2->b_compress != ZIO_COMPRESS_OFF)
+ l2arc_release_cdata_buf(ab);
+
if (zio->io_error != 0) {
/*
* Error - drop L2ARC entry.
*/
list_remove(buflist, ab);
- abl2 = ab->b_l2hdr;
+ ARCSTAT_INCR(arcstat_l2_asize, -abl2->b_asize);
ab->b_l2hdr = NULL;
trim_map_free(abl2->b_dev->l2ad_vdev, abl2->b_daddr,
ab->b_size, 0);
@@ -4500,6 +4624,13 @@
ASSERT3P(hash_lock, ==, HDR_LOCK(hdr));
/*
+ * If the buffer was compressed, decompress it first.
+ */
+ if (cb->l2rcb_compress != ZIO_COMPRESS_OFF)
+ l2arc_decompress_zio(zio, hdr, cb->l2rcb_compress);
+ ASSERT(zio->io_data != NULL);
+
+ /*
* Check this survived the L2ARC journey.
*/
equal = arc_cksum_equal(buf);
@@ -4695,6 +4826,7 @@
*/
if (ab->b_l2hdr != NULL) {
abl2 = ab->b_l2hdr;
+ ARCSTAT_INCR(arcstat_l2_asize, -abl2->b_asize);
ab->b_l2hdr = NULL;
kmem_free(abl2, sizeof (l2arc_buf_hdr_t));
ARCSTAT_INCR(arcstat_l2_size, -ab->b_size);
@@ -4720,26 +4852,36 @@
*
* An ARC_L2_WRITING flag is set so that the L2ARC buffers are not valid
* for reading until they have completed writing.
+ * The headroom_boost is an in-out parameter used to maintain headroom boost
+ * state between calls to this function.
+ *
+ * Returns the number of bytes actually written (which may be smaller than
+ * the delta by which the device hand has changed due to alignment).
*/
static uint64_t
-l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz)
+l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz,
+ boolean_t *headroom_boost)
{
arc_buf_hdr_t *ab, *ab_prev, *head;
- l2arc_buf_hdr_t *hdrl2;
list_t *list;
- uint64_t passed_sz, write_sz, buf_sz, headroom;
+ uint64_t write_asize, write_psize, write_sz, headroom,
+ buf_compress_minsz;
void *buf_data;
- kmutex_t *hash_lock, *list_lock;
- boolean_t have_lock, full;
+ kmutex_t *list_lock;
+ boolean_t full;
l2arc_write_callback_t *cb;
zio_t *pio, *wzio;
uint64_t guid = spa_load_guid(spa);
+ const boolean_t do_headroom_boost = *headroom_boost;
int try;
ASSERT(dev->l2ad_vdev != NULL);
+ /* Lower the flag now, we might want to raise it again later. */
+ *headroom_boost = B_FALSE;
+
pio = NULL;
- write_sz = 0;
+ write_sz = write_asize = write_psize = 0;
full = B_FALSE;
head = kmem_cache_alloc(hdr_cache, KM_PUSHPAGE);
head->b_flags |= ARC_L2_WRITE_HEAD;
@@ -4746,12 +4888,19 @@
ARCSTAT_BUMP(arcstat_l2_write_buffer_iter);
/*
+ * We will want to try to compress buffers that are at least 2x the
+ * device sector size.
+ */
+ buf_compress_minsz = 2 << dev->l2ad_vdev->vdev_ashift;
+
+ /*
* Copy buffers for L2ARC writing.
*/
mutex_enter(&l2arc_buflist_mtx);
for (try = 0; try < 2 * ARC_BUFC_NUMLISTS; try++) {
+ uint64_t passed_sz = 0;
+
list = l2arc_list_locked(try, &list_lock);
- passed_sz = 0;
ARCSTAT_BUMP(arcstat_l2_write_buffer_list_iter);
/*
@@ -4760,7 +4909,6 @@
* Until the ARC is warm and starts to evict, read from the
* head of the ARC lists rather than the tail.
*/
- headroom = target_sz * l2arc_headroom;
if (arc_warm == B_FALSE)
ab = list_head(list);
else
@@ -4768,7 +4916,15 @@
if (ab == NULL)
ARCSTAT_BUMP(arcstat_l2_write_buffer_list_null_iter);
+ headroom = target_sz * l2arc_headroom;
+ if (do_headroom_boost)
+ headroom = (headroom * l2arc_headroom_boost) / 100;
+
for (; ab; ab = ab_prev) {
+ l2arc_buf_hdr_t *l2hdr;
+ kmutex_t *hash_lock;
+ uint64_t buf_sz;
+
if (arc_warm == B_FALSE)
ab_prev = list_next(list, ab);
else
@@ -4776,8 +4932,7 @@
ARCSTAT_INCR(arcstat_l2_write_buffer_bytes_scanned, ab->b_size);
hash_lock = HDR_LOCK(ab);
- have_lock = MUTEX_HELD(hash_lock);
- if (!have_lock && !mutex_tryenter(hash_lock)) {
+ if (!mutex_tryenter(hash_lock)) {
ARCSTAT_BUMP(arcstat_l2_write_trylock_fail);
/*
* Skip this buffer rather than waiting.
@@ -4827,16 +4982,27 @@
/*
* Create and add a new L2ARC header.
*/
- hdrl2 = kmem_zalloc(sizeof (l2arc_buf_hdr_t), KM_SLEEP);
- hdrl2->b_dev = dev;
- hdrl2->b_daddr = dev->l2ad_hand;
+ l2hdr = kmem_zalloc(sizeof (l2arc_buf_hdr_t), KM_SLEEP);
+ l2hdr->b_dev = dev;
+ ab->b_flags |= ARC_L2_WRITING;
- ab->b_flags |= ARC_L2_WRITING;
- ab->b_l2hdr = hdrl2;
- list_insert_head(dev->l2ad_buflist, ab);
- buf_data = ab->b_buf->b_data;
+ /*
+ * Temporarily stash the data buffer in b_tmp_cdata.
+ * The subsequent write step will pick it up from
+ * there. This is because can't access ab->b_buf
+ * without holding the hash_lock, which we in turn
+ * can't access without holding the ARC list locks
+ * (which we want to avoid during compression/writing).
+ */
+ l2hdr->b_compress = ZIO_COMPRESS_OFF;
+ l2hdr->b_asize = ab->b_size;
+ l2hdr->b_tmp_cdata = ab->b_buf->b_data;
+
buf_sz = ab->b_size;
+ ab->b_l2hdr = l2hdr;
+ list_insert_head(dev->l2ad_buflist, ab);
+
/*
* Compute and store the buffer cksum before
* writing. On debug the cksum is verified first.
@@ -4846,6 +5012,64 @@
mutex_exit(hash_lock);
+ write_sz += buf_sz;
+ }
+
+ mutex_exit(list_lock);
+
+ if (full == B_TRUE)
+ break;
+ }
+
+ /* No buffers selected for writing? */
+ if (pio == NULL) {
+ ASSERT0(write_sz);
+ mutex_exit(&l2arc_buflist_mtx);
+ kmem_cache_free(hdr_cache, head);
+ return (0);
+ }
+
+ /*
+ * Now start writing the buffers. We're starting at the write head
+ * and work backwards, retracing the course of the buffer selector
+ * loop above.
+ */
+ for (ab = list_prev(dev->l2ad_buflist, head); ab;
+ ab = list_prev(dev->l2ad_buflist, ab)) {
+ l2arc_buf_hdr_t *l2hdr;
+ uint64_t buf_sz;
+
+ /*
+ * We shouldn't need to lock the buffer here, since we flagged
+ * it as ARC_L2_WRITING in the previous step, but we must take
+ * care to only access its L2 cache parameters. In particular,
+ * ab->b_buf may be invalid by now due to ARC eviction.
+ */
+ l2hdr = ab->b_l2hdr;
+ l2hdr->b_daddr = dev->l2ad_hand;
+
+ if ((ab->b_flags & ARC_L2COMPRESS) &&
+ l2hdr->b_asize >= buf_compress_minsz) {
+ if (l2arc_compress_buf(l2hdr)) {
+ /*
+ * If compression succeeded, enable headroom
+ * boost on the next scan cycle.
+ */
+ *headroom_boost = B_TRUE;
+ }
+ }
+
+ /*
+ * Pick up the buffer data we had previously stashed away
+ * (and now potentially also compressed).
+ */
+ buf_data = l2hdr->b_tmp_cdata;
+ buf_sz = l2hdr->b_asize;
+
+ /* Compression may have squashed the buffer to zero length. */
+ if (buf_sz != 0) {
+ uint64_t buf_p_sz;
+
wzio = zio_write_phys(pio, dev->l2ad_vdev,
dev->l2ad_hand, buf_sz, buf_data, ZIO_CHECKSUM_OFF,
NULL, NULL, ZIO_PRIORITY_ASYNC_WRITE,
@@ -4855,33 +5079,24 @@
zio_t *, wzio);
(void) zio_nowait(wzio);
+ write_asize += buf_sz;
/*
* Keep the clock hand suitably device-aligned.
*/
- buf_sz = vdev_psize_to_asize(dev->l2ad_vdev, buf_sz);
-
- write_sz += buf_sz;
- dev->l2ad_hand += buf_sz;
+ buf_p_sz = vdev_psize_to_asize(dev->l2ad_vdev, buf_sz);
+ write_psize += buf_p_sz;
+ dev->l2ad_hand += buf_p_sz;
}
+ }
- mutex_exit(list_lock);
-
- if (full == B_TRUE)
- break;
- }
mutex_exit(&l2arc_buflist_mtx);
- if (pio == NULL) {
- ASSERT0(write_sz);
- kmem_cache_free(hdr_cache, head);
- return (0);
- }
-
- ASSERT3U(write_sz, <=, target_sz);
+ ASSERT3U(write_asize, <=, target_sz);
ARCSTAT_BUMP(arcstat_l2_writes_sent);
- ARCSTAT_INCR(arcstat_l2_write_bytes, write_sz);
+ ARCSTAT_INCR(arcstat_l2_write_bytes, write_asize);
ARCSTAT_INCR(arcstat_l2_size, write_sz);
- vdev_space_update(dev->l2ad_vdev, write_sz, 0, 0);
+ ARCSTAT_INCR(arcstat_l2_asize, write_asize);
+ vdev_space_update(dev->l2ad_vdev, write_psize, 0, 0);
/*
* Bump device hand to the device start if it is approaching the end.
@@ -4899,10 +5114,156 @@
(void) zio_wait(pio);
dev->l2ad_writing = B_FALSE;
- return (write_sz);
+ return (write_asize);
}
/*
+ * Compresses an L2ARC buffer.
+ * The data to be compressed must be prefilled in l2hdr->b_tmp_cdata and its
+ * size in l2hdr->b_asize. This routine tries to compress the data and
+ * depending on the compression result there are three possible outcomes:
+ * *) The buffer was incompressible. The original l2hdr contents were left
+ * untouched and are ready for writing to an L2 device.
+ * *) The buffer was all-zeros, so there is no need to write it to an L2
+ * device. To indicate this situation b_tmp_cdata is NULL'ed, b_asize is
+ * set to zero and b_compress is set to ZIO_COMPRESS_EMPTY.
+ * *) Compression succeeded and b_tmp_cdata was replaced with a temporary
+ * data buffer which holds the compressed data to be written, and b_asize
+ * tells us how much data there is. b_compress is set to the appropriate
+ * compression algorithm. Once writing is done, invoke
+ * l2arc_release_cdata_buf on this l2hdr to free this temporary buffer.
+ *
+ * Returns B_TRUE if compression succeeded, or B_FALSE if it didn't (the
+ * buffer was incompressible).
+ */
+static boolean_t
+l2arc_compress_buf(l2arc_buf_hdr_t *l2hdr)
+{
+ void *cdata;
+ size_t csize, len;
+
+ ASSERT(l2hdr->b_compress == ZIO_COMPRESS_OFF);
+ ASSERT(l2hdr->b_tmp_cdata != NULL);
+
+ len = l2hdr->b_asize;
+ cdata = zio_data_buf_alloc(len);
+ csize = zio_compress_data(ZIO_COMPRESS_LZ4, l2hdr->b_tmp_cdata,
+ cdata, l2hdr->b_asize);
+
+ if (csize == 0) {
+ /* zero block, indicate that there's nothing to write */
+ zio_data_buf_free(cdata, len);
+ l2hdr->b_compress = ZIO_COMPRESS_EMPTY;
+ l2hdr->b_asize = 0;
+ l2hdr->b_tmp_cdata = NULL;
+ ARCSTAT_BUMP(arcstat_l2_compress_zeros);
+ return (B_TRUE);
+ } else if (csize > 0 && csize < len) {
+ /*
+ * Compression succeeded, we'll keep the cdata around for
+ * writing and release it afterwards.
+ */
+ l2hdr->b_compress = ZIO_COMPRESS_LZ4;
+ l2hdr->b_asize = csize;
+ l2hdr->b_tmp_cdata = cdata;
+ ARCSTAT_BUMP(arcstat_l2_compress_successes);
+ return (B_TRUE);
+ } else {
+ /*
+ * Compression failed, release the compressed buffer.
+ * l2hdr will be left unmodified.
+ */
+ zio_data_buf_free(cdata, len);
+ ARCSTAT_BUMP(arcstat_l2_compress_failures);
+ return (B_FALSE);
+ }
+}
+
+/*
+ * Decompresses a zio read back from an l2arc device. On success, the
+ * underlying zio's io_data buffer is overwritten by the uncompressed
+ * version. On decompression error (corrupt compressed stream), the
+ * zio->io_error value is set to signal an I/O error.
+ *
+ * Please note that the compressed data stream is not checksummed, so
+ * if the underlying device is experiencing data corruption, we may feed
+ * corrupt data to the decompressor, so the decompressor needs to be
+ * able to handle this situation (LZ4 does).
+ */
+static void
+l2arc_decompress_zio(zio_t *zio, arc_buf_hdr_t *hdr, enum zio_compress c)
+{
+ ASSERT(L2ARC_IS_VALID_COMPRESS(c));
+
+ if (zio->io_error != 0) {
+ /*
+ * An io error has occured, just restore the original io
+ * size in preparation for a main pool read.
+ */
+ zio->io_orig_size = zio->io_size = hdr->b_size;
+ return;
+ }
+
+ if (c == ZIO_COMPRESS_EMPTY) {
+ /*
+ * An empty buffer results in a null zio, which means we
+ * need to fill its io_data after we're done restoring the
+ * buffer's contents.
+ */
+ ASSERT(hdr->b_buf != NULL);
+ bzero(hdr->b_buf->b_data, hdr->b_size);
+ zio->io_data = zio->io_orig_data = hdr->b_buf->b_data;
+ } else {
+ ASSERT(zio->io_data != NULL);
+ /*
+ * We copy the compressed data from the start of the arc buffer
+ * (the zio_read will have pulled in only what we need, the
+ * rest is garbage which we will overwrite at decompression)
+ * and then decompress back to the ARC data buffer. This way we
+ * can minimize copying by simply decompressing back over the
+ * original compressed data (rather than decompressing to an
+ * aux buffer and then copying back the uncompressed buffer,
+ * which is likely to be much larger).
+ */
+ uint64_t csize;
+ void *cdata;
+
+ csize = zio->io_size;
+ cdata = zio_data_buf_alloc(csize);
+ bcopy(zio->io_data, cdata, csize);
+ if (zio_decompress_data(c, cdata, zio->io_data, csize,
+ hdr->b_size) != 0)
+ zio->io_error = EIO;
+ zio_data_buf_free(cdata, csize);
+ }
+
+ /* Restore the expected uncompressed IO size. */
+ zio->io_orig_size = zio->io_size = hdr->b_size;
+}
+
+/*
+ * Releases the temporary b_tmp_cdata buffer in an l2arc header structure.
+ * This buffer serves as a temporary holder of compressed data while
+ * the buffer entry is being written to an l2arc device. Once that is
+ * done, we can dispose of it.
+ */
+static void
+l2arc_release_cdata_buf(arc_buf_hdr_t *ab)
+{
+ l2arc_buf_hdr_t *l2hdr = ab->b_l2hdr;
+
+ if (l2hdr->b_compress == ZIO_COMPRESS_LZ4) {
+ /*
+ * If the data was compressed, then we've allocated a
+ * temporary buffer for it, so now we need to release it.
+ */
+ ASSERT(l2hdr->b_tmp_cdata != NULL);
+ zio_data_buf_free(l2hdr->b_tmp_cdata, ab->b_size);
+ }
+ l2hdr->b_tmp_cdata = NULL;
+}
+
+/*
* This thread feeds the L2ARC at regular intervals. This is the beating
* heart of the L2ARC.
*/
@@ -4914,6 +5275,7 @@
spa_t *spa;
uint64_t size, wrote;
clock_t begin, next = ddi_get_lbolt();
+ boolean_t headroom_boost = B_FALSE;
CALLB_CPR_INIT(&cpr, &l2arc_feed_thr_lock, callb_generic_cpr, FTAG);
@@ -4974,7 +5336,7 @@
ARCSTAT_BUMP(arcstat_l2_feeds);
- size = l2arc_write_size(dev);
+ size = l2arc_write_size();
/*
* Evict L2ARC buffers that will be overwritten.
@@ -4984,7 +5346,7 @@
/*
* Write ARC buffers.
*/
- wrote = l2arc_write_buffers(spa, dev, size);
+ wrote = l2arc_write_buffers(spa, dev, size, &headroom_boost);
/*
* Calculate interval between writes.
@@ -5032,8 +5394,6 @@
adddev = kmem_zalloc(sizeof (l2arc_dev_t), KM_SLEEP);
adddev->l2ad_spa = spa;
adddev->l2ad_vdev = vd;
- adddev->l2ad_write = l2arc_write_max;
- adddev->l2ad_boost = l2arc_write_boost;
adddev->l2ad_start = VDEV_LABEL_START_SIZE;
adddev->l2ad_end = VDEV_LABEL_START_SIZE + vdev_get_min_asize(vd);
adddev->l2ad_hand = adddev->l2ad_start;
@@ -5040,7 +5400,6 @@
adddev->l2ad_evict = adddev->l2ad_start;
adddev->l2ad_first = B_TRUE;
adddev->l2ad_writing = B_FALSE;
- ASSERT3U(adddev->l2ad_write, >, 0);
/*
* This is a list of all ARC buffers that are still valid on the
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/bplist.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/bplist.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/bplist.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/bpobj.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/bpobj.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/bpobj.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/bptree.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/bptree.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/bptree.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -43,7 +44,7 @@
* dsl_scan_sync. This allows the delete operation to finish without traversing
* all the dataset's blocks.
*
- * Note that while bt_begin and bt_end are only ever incremented in this code
+ * Note that while bt_begin and bt_end are only ever incremented in this code,
* they are effectively reset to 0 every time the entire bptree is freed because
* the bptree's object is destroyed and re-created.
*/
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -22,6 +23,7 @@
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
*/
#include <sys/zfs_context.h>
@@ -568,6 +570,8 @@
if (DBUF_IS_L2CACHEABLE(db))
aflags |= ARC_L2CACHE;
+ if (DBUF_IS_L2COMPRESSIBLE(db))
+ aflags |= ARC_L2COMPRESS;
SET_BOOKMARK(&zb, db->db_objset->os_dsl_dataset ?
db->db_objset->os_dsl_dataset->ds_object : DMU_META_OBJSET,
@@ -638,6 +642,14 @@
if (!havepzio)
err = zio_wait(zio);
} else {
+ /*
+ * Another reader came in while the dbuf was in flight
+ * between UNCACHED and CACHED. Either a writer will finish
+ * writing the buffer (sending the dbuf to CACHED) or the
+ * first reader's request will reach the read_done callback
+ * and send the dbuf to CACHED. Otherwise, a failure
+ * occurred and the dbuf went to UNCACHED.
+ */
mutex_exit(&db->db_mtx);
if (prefetch)
dmu_zfetch(&dn->dn_zfetch, db->db.db_offset,
@@ -646,6 +658,7 @@
rw_exit(&dn->dn_struct_rwlock);
DB_DNODE_EXIT(db);
+ /* Skip the wait per the caller's request. */
mutex_enter(&db->db_mtx);
if ((flags & DB_RF_NEVERWAIT) == 0) {
while (db->db_state == DB_READ ||
@@ -1261,7 +1274,8 @@
}
/*
- * Return TRUE if this evicted the dbuf.
+ * Undirty a buffer in the transaction group referenced by the given
+ * transaction. Return whether this evicted the dbuf.
*/
static boolean_t
dbuf_undirty(dmu_buf_impl_t *db, dmu_tx_t *tx)
@@ -2222,6 +2236,7 @@
ASSERT(db->db_level > 0);
DBUF_VERIFY(db);
+ /* Read the block if it hasn't been read yet. */
if (db->db_buf == NULL) {
mutex_exit(&db->db_mtx);
(void) dbuf_read(db, NULL, DB_RF_MUST_SUCCEED);
@@ -2232,10 +2247,12 @@
DB_DNODE_ENTER(db);
dn = DB_DNODE(db);
+ /* Indirect block size must match what the dnode thinks it is. */
ASSERT3U(db->db.db_size, ==, 1<<dn->dn_phys->dn_indblkshift);
dbuf_check_blkptr(dn, db);
DB_DNODE_EXIT(db);
+ /* Provide the pending dirty record to child dbufs */
db->db_data_pending = dr;
mutex_exit(&db->db_mtx);
@@ -2626,6 +2643,7 @@
dbuf_write_done(zio, NULL, db);
}
+/* Issue I/O to commit a dirty buffer to disk. */
static void
dbuf_write(dbuf_dirty_record_t *dr, arc_buf_t *data, dmu_tx_t *tx)
{
@@ -2660,11 +2678,19 @@
}
if (parent != dn->dn_dbuf) {
+ /* Our parent is an indirect block. */
+ /* We have a dirty parent that has been scheduled for write. */
ASSERT(parent && parent->db_data_pending);
+ /* Our parent's buffer is one level closer to the dnode. */
ASSERT(db->db_level == parent->db_level-1);
+ /*
+ * We're about to modify our parent's db_data by modifying
+ * our block pointer, so the parent must be released.
+ */
ASSERT(arc_released(parent->db_buf));
zio = parent->db_data_pending->dr_zio;
} else {
+ /* Our parent is the dnode itself. */
ASSERT((db->db_level == dn->dn_phys->dn_nlevels-1 &&
db->db_blkid != DMU_SPILL_BLKID) ||
(db->db_blkid == DMU_SPILL_BLKID && db->db_level == 0));
@@ -2710,8 +2736,9 @@
} else {
ASSERT(arc_released(data));
dr->dr_zio = arc_write(zio, os->os_spa, txg,
- db->db_blkptr, data, DBUF_IS_L2CACHEABLE(db), &zp,
- dbuf_write_ready, dbuf_write_done, db,
- ZIO_PRIORITY_ASYNC_WRITE, ZIO_FLAG_MUSTSUCCEED, &zb);
+ db->db_blkptr, data, DBUF_IS_L2CACHEABLE(db),
+ DBUF_IS_L2COMPRESSIBLE(db), &zp, dbuf_write_ready,
+ dbuf_write_done, db, ZIO_PRIORITY_ASYNC_WRITE,
+ ZIO_FLAG_MUSTSUCCEED, &zb);
}
}
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt_zap.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt_zap.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt_zap.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -23,6 +24,8 @@
* Copyright (c) 2013 by Delphix. All rights reserved.
*/
+/* Copyright (c) 2013 by Saso Kiselkov. All rights reserved. */
+
#include <sys/dmu.h>
#include <sys/dmu_impl.h>
#include <sys/dmu_tx.h>
@@ -1514,9 +1517,9 @@
dsa->dsa_tx = NULL;
zio_nowait(arc_write(pio, os->os_spa, txg,
- bp, dr->dt.dl.dr_data, DBUF_IS_L2CACHEABLE(db), &zp,
- dmu_sync_ready, dmu_sync_done, dsa,
- ZIO_PRIORITY_SYNC_WRITE, ZIO_FLAG_CANFAIL, &zb));
+ bp, dr->dt.dl.dr_data, DBUF_IS_L2CACHEABLE(db),
+ DBUF_IS_L2COMPRESSIBLE(db), &zp, dmu_sync_ready, dmu_sync_done,
+ dsa, ZIO_PRIORITY_SYNC_WRITE, ZIO_FLAG_CANFAIL, &zb));
return (0);
}
@@ -1837,7 +1840,7 @@
void
dmu_fini(void)
{
- arc_fini();
+ arc_fini(); /* arc depends on l2arc, so arc must go first */
l2arc_fini();
zfetch_fini();
dbuf_fini();
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_diff.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_diff.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_diff.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_object.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_object.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_object.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_objset.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_objset.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_objset.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -21,6 +22,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
*/
/* Portions Copyright 2010 Robert Milkowski */
@@ -276,6 +278,8 @@
if (DMU_OS_IS_L2CACHEABLE(os))
aflags |= ARC_L2CACHE;
+ if (DMU_OS_IS_L2COMPRESSIBLE(os))
+ aflags |= ARC_L2COMPRESS;
dprintf_bp(os->os_rootbp, "reading %s", "");
err = arc_read(NULL, spa, os->os_rootbp,
@@ -991,9 +995,10 @@
dmu_write_policy(os, NULL, 0, 0, &zp);
zio = arc_write(pio, os->os_spa, tx->tx_txg,
- os->os_rootbp, os->os_phys_buf, DMU_OS_IS_L2CACHEABLE(os), &zp,
- dmu_objset_write_ready, dmu_objset_write_done, os,
- ZIO_PRIORITY_ASYNC_WRITE, ZIO_FLAG_MUSTSUCCEED, &zb);
+ os->os_rootbp, os->os_phys_buf, DMU_OS_IS_L2CACHEABLE(os),
+ DMU_OS_IS_L2COMPRESSIBLE(os), &zp, dmu_objset_write_ready,
+ dmu_objset_write_done, os, ZIO_PRIORITY_ASYNC_WRITE,
+ ZIO_FLAG_MUSTSUCCEED, &zb);
/*
* Sync special dnodes - the parent IO for the sync is the root block
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_traverse.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_traverse.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_traverse.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_tx.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_tx.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_tx.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -1014,6 +1015,10 @@
txg_rele_to_quiesce(&tx->tx_txgh);
+ /*
+ * Walk the transaction's hold list, removing the hold on the
+ * associated dnode, and notifying waiters if the refcount drops to 0.
+ */
for (txh = list_head(&tx->tx_holds); txh != tx->tx_needassign_txh;
txh = list_next(&tx->tx_holds, txh)) {
dnode_t *dn = txh->txh_dnode;
@@ -1126,6 +1131,10 @@
ASSERT(tx->tx_txg != 0);
+ /*
+ * Go through the transaction's hold list and remove holds on
+ * associated dnodes, notifying waiters if no holds remain.
+ */
while (txh = list_head(&tx->tx_holds)) {
dnode_t *dn = txh->txh_dnode;
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_zfetch.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_zfetch.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_zfetch.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -66,11 +67,11 @@
"Number of bytes in a array_read at which we stop prefetching");
/* forward decls for static routines */
-static int dmu_zfetch_colinear(zfetch_t *, zstream_t *);
+static boolean_t dmu_zfetch_colinear(zfetch_t *, zstream_t *);
static void dmu_zfetch_dofetch(zfetch_t *, zstream_t *);
static uint64_t dmu_zfetch_fetch(dnode_t *, uint64_t, uint64_t);
static uint64_t dmu_zfetch_fetchsz(dnode_t *, uint64_t, uint64_t);
-static int dmu_zfetch_find(zfetch_t *, zstream_t *, int);
+static boolean_t dmu_zfetch_find(zfetch_t *, zstream_t *, int);
static int dmu_zfetch_stream_insert(zfetch_t *, zstream_t *);
static zstream_t *dmu_zfetch_stream_reclaim(zfetch_t *);
static void dmu_zfetch_stream_remove(zfetch_t *, zstream_t *);
@@ -122,9 +123,9 @@
* last stream, then we are probably in a strided access pattern. So
* combine the two sequential streams into a single strided stream.
*
- * If no co-linear streams are found, return NULL.
+ * Returns whether co-linear streams were found.
*/
-static int
+static boolean_t
dmu_zfetch_colinear(zfetch_t *zf, zstream_t *zh)
{
zstream_t *z_walk;
@@ -344,7 +345,7 @@
* for this block read. If so, it starts a prefetch for the stream it
* located and returns true, otherwise it returns false
*/
-static int
+static boolean_t
dmu_zfetch_find(zfetch_t *zf, zstream_t *zh, int prefetched)
{
zstream_t *zs;
@@ -669,7 +670,7 @@
{
zstream_t zst;
zstream_t *newstream;
- int fetched;
+ boolean_t fetched;
int inserted;
unsigned int blkshft;
uint64_t blksz;
@@ -695,7 +696,8 @@
ZFETCHSTAT_BUMP(zfetchstat_hits);
} else {
ZFETCHSTAT_BUMP(zfetchstat_misses);
- if (fetched = dmu_zfetch_colinear(zf, &zst)) {
+ fetched = dmu_zfetch_colinear(zf, &zst);
+ if (fetched) {
ZFETCHSTAT_BUMP(zfetchstat_colinear_hits);
} else {
ZFETCHSTAT_BUMP(zfetchstat_colinear_misses);
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -1808,15 +1809,17 @@
}
/*
- * This function scans a block at the indicated "level" looking for
- * a hole or data (depending on 'flags'). If level > 0, then we are
- * scanning an indirect block looking at its pointers. If level == 0,
- * then we are looking at a block of dnodes. If we don't find what we
- * are looking for in the block, we return ESRCH. Otherwise, return
- * with *offset pointing to the beginning (if searching forwards) or
- * end (if searching backwards) of the range covered by the block
- * pointer we matched on (or dnode).
+ * Scans a block at the indicated "level" looking for a hole or data,
+ * depending on 'flags'.
*
+ * If level > 0, then we are scanning an indirect block looking at its
+ * pointers. If level == 0, then we are looking at a block of dnodes.
+ *
+ * If we don't find what we are looking for in the block, we return ESRCH.
+ * Otherwise, return with *offset pointing to the beginning (if searching
+ * forwards) or end (if searching backwards) of the range covered by the
+ * block pointer we matched on (or dnode).
+ *
* The basic search algorithm used below by dnode_next_offset() is to
* use this function to search up the block tree (widen the search) until
* we find something (i.e., we don't return ESRCH) and then search back
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode_sync.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode_sync.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode_sync.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -302,7 +303,7 @@
}
/*
- * free_range: Traverse the indicated range of the provided file
+ * Traverse the indicated range of the provided file
* and "free" all the blocks contained there.
*/
static void
@@ -370,7 +371,7 @@
}
/*
- * Try to kick all the dnodes dbufs out of the cache...
+ * Try to kick all the dnode's dbufs out of the cache...
*/
void
dnode_evict_dbufs(dnode_t *dn)
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -361,8 +362,10 @@
/* Make sure dsobj has the correct object type. */
dmu_object_info_from_db(dbuf, &doi);
- if (doi.doi_type != DMU_OT_DSL_DATASET)
+ if (doi.doi_type != DMU_OT_DSL_DATASET) {
+ dmu_buf_rele(dbuf, tag);
return (SET_ERROR(EINVAL));
+ }
ds = dmu_buf_get_user(dbuf);
if (ds == NULL) {
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_deadlist.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_deadlist.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_deadlist.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_deleg.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_deleg.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_deleg.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_destroy.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_destroy.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_destroy.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -21,6 +22,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013 Steven Hartland. All rights reserved.
*/
#include <sys/zfs_context.h>
@@ -127,6 +129,7 @@
pair = nvlist_next_nvpair(dsda->dsda_errlist, NULL);
if (pair != NULL)
return (fnvpair_value_int32(pair));
+
return (0);
}
@@ -753,6 +756,8 @@
zil_destroy_sync(dmu_objset_zil(os), tx);
if (!spa_feature_is_active(dp->dp_spa, async_destroy)) {
+ dsl_scan_t *scn = dp->dp_scan;
+
spa_feature_incr(dp->dp_spa, async_destroy, tx);
dp->dp_bptree_obj = bptree_alloc(mos, tx);
VERIFY0(zap_add(mos,
@@ -759,6 +764,8 @@
DMU_POOL_DIRECTORY_OBJECT,
DMU_POOL_BPTREE_OBJ, sizeof (uint64_t), 1,
&dp->dp_bptree_obj, tx));
+ ASSERT(!scn->scn_async_destroying);
+ scn->scn_async_destroying = B_TRUE;
}
used = ds->ds_dir->dd_phys->dd_used_bytes;
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dir.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dir.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dir.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -972,12 +973,18 @@
VERIFY0(dsl_dataset_hold(dp, ddsqra->ddsqra_name, FTAG, &ds));
- dsl_prop_set_sync_impl(ds, zfs_prop_to_name(ZFS_PROP_QUOTA),
- ddsqra->ddsqra_source, sizeof (ddsqra->ddsqra_value), 1,
- &ddsqra->ddsqra_value, tx);
+ if (spa_version(dp->dp_spa) >= SPA_VERSION_RECVD_PROPS) {
+ dsl_prop_set_sync_impl(ds, zfs_prop_to_name(ZFS_PROP_QUOTA),
+ ddsqra->ddsqra_source, sizeof (ddsqra->ddsqra_value), 1,
+ &ddsqra->ddsqra_value, tx);
- VERIFY0(dsl_prop_get_int_ds(ds,
- zfs_prop_to_name(ZFS_PROP_QUOTA), &newval));
+ VERIFY0(dsl_prop_get_int_ds(ds,
+ zfs_prop_to_name(ZFS_PROP_QUOTA), &newval));
+ } else {
+ newval = ddsqra->ddsqra_value;
+ spa_history_log_internal_ds(ds, "set", tx, "%s=%lld",
+ zfs_prop_to_name(ZFS_PROP_QUOTA), (longlong_t)newval);
+ }
dmu_buf_will_dirty(ds->ds_dir->dd_dbuf, tx);
mutex_enter(&ds->ds_dir->dd_lock);
@@ -1087,12 +1094,20 @@
VERIFY0(dsl_dataset_hold(dp, ddsqra->ddsqra_name, FTAG, &ds));
- dsl_prop_set_sync_impl(ds, zfs_prop_to_name(ZFS_PROP_RESERVATION),
- ddsqra->ddsqra_source, sizeof (ddsqra->ddsqra_value), 1,
- &ddsqra->ddsqra_value, tx);
+ if (spa_version(dp->dp_spa) >= SPA_VERSION_RECVD_PROPS) {
+ dsl_prop_set_sync_impl(ds,
+ zfs_prop_to_name(ZFS_PROP_RESERVATION),
+ ddsqra->ddsqra_source, sizeof (ddsqra->ddsqra_value), 1,
+ &ddsqra->ddsqra_value, tx);
- VERIFY0(dsl_prop_get_int_ds(ds,
- zfs_prop_to_name(ZFS_PROP_RESERVATION), &newval));
+ VERIFY0(dsl_prop_get_int_ds(ds,
+ zfs_prop_to_name(ZFS_PROP_RESERVATION), &newval));
+ } else {
+ newval = ddsqra->ddsqra_value;
+ spa_history_log_internal_ds(ds, "set", tx, "%s=%lld",
+ zfs_prop_to_name(ZFS_PROP_RESERVATION),
+ (longlong_t)newval);
+ }
dsl_dir_set_reservation_sync_impl(ds->ds_dir, newval, tx);
dsl_dataset_rele(ds, FTAG);
@@ -1244,8 +1259,6 @@
int error;
objset_t *mos = dp->dp_meta_objset;
- ASSERT(dmu_buf_refcount(dd->dd_dbuf) <= 2);
-
VERIFY0(dsl_dir_hold(dp, ddra->ddra_oldname, FTAG, &dd, NULL));
VERIFY0(dsl_dir_hold(dp, ddra->ddra_newname, FTAG, &newparent,
&mynewname));
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -21,6 +22,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013 Steven Hartland. All rights reserved.
*/
#include <sys/dsl_pool.h>
@@ -78,10 +80,11 @@
&zfs_write_limit_max, 0, "Maximum data payload per txg");
TUNABLE_QUAD("vfs.zfs.write_limit_inflated", &zfs_write_limit_inflated);
SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, write_limit_inflated, CTLFLAG_RDTUN,
- &zfs_write_limit_inflated, 0, "");
+ &zfs_write_limit_inflated, 0, "Maximum size of the dynamic write limit");
TUNABLE_QUAD("vfs.zfs.write_limit_override", &zfs_write_limit_override);
SYSCTL_UQUAD(_vfs_zfs, OID_AUTO, write_limit_override, CTLFLAG_RDTUN,
- &zfs_write_limit_override, 0, "");
+ &zfs_write_limit_override, 0,
+ "Force a txg if dirty buffers exceed this value (bytes)");
int
dsl_pool_open_special_dir(dsl_pool_t *dp, const char *name, dsl_dir_t **ddp)
@@ -442,7 +445,6 @@
* clean up our in-memory structures accumulated while syncing:
*
* - move dead blocks from the pending deadlist to the on-disk deadlist
- * - clean up zil records
* - release hold from dsl_dataset_dirty()
*/
while (ds = list_remove_head(&synced_datasets)) {
@@ -856,23 +858,34 @@
zap_cursor_t zc;
objset_t *mos = dp->dp_meta_objset;
uint64_t zapobj = dp->dp_tmp_userrefs_obj;
+ nvlist_t *holds;
if (zapobj == 0)
return;
ASSERT(spa_version(dp->dp_spa) >= SPA_VERSION_USERREFS);
+ holds = fnvlist_alloc();
+
for (zap_cursor_init(&zc, mos, zapobj);
zap_cursor_retrieve(&zc, &za) == 0;
zap_cursor_advance(&zc)) {
char *htag;
- uint64_t dsobj;
+ nvlist_t *tags;
htag = strchr(za.za_name, '-');
*htag = '\0';
++htag;
- dsobj = strtonum(za.za_name, NULL);
- dsl_dataset_user_release_tmp(dp, dsobj, htag);
+ if (nvlist_lookup_nvlist(holds, za.za_name, &tags) != 0) {
+ tags = fnvlist_alloc();
+ fnvlist_add_boolean(tags, htag);
+ fnvlist_add_nvlist(holds, za.za_name, tags);
+ fnvlist_free(tags);
+ } else {
+ fnvlist_add_boolean(tags, htag);
+ }
}
+ dsl_dataset_user_release_tmp(dp, holds);
+ fnvlist_free(holds);
zap_cursor_fini(&zc);
}
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_prop.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_prop.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_prop.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -379,7 +380,7 @@
/*
* Unregister this callback. Return 0 on success, ENOENT if ddname is
- * invalid, ENOMSG if no matching callback registered.
+ * invalid, or ENOMSG if no matching callback registered.
*/
int
dsl_prop_unregister(dsl_dataset_t *ds, const char *propname,
@@ -557,10 +558,6 @@
}
if (version < SPA_VERSION_RECVD_PROPS) {
- zfs_prop_t prop = zfs_name_to_prop(propname);
- if (prop == ZFS_PROP_QUOTA || prop == ZFS_PROP_RESERVATION)
- return;
-
if (source & ZPROP_SRC_NONE)
source = ZPROP_SRC_NONE;
else if (source & ZPROP_SRC_RECEIVED)
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_scan.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_scan.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_scan.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -125,6 +126,15 @@
scn = dp->dp_scan = kmem_zalloc(sizeof (dsl_scan_t), KM_SLEEP);
scn->scn_dp = dp;
+ /*
+ * It's possible that we're resuming a scan after a reboot so
+ * make sure that the scan_async_destroying flag is initialized
+ * appropriately.
+ */
+ ASSERT(!scn->scn_async_destroying);
+ scn->scn_async_destroying = spa_feature_is_active(dp->dp_spa,
+ &spa_feature_table[SPA_FEATURE_ASYNC_DESTROY]);
+
err = zap_lookup(dp->dp_meta_objset, DMU_POOL_DIRECTORY_OBJECT,
"scrub_func", sizeof (uint64_t), 1, &f);
if (err == 0) {
@@ -1375,13 +1385,10 @@
if (spa_shutting_down(spa))
return (B_FALSE);
- if (scn->scn_phys.scn_state == DSS_SCANNING)
+ if (scn->scn_phys.scn_state == DSS_SCANNING ||
+ scn->scn_async_destroying)
return (B_TRUE);
- if (spa_feature_is_active(spa,
- &spa_feature_table[SPA_FEATURE_ASYNC_DESTROY])) {
- return (B_TRUE);
- }
if (spa_version(scn->scn_dp->dp_spa) >= SPA_VERSION_DEADLISTS) {
(void) bpobj_space(&scn->scn_dp->dp_free_bpobj,
&used, &comp, &uncomp);
@@ -1437,6 +1444,7 @@
if (err == 0 && spa_feature_is_active(spa,
&spa_feature_table[SPA_FEATURE_ASYNC_DESTROY])) {
+ ASSERT(scn->scn_async_destroying);
scn->scn_is_bptree = B_TRUE;
scn->scn_zio_root = zio_root(dp->dp_spa, NULL,
NULL, ZIO_FLAG_MUSTSUCCEED);
@@ -1457,6 +1465,7 @@
VERIFY0(bptree_free(dp->dp_meta_objset,
dp->dp_bptree_obj, tx));
dp->dp_bptree_obj = 0;
+ scn->scn_async_destroying = B_FALSE;
}
}
if (scn->scn_visited_this_txg) {
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_synctask.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_synctask.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_synctask.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_userhold.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_userhold.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_userhold.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -21,6 +22,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013 Steven Hartland. All rights reserved.
*/
#include <sys/zfs_context.h>
@@ -37,6 +39,7 @@
typedef struct dsl_dataset_user_hold_arg {
nvlist_t *dduha_holds;
+ nvlist_t *dduha_chkholds;
nvlist_t *dduha_errlist;
minor_t dduha_minor;
} dsl_dataset_user_hold_arg_t;
@@ -53,25 +56,24 @@
objset_t *mos = dp->dp_meta_objset;
int error = 0;
+ ASSERT(dsl_pool_config_held(dp));
+
if (strlen(htag) > MAXNAMELEN)
- return (E2BIG);
+ return (SET_ERROR(E2BIG));
/* Tempholds have a more restricted length */
if (temphold && strlen(htag) + MAX_TAG_PREFIX_LEN >= MAXNAMELEN)
- return (E2BIG);
+ return (SET_ERROR(E2BIG));
/* tags must be unique (if ds already exists) */
- if (ds != NULL) {
- mutex_enter(&ds->ds_lock);
- if (ds->ds_phys->ds_userrefs_obj != 0) {
- uint64_t value;
- error = zap_lookup(mos, ds->ds_phys->ds_userrefs_obj,
- htag, 8, 1, &value);
- if (error == 0)
- error = SET_ERROR(EEXIST);
- else if (error == ENOENT)
- error = 0;
- }
- mutex_exit(&ds->ds_lock);
+ if (ds != NULL && ds->ds_phys->ds_userrefs_obj != 0) {
+ uint64_t value;
+
+ error = zap_lookup(mos, ds->ds_phys->ds_userrefs_obj,
+ htag, 8, 1, &value);
+ if (error == 0)
+ error = SET_ERROR(EEXIST);
+ else if (error == ENOENT)
+ error = 0;
}
return (error);
@@ -82,52 +84,63 @@
{
dsl_dataset_user_hold_arg_t *dduha = arg;
dsl_pool_t *dp = dmu_tx_pool(tx);
- nvpair_t *pair;
- int rv = 0;
if (spa_version(dp->dp_spa) < SPA_VERSION_USERREFS)
return (SET_ERROR(ENOTSUP));
- for (pair = nvlist_next_nvpair(dduha->dduha_holds, NULL); pair != NULL;
- pair = nvlist_next_nvpair(dduha->dduha_holds, pair)) {
+ if (!dmu_tx_is_syncing(tx))
+ return (0);
+
+ for (nvpair_t *pair = nvlist_next_nvpair(dduha->dduha_holds, NULL);
+ pair != NULL; pair = nvlist_next_nvpair(dduha->dduha_holds, pair)) {
+ dsl_dataset_t *ds;
int error = 0;
- dsl_dataset_t *ds;
- char *htag;
+ char *htag, *name;
/* must be a snapshot */
- if (strchr(nvpair_name(pair), '@') == NULL)
+ name = nvpair_name(pair);
+ if (strchr(name, '@') == NULL)
error = SET_ERROR(EINVAL);
if (error == 0)
error = nvpair_value_string(pair, &htag);
+
+ if (error == 0)
+ error = dsl_dataset_hold(dp, name, FTAG, &ds);
+
if (error == 0) {
- error = dsl_dataset_hold(dp,
- nvpair_name(pair), FTAG, &ds);
- }
- if (error == 0) {
error = dsl_dataset_user_hold_check_one(ds, htag,
dduha->dduha_minor != 0, tx);
dsl_dataset_rele(ds, FTAG);
}
- if (error != 0) {
- rv = error;
- fnvlist_add_int32(dduha->dduha_errlist,
- nvpair_name(pair), error);
+ if (error == 0) {
+ fnvlist_add_string(dduha->dduha_chkholds, name, htag);
+ } else {
+ /*
+ * We register ENOENT errors so they can be correctly
+ * reported if needed, such as when all holds fail.
+ */
+ fnvlist_add_int32(dduha->dduha_errlist, name, error);
+ if (error != ENOENT)
+ return (error);
}
}
- return (rv);
+
+ return (0);
}
-void
-dsl_dataset_user_hold_sync_one(dsl_dataset_t *ds, const char *htag,
- minor_t minor, uint64_t now, dmu_tx_t *tx)
+
+static void
+dsl_dataset_user_hold_sync_one_impl(nvlist_t *tmpholds, dsl_dataset_t *ds,
+ const char *htag, minor_t minor, uint64_t now, dmu_tx_t *tx)
{
dsl_pool_t *dp = ds->ds_dir->dd_pool;
objset_t *mos = dp->dp_meta_objset;
uint64_t zapobj;
- mutex_enter(&ds->ds_lock);
+ ASSERT(RRW_WRITE_HELD(&dp->dp_config_rwlock));
+
if (ds->ds_phys->ds_userrefs_obj == 0) {
/*
* This is the first user hold for this dataset. Create
@@ -140,14 +153,26 @@
zapobj = ds->ds_phys->ds_userrefs_obj;
}
ds->ds_userrefs++;
- mutex_exit(&ds->ds_lock);
VERIFY0(zap_add(mos, zapobj, htag, 8, 1, &now, tx));
if (minor != 0) {
+ char name[MAXNAMELEN];
+ nvlist_t *tags;
+
VERIFY0(dsl_pool_user_hold(dp, ds->ds_object,
htag, now, tx));
- dsl_register_onexit_hold_cleanup(ds, htag, minor);
+ (void) snprintf(name, sizeof (name), "%llx",
+ (u_longlong_t)ds->ds_object);
+
+ if (nvlist_lookup_nvlist(tmpholds, name, &tags) != 0) {
+ tags = fnvlist_alloc();
+ fnvlist_add_boolean(tags, htag);
+ fnvlist_add_nvlist(tmpholds, name, tags);
+ fnvlist_free(tags);
+ } else {
+ fnvlist_add_boolean(tags, htag);
+ }
}
spa_history_log_internal_ds(ds, "hold", tx,
@@ -155,31 +180,126 @@
htag, minor != 0, ds->ds_userrefs);
}
+typedef struct zfs_hold_cleanup_arg {
+ char zhca_spaname[MAXNAMELEN];
+ uint64_t zhca_spa_load_guid;
+ nvlist_t *zhca_holds;
+} zfs_hold_cleanup_arg_t;
+
static void
+dsl_dataset_user_release_onexit(void *arg)
+{
+ zfs_hold_cleanup_arg_t *ca = arg;
+ spa_t *spa;
+ int error;
+
+ error = spa_open(ca->zhca_spaname, &spa, FTAG);
+ if (error != 0) {
+ zfs_dbgmsg("couldn't release holds on pool=%s "
+ "because pool is no longer loaded",
+ ca->zhca_spaname);
+ return;
+ }
+ if (spa_load_guid(spa) != ca->zhca_spa_load_guid) {
+ zfs_dbgmsg("couldn't release holds on pool=%s "
+ "because pool is no longer loaded (guid doesn't match)",
+ ca->zhca_spaname);
+ spa_close(spa, FTAG);
+ return;
+ }
+
+ (void) dsl_dataset_user_release_tmp(spa_get_dsl(spa), ca->zhca_holds);
+ fnvlist_free(ca->zhca_holds);
+ kmem_free(ca, sizeof (zfs_hold_cleanup_arg_t));
+ spa_close(spa, FTAG);
+}
+
+static void
+dsl_onexit_hold_cleanup(spa_t *spa, nvlist_t *holds, minor_t minor)
+{
+ zfs_hold_cleanup_arg_t *ca;
+
+ if (minor == 0 || nvlist_empty(holds)) {
+ fnvlist_free(holds);
+ return;
+ }
+
+ ASSERT(spa != NULL);
+ ca = kmem_alloc(sizeof (*ca), KM_SLEEP);
+
+ (void) strlcpy(ca->zhca_spaname, spa_name(spa),
+ sizeof (ca->zhca_spaname));
+ ca->zhca_spa_load_guid = spa_load_guid(spa);
+ ca->zhca_holds = holds;
+ VERIFY0(zfs_onexit_add_cb(minor,
+ dsl_dataset_user_release_onexit, ca, NULL));
+}
+
+void
+dsl_dataset_user_hold_sync_one(dsl_dataset_t *ds, const char *htag,
+ minor_t minor, uint64_t now, dmu_tx_t *tx)
+{
+ nvlist_t *tmpholds;
+
+ if (minor != 0)
+ tmpholds = fnvlist_alloc();
+ else
+ tmpholds = NULL;
+ dsl_dataset_user_hold_sync_one_impl(tmpholds, ds, htag, minor, now, tx);
+ dsl_onexit_hold_cleanup(dsl_dataset_get_spa(ds), tmpholds, minor);
+}
+
+static void
dsl_dataset_user_hold_sync(void *arg, dmu_tx_t *tx)
{
dsl_dataset_user_hold_arg_t *dduha = arg;
dsl_pool_t *dp = dmu_tx_pool(tx);
- nvpair_t *pair;
+ nvlist_t *tmpholds;
uint64_t now = gethrestime_sec();
- for (pair = nvlist_next_nvpair(dduha->dduha_holds, NULL); pair != NULL;
- pair = nvlist_next_nvpair(dduha->dduha_holds, pair)) {
+ if (dduha->dduha_minor != 0)
+ tmpholds = fnvlist_alloc();
+ else
+ tmpholds = NULL;
+ for (nvpair_t *pair = nvlist_next_nvpair(dduha->dduha_chkholds, NULL);
+ pair != NULL;
+ pair = nvlist_next_nvpair(dduha->dduha_chkholds, pair)) {
dsl_dataset_t *ds;
+
VERIFY0(dsl_dataset_hold(dp, nvpair_name(pair), FTAG, &ds));
- dsl_dataset_user_hold_sync_one(ds, fnvpair_value_string(pair),
- dduha->dduha_minor, now, tx);
+ dsl_dataset_user_hold_sync_one_impl(tmpholds, ds,
+ fnvpair_value_string(pair), dduha->dduha_minor, now, tx);
dsl_dataset_rele(ds, FTAG);
}
+ dsl_onexit_hold_cleanup(dp->dp_spa, tmpholds, dduha->dduha_minor);
}
/*
+ * The full semantics of this function are described in the comment above
+ * lzc_hold().
+ *
+ * To summarize:
* holds is nvl of snapname -> holdname
* errlist will be filled in with snapname -> error
- * if cleanup_minor is not 0, the holds will be temporary, cleaned up
- * when the process exits.
*
- * if any fails, all will fail.
+ * The snaphosts must all be in the same pool.
+ *
+ * Holds for snapshots that don't exist will be skipped.
+ *
+ * If none of the snapshots for requested holds exist then ENOENT will be
+ * returned.
+ *
+ * If cleanup_minor is not 0, the holds will be temporary, which will be cleaned
+ * up when the process exits.
+ *
+ * On success all the holds, for snapshots that existed, will be created and 0
+ * will be returned.
+ *
+ * On failure no holds will be created, the errlist will be filled in,
+ * and an errno will returned.
+ *
+ * In all cases the errlist will contain entries for holds where the snapshot
+ * didn't exist.
*/
int
dsl_dataset_user_hold(nvlist_t *holds, minor_t cleanup_minor, nvlist_t *errlist)
@@ -186,6 +306,7 @@
{
dsl_dataset_user_hold_arg_t dduha;
nvpair_t *pair;
+ int ret;
pair = nvlist_next_nvpair(holds, NULL);
if (pair == NULL)
@@ -192,47 +313,88 @@
return (0);
dduha.dduha_holds = holds;
+ dduha.dduha_chkholds = fnvlist_alloc();
dduha.dduha_errlist = errlist;
dduha.dduha_minor = cleanup_minor;
- return (dsl_sync_task(nvpair_name(pair), dsl_dataset_user_hold_check,
- dsl_dataset_user_hold_sync, &dduha, fnvlist_num_pairs(holds)));
+ ret = dsl_sync_task(nvpair_name(pair), dsl_dataset_user_hold_check,
+ dsl_dataset_user_hold_sync, &dduha, fnvlist_num_pairs(holds));
+ fnvlist_free(dduha.dduha_chkholds);
+
+ return (ret);
}
+typedef int (dsl_holdfunc_t)(dsl_pool_t *dp, const char *name, void *tag,
+ dsl_dataset_t **dsp);
+
typedef struct dsl_dataset_user_release_arg {
+ dsl_holdfunc_t *ddura_holdfunc;
nvlist_t *ddura_holds;
nvlist_t *ddura_todelete;
nvlist_t *ddura_errlist;
+ nvlist_t *ddura_chkholds;
} dsl_dataset_user_release_arg_t;
+/* Place a dataset hold on the snapshot identified by passed dsobj string */
static int
-dsl_dataset_user_release_check_one(dsl_dataset_t *ds,
- nvlist_t *holds, boolean_t *todelete)
+dsl_dataset_hold_obj_string(dsl_pool_t *dp, const char *dsobj, void *tag,
+ dsl_dataset_t **dsp)
{
+ return (dsl_dataset_hold_obj(dp, strtonum(dsobj, NULL), tag, dsp));
+}
+
+static int
+dsl_dataset_user_release_check_one(dsl_dataset_user_release_arg_t *ddura,
+ dsl_dataset_t *ds, nvlist_t *holds, const char *snapname)
+{
uint64_t zapobj;
- nvpair_t *pair;
- objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset;
- int error;
- int numholds = 0;
+ nvlist_t *holds_found;
+ objset_t *mos;
+ int numholds;
- *todelete = B_FALSE;
-
if (!dsl_dataset_is_snapshot(ds))
return (SET_ERROR(EINVAL));
+ if (nvlist_empty(holds))
+ return (0);
+
+ numholds = 0;
+ mos = ds->ds_dir->dd_pool->dp_meta_objset;
zapobj = ds->ds_phys->ds_userrefs_obj;
- if (zapobj == 0)
- return (SET_ERROR(ESRCH));
+ holds_found = fnvlist_alloc();
- for (pair = nvlist_next_nvpair(holds, NULL); pair != NULL;
+ for (nvpair_t *pair = nvlist_next_nvpair(holds, NULL); pair != NULL;
pair = nvlist_next_nvpair(holds, pair)) {
- /* Make sure the hold exists */
uint64_t tmp;
- error = zap_lookup(mos, zapobj, nvpair_name(pair), 8, 1, &tmp);
- if (error == ENOENT)
- error = SET_ERROR(ESRCH);
- if (error != 0)
+ int error;
+ const char *holdname = nvpair_name(pair);
+
+ if (zapobj != 0)
+ error = zap_lookup(mos, zapobj, holdname, 8, 1, &tmp);
+ else
+ error = SET_ERROR(ENOENT);
+
+ /*
+ * Non-existent holds are put on the errlist, but don't
+ * cause an overall failure.
+ */
+ if (error == ENOENT) {
+ if (ddura->ddura_errlist != NULL) {
+ char *errtag = kmem_asprintf("%s#%s",
+ snapname, holdname);
+ fnvlist_add_int32(ddura->ddura_errlist, errtag,
+ ENOENT);
+ strfree(errtag);
+ }
+ continue;
+ }
+
+ if (error != 0) {
+ fnvlist_free(holds_found);
return (error);
+ }
+
+ fnvlist_add_boolean(holds_found, holdname);
numholds++;
}
@@ -239,11 +401,19 @@
if (DS_IS_DEFER_DESTROY(ds) && ds->ds_phys->ds_num_children == 1 &&
ds->ds_userrefs == numholds) {
/* we need to destroy the snapshot as well */
-
- if (dsl_dataset_long_held(ds))
+ if (dsl_dataset_long_held(ds)) {
+ fnvlist_free(holds_found);
return (SET_ERROR(EBUSY));
- *todelete = B_TRUE;
+ }
+ fnvlist_add_boolean(ddura->ddura_todelete, snapname);
}
+
+ if (numholds != 0) {
+ fnvlist_add_nvlist(ddura->ddura_chkholds, snapname,
+ holds_found);
+ }
+ fnvlist_free(holds_found);
+
return (0);
}
@@ -250,45 +420,52 @@
static int
dsl_dataset_user_release_check(void *arg, dmu_tx_t *tx)
{
- dsl_dataset_user_release_arg_t *ddura = arg;
- dsl_pool_t *dp = dmu_tx_pool(tx);
- nvpair_t *pair;
- int rv = 0;
+ dsl_dataset_user_release_arg_t *ddura;
+ dsl_holdfunc_t *holdfunc;
+ dsl_pool_t *dp;
if (!dmu_tx_is_syncing(tx))
return (0);
- for (pair = nvlist_next_nvpair(ddura->ddura_holds, NULL); pair != NULL;
- pair = nvlist_next_nvpair(ddura->ddura_holds, pair)) {
- const char *name = nvpair_name(pair);
+ dp = dmu_tx_pool(tx);
+
+ ASSERT(RRW_WRITE_HELD(&dp->dp_config_rwlock));
+
+ ddura = arg;
+ holdfunc = ddura->ddura_holdfunc;
+
+ for (nvpair_t *pair = nvlist_next_nvpair(ddura->ddura_holds, NULL);
+ pair != NULL; pair = nvlist_next_nvpair(ddura->ddura_holds, pair)) {
int error;
dsl_dataset_t *ds;
nvlist_t *holds;
+ const char *snapname = nvpair_name(pair);
error = nvpair_value_nvlist(pair, &holds);
if (error != 0)
- return (SET_ERROR(EINVAL));
-
- error = dsl_dataset_hold(dp, name, FTAG, &ds);
+ error = (SET_ERROR(EINVAL));
+ else
+ error = holdfunc(dp, snapname, FTAG, &ds);
if (error == 0) {
- boolean_t deleteme;
- error = dsl_dataset_user_release_check_one(ds,
- holds, &deleteme);
- if (error == 0 && deleteme) {
- fnvlist_add_boolean(ddura->ddura_todelete,
- name);
- }
+ error = dsl_dataset_user_release_check_one(ddura, ds,
+ holds, snapname);
dsl_dataset_rele(ds, FTAG);
}
if (error != 0) {
if (ddura->ddura_errlist != NULL) {
fnvlist_add_int32(ddura->ddura_errlist,
- name, error);
+ snapname, error);
}
- rv = error;
+ /*
+ * Non-existent snapshots are put on the errlist,
+ * but don't cause an overall failure.
+ */
+ if (error != ENOENT)
+ return (error);
}
}
- return (rv);
+
+ return (0);
}
static void
@@ -297,22 +474,22 @@
{
dsl_pool_t *dp = ds->ds_dir->dd_pool;
objset_t *mos = dp->dp_meta_objset;
- uint64_t zapobj;
- int error;
- nvpair_t *pair;
- for (pair = nvlist_next_nvpair(holds, NULL); pair != NULL;
+ for (nvpair_t *pair = nvlist_next_nvpair(holds, NULL); pair != NULL;
pair = nvlist_next_nvpair(holds, pair)) {
- ds->ds_userrefs--;
- error = dsl_pool_user_release(dp, ds->ds_object,
- nvpair_name(pair), tx);
+ int error;
+ const char *holdname = nvpair_name(pair);
+
+ /* Remove temporary hold if one exists. */
+ error = dsl_pool_user_release(dp, ds->ds_object, holdname, tx);
VERIFY(error == 0 || error == ENOENT);
- zapobj = ds->ds_phys->ds_userrefs_obj;
- VERIFY0(zap_remove(mos, zapobj, nvpair_name(pair), tx));
+ VERIFY0(zap_remove(mos, ds->ds_phys->ds_userrefs_obj, holdname,
+ tx));
+ ds->ds_userrefs--;
+
spa_history_log_internal_ds(ds, "release", tx,
- "tag=%s refs=%lld", nvpair_name(pair),
- (longlong_t)ds->ds_userrefs);
+ "tag=%s refs=%lld", holdname, (longlong_t)ds->ds_userrefs);
}
}
@@ -320,18 +497,22 @@
dsl_dataset_user_release_sync(void *arg, dmu_tx_t *tx)
{
dsl_dataset_user_release_arg_t *ddura = arg;
+ dsl_holdfunc_t *holdfunc = ddura->ddura_holdfunc;
dsl_pool_t *dp = dmu_tx_pool(tx);
- nvpair_t *pair;
- for (pair = nvlist_next_nvpair(ddura->ddura_holds, NULL); pair != NULL;
- pair = nvlist_next_nvpair(ddura->ddura_holds, pair)) {
+ ASSERT(RRW_WRITE_HELD(&dp->dp_config_rwlock));
+
+ for (nvpair_t *pair = nvlist_next_nvpair(ddura->ddura_chkholds, NULL);
+ pair != NULL; pair = nvlist_next_nvpair(ddura->ddura_chkholds,
+ pair)) {
dsl_dataset_t *ds;
+ const char *name = nvpair_name(pair);
- VERIFY0(dsl_dataset_hold(dp, nvpair_name(pair), FTAG, &ds));
+ VERIFY0(holdfunc(dp, name, FTAG, &ds));
+
dsl_dataset_user_release_sync_one(ds,
fnvpair_value_nvlist(pair), tx);
- if (nvlist_exists(ddura->ddura_todelete,
- nvpair_name(pair))) {
+ if (nvlist_exists(ddura->ddura_todelete, name)) {
ASSERT(ds->ds_userrefs == 0 &&
ds->ds_phys->ds_num_children == 1 &&
DS_IS_DEFER_DESTROY(ds));
@@ -342,16 +523,33 @@
}
/*
+ * The full semantics of this function are described in the comment above
+ * lzc_release().
+ *
+ * To summarize:
+ * Releases holds specified in the nvl holds.
+ *
* holds is nvl of snapname -> { holdname, ... }
* errlist will be filled in with snapname -> error
*
- * if any fails, all will fail.
+ * If tmpdp is not NULL the names for holds should be the dsobj's of snapshots,
+ * otherwise they should be the names of shapshots.
+ *
+ * As a release may cause snapshots to be destroyed this trys to ensure they
+ * aren't mounted.
+ *
+ * The release of non-existent holds are skipped.
+ *
+ * At least one hold must have been released for the this function to succeed
+ * and return 0.
*/
-int
-dsl_dataset_user_release(nvlist_t *holds, nvlist_t *errlist)
+static int
+dsl_dataset_user_release_impl(nvlist_t *holds, nvlist_t *errlist,
+ dsl_pool_t *tmpdp)
{
dsl_dataset_user_release_arg_t ddura;
nvpair_t *pair;
+ char *pool;
int error;
pair = nvlist_next_nvpair(holds, NULL);
@@ -358,147 +556,77 @@
if (pair == NULL)
return (0);
+ /*
+ * The release may cause snapshots to be destroyed; make sure they
+ * are not mounted.
+ */
+ if (tmpdp != NULL) {
+ /* Temporary holds are specified by dsobj string. */
+ ddura.ddura_holdfunc = dsl_dataset_hold_obj_string;
+ pool = spa_name(tmpdp->dp_spa);
+#ifdef _KERNEL
+ dsl_pool_config_enter(tmpdp, FTAG);
+ for (pair = nvlist_next_nvpair(holds, NULL); pair != NULL;
+ pair = nvlist_next_nvpair(holds, pair)) {
+ dsl_dataset_t *ds;
+
+ error = dsl_dataset_hold_obj_string(tmpdp,
+ nvpair_name(pair), FTAG, &ds);
+ if (error == 0) {
+ char name[MAXNAMELEN];
+ dsl_dataset_name(ds, name);
+ dsl_dataset_rele(ds, FTAG);
+ (void) zfs_unmount_snap(name);
+ }
+ }
+ dsl_pool_config_exit(tmpdp, FTAG);
+#endif
+ } else {
+ /* Non-temporary holds are specified by name. */
+ ddura.ddura_holdfunc = dsl_dataset_hold;
+ pool = nvpair_name(pair);
+#ifdef _KERNEL
+ for (pair = nvlist_next_nvpair(holds, NULL); pair != NULL;
+ pair = nvlist_next_nvpair(holds, pair)) {
+ (void) zfs_unmount_snap(nvpair_name(pair));
+ }
+#endif
+ }
+
ddura.ddura_holds = holds;
ddura.ddura_errlist = errlist;
ddura.ddura_todelete = fnvlist_alloc();
+ ddura.ddura_chkholds = fnvlist_alloc();
- error = dsl_sync_task(nvpair_name(pair), dsl_dataset_user_release_check,
- dsl_dataset_user_release_sync, &ddura, fnvlist_num_pairs(holds));
+ error = dsl_sync_task(pool, dsl_dataset_user_release_check,
+ dsl_dataset_user_release_sync, &ddura,
+ fnvlist_num_pairs(holds));
fnvlist_free(ddura.ddura_todelete);
- return (error);
-}
+ fnvlist_free(ddura.ddura_chkholds);
-typedef struct dsl_dataset_user_release_tmp_arg {
- uint64_t ddurta_dsobj;
- nvlist_t *ddurta_holds;
- boolean_t ddurta_deleteme;
-} dsl_dataset_user_release_tmp_arg_t;
-
-static int
-dsl_dataset_user_release_tmp_check(void *arg, dmu_tx_t *tx)
-{
- dsl_dataset_user_release_tmp_arg_t *ddurta = arg;
- dsl_pool_t *dp = dmu_tx_pool(tx);
- dsl_dataset_t *ds;
- int error;
-
- if (!dmu_tx_is_syncing(tx))
- return (0);
-
- error = dsl_dataset_hold_obj(dp, ddurta->ddurta_dsobj, FTAG, &ds);
- if (error)
- return (error);
-
- error = dsl_dataset_user_release_check_one(ds,
- ddurta->ddurta_holds, &ddurta->ddurta_deleteme);
- dsl_dataset_rele(ds, FTAG);
return (error);
}
-static void
-dsl_dataset_user_release_tmp_sync(void *arg, dmu_tx_t *tx)
+/*
+ * holds is nvl of snapname -> { holdname, ... }
+ * errlist will be filled in with snapname -> error
+ */
+int
+dsl_dataset_user_release(nvlist_t *holds, nvlist_t *errlist)
{
- dsl_dataset_user_release_tmp_arg_t *ddurta = arg;
- dsl_pool_t *dp = dmu_tx_pool(tx);
- dsl_dataset_t *ds;
-
- VERIFY0(dsl_dataset_hold_obj(dp, ddurta->ddurta_dsobj, FTAG, &ds));
- dsl_dataset_user_release_sync_one(ds, ddurta->ddurta_holds, tx);
- if (ddurta->ddurta_deleteme) {
- ASSERT(ds->ds_userrefs == 0 &&
- ds->ds_phys->ds_num_children == 1 &&
- DS_IS_DEFER_DESTROY(ds));
- dsl_destroy_snapshot_sync_impl(ds, B_FALSE, tx);
- }
- dsl_dataset_rele(ds, FTAG);
+ return (dsl_dataset_user_release_impl(holds, errlist, NULL));
}
/*
- * Called at spa_load time to release a stale temporary user hold.
- * Also called by the onexit code.
+ * holds is nvl of snapdsobj -> { holdname, ... }
*/
void
-dsl_dataset_user_release_tmp(dsl_pool_t *dp, uint64_t dsobj, const char *htag)
+dsl_dataset_user_release_tmp(struct dsl_pool *dp, nvlist_t *holds)
{
- dsl_dataset_user_release_tmp_arg_t ddurta;
- dsl_dataset_t *ds;
- int error;
-
-#ifdef _KERNEL
- /* Make sure it is not mounted. */
- dsl_pool_config_enter(dp, FTAG);
- error = dsl_dataset_hold_obj(dp, dsobj, FTAG, &ds);
- if (error == 0) {
- char name[MAXNAMELEN];
- dsl_dataset_name(ds, name);
- dsl_dataset_rele(ds, FTAG);
- dsl_pool_config_exit(dp, FTAG);
- zfs_unmount_snap(name);
- } else {
- dsl_pool_config_exit(dp, FTAG);
- }
-#endif
-
- ddurta.ddurta_dsobj = dsobj;
- ddurta.ddurta_holds = fnvlist_alloc();
- fnvlist_add_boolean(ddurta.ddurta_holds, htag);
-
- (void) dsl_sync_task(spa_name(dp->dp_spa),
- dsl_dataset_user_release_tmp_check,
- dsl_dataset_user_release_tmp_sync, &ddurta, 1);
- fnvlist_free(ddurta.ddurta_holds);
+ ASSERT(dp != NULL);
+ (void) dsl_dataset_user_release_impl(holds, NULL, dp);
}
-typedef struct zfs_hold_cleanup_arg {
- char zhca_spaname[MAXNAMELEN];
- uint64_t zhca_spa_load_guid;
- uint64_t zhca_dsobj;
- char zhca_htag[MAXNAMELEN];
-} zfs_hold_cleanup_arg_t;
-
-static void
-dsl_dataset_user_release_onexit(void *arg)
-{
- zfs_hold_cleanup_arg_t *ca = arg;
- spa_t *spa;
- int error;
-
- error = spa_open(ca->zhca_spaname, &spa, FTAG);
- if (error != 0) {
- zfs_dbgmsg("couldn't release hold on pool=%s ds=%llu tag=%s "
- "because pool is no longer loaded",
- ca->zhca_spaname, ca->zhca_dsobj, ca->zhca_htag);
- return;
- }
- if (spa_load_guid(spa) != ca->zhca_spa_load_guid) {
- zfs_dbgmsg("couldn't release hold on pool=%s ds=%llu tag=%s "
- "because pool is no longer loaded (guid doesn't match)",
- ca->zhca_spaname, ca->zhca_dsobj, ca->zhca_htag);
- spa_close(spa, FTAG);
- return;
- }
-
- dsl_dataset_user_release_tmp(spa_get_dsl(spa),
- ca->zhca_dsobj, ca->zhca_htag);
- kmem_free(ca, sizeof (zfs_hold_cleanup_arg_t));
- spa_close(spa, FTAG);
-}
-
-void
-dsl_register_onexit_hold_cleanup(dsl_dataset_t *ds, const char *htag,
- minor_t minor)
-{
- zfs_hold_cleanup_arg_t *ca = kmem_alloc(sizeof (*ca), KM_SLEEP);
- spa_t *spa = dsl_dataset_get_spa(ds);
- (void) strlcpy(ca->zhca_spaname, spa_name(spa),
- sizeof (ca->zhca_spaname));
- ca->zhca_spa_load_guid = spa_load_guid(spa);
- ca->zhca_dsobj = ds->ds_object;
- (void) strlcpy(ca->zhca_htag, htag, sizeof (ca->zhca_htag));
- VERIFY0(zfs_onexit_add_cb(minor,
- dsl_dataset_user_release_onexit, ca, NULL));
-}
-
int
dsl_dataset_get_holds(const char *dsname, nvlist_t *nvl)
{
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/gzip.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/gzip.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/gzip.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/lz4.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/lz4.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/lz4.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* LZ4 - Fast LZ compression algorithm
* Header File
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/lzjb.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/lzjb.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/lzjb.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/metaslab.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/metaslab.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/metaslab.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/refcount.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/refcount.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/refcount.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/rrwlock.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/rrwlock.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/rrwlock.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sa.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sa.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sa.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -111,6 +112,7 @@
* location.
*
* Byteswap implications:
+ *
* Since the SA attributes are not entirely self describing we can't do
* the normal byteswap processing. The special ZAP layout attribute and
* attribute registration attributes define the byteswap function and the
@@ -189,7 +191,6 @@
};
/*
- * ZPL legacy layout
* This is only used for objects of type DMU_OT_ZNODE
*/
sa_attr_type_t sa_legacy_zpl_layout[] = {
@@ -199,7 +200,6 @@
/*
* Special dummy layout used for buffers with no attributes.
*/
-
sa_attr_type_t sa_dummy_zpl_layout[] = { 0 };
static int sa_legacy_attr_count = 16;
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sha256.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sha256.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sha256.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -27,6 +28,8 @@
*/
/*
+ * SPA: Storage Pool Allocator
+ *
* This file contains all the routines used when modifying on-disk SPA state.
* This includes opening, importing, destroying, exporting a pool, and syncing a
* pool.
@@ -86,6 +89,12 @@
SYSCTL_INT(_vfs_zfs, OID_AUTO, check_hostid, CTLFLAG_RW, &check_hostid, 0,
"Check hostid on import?");
+/*
+ * The interval, in seconds, at which failed configuration cache file writes
+ * should be retried.
+ */
+static int zfs_ccw_retry_interval = 300;
+
typedef enum zti_modes {
zti_mode_fixed, /* value is # of threads (min 1) */
zti_mode_online_percent, /* value is % of online CPUs */
@@ -2887,7 +2896,7 @@
#ifdef __FreeBSD__
#ifdef _KERNEL
if (firstopen)
- zvol_create_minors(pool);
+ zvol_create_minors(spa->spa_name);
#endif
#endif
}
@@ -4696,6 +4705,7 @@
/*
* Detach a device from a mirror or replacing vdev.
+ *
* If 'replace_done' is specified, only detach if the parent
* is a replacing vdev.
*/
@@ -5357,12 +5367,10 @@
* the spa_vdev_config_[enter/exit] functions which allow us to
* grab and release the spa_config_lock while still holding the namespace
* lock. During each step the configuration is synced out.
+ *
+ * Currently, this supports removing only hot spares, slogs, and level 2 ARC
+ * devices.
*/
-
-/*
- * Remove a device from the pool. Currently, this supports removing only hot
- * spares, slogs, and level 2 ARC devices.
- */
int
spa_vdev_remove(spa_t *spa, uint64_t guid, boolean_t unspare)
{
@@ -5471,7 +5479,7 @@
/*
* Find any device that's done replacing, or a vdev marked 'unspare' that's
- * current spared, so we can detach it.
+ * currently spared, so we can detach it.
*/
static vdev_t *
spa_vdev_resilver_done_hunt(vdev_t *vd)
@@ -5851,13 +5859,34 @@
mutex_exit(&spa->spa_async_lock);
}
+static boolean_t
+spa_async_tasks_pending(spa_t *spa)
+{
+ uint_t non_config_tasks;
+ uint_t config_task;
+ boolean_t config_task_suspended;
+
+ non_config_tasks = spa->spa_async_tasks & ~SPA_ASYNC_CONFIG_UPDATE;
+ config_task = spa->spa_async_tasks & SPA_ASYNC_CONFIG_UPDATE;
+ if (spa->spa_ccw_fail_time == 0) {
+ config_task_suspended = B_FALSE;
+ } else {
+ config_task_suspended =
+ (gethrtime() - spa->spa_ccw_fail_time) <
+ (zfs_ccw_retry_interval * NANOSEC);
+ }
+
+ return (non_config_tasks || (config_task && !config_task_suspended));
+}
+
static void
spa_async_dispatch(spa_t *spa)
{
mutex_enter(&spa->spa_async_lock);
- if (spa->spa_async_tasks && !spa->spa_async_suspended &&
+ if (spa_async_tasks_pending(spa) &&
+ !spa->spa_async_suspended &&
spa->spa_async_thread == NULL &&
- rootdir != NULL && !vn_is_readonly(rootdir))
+ rootdir != NULL)
spa->spa_async_thread = thread_create(NULL, 0,
spa_async_thread, spa, 0, &p0, TS_RUN, maxclsyspri);
mutex_exit(&spa->spa_async_lock);
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_config.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_config.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_config.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -27,6 +28,7 @@
#include <sys/zfs_context.h>
#include <sys/spa.h>
+#include <sys/fm/fs/zfs.h>
#include <sys/spa_impl.h>
#include <sys/nvpair.h>
#include <sys/uio.h>
@@ -139,7 +141,7 @@
kobj_close_file(file);
}
-static void
+static int
spa_config_write(spa_config_dirent_t *dp, nvlist_t *nvl)
{
size_t buflen;
@@ -147,13 +149,14 @@
vnode_t *vp;
int oflags = FWRITE | FTRUNC | FCREAT | FOFFMAX;
char *temp;
+ int err;
/*
* If the nvlist is empty (NULL), then remove the old cachefile.
*/
if (nvl == NULL) {
- (void) vn_remove(dp->scd_path, UIO_SYSSPACE, RMFILE);
- return;
+ err = vn_remove(dp->scd_path, UIO_SYSSPACE, RMFILE);
+ return (err);
}
/*
@@ -174,12 +177,14 @@
*/
(void) snprintf(temp, MAXPATHLEN, "%s.tmp", dp->scd_path);
- if (vn_open(temp, UIO_SYSSPACE, oflags, 0644, &vp, CRCREAT, 0) == 0) {
- if (vn_rdwr(UIO_WRITE, vp, buf, buflen, 0, UIO_SYSSPACE,
- 0, RLIM64_INFINITY, kcred, NULL) == 0 &&
- VOP_FSYNC(vp, FSYNC, kcred, NULL) == 0) {
- (void) vn_rename(temp, dp->scd_path, UIO_SYSSPACE);
- }
+ err = vn_open(temp, UIO_SYSSPACE, oflags, 0644, &vp, CRCREAT, 0);
+ if (err == 0) {
+ err = vn_rdwr(UIO_WRITE, vp, buf, buflen, 0, UIO_SYSSPACE,
+ 0, RLIM64_INFINITY, kcred, NULL);
+ if (err == 0)
+ err = VOP_FSYNC(vp, FSYNC, kcred, NULL);
+ if (err == 0)
+ err = vn_rename(temp, dp->scd_path, UIO_SYSSPACE);
(void) VOP_CLOSE(vp, oflags, 1, 0, kcred, NULL);
}
@@ -187,6 +192,7 @@
kmem_free(buf, buflen);
kmem_free(temp, MAXPATHLEN);
+ return (err);
}
/*
@@ -198,6 +204,8 @@
{
spa_config_dirent_t *dp, *tdp;
nvlist_t *nvl;
+ boolean_t ccw_failure;
+ int error;
ASSERT(MUTEX_HELD(&spa_namespace_lock));
@@ -209,6 +217,7 @@
* cachefile is changed, the new one is pushed onto this list, allowing
* us to update previous cachefiles that no longer contain this pool.
*/
+ ccw_failure = B_FALSE;
for (dp = list_head(&target->spa_config_list); dp != NULL;
dp = list_next(&target->spa_config_list, dp)) {
spa_t *spa = NULL;
@@ -249,10 +258,32 @@
mutex_exit(&spa->spa_props_lock);
}
- spa_config_write(dp, nvl);
+ error = spa_config_write(dp, nvl);
+ if (error != 0)
+ ccw_failure = B_TRUE;
nvlist_free(nvl);
}
+ if (ccw_failure) {
+ /*
+ * Keep trying so that configuration data is
+ * written if/when any temporary filesystem
+ * resource issues are resolved.
+ */
+ if (target->spa_ccw_fail_time == 0) {
+ zfs_ereport_post(FM_EREPORT_ZFS_CONFIG_CACHE_WRITE,
+ target, NULL, NULL, 0, 0);
+ }
+ target->spa_ccw_fail_time = gethrtime();
+ spa_async_request(target, SPA_ASYNC_CONFIG_UPDATE);
+ } else {
+ /*
+ * Do not rate limit future attempts to update
+ * the config cache.
+ */
+ target->spa_ccw_fail_time = 0;
+ }
+
/*
* Remove any config entries older than the current one.
*/
@@ -315,6 +346,7 @@
/*
* Generate the pool's configuration based on the current in-core state.
+ *
* We infer whether to generate a complete config or just one top-level config
* based on whether vd is the root vdev.
*/
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_errlog.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_errlog.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_errlog.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -183,8 +184,10 @@
if (copyout(&zb, (char *)addr +
(*count - 1) * sizeof (zbookmark_t),
- sizeof (zbookmark_t)) != 0)
+ sizeof (zbookmark_t)) != 0) {
+ zap_cursor_fini(&zc);
return (SET_ERROR(EFAULT));
+ }
*count -= 1;
}
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_history.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_history.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_history.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -1369,7 +1370,7 @@
/*
* This is a stripped-down version of strtoull, suitable only for converting
- * lowercase hexidecimal numbers that don't overflow.
+ * lowercase hexadecimal numbers that don't overflow.
*/
uint64_t
zfs_strtonum(const char *str, char **nptr)
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/space_map.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/space_map.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/space_map.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/arc.h
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/arc.h 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/arc.h 2016-10-14 02:04:39 UTC (rev 9155)
@@ -20,7 +20,8 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
*/
#ifndef _SYS_ARC_H
@@ -67,6 +68,7 @@
#define ARC_PREFETCH (1 << 3) /* I/O is a prefetch */
#define ARC_CACHED (1 << 4) /* I/O was already in cache */
#define ARC_L2CACHE (1 << 5) /* cache in L2ARC */
+#define ARC_L2COMPRESS (1 << 6) /* compress in L2ARC */
/*
* The following breakdows of arc_size exist for kstat only.
@@ -105,9 +107,10 @@
arc_done_func_t *done, void *priv, int priority, int flags,
uint32_t *arc_flags, const zbookmark_t *zb);
zio_t *arc_write(zio_t *pio, spa_t *spa, uint64_t txg,
- blkptr_t *bp, arc_buf_t *buf, boolean_t l2arc, const zio_prop_t *zp,
- arc_done_func_t *ready, arc_done_func_t *done, void *priv,
- int priority, int zio_flags, const zbookmark_t *zb);
+ blkptr_t *bp, arc_buf_t *buf, boolean_t l2arc, boolean_t l2arc_compress,
+ const zio_prop_t *zp, arc_done_func_t *ready, arc_done_func_t *done,
+ void *priv, int priority, int zio_flags, const zbookmark_t *zb);
+void arc_freed(spa_t *spa, const blkptr_t *bp);
void arc_set_callback(arc_buf_t *buf, arc_evict_func_t *func, void *priv);
int arc_buf_evict(arc_buf_t *buf);
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dbuf.h
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dbuf.h 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dbuf.h 2016-10-14 02:04:39 UTC (rev 9155)
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
*/
#ifndef _SYS_DBUF_H
@@ -324,6 +325,9 @@
(dbuf_is_metadata(_db) && \
((_db)->db_objset->os_secondary_cache == ZFS_CACHE_METADATA)))
+#define DBUF_IS_L2COMPRESSIBLE(_db) \
+ ((_db)->db_objset->os_compress != ZIO_COMPRESS_OFF)
+
#ifdef ZFS_DEBUG
/*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/ddt.h
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/ddt.h 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/ddt.h 2016-10-14 02:04:39 UTC (rev 9155)
@@ -63,16 +63,15 @@
*/
typedef struct ddt_key {
zio_cksum_t ddk_cksum; /* 256-bit block checksum */
- uint64_t ddk_prop; /* LSIZE, PSIZE, compression */
+ /*
+ * Encoded with logical & physical size, and compression, as follows:
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * | 0 | 0 | 0 | comp | PSIZE | LSIZE |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ */
+ uint64_t ddk_prop;
} ddt_key_t;
-/*
- * ddk_prop layout:
- *
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * | 0 | 0 | 0 | comp | PSIZE | LSIZE |
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- */
#define DDK_GET_LSIZE(ddk) \
BF64_GET_SB((ddk)->ddk_prop, 0, 16, SPA_MINBLOCKSHIFT, 1)
#define DDK_SET_LSIZE(ddk, x) \
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h 2016-10-14 02:04:39 UTC (rev 9155)
@@ -411,6 +411,8 @@
* object must be held in an assigned transaction before calling
* dmu_buf_will_dirty. You may use dmu_buf_set_user() on the bonus
* buffer as well. You must release your hold with dmu_buf_rele().
+ *
+ * Returns ENOENT, EIO, or 0.
*/
int dmu_bonus_hold(objset_t *os, uint64_t object, void *tag, dmu_buf_t **);
int dmu_bonus_max(void);
@@ -666,8 +668,14 @@
* If doi is NULL, just indicates whether the object exists.
*/
int dmu_object_info(objset_t *os, uint64_t object, dmu_object_info_t *doi);
+/* Like dmu_object_info, but faster if you have a held dnode in hand. */
void dmu_object_info_from_dnode(struct dnode *dn, dmu_object_info_t *doi);
+/* Like dmu_object_info, but faster if you have a held dbuf in hand. */
void dmu_object_info_from_db(dmu_buf_t *db, dmu_object_info_t *doi);
+/*
+ * Like dmu_object_info_from_db, but faster still when you only care about
+ * the size. This is specifically optimized for zfs_getattr().
+ */
void dmu_object_size_from_db(dmu_buf_t *db, uint32_t *blksize,
u_longlong_t *nblk512);
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu_objset.h
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu_objset.h 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu_objset.h 2016-10-14 02:04:39 UTC (rev 9155)
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
*/
/* Portions Copyright 2010 Robert Milkowski */
@@ -129,6 +130,8 @@
((os)->os_secondary_cache == ZFS_CACHE_ALL || \
(os)->os_secondary_cache == ZFS_CACHE_METADATA)
+#define DMU_OS_IS_L2COMPRESSIBLE(os) ((os)->os_compress != ZIO_COMPRESS_OFF)
+
/* called from zpl */
int dmu_objset_hold(const char *name, void *tag, objset_t **osp);
int dmu_objset_own(const char *name, dmu_objset_type_t type,
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dnode.h
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dnode.h 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dnode.h 2016-10-14 02:04:39 UTC (rev 9155)
@@ -145,9 +145,8 @@
typedef struct dnode {
/*
- * dn_struct_rwlock protects the structure of the dnode,
- * including the number of levels of indirection (dn_nlevels),
- * dn_maxblkid, and dn_next_*
+ * Protects the structure of the dnode, including the number of levels
+ * of indirection (dn_nlevels), dn_maxblkid, and dn_next_*
*/
krwlock_t dn_struct_rwlock;
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dataset.h
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dataset.h 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dataset.h 2016-10-14 02:04:39 UTC (rev 9155)
@@ -22,6 +22,7 @@
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2013 Steven Hartland. All rights reserved.
*/
#ifndef _SYS_DSL_DATASET_H
@@ -187,8 +188,6 @@
void dsl_dataset_disown(dsl_dataset_t *ds, void *tag);
void dsl_dataset_name(dsl_dataset_t *ds, char *name);
boolean_t dsl_dataset_tryown(dsl_dataset_t *ds, void *tag);
-void dsl_register_onexit_hold_cleanup(dsl_dataset_t *ds, const char *htag,
- minor_t minor);
uint64_t dsl_dataset_create_sync(dsl_dir_t *pds, const char *lastname,
dsl_dataset_t *origin, uint64_t flags, cred_t *, dmu_tx_t *);
uint64_t dsl_dataset_create_sync_dd(dsl_dir_t *dd, dsl_dataset_t *origin,
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_pool.h
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_pool.h 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_pool.h 2016-10-14 02:04:39 UTC (rev 9155)
@@ -110,6 +110,7 @@
/*
* Protects administrative changes (properties, namespace)
+ *
* It is only held for write in syncing context. Therefore
* syncing context does not need to ever have it for read, since
* nobody else could possibly have it for write.
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_scan.h
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_scan.h 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_scan.h 2016-10-14 02:04:39 UTC (rev 9155)
@@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
*/
#ifndef _SYS_DSL_SCAN_H
@@ -82,6 +82,7 @@
/* for freeing blocks */
boolean_t scn_is_bptree;
+ boolean_t scn_async_destroying;
/* for debugging / information */
uint64_t scn_visited_this_txg;
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_userhold.h
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_userhold.h 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_userhold.h 2016-10-14 02:04:39 UTC (rev 9155)
@@ -23,6 +23,7 @@
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2013 Steven Hartland. All rights reserved.
*/
#ifndef _SYS_DSL_USERHOLD_H
@@ -43,8 +44,7 @@
nvlist_t *errlist);
int dsl_dataset_user_release(nvlist_t *holds, nvlist_t *errlist);
int dsl_dataset_get_holds(const char *dsname, nvlist_t *nvl);
-void dsl_dataset_user_release_tmp(struct dsl_pool *dp, uint64_t dsobj,
- const char *htag);
+void dsl_dataset_user_release_tmp(struct dsl_pool *dp, nvlist_t *holds);
int dsl_dataset_user_hold_check_one(struct dsl_dataset *ds, const char *htag,
boolean_t temphold, struct dmu_tx *tx);
void dsl_dataset_user_hold_sync_one(struct dsl_dataset *ds, const char *htag,
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/sa_impl.h
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/sa_impl.h 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/sa_impl.h 2016-10-14 02:04:39 UTC (rev 9155)
@@ -150,6 +150,7 @@
/*
* header for all bonus and spill buffers.
+ *
* The header has a fixed portion with a variable number
* of "lengths" depending on the number of variable sized
* attribues which are determined by the "layout number"
@@ -158,29 +159,27 @@
#define SA_MAGIC 0x2F505A /* ZFS SA */
typedef struct sa_hdr_phys {
uint32_t sa_magic;
- uint16_t sa_layout_info; /* Encoded with hdrsize and layout number */
+ /*
+ * Encoded with hdrsize and layout number as follows:
+ * 16 10 0
+ * +--------+-------+
+ * | hdrsz |layout |
+ * +--------+-------+
+ *
+ * Bits 0-10 are the layout number
+ * Bits 11-16 are the size of the header.
+ * The hdrsize is the number * 8
+ *
+ * For example.
+ * hdrsz of 1 ==> 8 byte header
+ * 2 ==> 16 byte header
+ *
+ */
+ uint16_t sa_layout_info;
uint16_t sa_lengths[1]; /* optional sizes for variable length attrs */
/* ... Data follows the lengths. */
} sa_hdr_phys_t;
-/*
- * sa_hdr_phys -> sa_layout_info
- *
- * 16 10 0
- * +--------+-------+
- * | hdrsz |layout |
- * +--------+-------+
- *
- * Bits 0-10 are the layout number
- * Bits 11-16 are the size of the header.
- * The hdrsize is the number * 8
- *
- * For example.
- * hdrsz of 1 ==> 8 byte header
- * 2 ==> 16 byte header
- *
- */
-
#define SA_HDR_LAYOUT_NUM(hdr) BF32_GET(hdr->sa_layout_info, 0, 10)
#define SA_HDR_SIZE(hdr) BF32_GET_SB(hdr->sa_layout_info, 10, 6, 3, 0)
#define SA_HDR_LAYOUT_INFO_ENCODE(x, num, size) \
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa_impl.h
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa_impl.h 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa_impl.h 2016-10-14 02:04:39 UTC (rev 9155)
@@ -241,8 +241,9 @@
uint64_t spa_deadman_calls; /* number of deadman calls */
uint64_t spa_sync_starttime; /* starting time fo spa_sync */
uint64_t spa_deadman_synctime; /* deadman expiration timer */
+ hrtime_t spa_ccw_fail_time; /* Conf cache write fail time */
/*
- * spa_refcnt & spa_config_lock must be the last elements
+ * spa_refcount & spa_config_lock must be the last elements
* because refcount_t changes size based on compilation options.
* In order for the MDB module to function correctly, the other
* fields must remain in the same location.
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/space_map.h
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/space_map.h 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/space_map.h 2016-10-14 02:04:39 UTC (rev 9155)
@@ -94,7 +94,6 @@
* 63 62 60 59 50 49 0
*
*
- *
* non-debug entry
*
* 1 47 1 15
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/txg_impl.h
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/txg_impl.h 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/txg_impl.h 2016-10-14 02:04:39 UTC (rev 9155)
@@ -23,6 +23,10 @@
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ */
+
#ifndef _SYS_TXG_IMPL_H
#define _SYS_TXG_IMPL_H
@@ -33,14 +37,55 @@
extern "C" {
#endif
+/*
+ * The tx_cpu structure is a per-cpu structure that is used to track
+ * the number of active transaction holds (tc_count). As transactions
+ * are assigned into a transaction group the appropriate tc_count is
+ * incremented to indicate that there are pending changes that have yet
+ * to quiesce. Consumers evenutally call txg_rele_to_sync() to decrement
+ * the tc_count. A transaction group is not considered quiesced until all
+ * tx_cpu structures have reached a tc_count of zero.
+ *
+ * This structure is a per-cpu structure by design. Updates to this structure
+ * are frequent and concurrent. Having a single structure would result in
+ * heavy lock contention so a per-cpu design was implemented. With the fanned
+ * out mutex design, consumers only need to lock the mutex associated with
+ * thread's cpu.
+ *
+ * The tx_cpu contains two locks, the tc_lock and tc_open_lock.
+ * The tc_lock is used to protect all members of the tx_cpu structure with
+ * the exception of the tc_open_lock. This lock should only be held for a
+ * short period of time, typically when updating the value of tc_count.
+ *
+ * The tc_open_lock protects the tx_open_txg member of the tx_state structure.
+ * This lock is used to ensure that transactions are only assigned into
+ * the current open transaction group. In order to move the current open
+ * transaction group to the quiesce phase, the txg_quiesce thread must
+ * grab all tc_open_locks, increment the tx_open_txg, and drop the locks.
+ * The tc_open_lock is held until the transaction is assigned into the
+ * transaction group. Typically, this is a short operation but if throttling
+ * is occuring it may be held for longer periods of time.
+ */
struct tx_cpu {
- kmutex_t tc_lock;
+ kmutex_t tc_open_lock; /* protects tx_open_txg */
+ kmutex_t tc_lock; /* protects the rest of this struct */
kcondvar_t tc_cv[TXG_SIZE];
uint64_t tc_count[TXG_SIZE];
list_t tc_callbacks[TXG_SIZE]; /* commit cb list */
- char tc_pad[16];
+ char tc_pad[8]; /* pad to fill 3 cache lines */
};
+/*
+ * The tx_state structure maintains the state information about the different
+ * stages of the pool's transcation groups. A per pool tx_state structure
+ * is used to track this information. The tx_state structure also points to
+ * an array of tx_cpu structures (described above). Although the tx_sync_lock
+ * is used to protect the members of this structure, it is not used to
+ * protect the tx_open_txg. Instead a special lock in the tx_cpu structure
+ * is used. Readers of tx_open_txg must grab the per-cpu tc_open_lock.
+ * Any thread wishing to update tx_open_txg must grab the tc_open_lock on
+ * every cpu (see txg_quiesce()).
+ */
typedef struct tx_state {
tx_cpu_t *tx_cpu; /* protects right to enter txg */
kmutex_t tx_sync_lock; /* protects tx_state_t */
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/unique.h
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/unique.h 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/unique.h 2016-10-14 02:04:39 UTC (rev 9155)
@@ -26,8 +26,6 @@
#ifndef _SYS_UNIQUE_H
#define _SYS_UNIQUE_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/zfs_context.h>
#ifdef __cplusplus
@@ -42,7 +40,7 @@
/*
* Return a new unique value (which will not be uniquified against until
- * it is unique_insert()-ed.
+ * it is unique_insert()-ed).
*/
uint64_t unique_create(void);
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/vdev_impl.h
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/vdev_impl.h 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/vdev_impl.h 2016-10-14 02:04:39 UTC (rev 9155)
@@ -247,12 +247,13 @@
#define VDD_METASLAB 0x01
#define VDD_DTL 0x02
+/* Offset of embedded boot loader region on each label */
+#define VDEV_BOOT_OFFSET (2 * sizeof (vdev_label_t))
/*
- * Size and offset of embedded boot loader region on each label.
+ * Size of embedded boot loader region on each label.
* The total size of the first two labels plus the boot area is 4MB.
*/
-#define VDEV_BOOT_OFFSET (2 * sizeof (vdev_label_t))
-#define VDEV_BOOT_SIZE (7ULL << 19) /* 3.5M */
+#define VDEV_BOOT_SIZE (7ULL << 19) /* 3.5M */
/*
* Size of label regions at the start and end of each leaf device.
@@ -323,8 +324,9 @@
extern void vdev_set_min_asize(vdev_t *vd);
/*
- * zdb uses this tunable, so it must be declared here to make lint happy.
+ * Global variables
*/
+/* zdb uses this tunable, so it must be declared here to make lint happy. */
extern int zfs_vdev_cache_size;
#ifdef __cplusplus
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zap.h
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zap.h 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zap.h 2016-10-14 02:04:39 UTC (rev 9155)
@@ -86,18 +86,22 @@
#endif
/*
- * The matchtype specifies which entry will be accessed.
- * MT_EXACT: only find an exact match (non-normalized)
- * MT_FIRST: find the "first" normalized (case and Unicode
- * form) match; the designated "first" match will not change as long
- * as the set of entries with this normalization doesn't change
- * MT_BEST: if there is an exact match, find that, otherwise find the
- * first normalized match
+ * Specifies matching criteria for ZAP lookups.
*/
typedef enum matchtype
{
+ /* Only find an exact match (non-normalized) */
MT_EXACT,
+ /*
+ * If there is an exact match, find that, otherwise find the
+ * first normalized match.
+ */
MT_BEST,
+ /*
+ * Find the "first" normalized (case and Unicode form) match;
+ * the designated "first" match will not change as long as the
+ * set of entries with this normalization doesn't change.
+ */
MT_FIRST
} matchtype_t;
@@ -174,16 +178,21 @@
* call will fail and return EINVAL.
*
* If 'integer_size' is equal to or larger than the attribute's integer
- * size, the call will succeed and return 0. * When converting to a
- * larger integer size, the integers will be treated as unsigned (ie. no
- * sign-extension will be performed).
+ * size, the call will succeed and return 0.
*
+ * When converting to a larger integer size, the integers will be treated as
+ * unsigned (ie. no sign-extension will be performed).
+ *
* 'num_integers' is the length (in integers) of 'buf'.
*
* If the attribute is longer than the buffer, as many integers as will
* fit will be transferred to 'buf'. If the entire attribute was not
* transferred, the call will return EOVERFLOW.
- *
+ */
+int zap_lookup(objset_t *ds, uint64_t zapobj, const char *name,
+ uint64_t integer_size, uint64_t num_integers, void *buf);
+
+/*
* If rn_len is nonzero, realname will be set to the name of the found
* entry (which may be different from the requested name if matchtype is
* not MT_EXACT).
@@ -191,8 +200,6 @@
* If normalization_conflictp is not NULL, it will be set if there is
* another name with the same case/unicode normalized form.
*/
-int zap_lookup(objset_t *ds, uint64_t zapobj, const char *name,
- uint64_t integer_size, uint64_t num_integers, void *buf);
int zap_lookup_norm(objset_t *ds, uint64_t zapobj, const char *name,
uint64_t integer_size, uint64_t num_integers, void *buf,
matchtype_t mt, char *realname, int rn_len,
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zap_leaf.h
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zap_leaf.h 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zap_leaf.h 2016-10-14 02:04:39 UTC (rev 9155)
@@ -101,6 +101,7 @@
*/
typedef struct zap_leaf_phys {
struct zap_leaf_header {
+ /* Public to ZAP */
uint64_t lh_block_type; /* ZBT_LEAF */
uint64_t lh_pad1;
uint64_t lh_prefix; /* hash prefix of this leaf */
@@ -109,8 +110,7 @@
uint16_t lh_nentries; /* number of entries */
uint16_t lh_prefix_len; /* num bits used to id this */
-/* above is accessable to zap, below is zap_leaf private */
-
+ /* Private to zap_leaf */
uint16_t lh_freelist; /* chunk head of free list */
uint8_t lh_flags; /* ZLF_* flags */
uint8_t lh_pad2[11];
@@ -161,13 +161,13 @@
typedef struct zap_entry_handle {
- /* below is set by zap_leaf.c and is public to zap.c */
+ /* Set by zap_leaf and public to ZAP */
uint64_t zeh_num_integers;
uint64_t zeh_hash;
uint32_t zeh_cd;
uint8_t zeh_integer_size;
- /* below is private to zap_leaf.c */
+ /* Private to zap_leaf */
uint16_t zeh_fakechunk;
uint16_t *zeh_chunkp;
zap_leaf_t *zeh_leaf;
@@ -202,7 +202,7 @@
/*
* Replace the value of an existing entry.
*
- * zap_entry_update may fail if it runs out of space (ENOSPC).
+ * May fail if it runs out of space (ENOSPC).
*/
extern int zap_entry_update(zap_entry_handle_t *zeh,
uint8_t integer_size, uint64_t num_integers, const void *buf);
@@ -221,10 +221,7 @@
uint8_t integer_size, uint64_t num_integers, const void *buf,
zap_entry_handle_t *zeh);
-/*
- * Return true if there are additional entries with the same normalized
- * form.
- */
+/* Determine whether there is another entry with the same normalized form. */
extern boolean_t zap_entry_normalization_conflict(zap_entry_handle_t *zeh,
struct zap_name *zn, const char *name, struct zap *zap);
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_acl.h
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_acl.h 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_acl.h 2016-10-14 02:04:39 UTC (rev 9155)
@@ -45,7 +45,8 @@
#define ZFS_ACL_VERSION ZFS_ACL_VERSION_FUID
/*
- * ZFS ACLs are store in various forms.
+ * ZFS ACLs (Access Control Lists) are stored in various forms.
+ *
* Files created with ACL version ZFS_ACL_VERSION_INITIAL
* will all be created with fixed length ACEs of type
* zfs_oldace_t.
@@ -135,8 +136,8 @@
size_t (*ace_size)(void *acep); /* how big is this ace */
size_t (*ace_abstract_size)(void); /* sizeof abstract entry */
int (*ace_mask_off)(void); /* off of access mask in ace */
+ /* ptr to data if any */
int (*ace_data)(void *acep, void **datap);
- /* ptr to data if any */
} acl_ops_t;
/*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_ioctl.h
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_ioctl.h 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_ioctl.h 2016-10-14 02:04:39 UTC (rev 9155)
@@ -360,7 +360,7 @@
const char *to, cred_t *cr);
extern int zfs_secpolicy_destroy_perms(const char *name, cred_t *cr);
extern int zfs_busy(void);
-extern void zfs_unmount_snap(const char *);
+extern int zfs_unmount_snap(const char *);
extern void zfs_destroy_unmount_origin(const char *);
/*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_rlock.h
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_rlock.h 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_rlock.h 2016-10-14 02:04:39 UTC (rev 9155)
@@ -26,8 +26,6 @@
#ifndef _SYS_FS_ZFS_RLOCK_H
#define _SYS_FS_ZFS_RLOCK_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -57,16 +55,14 @@
} rl_t;
/*
- * Lock a range (offset, length) as either shared (READER)
- * or exclusive (WRITER or APPEND). APPEND is a special type that
- * is converted to WRITER that specified to lock from the start of the
- * end of file. zfs_range_lock() returns the range lock structure.
+ * Lock a range (offset, length) as either shared (RL_READER)
+ * or exclusive (RL_WRITER or RL_APPEND). RL_APPEND is a special type that
+ * is converted to RL_WRITER that specified to lock from the start of the
+ * end of file. Returns the range lock structure.
*/
rl_t *zfs_range_lock(znode_t *zp, uint64_t off, uint64_t len, rl_type_t type);
-/*
- * Unlock range and destroy range lock structure.
- */
+/* Unlock range and destroy range lock structure. */
void zfs_range_unlock(rl_t *rl);
/*
@@ -76,7 +72,8 @@
void zfs_range_reduce(rl_t *rl, uint64_t off, uint64_t len);
/*
- * AVL comparison function used to compare range locks
+ * AVL comparison function used to order range locks
+ * Locks are ordered on the start offset of the range.
*/
int zfs_range_compare(const void *arg1, const void *arg2);
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_znode.h
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_znode.h 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_znode.h 2016-10-14 02:04:39 UTC (rev 9155)
@@ -135,8 +135,9 @@
#define ZFS_MAX_BLOCKSIZE (SPA_MAXBLOCKSIZE)
-/* Path component length */
/*
+ * Path component length
+ *
* The generic fs code uses MAXNAMELEN to represent
* what the largest component length is. Unfortunately,
* this length includes the terminating NULL. ZFS needs
@@ -252,12 +253,7 @@
#define VTOZ(VP) ((znode_t *)(VP)->v_data)
#endif
-/*
- * ZFS_ENTER() is called on entry to each ZFS vnode and vfs operation.
- * ZFS_ENTER_NOERROR() is called when we can't return EIO.
- * ZFS_EXIT() must be called before exitting the vop.
- * ZFS_VERIFY_ZP() verifies the znode is valid.
- */
+/* Called on entry to each ZFS vnode and vfs operation */
#define ZFS_ENTER(zfsvfs) \
{ \
rrw_enter_read(&(zfsvfs)->z_teardown_lock, FTAG); \
@@ -267,11 +263,14 @@
} \
}
+/* Called on entry to each ZFS vnode and vfs operation that can not return EIO */
#define ZFS_ENTER_NOERROR(zfsvfs) \
rrw_enter(&(zfsvfs)->z_teardown_lock, RW_READER, FTAG)
+/* Must be called before exiting the vop */
#define ZFS_EXIT(zfsvfs) rrw_exit(&(zfsvfs)->z_teardown_lock, FTAG)
+/* Verifies the znode is valid */
#define ZFS_VERIFY_ZP(zp) \
if ((zp)->z_sa_hdl == NULL) { \
ZFS_EXIT((zp)->z_zfsvfs); \
@@ -291,9 +290,7 @@
#define ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num) \
mutex_exit(ZFS_OBJ_MUTEX((zfsvfs), (obj_num)))
-/*
- * Macros to encode/decode ZFS stored time values from/to struct timespec
- */
+/* Encode ZFS stored time values from a struct timespec */
#define ZFS_TIME_ENCODE(tp, stmp) \
{ \
(stmp)[0] = (uint64_t)(tp)->tv_sec; \
@@ -300,6 +297,7 @@
(stmp)[1] = (uint64_t)(tp)->tv_nsec; \
}
+/* Decode ZFS stored time values to a struct timespec */
#define ZFS_TIME_DECODE(tp, stmp) \
{ \
(tp)->tv_sec = (time_t)(stmp)[0]; \
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zil.h
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zil.h 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zil.h 2016-10-14 02:04:39 UTC (rev 9155)
@@ -242,6 +242,12 @@
* information needed for replaying the create. If the
* file doesn't have any actual ACEs then the lr_aclcnt
* would be zero.
+ *
+ * After lr_acl_flags, there are a lr_acl_bytes number of variable sized ace's.
+ * If create is also setting xvattr's, then acl data follows xvattr.
+ * If ACE FUIDs are needed then they will follow the xvattr_t. Following
+ * the FUIDs will be the domain table information. The FUIDs for the owner
+ * and group will be in lr_create. Name follows ACL data.
*/
typedef struct {
lr_create_t lr_create; /* common create portion */
@@ -250,13 +256,6 @@
uint64_t lr_fuidcnt; /* number of real fuids */
uint64_t lr_acl_bytes; /* number of bytes in ACL */
uint64_t lr_acl_flags; /* ACL flags */
- /* lr_acl_bytes number of variable sized ace's follows */
- /* if create is also setting xvattr's, then acl data follows xvattr */
- /* if ACE FUIDs are needed then they will follow the xvattr_t */
- /* Following the FUIDs will be the domain table information. */
- /* The FUIDs for the owner and group will be in the lr_create */
- /* portion of the record. */
- /* name follows ACL data */
} lr_acl_create_t;
typedef struct {
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio_impl.h
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio_impl.h 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zio_impl.h 2016-10-14 02:04:39 UTC (rev 9155)
@@ -115,27 +115,28 @@
ZIO_STAGE_CHECKSUM_GENERATE = 1 << 5, /* -W--- */
ZIO_STAGE_NOP_WRITE = 1 << 6, /* -W--- */
- ZIO_STAGE_DDT_READ_START = 1 << 6, /* R---- */
- ZIO_STAGE_DDT_READ_DONE = 1 << 7, /* R---- */
- ZIO_STAGE_DDT_WRITE = 1 << 8, /* -W--- */
- ZIO_STAGE_DDT_FREE = 1 << 9, /* --F-- */
- ZIO_STAGE_GANG_ASSEMBLE = 1 << 10, /* RWFC- */
- ZIO_STAGE_GANG_ISSUE = 1 << 11, /* RWFC- */
+ ZIO_STAGE_DDT_READ_START = 1 << 7, /* R---- */
+ ZIO_STAGE_DDT_READ_DONE = 1 << 8, /* R---- */
+ ZIO_STAGE_DDT_WRITE = 1 << 9, /* -W--- */
+ ZIO_STAGE_DDT_FREE = 1 << 10, /* --F-- */
- ZIO_STAGE_DVA_ALLOCATE = 1 << 12, /* -W--- */
- ZIO_STAGE_DVA_FREE = 1 << 13, /* --F-- */
- ZIO_STAGE_DVA_CLAIM = 1 << 14, /* ---C- */
+ ZIO_STAGE_GANG_ASSEMBLE = 1 << 11, /* RWFC- */
+ ZIO_STAGE_GANG_ISSUE = 1 << 12, /* RWFC- */
- ZIO_STAGE_READY = 1 << 15, /* RWFCI */
+ ZIO_STAGE_DVA_ALLOCATE = 1 << 13, /* -W--- */
+ ZIO_STAGE_DVA_FREE = 1 << 14, /* --F-- */
+ ZIO_STAGE_DVA_CLAIM = 1 << 15, /* ---C- */
- ZIO_STAGE_VDEV_IO_START = 1 << 16, /* RWF-I */
- ZIO_STAGE_VDEV_IO_DONE = 1 << 17, /* RWF-- */
- ZIO_STAGE_VDEV_IO_ASSESS = 1 << 18, /* RWF-I */
+ ZIO_STAGE_READY = 1 << 16, /* RWFCI */
- ZIO_STAGE_CHECKSUM_VERIFY = 1 << 19, /* R---- */
+ ZIO_STAGE_VDEV_IO_START = 1 << 17, /* RWF-I */
+ ZIO_STAGE_VDEV_IO_DONE = 1 << 18, /* RWF-- */
+ ZIO_STAGE_VDEV_IO_ASSESS = 1 << 19, /* RWF-I */
- ZIO_STAGE_DONE = 1 << 20 /* RWFCI */
+ ZIO_STAGE_CHECKSUM_VERIFY = 1 << 20, /* R---- */
+
+ ZIO_STAGE_DONE = 1 << 21 /* RWFCI */
};
#define ZIO_INTERLOCK_STAGES \
@@ -212,6 +213,7 @@
#define ZIO_FREE_PIPELINE \
(ZIO_INTERLOCK_STAGES | \
ZIO_STAGE_FREE_BP_INIT | \
+ ZIO_STAGE_ISSUE_ASYNC | \
ZIO_STAGE_DVA_FREE | \
ZIO_STAGE_VDEV_IO_START | \
ZIO_STAGE_VDEV_IO_ASSESS)
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/trim_map.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/trim_map.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/trim_map.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/txg.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/txg.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/txg.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -132,6 +133,8 @@
int i;
mutex_init(&tx->tx_cpu[c].tc_lock, NULL, MUTEX_DEFAULT, NULL);
+ mutex_init(&tx->tx_cpu[c].tc_open_lock, NULL, MUTEX_DEFAULT,
+ NULL);
for (i = 0; i < TXG_SIZE; i++) {
cv_init(&tx->tx_cpu[c].tc_cv[i], NULL, CV_DEFAULT,
NULL);
@@ -174,6 +177,7 @@
for (c = 0; c < max_ncpus; c++) {
int i;
+ mutex_destroy(&tx->tx_cpu[c].tc_open_lock);
mutex_destroy(&tx->tx_cpu[c].tc_lock);
for (i = 0; i < TXG_SIZE; i++) {
cv_destroy(&tx->tx_cpu[c].tc_cv[i]);
@@ -297,10 +301,12 @@
tx_cpu_t *tc = &tx->tx_cpu[CPU_SEQID];
uint64_t txg;
+ mutex_enter(&tc->tc_open_lock);
+ txg = tx->tx_open_txg;
+
mutex_enter(&tc->tc_lock);
-
- txg = tx->tx_open_txg;
tc->tc_count[txg & TXG_MASK]++;
+ mutex_exit(&tc->tc_lock);
th->th_cpu = tc;
th->th_txg = txg;
@@ -313,7 +319,8 @@
{
tx_cpu_t *tc = th->th_cpu;
- mutex_exit(&tc->tc_lock);
+ ASSERT(!MUTEX_HELD(&tc->tc_lock));
+ mutex_exit(&tc->tc_open_lock);
}
void
@@ -342,6 +349,12 @@
th->th_cpu = NULL; /* defensive */
}
+/*
+ * Blocks until all transactions in the group are committed.
+ *
+ * On return, the transaction group has reached a stable state in which it can
+ * then be passed off to the syncing context.
+ */
static void
txg_quiesce(dsl_pool_t *dp, uint64_t txg)
{
@@ -350,10 +363,10 @@
int c;
/*
- * Grab all tx_cpu locks so nobody else can get into this txg.
+ * Grab all tc_open_locks so nobody else can get into this txg.
*/
for (c = 0; c < max_ncpus; c++)
- mutex_enter(&tx->tx_cpu[c].tc_lock);
+ mutex_enter(&tx->tx_cpu[c].tc_open_lock);
ASSERT(txg == tx->tx_open_txg);
tx->tx_open_txg++;
@@ -363,7 +376,7 @@
* enter the next transaction group.
*/
for (c = 0; c < max_ncpus; c++)
- mutex_exit(&tx->tx_cpu[c].tc_lock);
+ mutex_exit(&tx->tx_cpu[c].tc_open_lock);
/*
* Quiesce the transaction group by waiting for everyone to txg_exit().
@@ -391,6 +404,9 @@
/*
* Dispatch the commit callbacks registered on this txg to worker threads.
+ *
+ * If no callbacks are registered for a given TXG, nothing happens.
+ * This function creates a taskq for the associated pool, if needed.
*/
static void
txg_dispatch_callbacks(dsl_pool_t *dp, uint64_t txg)
@@ -401,7 +417,10 @@
for (c = 0; c < max_ncpus; c++) {
tx_cpu_t *tc = &tx->tx_cpu[c];
- /* No need to lock tx_cpu_t at this point */
+ /*
+ * No need to lock tx_cpu_t at this point, since this can
+ * only be called once a txg has been synced.
+ */
int g = txg & TXG_MASK;
@@ -421,7 +440,7 @@
list_create(cb_list, sizeof (dmu_tx_callback_t),
offsetof(dmu_tx_callback_t, dcb_node));
- list_move_tail(&tc->tc_callbacks[g], cb_list);
+ list_move_tail(cb_list, &tc->tc_callbacks[g]);
(void) taskq_dispatch(tx->tx_commit_cb_taskq, (task_func_t *)
txg_do_callbacks, cb_list, TQ_SLEEP);
@@ -552,8 +571,8 @@
/*
* Delay this thread by 'ticks' if we are still in the open transaction
- * group and there is already a waiting txg quiesing or quiesced. Abort
- * the delay if this txg stalls or enters the quiesing state.
+ * group and there is already a waiting txg quiescing or quiesced.
+ * Abort the delay if this txg stalls or enters the quiescing state.
*/
void
txg_delay(dsl_pool_t *dp, uint64_t txg, int ticks)
@@ -561,7 +580,7 @@
tx_state_t *tx = &dp->dp_tx;
clock_t timeout = ddi_get_lbolt() + ticks;
- /* don't delay if this txg could transition to quiesing immediately */
+ /* don't delay if this txg could transition to quiescing immediately */
if (tx->tx_open_txg > txg ||
tx->tx_syncing_txg == txg-1 || tx->tx_synced_txg == txg-1)
return;
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/uberblock.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/uberblock.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/uberblock.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/unique.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/unique.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/unique.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -963,9 +964,11 @@
}
/*
- * Determine whether this device is accessible by reading and writing
- * to several known locations: the pad regions of each vdev label
- * but the first (which we leave alone in case it contains a VTOC).
+ * Determine whether this device is accessible.
+ *
+ * Read and write to several known locations: the pad regions of each
+ * vdev label but the first, which we leave alone in case it contains
+ * a VTOC.
*/
zio_t *
vdev_probe(vdev_t *vd, zio_t *zio)
@@ -1834,6 +1837,7 @@
vdev_config_dirty(vd->vdev_top);
}
+ bzero(&smlock, sizeof (smlock));
mutex_init(&smlock, NULL, MUTEX_DEFAULT, NULL);
space_map_create(&smsync, sm->sm_start, sm->sm_size, sm->sm_shift,
@@ -2190,10 +2194,12 @@
}
/*
- * Online the given vdev. If 'unspare' is set, it implies two things. First,
- * any attached spare device should be detached when the device finishes
- * resilvering. Second, the online should be treated like a 'test' online case,
- * so no FMA events are generated if the device fails to open.
+ * Online the given vdev.
+ *
+ * If 'ZFS_ONLINE_UNSPARE' is set, it implies two things. First, any attached
+ * spare device should be detached when the device finishes resilvering.
+ * Second, the online should be treated like a 'test' online case, so no FMA
+ * events are generated if the device fails to open.
*/
int
vdev_online(spa_t *spa, uint64_t guid, uint64_t flags, vdev_state_t *newstate)
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_cache.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_cache.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_cache.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_disk.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_disk.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_disk.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_file.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_file.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_file.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -69,6 +70,8 @@
g_topology_assert();
vd = cp->private;
+ if (vd == NULL)
+ return;
/*
* Orphan callbacks occur from the GEOM event thread.
@@ -270,8 +273,7 @@
continue;
if (nvlist_lookup_uint64(*config, ZPOOL_CONFIG_POOL_STATE,
- &state) != 0 || state == POOL_STATE_DESTROYED ||
- state > POOL_STATE_L2CACHE) {
+ &state) != 0 || state > POOL_STATE_L2CACHE) {
nvlist_free(*config);
*config = NULL;
continue;
@@ -379,7 +381,7 @@
}
static void
-vdev_geom_dettach_taster(struct g_consumer *cp)
+vdev_geom_detach_taster(struct g_consumer *cp)
{
g_access(cp, -1, 0, 0);
g_detach(cp);
@@ -422,7 +424,7 @@
g_topology_unlock();
error = vdev_geom_read_config(zcp, &vdev_cfg);
g_topology_lock();
- vdev_geom_dettach_taster(zcp);
+ vdev_geom_detach_taster(zcp);
if (error)
continue;
ZFS_LOG(1, "successfully read vdev config");
@@ -486,7 +488,7 @@
g_topology_unlock();
pguid = vdev_geom_read_guid(zcp);
g_topology_lock();
- vdev_geom_dettach_taster(zcp);
+ vdev_geom_detach_taster(zcp);
if (pguid != guid)
continue;
cp = vdev_geom_attach(pp);
@@ -690,6 +692,7 @@
return;
vd->vdev_tsd = NULL;
vd->vdev_delayed_close = B_FALSE;
+ cp->private = NULL; /* XXX locking */
g_post_event(vdev_geom_detach, cp, M_WAITOK, NULL);
}
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_label.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_label.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_label.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -1044,6 +1045,7 @@
zio_buf_free(ubbuf, VDEV_UBERBLOCK_SIZE(vd));
}
+/* Sync the uberblocks to all vdevs in svd[] */
int
vdev_uberblock_sync_list(vdev_t **svd, int svdcount, uberblock_t *ub, int flags)
{
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_mirror.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_mirror.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_mirror.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_missing.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_missing.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_missing.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_queue.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_queue.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_queue.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -35,13 +36,14 @@
/*
* These tunables are for performance analysis.
*/
+
+/* The maximum number of I/Os concurrently pending to each device. */
+int zfs_vdev_max_pending = 10;
+
/*
- * zfs_vdev_max_pending is the maximum number of i/os concurrently
- * pending to each device. zfs_vdev_min_pending is the initial number
- * of i/os pending to each device (before it starts ramping up to
- * max_pending).
+ * The initial number of I/Os pending to each device, before it starts ramping
+ * up to zfs_vdev_max_pending.
*/
-int zfs_vdev_max_pending = 10;
int zfs_vdev_min_pending = 4;
/*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_raidz.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_raidz.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_raidz.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -60,6 +61,7 @@
* o addition (+) is represented by a bitwise XOR
* o subtraction (-) is therefore identical to addition: A + B = A - B
* o multiplication of A by 2 is defined by the following bitwise expression:
+ *
* (A * 2)_7 = A_6
* (A * 2)_6 = A_5
* (A * 2)_5 = A_4
@@ -118,7 +120,7 @@
uint64_t rm_missingparity; /* Count of missing parity devices */
uint64_t rm_firstdatacol; /* First data column/parity count */
uint64_t rm_nskip; /* Skipped sectors for padding */
- uint64_t rm_skipstart; /* Column index of padding start */
+ uint64_t rm_skipstart; /* Column index of padding start */
void *rm_datacopy; /* rm_asize-buffer of copied data */
uintptr_t rm_reports; /* # of referencing checksum reports */
uint8_t rm_freed; /* map no longer has referencing ZIO */
@@ -158,10 +160,7 @@
*/
int vdev_raidz_default_to_general;
-/*
- * These two tables represent powers and logs of 2 in the Galois field defined
- * above. These values were computed by repeatedly multiplying by 2 as above.
- */
+/* Powers of 2 in the Galois field defined above. */
static const uint8_t vdev_raidz_pow2[256] = {
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
0x1d, 0x3a, 0x74, 0xe8, 0xcd, 0x87, 0x13, 0x26,
@@ -196,6 +195,7 @@
0x2c, 0x58, 0xb0, 0x7d, 0xfa, 0xe9, 0xcf, 0x83,
0x1b, 0x36, 0x6c, 0xd8, 0xad, 0x47, 0x8e, 0x01
};
+/* Logs of 2 in the Galois field defined above. */
static const uint8_t vdev_raidz_log2[256] = {
0x00, 0x00, 0x01, 0x19, 0x02, 0x32, 0x1a, 0xc6,
0x03, 0xdf, 0x33, 0xee, 0x1b, 0x68, 0xc7, 0x4b,
@@ -433,23 +433,50 @@
vdev_raidz_cksum_report
};
+/*
+ * Divides the IO evenly across all child vdevs; usually, dcols is
+ * the number of children in the target vdev.
+ */
static raidz_map_t *
vdev_raidz_map_alloc(zio_t *zio, uint64_t unit_shift, uint64_t dcols,
uint64_t nparity)
{
raidz_map_t *rm;
+ /* The starting RAIDZ (parent) vdev sector of the block. */
uint64_t b = zio->io_offset >> unit_shift;
+ /* The zio's size in units of the vdev's minimum sector size. */
uint64_t s = zio->io_size >> unit_shift;
+ /* The first column for this stripe. */
uint64_t f = b % dcols;
+ /* The starting byte offset on each child vdev. */
uint64_t o = (b / dcols) << unit_shift;
uint64_t q, r, c, bc, col, acols, scols, coff, devidx, asize, tot;
+ /*
+ * "Quotient": The number of data sectors for this stripe on all but
+ * the "big column" child vdevs that also contain "remainder" data.
+ */
q = s / (dcols - nparity);
+
+ /*
+ * "Remainder": The number of partial stripe data sectors in this I/O.
+ * This will add a sector to some, but not all, child vdevs.
+ */
r = s - q * (dcols - nparity);
+
+ /* The number of "big columns" - those which contain remainder data. */
bc = (r == 0 ? 0 : r + nparity);
+
+ /*
+ * The total number of data and parity sectors associated with
+ * this I/O.
+ */
tot = s + nparity * (q + (r == 0 ? 0 : 1));
+ /* acols: The columns that will be accessed. */
+ /* scols: The columns that will be accessed or skipped. */
if (q == 0) {
+ /* Our I/O request doesn't span all child vdevs. */
acols = bc;
scols = MIN(dcols, roundup(bc, nparity + 1));
} else {
@@ -1529,6 +1556,23 @@
rc->rc_skipped = 0;
}
+/*
+ * Start an IO operation on a RAIDZ VDev
+ *
+ * Outline:
+ * - For write operations:
+ * 1. Generate the parity data
+ * 2. Create child zio write operations to each column's vdev, for both
+ * data and parity.
+ * 3. If the column skips any sectors for padding, create optional dummy
+ * write zio children for those areas to improve aggregation continuity.
+ * - For read operations:
+ * 1. Create child zio read operations to each data column's vdev to read
+ * the range of data required for zio.
+ * 2. If this is a scrub or resilver operation, or if any of the data
+ * vdevs have had errors, then create zio read operations to the parity
+ * columns' VDevs as well.
+ */
static int
vdev_raidz_io_start(zio_t *zio)
{
@@ -1881,6 +1925,27 @@
return (ret);
}
+/*
+ * Complete an IO operation on a RAIDZ VDev
+ *
+ * Outline:
+ * - For write operations:
+ * 1. Check for errors on the child IOs.
+ * 2. Return, setting an error code if too few child VDevs were written
+ * to reconstruct the data later. Note that partial writes are
+ * considered successful if they can be reconstructed at all.
+ * - For read operations:
+ * 1. Check for errors on the child IOs.
+ * 2. If data errors occurred:
+ * a. Try to reassemble the data from the parity available.
+ * b. If we haven't yet read the parity drives, read them now.
+ * c. If all parity drives have been read but the data still doesn't
+ * reassemble with a correct checksum, then try combinatorial
+ * reconstruction.
+ * d. If that doesn't work, return an error.
+ * 3. If there were unexpected errors or this is a resilver operation,
+ * rewrite the vdevs that had errors.
+ */
static void
vdev_raidz_io_done(zio_t *zio)
{
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_root.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_root.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_root.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -295,7 +296,8 @@
err = dmu_buf_hold(zap->zap_objset, zap->zap_object,
(tbl->zt_nextblk + blk) << bs, FTAG, &db,
DMU_READ_NO_PREFETCH);
- dmu_buf_rele(db, FTAG);
+ if (err == 0)
+ dmu_buf_rele(db, FTAG);
}
return (err);
}
@@ -992,18 +994,21 @@
zap_attribute_t za;
int err;
+ err = 0;
for (zap_cursor_init(&zc, os, fromobj);
zap_cursor_retrieve(&zc, &za) == 0;
(void) zap_cursor_advance(&zc)) {
- if (za.za_integer_length != 8 || za.za_num_integers != 1)
- return (SET_ERROR(EINVAL));
+ if (za.za_integer_length != 8 || za.za_num_integers != 1) {
+ err = SET_ERROR(EINVAL);
+ break;
+ }
err = zap_add(os, intoobj, za.za_name,
8, 1, &za.za_first_integer, tx);
if (err)
- return (err);
+ break;
}
zap_cursor_fini(&zc);
- return (0);
+ return (err);
}
int
@@ -1014,18 +1019,21 @@
zap_attribute_t za;
int err;
+ err = 0;
for (zap_cursor_init(&zc, os, fromobj);
zap_cursor_retrieve(&zc, &za) == 0;
(void) zap_cursor_advance(&zc)) {
- if (za.za_integer_length != 8 || za.za_num_integers != 1)
- return (SET_ERROR(EINVAL));
+ if (za.za_integer_length != 8 || za.za_num_integers != 1) {
+ err = SET_ERROR(EINVAL);
+ break;
+ }
err = zap_add(os, intoobj, za.za_name,
8, 1, &value, tx);
if (err)
- return (err);
+ break;
}
zap_cursor_fini(&zc);
- return (0);
+ return (err);
}
int
@@ -1036,24 +1044,27 @@
zap_attribute_t za;
int err;
+ err = 0;
for (zap_cursor_init(&zc, os, fromobj);
zap_cursor_retrieve(&zc, &za) == 0;
(void) zap_cursor_advance(&zc)) {
uint64_t delta = 0;
- if (za.za_integer_length != 8 || za.za_num_integers != 1)
- return (SET_ERROR(EINVAL));
+ if (za.za_integer_length != 8 || za.za_num_integers != 1) {
+ err = SET_ERROR(EINVAL);
+ break;
+ }
err = zap_lookup(os, intoobj, za.za_name, 8, 1, &delta);
if (err != 0 && err != ENOENT)
- return (err);
+ break;
delta += za.za_first_integer;
err = zap_update(os, intoobj, za.za_name, 8, 1, &delta, tx);
if (err)
- return (err);
+ break;
}
zap_cursor_fini(&zc);
- return (0);
+ return (err);
}
int
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap_leaf.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap_leaf.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap_leaf.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap_micro.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap_micro.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zap_micro.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfeature.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfeature.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfeature.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_acl.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_acl.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_acl.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -1359,7 +1360,8 @@
zacep = (void *)((uintptr_t)zacep + abstract_size);
new_count++;
new_bytes += abstract_size;
- } if (masks.deny1) {
+ }
+ if (masks.deny1) {
zfs_set_ace(aclp, zacep, masks.deny1, DENY, -1, ACE_OWNER);
zacep = (void *)((uintptr_t)zacep + abstract_size);
new_count++;
@@ -1767,7 +1769,7 @@
}
/*
- * Retrieve a files ACL
+ * Retrieve a file's ACL
*/
int
zfs_getacl(znode_t *zp, vsecattr_t *vsecp, boolean_t skipaclchk, cred_t *cr)
@@ -1922,7 +1924,7 @@
}
/*
- * Set a files ACL
+ * Set a file's ACL
*/
int
zfs_setacl(znode_t *zp, vsecattr_t *vsecp, boolean_t skipaclchk, cred_t *cr)
@@ -2355,6 +2357,7 @@
/*
* Determine whether Access should be granted/denied.
+ *
* The least priv subsytem is always consulted as a basic privilege
* can define any form of access.
*/
@@ -2560,7 +2563,6 @@
* Determine whether Access should be granted/deny, without
* consulting least priv subsystem.
*
- *
* The following chart is the recommended NFSv4 enforcement for
* ability to delete an object.
*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_byteswap.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_byteswap.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_byteswap.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -633,6 +634,11 @@
.vop_fid = zfsctl_common_fid,
};
+/*
+ * Gets the full dataset name that corresponds to the given snapshot name
+ * Example:
+ * zfsctl_snapshot_zname("snap1") -> "mypool/myfs at snap1"
+ */
static int
zfsctl_snapshot_zname(vnode_t *vp, const char *name, int len, char *zname)
{
@@ -1229,6 +1235,7 @@
/*
* pvp is the '.zfs' directory (zfsctl_node_t).
+ *
* Creates vp, which is '.zfs/snapshot' (zfsctl_snapdir_t).
*
* This function is the callback to create a GFS vnode for '.zfs/snapshot'
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_debug.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_debug.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_debug.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_dir.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_dir.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_dir.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_fm.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_fm.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_fm.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_fuid.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_fuid.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_fuid.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -28,6 +29,7 @@
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
* Copyright (c) 2013 by Delphix. All rights reserved.
* Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
+ * Copyright (c) 2013 Steven Hartland. All rights reserved.
*/
/*
@@ -335,9 +337,7 @@
}
/*
- * zfs_earlier_version
- *
- * Return non-zero if the spa version is less than requested version.
+ * Return non-zero if the spa version is less than requested version.
*/
static int
zfs_earlier_version(const char *name, int version)
@@ -355,8 +355,6 @@
}
/*
- * zpl_earlier_version
- *
* Return TRUE if the ZPL version is less than requested version.
*/
static boolean_t
@@ -3000,10 +2998,10 @@
/*
* inputs:
+ * os parent objset pointer (NULL if root fs)
+ * fuids_ok fuids allowed in this version of the spa?
+ * sa_ok SAs allowed in this version of the spa?
* createprops list of properties requested by creator
- * default_zplver zpl version to use if unspecified in createprops
- * fuids_ok fuids allowed in this version of the spa?
- * os parent objset pointer (NULL if root fs)
*
* outputs:
* zplprops values for the zplprops we attach to the master node object
@@ -3409,28 +3407,31 @@
*
* This function is best-effort. Callers must deal gracefully if it
* remains mounted (or is remounted after this call).
+ *
+ * Returns 0 if the argument is not a snapshot, or it is not currently a
+ * filesystem, or we were able to unmount it. Returns error code otherwise.
*/
-void
+int
zfs_unmount_snap(const char *snapname)
{
vfs_t *vfsp;
zfsvfs_t *zfsvfs;
+ int err;
if (strchr(snapname, '@') == NULL)
- return;
+ return (0);
vfsp = zfs_get_vfs(snapname);
if (vfsp == NULL)
- return;
+ return (0);
zfsvfs = vfsp->vfs_data;
ASSERT(!dsl_pool_config_held(dmu_objset_pool(zfsvfs->z_os)));
- if (vn_vfswlock(vfsp->vfs_vnodecovered) != 0) {
- VFS_RELE(vfsp);
- return;
- }
+ err = vn_vfswlock(vfsp->vfs_vnodecovered);
VFS_RELE(vfsp);
+ if (err != 0)
+ return (SET_ERROR(err));
/*
* Always force the unmount for snapshots.
@@ -3440,9 +3441,10 @@
(void) dounmount(vfsp, MS_FORCE, kcred);
#else
mtx_lock(&Giant); /* dounmount() */
- dounmount(vfsp, MS_FORCE, curthread);
+ (void) dounmount(vfsp, MS_FORCE, curthread);
mtx_unlock(&Giant); /* dounmount() */
#endif
+ return (0);
}
/* ARGSUSED */
@@ -3449,8 +3451,7 @@
static int
zfs_unmount_snap_cb(const char *snapname, void *arg)
{
- zfs_unmount_snap(snapname);
- return (0);
+ return (zfs_unmount_snap(snapname));
}
/*
@@ -3473,7 +3474,7 @@
char originname[MAXNAMELEN];
dsl_dataset_name(ds->ds_prev, originname);
dmu_objset_rele(os, FTAG);
- zfs_unmount_snap(originname);
+ (void) zfs_unmount_snap(originname);
} else {
dmu_objset_rele(os, FTAG);
}
@@ -3491,7 +3492,7 @@
static int
zfs_ioc_destroy_snaps(const char *poolname, nvlist_t *innvl, nvlist_t *outnvl)
{
- int poollen;
+ int error, poollen;
nvlist_t *snaps;
nvpair_t *pair;
boolean_t defer;
@@ -3512,7 +3513,9 @@
(name[poollen] != '/' && name[poollen] != '@'))
return (SET_ERROR(EXDEV));
- zfs_unmount_snap(name);
+ error = zfs_unmount_snap(name);
+ if (error != 0)
+ return (error);
(void) zvol_remove_minor(name);
}
@@ -3531,9 +3534,13 @@
zfs_ioc_destroy(zfs_cmd_t *zc)
{
int err;
- if (strchr(zc->zc_name, '@') && zc->zc_objset_type == DMU_OST_ZFS)
- zfs_unmount_snap(zc->zc_name);
+ if (zc->zc_objset_type == DMU_OST_ZFS) {
+ err = zfs_unmount_snap(zc->zc_name);
+ if (err != 0)
+ return (err);
+ }
+
if (strchr(zc->zc_name, '@'))
err = dsl_destroy_snapshot(zc->zc_name, zc->zc_defer_destroy);
else
@@ -3578,8 +3585,7 @@
char fullname[MAXNAMELEN];
(void) snprintf(fullname, sizeof (fullname), "%s@%s", fsname, snapname);
- zfs_unmount_snap(fullname);
- return (0);
+ return (zfs_unmount_snap(fullname));
}
/*
@@ -5074,16 +5080,6 @@
static int
zfs_ioc_release(const char *pool, nvlist_t *holds, nvlist_t *errlist)
{
- nvpair_t *pair;
-
- /*
- * The release may cause the snapshot to be destroyed; make sure it
- * is not mounted.
- */
- for (pair = nvlist_next_nvpair(holds, NULL); pair != NULL;
- pair = nvlist_next_nvpair(holds, pair))
- zfs_unmount_snap(nvpair_name(pair));
-
return (dsl_dataset_user_release(holds, errlist));
}
@@ -5575,6 +5571,13 @@
zfs_ioctl_register_dataset_nolog(ZFS_IOC_TMP_SNAPSHOT,
zfs_ioc_tmp_snapshot, zfs_secpolicy_tmp_snapshot,
POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY);
+
+#ifdef __FreeBSD__
+ zfs_ioctl_register_dataset_nolog(ZFS_IOC_JAIL, zfs_ioc_jail,
+ zfs_secpolicy_config, POOL_CHECK_NONE);
+ zfs_ioctl_register_dataset_nolog(ZFS_IOC_UNJAIL, zfs_ioc_unjail,
+ zfs_secpolicy_config, POOL_CHECK_NONE);
+#endif
}
int
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_log.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_log.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_log.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -216,9 +217,8 @@
}
/*
- * zfs_log_create() is used to handle TX_CREATE, TX_CREATE_ATTR, TX_MKDIR,
- * TX_MKDIR_ATTR and TX_MKXATTR
- * transactions.
+ * Handles TX_CREATE, TX_CREATE_ATTR, TX_MKDIR, TX_MKDIR_ATTR and
+ * TK_MKXATTR transactions.
*
* TX_CREATE and TX_MKDIR are standard creates, but they may have FUID
* domain information appended prior to the name. In this case the
@@ -345,7 +345,7 @@
}
/*
- * zfs_log_remove() handles both TX_REMOVE and TX_RMDIR transactions.
+ * Handles both TX_REMOVE and TX_RMDIR transactions.
*/
void
zfs_log_remove(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype,
@@ -369,7 +369,7 @@
}
/*
- * zfs_log_link() handles TX_LINK transactions.
+ * Handles TX_LINK transactions.
*/
void
zfs_log_link(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype,
@@ -392,7 +392,7 @@
}
/*
- * zfs_log_symlink() handles TX_SYMLINK transactions.
+ * Handles TX_SYMLINK transactions.
*/
void
zfs_log_symlink(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype,
@@ -424,7 +424,7 @@
}
/*
- * zfs_log_rename() handles TX_RENAME transactions.
+ * Handles TX_RENAME transactions.
*/
void
zfs_log_rename(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype,
@@ -450,7 +450,7 @@
}
/*
- * zfs_log_write() handles TX_WRITE transactions.
+ * Handles TX_WRITE transactions.
*/
ssize_t zfs_immediate_write_sz = 32768;
@@ -529,7 +529,7 @@
}
/*
- * zfs_log_truncate() handles TX_TRUNCATE transactions.
+ * Handles TX_TRUNCATE transactions.
*/
void
zfs_log_truncate(zilog_t *zilog, dmu_tx_t *tx, int txtype,
@@ -552,7 +552,7 @@
}
/*
- * zfs_log_setattr() handles TX_SETATTR transactions.
+ * Handles TX_SETATTR transactions.
*/
void
zfs_log_setattr(zilog_t *zilog, dmu_tx_t *tx, int txtype,
@@ -614,7 +614,7 @@
}
/*
- * zfs_log_acl() handles TX_ACL transactions.
+ * Handles TX_ACL transactions.
*/
void
zfs_log_acl(zilog_t *zilog, dmu_tx_t *tx, znode_t *zp,
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_onexit.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_onexit.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_onexit.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_replay.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_replay.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_replay.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_rlock.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_rlock.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_rlock.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -28,7 +29,7 @@
/*
* This file contains the code to implement file range locking in
- * ZFS, although there isn't much specific to ZFS (all that comes to mind
+ * ZFS, although there isn't much specific to ZFS (all that comes to mind is
* support for growing the blocksize).
*
* Interface
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_sa.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_sa.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_sa.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -187,7 +188,7 @@
/*
* I'm not convinced we should do any of this upgrade.
* since the SA code can read both old/new znode formats
- * with probably little to know performance difference.
+ * with probably little to no performance difference.
*
* All new files will be created with the new format.
*/
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -1341,13 +1342,12 @@
}
/*
- * zfs_check_global_label:
- * Check that the hex label string is appropriate for the dataset
- * being mounted into the global_zone proper.
+ * Check that the hex label string is appropriate for the dataset being
+ * mounted into the global_zone proper.
*
- * Return an error if the hex label string is not default or
- * admin_low/admin_high. For admin_low labels, the corresponding
- * dataset must be readonly.
+ * Return an error if the hex label string is not default or
+ * admin_low/admin_high. For admin_low labels, the corresponding
+ * dataset must be readonly.
*/
int
zfs_check_global_label(const char *dsname, const char *hexsl)
@@ -1369,15 +1369,12 @@
}
/*
- * zfs_mount_label_policy:
- * Determine whether the mount is allowed according to MAC check.
- * by comparing (where appropriate) label of the dataset against
- * the label of the zone being mounted into. If the dataset has
- * no label, create one.
+ * Determine whether the mount is allowed according to MAC check.
+ * by comparing (where appropriate) label of the dataset against
+ * the label of the zone being mounted into. If the dataset has
+ * no label, create one.
*
- * Returns:
- * 0 : access allowed
- * >0 : error code, such as EACCES
+ * Returns 0 if access allowed, error otherwise (e.g. EACCES)
*/
static int
zfs_mount_label_policy(vfs_t *vfsp, char *osname)
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -85,11 +86,11 @@
* The ordering of events is important to avoid deadlocks and references
* to freed memory. The example below illustrates the following Big Rules:
*
- * (1) A check must be made in each zfs thread for a mounted file system.
+ * (1) A check must be made in each zfs thread for a mounted file system.
* This is done avoiding races using ZFS_ENTER(zfsvfs).
- * A ZFS_EXIT(zfsvfs) is needed before all returns. Any znodes
- * must be checked with ZFS_VERIFY_ZP(zp). Both of these macros
- * can return EIO from the calling function.
+ * A ZFS_EXIT(zfsvfs) is needed before all returns. Any znodes
+ * must be checked with ZFS_VERIFY_ZP(zp). Both of these macros
+ * can return EIO from the calling function.
*
* (2) VN_RELE() should always be the last thing except for zil_commit()
* (if necessary) and ZFS_EXIT(). This is for 3 reasons:
@@ -121,7 +122,7 @@
* (5) If the operation succeeded, generate the intent log entry for it
* before dropping locks. This ensures that the ordering of events
* in the intent log matches the order in which they actually occurred.
- * During ZIL replay the zfs_log_* functions will update the sequence
+ * During ZIL replay the zfs_log_* functions will update the sequence
* number to indicate the zil transaction has replayed.
*
* (6) At the end of each vnode op, the DMU tx must always commit,
@@ -343,10 +344,13 @@
vm_page_sleep(pp, "zfsmwb");
continue;
}
- } else {
+ } else if (pp == NULL) {
pp = vm_page_alloc(obj, OFF_TO_IDX(start),
VM_ALLOC_SYSTEM | VM_ALLOC_IFCACHED |
VM_ALLOC_NOBUSY);
+ } else {
+ ASSERT(pp != NULL && !pp->valid);
+ pp = NULL;
}
if (pp != NULL) {
@@ -566,7 +570,7 @@
* else we default from the dmu buffer.
*
* NOTE: We will always "break up" the IO into PAGESIZE uiomoves when
- * the file is memory mapped.
+ * the file is memory mapped.
*/
static int
mappedread(vnode_t *vp, int nbytes, uio_t *uio)
@@ -629,8 +633,7 @@
*
* OUT: uio - updated offset and range, buffer filled.
*
- * RETURN: 0 if success
- * error code if failure
+ * RETURN: 0 on success, error code on failure.
*
* Side Effects:
* vp - atime updated if byte count > 0
@@ -774,14 +777,14 @@
* IN: vp - vnode of file to be written to.
* uio - structure supplying write location, range info,
* and data buffer.
- * ioflag - FAPPEND flag set if in append mode.
+ * ioflag - FAPPEND, FSYNC, and/or FDSYNC. FAPPEND is
+ * set if in append mode.
* cr - credentials of caller.
* ct - caller context (NFS/CIFS fem monitor only)
*
* OUT: uio - updated offset and range.
*
- * RETURN: 0 if success
- * error code if failure
+ * RETURN: 0 on success, error code on failure.
*
* Timestamps:
* vp - ctime|mtime updated if byte count > 0
@@ -1368,8 +1371,7 @@
*
* OUT: vpp - vnode of located entry, NULL if not found.
*
- * RETURN: 0 if success
- * error code if failure
+ * RETURN: 0 on success, error code on failure.
*
* Timestamps:
* NA
@@ -1566,8 +1568,7 @@
*
* OUT: vpp - vnode of created or trunc'd entry.
*
- * RETURN: 0 if success
- * error code if failure
+ * RETURN: 0 on success, error code on failure.
*
* Timestamps:
* dvp - ctime|mtime updated if new entry created
@@ -1817,8 +1818,7 @@
* ct - caller context
* flags - case flags
*
- * RETURN: 0 if success
- * error code if failure
+ * RETURN: 0 on success, error code on failure.
*
* Timestamps:
* dvp - ctime|mtime
@@ -2054,12 +2054,12 @@
* vap - attributes of new directory.
* cr - credentials of caller.
* ct - caller context
+ * flags - case flags
* vsecp - ACL to be set
*
* OUT: vpp - vnode of created directory.
*
- * RETURN: 0 if success
- * error code if failure
+ * RETURN: 0 on success, error code on failure.
*
* Timestamps:
* dvp - ctime|mtime updated
@@ -2239,8 +2239,7 @@
* ct - caller context
* flags - case flags
*
- * RETURN: 0 if success
- * error code if failure
+ * RETURN: 0 on success, error code on failure.
*
* Timestamps:
* dvp - ctime|mtime updated
@@ -2365,7 +2364,7 @@
/*
* Read as many directory entries as will fit into the provided
* buffer from the given directory cursor position (specified in
- * the uio structure.
+ * the uio structure).
*
* IN: vp - vnode of directory to read.
* uio - structure supplying read location, range info,
@@ -2377,8 +2376,7 @@
* OUT: uio - updated offset and range, buffer filled.
* eofp - set to true if end-of-file detected.
*
- * RETURN: 0 if success
- * error code if failure
+ * RETURN: 0 on success, error code on failure.
*
* Timestamps:
* vp - atime updated
@@ -2723,7 +2721,7 @@
*
* OUT: vap - attribute values.
*
- * RETURN: 0 (always succeeds)
+ * RETURN: 0 (always succeeds).
*/
/* ARGSUSED */
static int
@@ -2944,8 +2942,7 @@
* cr - credentials of caller.
* ct - caller context
*
- * RETURN: 0 if success
- * error code if failure
+ * RETURN: 0 on success, error code on failure.
*
* Timestamps:
* vp - ctime updated, mtime updated if size changed.
@@ -2953,7 +2950,7 @@
/* ARGSUSED */
static int
zfs_setattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
- caller_context_t *ct)
+ caller_context_t *ct)
{
znode_t *zp = VTOZ(vp);
zfsvfs_t *zfsvfs = zp->z_zfsvfs;
@@ -3557,6 +3554,7 @@
if (attrzp)
VN_RELE(ZTOV(attrzp));
+
if (aclp)
zfs_acl_free(aclp);
@@ -3691,8 +3689,7 @@
* ct - caller context
* flags - case flags
*
- * RETURN: 0 if success
- * error code if failure
+ * RETURN: 0 on success, error code on failure.
*
* Timestamps:
* sdvp,tdvp - ctime|mtime updated
@@ -4051,13 +4048,11 @@
* IN: dvp - Directory to contain new symbolic link.
* link - Name for new symlink entry.
* vap - Attributes of new entry.
- * target - Target path of new symlink.
* cr - credentials of caller.
* ct - caller context
* flags - case flags
*
- * RETURN: 0 if success
- * error code if failure
+ * RETURN: 0 on success, error code on failure.
*
* Timestamps:
* dvp - ctime|mtime updated
@@ -4203,14 +4198,13 @@
* the symbolic path referred to by vp.
*
* IN: vp - vnode of symbolic link.
- * uoip - structure to contain the link path.
+ * uio - structure to contain the link path.
* cr - credentials of caller.
* ct - caller context
*
- * OUT: uio - structure to contain the link path.
+ * OUT: uio - structure containing the link path.
*
- * RETURN: 0 if success
- * error code if failure
+ * RETURN: 0 on success, error code on failure.
*
* Timestamps:
* vp - atime updated
@@ -4249,8 +4243,7 @@
* cr - credentials of caller.
* ct - caller context
*
- * RETURN: 0 if success
- * error code if failure
+ * RETURN: 0 on success, error code on failure.
*
* Timestamps:
* tdvp - ctime|mtime updated
@@ -4419,8 +4412,7 @@
* OUT: offp - start of range pushed.
* lenp - len of range pushed.
*
- * RETURN: 0 if success
- * error code if failure
+ * RETURN: 0 on success, error code on failure.
*
* NOTE: callers must have locked the page to be pushed. On
* exit, the page (and all other pages in the kluster) must be
@@ -4542,8 +4534,7 @@
* cr - credentials of caller.
* ct - caller context.
*
- * RETURN: 0 if success
- * error code if failure
+ * RETURN: 0 on success, error code on failure.
*
* Timestamps:
* vp - ctime|mtime updated
@@ -4692,8 +4683,7 @@
* noffp - pointer to new file offset
* ct - caller context
*
- * RETURN: 0 if success
- * EINVAL if new offset invalid
+ * RETURN: 0 on success, EINVAL if new offset invalid.
*/
/* ARGSUSED */
static int
@@ -4829,8 +4819,7 @@
* OUT: protp - protection mode of created pages.
* pl - list of pages created.
*
- * RETURN: 0 if success
- * error code if failure
+ * RETURN: 0 on success, error code on failure.
*
* Timestamps:
* vp - atime updated
@@ -4838,8 +4827,8 @@
/* ARGSUSED */
static int
zfs_getpage(vnode_t *vp, offset_t off, size_t len, uint_t *protp,
- page_t *pl[], size_t plsz, struct seg *seg, caddr_t addr,
- enum seg_rw rw, cred_t *cr, caller_context_t *ct)
+ page_t *pl[], size_t plsz, struct seg *seg, caddr_t addr,
+ enum seg_rw rw, cred_t *cr, caller_context_t *ct)
{
znode_t *zp = VTOZ(vp);
zfsvfs_t *zfsvfs = zp->z_zfsvfs;
@@ -4914,15 +4903,11 @@
* Request a memory map for a section of a file. This code interacts
* with common code and the VM system as follows:
*
- * common code calls mmap(), which ends up in smmap_common()
- *
- * this calls VOP_MAP(), which takes you into (say) zfs
- *
- * zfs_map() calls as_map(), passing segvn_create() as the callback
- *
- * segvn_create() creates the new segment and calls VOP_ADDMAP()
- *
- * zfs_addmap() updates z_mapcnt
+ * - common code calls mmap(), which ends up in smmap_common()
+ * - this calls VOP_MAP(), which takes you into (say) zfs
+ * - zfs_map() calls as_map(), passing segvn_create() as the callback
+ * - segvn_create() creates the new segment and calls VOP_ADDMAP()
+ * - zfs_addmap() updates z_mapcnt
*/
/*ARGSUSED*/
static int
@@ -5064,8 +5049,7 @@
* cr - credentials of caller [UNUSED].
* ct - caller context.
*
- * RETURN: 0 if success
- * error code if failure
+ * RETURN: 0 on success, error code on failure.
*
* Timestamps:
* vp - ctime|mtime updated
@@ -5302,13 +5286,14 @@
#ifdef sun
/*
- * Tunable, both must be a power of 2.
- *
- * zcr_blksz_min: the smallest read we may consider to loan out an arcbuf
- * zcr_blksz_max: if set to less than the file block size, allow loaning out of
- * an arcbuf for a partial block read
+ * The smallest read we may consider to loan out an arcbuf.
+ * This must be a power of 2.
*/
int zcr_blksz_min = (1 << 10); /* 1K */
+/*
+ * If set to less than the file block size, allow loaning out of an
+ * arcbuf for a partial block read. This must be a power of 2.
+ */
int zcr_blksz_max = (1 << 17); /* 128K */
/*ARGSUSED*/
@@ -5582,10 +5567,12 @@
/*
* Extended attribute directory vnode operations template
- * This template is identical to the directory vnodes
- * operation template except for restricted operations:
- * VOP_MKDIR()
- * VOP_SYMLINK()
+ *
+ * This template is identical to the directory vnodes
+ * operation template except for restricted operations:
+ * VOP_MKDIR()
+ * VOP_SYMLINK()
+ *
* Note that there are other restrictions embedded in:
* zfs_create() - restrict type to VREG
* zfs_link() - no links into/out of attribute space
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -1046,9 +1047,8 @@
}
/*
- * zfs_xvattr_set only updates the in-core attributes
- * it is assumed the caller will be doing an sa_bulk_update
- * to push the changes out
+ * Update in-core attributes. It is assumed the caller will be doing an
+ * sa_bulk_update to push the changes out.
*/
void
zfs_xvattr_set(znode_t *zp, xvattr_t *xvap, dmu_tx_t *tx)
@@ -1537,8 +1537,7 @@
* IN: zp - znode of file to free data in.
* end - new end-of-file
*
- * RETURN: 0 if success
- * error code if failure
+ * RETURN: 0 on success, error code on failure
*/
static int
zfs_extend(znode_t *zp, uint64_t end)
@@ -1617,8 +1616,7 @@
* off - start of section to free.
* len - length of section to free.
*
- * RETURN: 0 if success
- * error code if failure
+ * RETURN: 0 on success, error code on failure
*/
static int
zfs_free_range(znode_t *zp, uint64_t off, uint64_t len)
@@ -1665,8 +1663,7 @@
* IN: zp - znode of file to free data in.
* end - new end-of-file.
*
- * RETURN: 0 if success
- * error code if failure
+ * RETURN: 0 on success, error code on failure
*/
static int
zfs_trunc(znode_t *zp, uint64_t end)
@@ -1748,8 +1745,7 @@
* flag - current file open mode flags.
* log - TRUE if this action should be logged
*
- * RETURN: 0 if success
- * error code if failure
+ * RETURN: 0 on success, error code on failure
*/
int
zfs_freesp(znode_t *zp, uint64_t off, uint64_t len, int flag, boolean_t log)
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -66,9 +67,9 @@
*/
/*
- * This global ZIL switch affects all pools
+ * Disable intent logging replay. This global ZIL switch affects all pools.
*/
-int zil_replay_disable = 0; /* disable intent logging replay */
+int zil_replay_disable = 0;
SYSCTL_DECL(_vfs_zfs);
TUNABLE_INT("vfs.zfs.zil_replay_disable", &zil_replay_disable);
SYSCTL_INT(_vfs_zfs, OID_AUTO, zil_replay_disable, CTLFLAG_RW,
@@ -891,6 +892,7 @@
/*
* Define a limited set of intent log block sizes.
+ *
* These must be a multiple of 4KB. Note only the amount used (again
* aligned to 4KB) actually gets written. However, we can't always just
* allocate SPA_MAXBLOCKSIZE as the slog space could be exhausted.
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
@@ -771,6 +772,9 @@
ASSERT(spa_syncing_txg(spa) == txg);
ASSERT(spa_sync_pass(spa) < zfs_sync_pass_deferred_free);
+ metaslab_check_free(spa, bp);
+ arc_freed(spa, bp);
+
zio = zio_create(pio, spa, txg, bp, NULL, size,
NULL, NULL, ZIO_TYPE_FREE, ZIO_PRIORITY_FREE, flags,
NULL, 0, NULL, ZIO_STAGE_OPEN, ZIO_FREE_PIPELINE);
@@ -800,8 +804,6 @@
ASSERT(txg == spa_first_txg(spa) || txg == 0);
ASSERT(!BP_GET_DEDUP(bp) || !spa_writeable(spa)); /* zdb(1M) */
- metaslab_check_free(spa, bp);
-
zio = zio_create(pio, spa, txg, bp, NULL, BP_GET_PSIZE(bp),
done, private, ZIO_TYPE_CLAIM, ZIO_PRIORITY_NOW, flags,
NULL, 0, NULL, ZIO_STAGE_OPEN, ZIO_CLAIM_PIPELINE);
@@ -1247,14 +1249,17 @@
/*
* Execute the I/O pipeline until one of the following occurs:
- * (1) the I/O completes; (2) the pipeline stalls waiting for
- * dependent child I/Os; (3) the I/O issues, so we're waiting
- * for an I/O completion interrupt; (4) the I/O is delegated by
- * vdev-level caching or aggregation; (5) the I/O is deferred
- * due to vdev-level queueing; (6) the I/O is handed off to
- * another thread. In all cases, the pipeline stops whenever
- * there's no CPU work; it never burns a thread in cv_wait().
*
+ * (1) the I/O completes
+ * (2) the pipeline stalls waiting for dependent child I/Os
+ * (3) the I/O issues, so we're waiting for an I/O completion interrupt
+ * (4) the I/O is delegated by vdev-level caching or aggregation
+ * (5) the I/O is deferred due to vdev-level queueing
+ * (6) the I/O is handed off to another thread.
+ *
+ * In all cases, the pipeline stops whenever there's no CPU work; it never
+ * burns a thread in cv_wait().
+ *
* There's no locking on io_stage because there's no legitimate way
* for multiple threads to be attempting to process the same I/O.
*/
@@ -2553,7 +2558,13 @@
}
}
- if (vd->vdev_ops->vdev_op_leaf && zio->io_type == ZIO_TYPE_WRITE) {
+ /*
+ * Note that we ignore repair writes for TRIM because they can conflict
+ * with normal writes. This isn't an issue because, by definition, we
+ * only repair blocks that aren't freed.
+ */
+ if (vd->vdev_ops->vdev_op_leaf && zio->io_type == ZIO_TYPE_WRITE &&
+ !(zio->io_flags & ZIO_FLAG_IO_REPAIR)) {
if (!trim_map_write_start(zio))
return (ZIO_PIPELINE_STOP);
}
@@ -2575,13 +2586,12 @@
zio->io_type == ZIO_TYPE_WRITE || zio->io_type == ZIO_TYPE_FREE);
if (vd != NULL && vd->vdev_ops->vdev_op_leaf &&
- zio->io_type == ZIO_TYPE_WRITE) {
- trim_map_write_done(zio);
- }
-
- if (vd != NULL && vd->vdev_ops->vdev_op_leaf &&
(zio->io_type == ZIO_TYPE_READ || zio->io_type == ZIO_TYPE_WRITE)) {
+ if (zio->io_type == ZIO_TYPE_WRITE &&
+ !(zio->io_flags & ZIO_FLAG_IO_REPAIR))
+ trim_map_write_done(zio);
+
vdev_queue_io_done(zio);
if (zio->io_type == ZIO_TYPE_WRITE)
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio_checksum.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio_checksum.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio_checksum.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio_compress.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio_compress.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio_compress.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio_inject.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio_inject.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio_inject.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zle.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zle.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zle.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zrlock.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zrlock.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zrlock.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
Modified: trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c
===================================================================
--- trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c 2016-10-14 02:04:19 UTC (rev 9154)
+++ trunk/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c 2016-10-14 02:04:39 UTC (rev 9155)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
/*
* CDDL HEADER START
*
More information about the Midnightbsd-cvs
mailing list