mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-22 10:37:35 +03:00
Illumos 4370, 4371
4370 avoid transmitting holes during zfs send 4371 DMU code clean up Reviewed by: Matthew Ahrens <mahrens@delphix.com> Reviewed by: George Wilson <george.wilson@delphix.com> Reviewed by: Christopher Siden <christopher.siden@delphix.com> Reviewed by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net> Approved by: Garrett D'Amore <garrett@damore.org>a References: https://www.illumos.org/issues/4370 https://www.illumos.org/issues/4371 https://github.com/illumos/illumos-gate/commit/43466aa Ported by: Tim Chase <tim@chase2k.com> Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov> Closes #2529
This commit is contained in:
committed by
Brian Behlendorf
parent
fa86b5dbb6
commit
b0bc7a84d9
+1
-17
@@ -266,8 +266,6 @@ void dbuf_rele_and_unlock(dmu_buf_impl_t *db, void *tag);
|
||||
dmu_buf_impl_t *dbuf_find(struct dnode *dn, uint8_t level, uint64_t blkid);
|
||||
|
||||
int dbuf_read(dmu_buf_impl_t *db, zio_t *zio, uint32_t flags);
|
||||
void dbuf_will_dirty(dmu_buf_impl_t *db, dmu_tx_t *tx);
|
||||
void dbuf_fill_done(dmu_buf_impl_t *db, dmu_tx_t *tx);
|
||||
void dmu_buf_will_not_fill(dmu_buf_t *db, dmu_tx_t *tx);
|
||||
void dmu_buf_will_fill(dmu_buf_t *db, dmu_tx_t *tx);
|
||||
void dmu_buf_fill_done(dmu_buf_t *db, dmu_tx_t *tx);
|
||||
@@ -295,20 +293,6 @@ void dbuf_stats_destroy(void);
|
||||
#define DB_DNODE_ENTER(_db) (zrl_add(&DB_DNODE_LOCK(_db)))
|
||||
#define DB_DNODE_EXIT(_db) (zrl_remove(&DB_DNODE_LOCK(_db)))
|
||||
#define DB_DNODE_HELD(_db) (!zrl_is_zero(&DB_DNODE_LOCK(_db)))
|
||||
#define DB_GET_SPA(_spa_p, _db) { \
|
||||
dnode_t *__dn; \
|
||||
DB_DNODE_ENTER(_db); \
|
||||
__dn = DB_DNODE(_db); \
|
||||
*(_spa_p) = __dn->dn_objset->os_spa; \
|
||||
DB_DNODE_EXIT(_db); \
|
||||
}
|
||||
#define DB_GET_OBJSET(_os_p, _db) { \
|
||||
dnode_t *__dn; \
|
||||
DB_DNODE_ENTER(_db); \
|
||||
__dn = DB_DNODE(_db); \
|
||||
*(_os_p) = __dn->dn_objset; \
|
||||
DB_DNODE_EXIT(_db); \
|
||||
}
|
||||
|
||||
void dbuf_init(void);
|
||||
void dbuf_fini(void);
|
||||
@@ -358,7 +342,7 @@ _NOTE(CONSTCOND) } while (0)
|
||||
#define dprintf_dbuf_bp(db, bp, fmt, ...) do { \
|
||||
if (zfs_flags & ZFS_DEBUG_DPRINTF) { \
|
||||
char *__blkbuf = kmem_alloc(BP_SPRINTF_LEN, KM_PUSHPAGE); \
|
||||
sprintf_blkptr(__blkbuf, bp); \
|
||||
snprintf_blkptr(__blkbuf, BP_SPRINTF_LEN, bp); \
|
||||
dprintf_dbuf(db, fmt " %s\n", __VA_ARGS__, __blkbuf); \
|
||||
kmem_free(__blkbuf, BP_SPRINTF_LEN); \
|
||||
} \
|
||||
|
||||
@@ -290,6 +290,7 @@ typedef void dmu_buf_evict_func_t(struct dmu_buf *db, void *user_ptr);
|
||||
#define DMU_POOL_FEATURES_FOR_WRITE "features_for_write"
|
||||
#define DMU_POOL_FEATURES_FOR_READ "features_for_read"
|
||||
#define DMU_POOL_FEATURE_DESCRIPTIONS "feature_descriptions"
|
||||
#define DMU_POOL_FEATURE_ENABLED_TXG "feature_enabled_txg"
|
||||
#define DMU_POOL_ROOT_DATASET "root_dataset"
|
||||
#define DMU_POOL_SYNC_BPOBJ "sync_bplist"
|
||||
#define DMU_POOL_ERRLOG_SCRUB "errlog_scrub"
|
||||
|
||||
+55
-29
@@ -20,7 +20,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 Delphix. All rights reserved.
|
||||
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
@@ -67,20 +67,33 @@ struct dsl_dataset;
|
||||
#define BF32_GET(x, low, len) BF32_DECODE(x, low, len)
|
||||
#define BF64_GET(x, low, len) BF64_DECODE(x, low, len)
|
||||
|
||||
#define BF32_SET(x, low, len, val) \
|
||||
((x) ^= BF32_ENCODE((x >> low) ^ (val), low, len))
|
||||
#define BF64_SET(x, low, len, val) \
|
||||
((x) ^= BF64_ENCODE((x >> low) ^ (val), low, len))
|
||||
#define BF32_SET(x, low, len, val) do { \
|
||||
ASSERT3U(val, <, 1U << (len)); \
|
||||
ASSERT3U(low + len, <=, 32); \
|
||||
(x) ^= BF32_ENCODE((x >> low) ^ (val), low, len); \
|
||||
_NOTE(CONSTCOND) } while (0)
|
||||
|
||||
#define BF64_SET(x, low, len, val) do { \
|
||||
ASSERT3U(val, <, 1ULL << (len)); \
|
||||
ASSERT3U(low + len, <=, 64); \
|
||||
((x) ^= BF64_ENCODE((x >> low) ^ (val), low, len)); \
|
||||
_NOTE(CONSTCOND) } while (0)
|
||||
|
||||
#define BF32_GET_SB(x, low, len, shift, bias) \
|
||||
((BF32_GET(x, low, len) + (bias)) << (shift))
|
||||
#define BF64_GET_SB(x, low, len, shift, bias) \
|
||||
((BF64_GET(x, low, len) + (bias)) << (shift))
|
||||
|
||||
#define BF32_SET_SB(x, low, len, shift, bias, val) \
|
||||
BF32_SET(x, low, len, ((val) >> (shift)) - (bias))
|
||||
#define BF64_SET_SB(x, low, len, shift, bias, val) \
|
||||
BF64_SET(x, low, len, ((val) >> (shift)) - (bias))
|
||||
#define BF32_SET_SB(x, low, len, shift, bias, val) do { \
|
||||
ASSERT(IS_P2ALIGNED(val, 1U << shift)); \
|
||||
ASSERT3S((val) >> (shift), >=, bias); \
|
||||
BF32_SET(x, low, len, ((val) >> (shift)) - (bias)); \
|
||||
_NOTE(CONSTCOND) } while (0)
|
||||
#define BF64_SET_SB(x, low, len, shift, bias, val) do { \
|
||||
ASSERT(IS_P2ALIGNED(val, 1ULL << shift)); \
|
||||
ASSERT3S((val) >> (shift), >=, bias); \
|
||||
BF64_SET(x, low, len, ((val) >> (shift)) - (bias)); \
|
||||
_NOTE(CONSTCOND) } while (0)
|
||||
|
||||
/*
|
||||
* We currently support nine block sizes, from 512 bytes to 128K.
|
||||
@@ -188,6 +201,15 @@ typedef struct zio_cksum {
|
||||
#define SPA_BLKPTRSHIFT 7 /* blkptr_t is 128 bytes */
|
||||
#define SPA_DVAS_PER_BP 3 /* Number of DVAs in a bp */
|
||||
|
||||
/*
|
||||
* A block is a hole when it has either 1) never been written to, or
|
||||
* 2) is zero-filled. In both cases, ZFS can return all zeroes for all reads
|
||||
* without physically allocating disk space. Holes are represented in the
|
||||
* blkptr_t structure by zeroed blk_dva. Correct checking for holes is
|
||||
* done through the BP_IS_HOLE macro. For holes, the logical size, level,
|
||||
* DMU object type, and birth times are all also stored for holes that
|
||||
* were written to at some point (i.e. were punched after having been filled).
|
||||
*/
|
||||
typedef struct blkptr {
|
||||
dva_t blk_dva[SPA_DVAS_PER_BP]; /* Data Virtual Addresses */
|
||||
uint64_t blk_prop; /* size, compression, type, etc */
|
||||
@@ -202,9 +224,10 @@ typedef struct blkptr {
|
||||
* Macros to get and set fields in a bp or DVA.
|
||||
*/
|
||||
#define DVA_GET_ASIZE(dva) \
|
||||
BF64_GET_SB((dva)->dva_word[0], 0, 24, SPA_MINBLOCKSHIFT, 0)
|
||||
BF64_GET_SB((dva)->dva_word[0], 0, SPA_ASIZEBITS, SPA_MINBLOCKSHIFT, 0)
|
||||
#define DVA_SET_ASIZE(dva, x) \
|
||||
BF64_SET_SB((dva)->dva_word[0], 0, 24, SPA_MINBLOCKSHIFT, 0, x)
|
||||
BF64_SET_SB((dva)->dva_word[0], 0, SPA_ASIZEBITS, \
|
||||
SPA_MINBLOCKSHIFT, 0, x)
|
||||
|
||||
#define DVA_GET_GRID(dva) BF64_GET((dva)->dva_word[0], 24, 8)
|
||||
#define DVA_SET_GRID(dva, x) BF64_SET((dva)->dva_word[0], 24, 8, x)
|
||||
@@ -221,14 +244,14 @@ typedef struct blkptr {
|
||||
#define DVA_SET_GANG(dva, x) BF64_SET((dva)->dva_word[1], 63, 1, x)
|
||||
|
||||
#define BP_GET_LSIZE(bp) \
|
||||
BF64_GET_SB((bp)->blk_prop, 0, 16, SPA_MINBLOCKSHIFT, 1)
|
||||
BF64_GET_SB((bp)->blk_prop, 0, SPA_LSIZEBITS, SPA_MINBLOCKSHIFT, 1)
|
||||
#define BP_SET_LSIZE(bp, x) \
|
||||
BF64_SET_SB((bp)->blk_prop, 0, 16, SPA_MINBLOCKSHIFT, 1, x)
|
||||
BF64_SET_SB((bp)->blk_prop, 0, SPA_LSIZEBITS, SPA_MINBLOCKSHIFT, 1, x)
|
||||
|
||||
#define BP_GET_PSIZE(bp) \
|
||||
BF64_GET_SB((bp)->blk_prop, 16, 16, SPA_MINBLOCKSHIFT, 1)
|
||||
BF64_GET_SB((bp)->blk_prop, 16, SPA_PSIZEBITS, SPA_MINBLOCKSHIFT, 1)
|
||||
#define BP_SET_PSIZE(bp, x) \
|
||||
BF64_SET_SB((bp)->blk_prop, 16, 16, SPA_MINBLOCKSHIFT, 1, x)
|
||||
BF64_SET_SB((bp)->blk_prop, 16, SPA_PSIZEBITS, SPA_MINBLOCKSHIFT, 1, x)
|
||||
|
||||
#define BP_GET_COMPRESS(bp) BF64_GET((bp)->blk_prop, 32, 8)
|
||||
#define BP_SET_COMPRESS(bp, x) BF64_SET((bp)->blk_prop, 32, 8, x)
|
||||
@@ -248,7 +271,7 @@ typedef struct blkptr {
|
||||
#define BP_GET_DEDUP(bp) BF64_GET((bp)->blk_prop, 62, 1)
|
||||
#define BP_SET_DEDUP(bp, x) BF64_SET((bp)->blk_prop, 62, 1, x)
|
||||
|
||||
#define BP_GET_BYTEORDER(bp) (0 - BF64_GET((bp)->blk_prop, 63, 1))
|
||||
#define BP_GET_BYTEORDER(bp) BF64_GET((bp)->blk_prop, 63, 1)
|
||||
#define BP_SET_BYTEORDER(bp, x) BF64_SET((bp)->blk_prop, 63, 1, x)
|
||||
|
||||
#define BP_PHYSICAL_BIRTH(bp) \
|
||||
@@ -306,7 +329,9 @@ typedef struct blkptr {
|
||||
|
||||
#define BP_IDENTITY(bp) (&(bp)->blk_dva[0])
|
||||
#define BP_IS_GANG(bp) DVA_GET_GANG(BP_IDENTITY(bp))
|
||||
#define BP_IS_HOLE(bp) ((bp)->blk_birth == 0)
|
||||
#define DVA_IS_EMPTY(dva) ((dva)->dva_word[0] == 0ULL && \
|
||||
(dva)->dva_word[1] == 0ULL)
|
||||
#define BP_IS_HOLE(bp) DVA_IS_EMPTY(BP_IDENTITY(bp))
|
||||
|
||||
/* BP_IS_RAIDZ(bp) assumes no block compression */
|
||||
#define BP_IS_RAIDZ(bp) (DVA_GET_ASIZE(&(bp)->blk_dva[0]) > \
|
||||
@@ -329,14 +354,10 @@ typedef struct blkptr {
|
||||
ZIO_SET_CHECKSUM(&(bp)->blk_cksum, 0, 0, 0, 0); \
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: the byteorder is either 0 or -1, both of which are palindromes.
|
||||
* This simplifies the endianness handling a bit.
|
||||
*/
|
||||
#ifdef _BIG_ENDIAN
|
||||
#define ZFS_HOST_BYTEORDER (0ULL)
|
||||
#else
|
||||
#define ZFS_HOST_BYTEORDER (-1ULL)
|
||||
#define ZFS_HOST_BYTEORDER (1ULL)
|
||||
#endif
|
||||
|
||||
#define BP_SHOULD_BYTESWAP(bp) (BP_GET_BYTEORDER(bp) != ZFS_HOST_BYTEORDER)
|
||||
@@ -348,19 +369,23 @@ typedef struct blkptr {
|
||||
* 'func' is either snprintf() or mdb_snprintf().
|
||||
* 'ws' (whitespace) can be ' ' for single-line format, '\n' for multi-line.
|
||||
*/
|
||||
#define SPRINTF_BLKPTR(func, ws, buf, bp, type, checksum, compress) \
|
||||
#define SNPRINTF_BLKPTR(func, ws, buf, size, bp, type, checksum, compress) \
|
||||
{ \
|
||||
static const char *copyname[] = \
|
||||
{ "zero", "single", "double", "triple" }; \
|
||||
int size = BP_SPRINTF_LEN; \
|
||||
int len = 0; \
|
||||
int copies = 0; \
|
||||
int d; \
|
||||
\
|
||||
if (bp == NULL) { \
|
||||
len = func(buf + len, size - len, "<NULL>"); \
|
||||
len += func(buf + len, size - len, "<NULL>"); \
|
||||
} else if (BP_IS_HOLE(bp)) { \
|
||||
len = func(buf + len, size - len, "<hole>"); \
|
||||
len += func(buf + len, size - len, "<hole>"); \
|
||||
if (bp->blk_birth > 0) { \
|
||||
len += func(buf + len, size - len, \
|
||||
" birth=%lluL", \
|
||||
(u_longlong_t)bp->blk_birth); \
|
||||
} \
|
||||
} else { \
|
||||
for (d = 0; d < BP_GET_NDVAS(bp); d++) { \
|
||||
const dva_t *dva = &bp->blk_dva[d]; \
|
||||
@@ -642,7 +667,8 @@ extern objset_t *spa_meta_objset(spa_t *spa);
|
||||
extern uint64_t spa_deadman_synctime(spa_t *spa);
|
||||
|
||||
/* Miscellaneous support routines */
|
||||
extern void spa_activate_mos_feature(spa_t *spa, const char *feature);
|
||||
extern void spa_activate_mos_feature(spa_t *spa, const char *feature,
|
||||
dmu_tx_t *tx);
|
||||
extern void spa_deactivate_mos_feature(spa_t *spa, const char *feature);
|
||||
extern int spa_rename(const char *oldname, const char *newname);
|
||||
extern spa_t *spa_by_guid(uint64_t pool_guid, uint64_t device_guid);
|
||||
@@ -651,7 +677,7 @@ extern char *spa_strdup(const char *);
|
||||
extern void spa_strfree(char *);
|
||||
extern uint64_t spa_get_random(uint64_t range);
|
||||
extern uint64_t spa_generate_guid(spa_t *spa);
|
||||
extern void sprintf_blkptr(char *buf, const blkptr_t *bp);
|
||||
extern void snprintf_blkptr(char *buf, size_t buflen, const blkptr_t *bp);
|
||||
extern void spa_freeze(spa_t *spa);
|
||||
extern int spa_change_guid(spa_t *spa);
|
||||
extern void spa_upgrade(spa_t *spa, uint64_t version);
|
||||
@@ -721,7 +747,7 @@ extern void spa_event_notify(spa_t *spa, vdev_t *vdev, const char *name);
|
||||
#define dprintf_bp(bp, fmt, ...) do { \
|
||||
if (zfs_flags & ZFS_DEBUG_DPRINTF) { \
|
||||
char *__blkbuf = kmem_alloc(BP_SPRINTF_LEN, KM_PUSHPAGE); \
|
||||
sprintf_blkptr(__blkbuf, (bp)); \
|
||||
snprintf_blkptr(__blkbuf, BP_SPRINTF_LEN, (bp)); \
|
||||
dprintf(fmt " %s\n", __VA_ARGS__, __blkbuf); \
|
||||
kmem_free(__blkbuf, BP_SPRINTF_LEN); \
|
||||
} \
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include <sys/refcount.h>
|
||||
#include <sys/bplist.h>
|
||||
#include <sys/bpobj.h>
|
||||
#include <zfeature_common.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -232,6 +233,9 @@ struct spa {
|
||||
uint64_t spa_feat_for_write_obj; /* required to write to pool */
|
||||
uint64_t spa_feat_for_read_obj; /* required to read from pool */
|
||||
uint64_t spa_feat_desc_obj; /* Feature descriptions */
|
||||
uint64_t spa_feat_enabled_txg_obj; /* Feature enabled txg */
|
||||
/* cache feature refcounts */
|
||||
uint64_t spa_feat_refcount_cache[SPA_FEATURES];
|
||||
taskqid_t spa_deadman_tqid; /* Task id */
|
||||
uint64_t spa_deadman_calls; /* number of deadman calls */
|
||||
hrtime_t spa_sync_starttime; /* starting time of spa_sync */
|
||||
|
||||
+2
-2
@@ -21,7 +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 Delphix. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _SYS_VDEV_H
|
||||
@@ -109,7 +109,7 @@ extern boolean_t vdev_accessible(vdev_t *vd, zio_t *zio);
|
||||
|
||||
extern void vdev_cache_init(vdev_t *vd);
|
||||
extern void vdev_cache_fini(vdev_t *vd);
|
||||
extern int vdev_cache_read(zio_t *zio);
|
||||
extern boolean_t vdev_cache_read(zio_t *zio);
|
||||
extern void vdev_cache_write(zio_t *zio);
|
||||
extern void vdev_cache_purge(vdev_t *vd);
|
||||
|
||||
|
||||
@@ -34,6 +34,10 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define VALID_FEATURE_FID(fid) ((fid) >= 0 && (fid) < SPA_FEATURES)
|
||||
#define VALID_FEATURE_OR_NONE(fid) ((fid) == SPA_FEATURE_NONE || \
|
||||
VALID_FEATURE_FID(fid))
|
||||
|
||||
struct spa;
|
||||
struct dmu_tx;
|
||||
struct objset;
|
||||
@@ -45,6 +49,8 @@ extern void spa_feature_incr(struct spa *, spa_feature_t, struct dmu_tx *);
|
||||
extern void spa_feature_decr(struct spa *, spa_feature_t, struct dmu_tx *);
|
||||
extern boolean_t spa_feature_is_enabled(struct spa *, spa_feature_t);
|
||||
extern boolean_t spa_feature_is_active(struct spa *, spa_feature_t);
|
||||
extern boolean_t spa_feature_enabled_txg(spa_t *spa, spa_feature_t fid,
|
||||
uint64_t *txg);
|
||||
extern uint64_t spa_feature_refcount(spa_t *, spa_feature_t, uint64_t);
|
||||
extern boolean_t spa_features_check(spa_t *, boolean_t, nvlist_t *, nvlist_t *);
|
||||
|
||||
@@ -53,6 +59,8 @@ extern boolean_t spa_features_check(spa_t *, boolean_t, nvlist_t *, nvlist_t *);
|
||||
* use the above interfaces.
|
||||
*/
|
||||
extern int feature_get_refcount(struct spa *, zfeature_info_t *, uint64_t *);
|
||||
extern int feature_get_refcount_from_disk(spa_t *spa, zfeature_info_t *feature,
|
||||
uint64_t *res);
|
||||
extern void feature_enable_sync(struct spa *, zfeature_info_t *,
|
||||
struct dmu_tx *);
|
||||
extern void feature_sync(struct spa *, zfeature_info_t *, uint64_t,
|
||||
|
||||
Reference in New Issue
Block a user