Persistent L2ARC

This commit makes the L2ARC persistent across reboots. We implement
a light-weight persistent L2ARC metadata structure that allows L2ARC
contents to be recovered after a reboot. This significantly eases the
impact a reboot has on read performance on systems with large caches.

Reviewed-by: Matthew Ahrens <mahrens@delphix.com>
Reviewed-by: George Wilson <gwilson@delphix.com>
Reviewed-by: Ryan Moeller <ryan@iXsystems.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Co-authored-by: Saso Kiselkov <skiselkov@gmail.com>
Co-authored-by: Jorgen Lundman <lundman@lundman.net>
Co-authored-by: George Amanakis <gamanakis@gmail.com>
Ported-by: Yuxuan Shui <yshuiv7@gmail.com>
Signed-off-by: George Amanakis <gamanakis@gmail.com>
Closes #925 
Closes #1823 
Closes #2672 
Closes #3744 
Closes #9582
This commit is contained in:
George Amanakis 2020-04-10 13:33:35 -04:00 committed by GitHub
parent 36a6e2335c
commit 77f6826b83
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 3020 additions and 88 deletions

View File

@ -62,6 +62,7 @@
#include <sys/zio_compress.h> #include <sys/zio_compress.h>
#include <sys/zfs_fuid.h> #include <sys/zfs_fuid.h>
#include <sys/arc.h> #include <sys/arc.h>
#include <sys/arc_impl.h>
#include <sys/ddt.h> #include <sys/ddt.h>
#include <sys/zfeature.h> #include <sys/zfeature.h>
#include <sys/abd.h> #include <sys/abd.h>
@ -3474,6 +3475,216 @@ print_label_header(zdb_label_t *label, int l)
label->header_printed = B_TRUE; label->header_printed = B_TRUE;
} }
static void
print_l2arc_header(void)
{
(void) printf("------------------------------------\n");
(void) printf("L2ARC device header\n");
(void) printf("------------------------------------\n");
}
static void
print_l2arc_log_blocks(void)
{
(void) printf("------------------------------------\n");
(void) printf("L2ARC device log blocks\n");
(void) printf("------------------------------------\n");
}
static void
dump_l2arc_log_entries(uint64_t log_entries,
l2arc_log_ent_phys_t *le, int i)
{
for (int j = 0; j < log_entries; j++) {
dva_t dva = le[j].le_dva;
(void) printf("lb[%4d]\tle[%4d]\tDVA asize: %llu, "
"vdev: %llu, offset: %llu\n", i, j + 1,
(u_longlong_t)DVA_GET_ASIZE(&dva),
(u_longlong_t)DVA_GET_VDEV(&dva),
(u_longlong_t)DVA_GET_OFFSET(&dva));
(void) printf("|\t\t\t\tbirth: %llu\n",
(u_longlong_t)le[j].le_birth);
(void) printf("|\t\t\t\tlsize: %llu\n",
(u_longlong_t)L2BLK_GET_LSIZE((&le[j])->le_prop));
(void) printf("|\t\t\t\tpsize: %llu\n",
(u_longlong_t)L2BLK_GET_PSIZE((&le[j])->le_prop));
(void) printf("|\t\t\t\tcompr: %llu\n",
(u_longlong_t)L2BLK_GET_COMPRESS((&le[j])->le_prop));
(void) printf("|\t\t\t\ttype: %llu\n",
(u_longlong_t)L2BLK_GET_TYPE((&le[j])->le_prop));
(void) printf("|\t\t\t\tprotected: %llu\n",
(u_longlong_t)L2BLK_GET_PROTECTED((&le[j])->le_prop));
(void) printf("|\t\t\t\tprefetch: %llu\n",
(u_longlong_t)L2BLK_GET_PREFETCH((&le[j])->le_prop));
(void) printf("|\t\t\t\taddress: %llu\n",
(u_longlong_t)le[j].le_daddr);
(void) printf("|\n");
}
(void) printf("\n");
}
static void
dump_l2arc_log_blkptr(l2arc_log_blkptr_t lbps)
{
(void) printf("|\t\tdaddr: %llu\n", (u_longlong_t)lbps.lbp_daddr);
(void) printf("|\t\tpayload_asize: %llu\n",
(u_longlong_t)lbps.lbp_payload_asize);
(void) printf("|\t\tpayload_start: %llu\n",
(u_longlong_t)lbps.lbp_payload_start);
(void) printf("|\t\tlsize: %llu\n",
(u_longlong_t)L2BLK_GET_LSIZE((&lbps)->lbp_prop));
(void) printf("|\t\tpsize: %llu\n",
(u_longlong_t)L2BLK_GET_PSIZE((&lbps)->lbp_prop));
(void) printf("|\t\tcompralgo: %llu\n",
(u_longlong_t)L2BLK_GET_COMPRESS((&lbps)->lbp_prop));
(void) printf("|\t\tcksumalgo: %llu\n",
(u_longlong_t)L2BLK_GET_CHECKSUM((&lbps)->lbp_prop));
(void) printf("|\n\n");
}
static void
dump_l2arc_log_blocks(int fd, l2arc_dev_hdr_phys_t l2dhdr)
{
l2arc_log_blk_phys_t this_lb;
uint64_t psize;
l2arc_log_blkptr_t lbps[2];
abd_t *abd;
zio_cksum_t cksum;
int i = 0, failed = 0;
l2arc_dev_t dev;
print_l2arc_log_blocks();
bcopy((&l2dhdr)->dh_start_lbps, lbps, sizeof (lbps));
dev.l2ad_evict = l2dhdr.dh_evict;
dev.l2ad_start = l2dhdr.dh_start;
dev.l2ad_end = l2dhdr.dh_end;
if (l2dhdr.dh_start_lbps[0].lbp_daddr == 0) {
/* no log blocks to read */
(void) printf("No log blocks to read\n");
(void) printf("\n");
return;
} else {
dev.l2ad_hand = lbps[0].lbp_daddr +
L2BLK_GET_PSIZE((&lbps[0])->lbp_prop);
}
dev.l2ad_first = !!(l2dhdr.dh_flags & L2ARC_DEV_HDR_EVICT_FIRST);
for (;;) {
if (!l2arc_log_blkptr_valid(&dev, &lbps[0]))
break;
psize = L2BLK_GET_PSIZE((&lbps[0])->lbp_prop);
if (pread64(fd, &this_lb, psize, lbps[0].lbp_daddr) != psize) {
(void) printf("Error while reading next log block\n\n");
break;
}
fletcher_4_native_varsize(&this_lb, psize, &cksum);
if (!ZIO_CHECKSUM_EQUAL(cksum, lbps[0].lbp_cksum)) {
failed++;
(void) printf("Invalid cksum\n");
dump_l2arc_log_blkptr(lbps[0]);
break;
}
switch (L2BLK_GET_COMPRESS((&lbps[0])->lbp_prop)) {
case ZIO_COMPRESS_OFF:
break;
case ZIO_COMPRESS_LZ4:
abd = abd_alloc_for_io(psize, B_TRUE);
abd_copy_from_buf_off(abd, &this_lb, 0, psize);
zio_decompress_data(L2BLK_GET_COMPRESS(
(&lbps[0])->lbp_prop), abd, &this_lb,
psize, sizeof (this_lb));
abd_free(abd);
break;
default:
break;
}
if (this_lb.lb_magic == BSWAP_64(L2ARC_LOG_BLK_MAGIC))
byteswap_uint64_array(&this_lb, psize);
if (this_lb.lb_magic != L2ARC_LOG_BLK_MAGIC) {
(void) printf("Invalid log block magic\n\n");
break;
}
i++;
if (dump_opt['l'] > 1) {
(void) printf("lb[%4d]\tmagic: %llu\n", i,
(u_longlong_t)this_lb.lb_magic);
dump_l2arc_log_blkptr(lbps[0]);
}
if (dump_opt['l'] > 2)
dump_l2arc_log_entries(l2dhdr.dh_log_blk_ent,
this_lb.lb_entries, i);
if (l2arc_range_check_overlap(lbps[1].lbp_daddr,
lbps[0].lbp_daddr, dev.l2ad_evict) && !dev.l2ad_first)
break;
lbps[0] = lbps[1];
lbps[1] = this_lb.lb_prev_lbp;
}
(void) printf("log_blk_count:\t %d with valid cksum\n", i);
(void) printf("\t\t %d with invalid cksum\n\n", failed);
}
static void
dump_l2arc_header(int fd)
{
l2arc_dev_hdr_phys_t l2dhdr;
int error = B_FALSE;
if (pread64(fd, &l2dhdr, sizeof (l2dhdr),
VDEV_LABEL_START_SIZE) != sizeof (l2dhdr)) {
error = B_TRUE;
} else {
if (l2dhdr.dh_magic == BSWAP_64(L2ARC_DEV_HDR_MAGIC))
byteswap_uint64_array(&l2dhdr, sizeof (l2dhdr));
if (l2dhdr.dh_magic != L2ARC_DEV_HDR_MAGIC)
error = B_TRUE;
}
if (error) {
(void) printf("L2ARC device header not found\n\n");
} else if (!dump_opt['q']) {
print_l2arc_header();
(void) printf(" magic: %llu\n",
(u_longlong_t)l2dhdr.dh_magic);
(void) printf(" version: %llu\n",
(u_longlong_t)l2dhdr.dh_version);
(void) printf(" pool_guid: %llu\n",
(u_longlong_t)l2dhdr.dh_spa_guid);
(void) printf(" flags: %llu\n",
(u_longlong_t)l2dhdr.dh_flags);
(void) printf(" start_lbps[0]: %llu\n",
(u_longlong_t)
l2dhdr.dh_start_lbps[0].lbp_daddr);
(void) printf(" start_lbps[1]: %llu\n",
(u_longlong_t)
l2dhdr.dh_start_lbps[1].lbp_daddr);
(void) printf(" log_blk_ent: %llu\n",
(u_longlong_t)l2dhdr.dh_log_blk_ent);
(void) printf(" start: %llu\n",
(u_longlong_t)l2dhdr.dh_start);
(void) printf(" end: %llu\n",
(u_longlong_t)l2dhdr.dh_end);
(void) printf(" evict: %llu\n\n",
(u_longlong_t)l2dhdr.dh_evict);
dump_l2arc_log_blocks(fd, l2dhdr);
}
}
static void static void
dump_config_from_label(zdb_label_t *label, size_t buflen, int l) dump_config_from_label(zdb_label_t *label, size_t buflen, int l)
{ {
@ -3639,10 +3850,11 @@ dump_label(const char *dev)
{ {
char path[MAXPATHLEN]; char path[MAXPATHLEN];
zdb_label_t labels[VDEV_LABELS]; zdb_label_t labels[VDEV_LABELS];
uint64_t psize, ashift; uint64_t psize, ashift, l2cache;
struct stat64 statbuf; struct stat64 statbuf;
boolean_t config_found = B_FALSE; boolean_t config_found = B_FALSE;
boolean_t error = B_FALSE; boolean_t error = B_FALSE;
boolean_t read_l2arc_header = B_FALSE;
avl_tree_t config_tree; avl_tree_t config_tree;
avl_tree_t uberblock_tree; avl_tree_t uberblock_tree;
void *node, *cookie; void *node, *cookie;
@ -3735,6 +3947,15 @@ dump_label(const char *dev)
if (nvlist_size(config, &size, NV_ENCODE_XDR) != 0) if (nvlist_size(config, &size, NV_ENCODE_XDR) != 0)
size = buflen; size = buflen;
/* If the device is a cache device clear the header. */
if (!read_l2arc_header) {
if (nvlist_lookup_uint64(config,
ZPOOL_CONFIG_POOL_STATE, &l2cache) == 0 &&
l2cache == POOL_STATE_L2CACHE) {
read_l2arc_header = B_TRUE;
}
}
fletcher_4_native_varsize(buf, size, &cksum); fletcher_4_native_varsize(buf, size, &cksum);
rec = cksum_record_insert(&config_tree, &cksum, l); rec = cksum_record_insert(&config_tree, &cksum, l);
@ -3785,6 +4006,12 @@ dump_label(const char *dev)
nvlist_free(label->config_nv); nvlist_free(label->config_nv);
} }
/*
* Dump the L2ARC header, if existent.
*/
if (read_l2arc_header)
dump_l2arc_header(fd);
cookie = NULL; cookie = NULL;
while ((node = avl_destroy_nodes(&config_tree, &cookie)) != NULL) while ((node = avl_destroy_nodes(&config_tree, &cookie)) != NULL)
umem_free(node, sizeof (cksum_record_t)); umem_free(node, sizeof (cksum_record_t));

View File

@ -336,6 +336,7 @@ AC_CONFIG_FILES([
tests/zfs-tests/tests/functional/no_space/Makefile tests/zfs-tests/tests/functional/no_space/Makefile
tests/zfs-tests/tests/functional/nopwrite/Makefile tests/zfs-tests/tests/functional/nopwrite/Makefile
tests/zfs-tests/tests/functional/online_offline/Makefile tests/zfs-tests/tests/functional/online_offline/Makefile
tests/zfs-tests/tests/functional/persist_l2arc/Makefile
tests/zfs-tests/tests/functional/pool_checkpoint/Makefile tests/zfs-tests/tests/functional/pool_checkpoint/Makefile
tests/zfs-tests/tests/functional/pool_names/Makefile tests/zfs-tests/tests/functional/pool_names/Makefile
tests/zfs-tests/tests/functional/poolversion/Makefile tests/zfs-tests/tests/functional/poolversion/Makefile

View File

@ -310,10 +310,14 @@ void arc_fini(void);
void l2arc_add_vdev(spa_t *spa, vdev_t *vd); void l2arc_add_vdev(spa_t *spa, vdev_t *vd);
void l2arc_remove_vdev(vdev_t *vd); void l2arc_remove_vdev(vdev_t *vd);
boolean_t l2arc_vdev_present(vdev_t *vd); boolean_t l2arc_vdev_present(vdev_t *vd);
void l2arc_rebuild_vdev(vdev_t *vd, boolean_t reopen);
boolean_t l2arc_range_check_overlap(uint64_t bottom, uint64_t top,
uint64_t check);
void l2arc_init(void); void l2arc_init(void);
void l2arc_fini(void); void l2arc_fini(void);
void l2arc_start(void); void l2arc_start(void);
void l2arc_stop(void); void l2arc_stop(void);
void l2arc_spa_rebuild_start(spa_t *spa);
#ifndef _KERNEL #ifndef _KERNEL
extern boolean_t arc_watch; extern boolean_t arc_watch;

View File

@ -20,9 +20,10 @@
*/ */
/* /*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013 by Delphix. All rights reserved. * Copyright (c) 2013, Delphix. All rights reserved.
* Copyright (c) 2013 by Saso Kiselkov. All rights reserved. * Copyright (c) 2013, Saso Kiselkov. All rights reserved.
* Copyright 2013 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2013, Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2020, George Amanakis. All rights reserved.
*/ */
#ifndef _SYS_ARC_IMPL_H #ifndef _SYS_ARC_IMPL_H
@ -176,6 +177,218 @@ typedef struct l1arc_buf_hdr {
abd_t *b_pabd; abd_t *b_pabd;
} l1arc_buf_hdr_t; } l1arc_buf_hdr_t;
typedef enum l2arc_dev_hdr_flags_t {
L2ARC_DEV_HDR_EVICT_FIRST = (1 << 0) /* mirror of l2ad_first */
} l2arc_dev_hdr_flags_t;
/*
* Pointer used in persistent L2ARC (for pointing to log blocks).
*/
typedef struct l2arc_log_blkptr {
/*
* Offset of log block within the device, in bytes
*/
uint64_t lbp_daddr;
/*
* Aligned payload size (in bytes) of the log block
*/
uint64_t lbp_payload_asize;
/*
* Offset in bytes of the first buffer in the payload
*/
uint64_t lbp_payload_start;
/*
* lbp_prop has the following format:
* * logical size (in bytes)
* * physical (compressed) size (in bytes)
* * compression algorithm (we always LZ4-compress l2arc logs)
* * checksum algorithm (used for lbp_cksum)
*/
uint64_t lbp_prop;
zio_cksum_t lbp_cksum; /* checksum of log */
} l2arc_log_blkptr_t;
/*
* The persistent L2ARC device header.
* Byte order of magic determines whether 64-bit bswap of fields is necessary.
*/
typedef struct l2arc_dev_hdr_phys {
uint64_t dh_magic; /* L2ARC_DEV_HDR_MAGIC */
uint64_t dh_version; /* Persistent L2ARC version */
/*
* Global L2ARC device state and metadata.
*/
uint64_t dh_spa_guid;
uint64_t dh_vdev_guid;
uint64_t dh_log_blk_ent; /* entries per log blk */
uint64_t dh_evict; /* evicted offset in bytes */
uint64_t dh_flags; /* l2arc_dev_hdr_flags_t */
/*
* Used in zdb.c for determining if a log block is valid, in the same
* way that l2arc_rebuild() does.
*/
uint64_t dh_start;
uint64_t dh_end;
/*
* Start of log block chain. [0] -> newest log, [1] -> one older (used
* for initiating prefetch).
*/
l2arc_log_blkptr_t dh_start_lbps[2];
const uint64_t dh_pad[34]; /* pad to 512 bytes */
zio_eck_t dh_tail;
} l2arc_dev_hdr_phys_t;
CTASSERT_GLOBAL(sizeof (l2arc_dev_hdr_phys_t) == SPA_MINBLOCKSIZE);
/*
* A single ARC buffer header entry in a l2arc_log_blk_phys_t.
*/
typedef struct l2arc_log_ent_phys {
dva_t le_dva; /* dva of buffer */
uint64_t le_birth; /* birth txg of buffer */
/*
* le_prop has the following format:
* * logical size (in bytes)
* * physical (compressed) size (in bytes)
* * compression algorithm
* * object type (used to restore arc_buf_contents_t)
* * protected status (used for encryption)
* * prefetch status (used in l2arc_read_done())
*/
uint64_t le_prop;
uint64_t le_daddr; /* buf location on l2dev */
/*
* We pad the size of each entry to a power of 2 so that the size of
* l2arc_log_blk_phys_t is power-of-2 aligned with SPA_MINBLOCKSHIFT,
* because of the L2ARC_SET_*SIZE macros.
*/
const uint64_t le_pad[3]; /* pad to 64 bytes */
} l2arc_log_ent_phys_t;
#define L2ARC_LOG_BLK_MAX_ENTRIES (1022)
/*
* A log block of up to 1022 ARC buffer log entries, chained into the
* persistent L2ARC metadata linked list. Byte order of magic determines
* whether 64-bit bswap of fields is necessary.
*/
typedef struct l2arc_log_blk_phys {
uint64_t lb_magic; /* L2ARC_LOG_BLK_MAGIC */
/*
* There are 2 chains (headed by dh_start_lbps[2]), and this field
* points back to the previous block in this chain. We alternate
* which chain we append to, so they are time-wise and offset-wise
* interleaved, but that is an optimization rather than for
* correctness.
*/
l2arc_log_blkptr_t lb_prev_lbp; /* pointer to prev log block */
/*
* Pad header section to 128 bytes
*/
uint64_t lb_pad[7];
/* Payload */
l2arc_log_ent_phys_t lb_entries[L2ARC_LOG_BLK_MAX_ENTRIES];
} l2arc_log_blk_phys_t; /* 64K total */
/*
* The size of l2arc_log_blk_phys_t has to be power-of-2 aligned with
* SPA_MINBLOCKSHIFT because of L2BLK_SET_*SIZE macros.
*/
CTASSERT_GLOBAL(IS_P2ALIGNED(sizeof (l2arc_log_blk_phys_t),
1ULL << SPA_MINBLOCKSHIFT));
CTASSERT_GLOBAL(sizeof (l2arc_log_blk_phys_t) >= SPA_MINBLOCKSIZE);
CTASSERT_GLOBAL(sizeof (l2arc_log_blk_phys_t) <= SPA_MAXBLOCKSIZE);
/*
* These structures hold in-flight abd buffers for log blocks as they're being
* written to the L2ARC device.
*/
typedef struct l2arc_lb_abd_buf {
abd_t *abd;
list_node_t node;
} l2arc_lb_abd_buf_t;
/*
* These structures hold pointers to log blocks present on the L2ARC device.
*/
typedef struct l2arc_lb_ptr_buf {
l2arc_log_blkptr_t *lb_ptr;
list_node_t node;
} l2arc_lb_ptr_buf_t;
/* Macros for setting fields in le_prop and lbp_prop */
#define L2BLK_GET_LSIZE(field) \
BF64_GET_SB((field), 0, SPA_LSIZEBITS, SPA_MINBLOCKSHIFT, 1)
#define L2BLK_SET_LSIZE(field, x) \
BF64_SET_SB((field), 0, SPA_LSIZEBITS, SPA_MINBLOCKSHIFT, 1, x)
#define L2BLK_GET_PSIZE(field) \
BF64_GET_SB((field), 16, SPA_PSIZEBITS, SPA_MINBLOCKSHIFT, 1)
#define L2BLK_SET_PSIZE(field, x) \
BF64_SET_SB((field), 16, SPA_PSIZEBITS, SPA_MINBLOCKSHIFT, 1, x)
#define L2BLK_GET_COMPRESS(field) \
BF64_GET((field), 32, SPA_COMPRESSBITS)
#define L2BLK_SET_COMPRESS(field, x) \
BF64_SET((field), 32, SPA_COMPRESSBITS, x)
#define L2BLK_GET_PREFETCH(field) BF64_GET((field), 39, 1)
#define L2BLK_SET_PREFETCH(field, x) BF64_SET((field), 39, 1, x)
#define L2BLK_GET_CHECKSUM(field) BF64_GET((field), 40, 8)
#define L2BLK_SET_CHECKSUM(field, x) BF64_SET((field), 40, 8, x)
#define L2BLK_GET_TYPE(field) BF64_GET((field), 48, 8)
#define L2BLK_SET_TYPE(field, x) BF64_SET((field), 48, 8, x)
#define L2BLK_GET_PROTECTED(field) BF64_GET((field), 56, 1)
#define L2BLK_SET_PROTECTED(field, x) BF64_SET((field), 56, 1, x)
#define PTR_SWAP(x, y) \
do { \
void *tmp = (x);\
x = y; \
y = tmp; \
_NOTE(CONSTCOND)\
} while (0)
#define L2ARC_DEV_HDR_MAGIC 0x5a46534341434845LLU /* ASCII: "ZFSCACHE" */
#define L2ARC_LOG_BLK_MAGIC 0x4c4f47424c4b4844LLU /* ASCII: "LOGBLKHD" */
/*
* L2ARC Internals
*/
typedef struct l2arc_dev {
vdev_t *l2ad_vdev; /* vdev */
spa_t *l2ad_spa; /* spa */
uint64_t l2ad_hand; /* next write location */
uint64_t l2ad_start; /* first addr on device */
uint64_t l2ad_end; /* last addr on device */
boolean_t l2ad_first; /* first sweep through */
boolean_t l2ad_writing; /* currently writing */
kmutex_t l2ad_mtx; /* lock for buffer list */
list_t l2ad_buflist; /* buffer list */
list_node_t l2ad_node; /* device list node */
zfs_refcount_t l2ad_alloc; /* allocated bytes */
/*
* Persistence-related stuff
*/
l2arc_dev_hdr_phys_t *l2ad_dev_hdr; /* persistent device header */
uint64_t l2ad_dev_hdr_asize; /* aligned hdr size */
l2arc_log_blk_phys_t l2ad_log_blk; /* currently open log block */
int l2ad_log_ent_idx; /* index into cur log blk */
/* Number of bytes in current log block's payload */
uint64_t l2ad_log_blk_payload_asize;
/*
* Offset (in bytes) of the first buffer in current log block's
* payload.
*/
uint64_t l2ad_log_blk_payload_start;
/* Flag indicating whether a rebuild is scheduled or is going on */
boolean_t l2ad_rebuild;
boolean_t l2ad_rebuild_cancel;
boolean_t l2ad_rebuild_began;
uint64_t l2ad_log_entries; /* entries per log blk */
uint64_t l2ad_evict; /* evicted offset in bytes */
/* List of pointers to log blocks present in the L2ARC device */
list_t l2ad_lbptr_list;
} l2arc_dev_t;
/* /*
* Encrypted blocks will need to be stored encrypted on the L2ARC * Encrypted blocks will need to be stored encrypted on the L2ARC
* disk as they appear in the main pool. In order for this to work we * disk as they appear in the main pool. In order for this to work we
@ -206,32 +419,19 @@ typedef struct arc_buf_hdr_crypt {
uint8_t b_mac[ZIO_DATA_MAC_LEN]; uint8_t b_mac[ZIO_DATA_MAC_LEN];
} arc_buf_hdr_crypt_t; } arc_buf_hdr_crypt_t;
typedef struct l2arc_dev {
vdev_t *l2ad_vdev; /* vdev */
spa_t *l2ad_spa; /* spa */
uint64_t l2ad_hand; /* next write location */
uint64_t l2ad_start; /* first addr on device */
uint64_t l2ad_end; /* last addr on device */
boolean_t l2ad_first; /* first sweep through */
boolean_t l2ad_writing; /* currently writing */
kmutex_t l2ad_mtx; /* lock for buffer list */
list_t l2ad_buflist; /* buffer list */
list_node_t l2ad_node; /* device list node */
zfs_refcount_t l2ad_alloc; /* allocated bytes */
} l2arc_dev_t;
typedef struct l2arc_buf_hdr { typedef struct l2arc_buf_hdr {
/* protected by arc_buf_hdr mutex */ /* protected by arc_buf_hdr mutex */
l2arc_dev_t *b_dev; /* L2ARC device */ l2arc_dev_t *b_dev; /* L2ARC device */
uint64_t b_daddr; /* disk address, offset byte */ uint64_t b_daddr; /* disk address, offset byte */
uint32_t b_hits; uint32_t b_hits;
list_node_t b_l2node; list_node_t b_l2node;
} l2arc_buf_hdr_t; } l2arc_buf_hdr_t;
typedef struct l2arc_write_callback { typedef struct l2arc_write_callback {
l2arc_dev_t *l2wcb_dev; /* device info */ l2arc_dev_t *l2wcb_dev; /* device info */
arc_buf_hdr_t *l2wcb_head; /* head of write buflist */ arc_buf_hdr_t *l2wcb_head; /* head of write buflist */
/* in-flight list of log blocks */
list_t l2wcb_abd_list;
} l2arc_write_callback_t; } l2arc_write_callback_t;
struct arc_buf_hdr { struct arc_buf_hdr {
@ -532,6 +732,71 @@ typedef struct arc_stats {
kstat_named_t arcstat_l2_psize; kstat_named_t arcstat_l2_psize;
/* Not updated directly; only synced in arc_kstat_update. */ /* Not updated directly; only synced in arc_kstat_update. */
kstat_named_t arcstat_l2_hdr_size; kstat_named_t arcstat_l2_hdr_size;
/*
* Number of L2ARC log blocks written. These are used for restoring the
* L2ARC. Updated during writing of L2ARC log blocks.
*/
kstat_named_t arcstat_l2_log_blk_writes;
/*
* Moving average of the physical size of the L2ARC log blocks, in
* bytes. Updated during L2ARC rebuild and during writing of L2ARC
* log blocks.
*/
kstat_named_t arcstat_l2_log_blk_avg_size;
/*
* Moving average of the physical size of L2ARC restored data, in bytes,
* to the physical size of their metadata in ARC, in bytes.
* Updated during L2ARC rebuild and during writing of L2ARC log blocks.
*/
kstat_named_t arcstat_l2_data_to_meta_ratio;
/*
* Number of times the L2ARC rebuild was successful for an L2ARC device.
*/
kstat_named_t arcstat_l2_rebuild_success;
/*
* Number of times the L2ARC rebuild failed because the device header
* was in an unsupported format or corrupted.
*/
kstat_named_t arcstat_l2_rebuild_abort_unsupported;
/*
* Number of times the L2ARC rebuild failed because of IO errors
* while reading a log block.
*/
kstat_named_t arcstat_l2_rebuild_abort_io_errors;
/*
* Number of times the L2ARC rebuild failed because of IO errors when
* reading the device header.
*/
kstat_named_t arcstat_l2_rebuild_abort_dh_errors;
/*
* Number of L2ARC log blocks which failed to be restored due to
* checksum errors.
*/
kstat_named_t arcstat_l2_rebuild_abort_cksum_lb_errors;
/*
* Number of times the L2ARC rebuild was aborted due to low system
* memory.
*/
kstat_named_t arcstat_l2_rebuild_abort_lowmem;
/* Logical size of L2ARC restored data, in bytes. */
kstat_named_t arcstat_l2_rebuild_size;
/*
* Number of L2ARC log entries (buffers) that were successfully
* restored in ARC.
*/
kstat_named_t arcstat_l2_rebuild_bufs;
/*
* Number of L2ARC log entries (buffers) already cached in ARC. These
* were not restored again.
*/
kstat_named_t arcstat_l2_rebuild_bufs_precached;
/* Physical size of L2ARC restored data, in bytes. */
kstat_named_t arcstat_l2_rebuild_psize;
/*
* Number of L2ARC log blocks that were restored successfully. Each
* log block may hold up to L2ARC_LOG_BLK_MAX_ENTRIES buffers.
*/
kstat_named_t arcstat_l2_rebuild_log_blks;
kstat_named_t arcstat_memory_throttle_count; kstat_named_t arcstat_memory_throttle_count;
kstat_named_t arcstat_memory_direct_count; kstat_named_t arcstat_memory_direct_count;
kstat_named_t arcstat_memory_indirect_count; kstat_named_t arcstat_memory_indirect_count;
@ -617,6 +882,10 @@ extern void arc_tuning_update(boolean_t);
extern int param_set_arc_long(ZFS_MODULE_PARAM_ARGS); extern int param_set_arc_long(ZFS_MODULE_PARAM_ARGS);
extern int param_set_arc_int(ZFS_MODULE_PARAM_ARGS); extern int param_set_arc_int(ZFS_MODULE_PARAM_ARGS);
/* used in zdb.c */
boolean_t l2arc_log_blkptr_valid(l2arc_dev_t *dev,
const l2arc_log_blkptr_t *lbp);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -573,6 +573,11 @@ typedef enum zfs_key_location {
#define ZPL_VERSION_USERSPACE ZPL_VERSION_4 #define ZPL_VERSION_USERSPACE ZPL_VERSION_4
#define ZPL_VERSION_SA ZPL_VERSION_5 #define ZPL_VERSION_SA ZPL_VERSION_5
/* Persistent L2ARC version */
#define L2ARC_PERSISTENT_VERSION_1 1ULL
#define L2ARC_PERSISTENT_VERSION L2ARC_PERSISTENT_VERSION_1
#define L2ARC_PERSISTENT_VERSION_STRING "1"
/* Rewind policy information */ /* Rewind policy information */
#define ZPOOL_NO_REWIND 1 /* No policy - default behavior */ #define ZPOOL_NO_REWIND 1 /* No policy - default behavior */
#define ZPOOL_NEVER_REWIND 2 /* Do not search for best txg or rewind */ #define ZPOOL_NEVER_REWIND 2 /* Do not search for best txg or rewind */

View File

@ -787,6 +787,7 @@ extern int bpobj_enqueue_free_cb(void *arg, const blkptr_t *bp, dmu_tx_t *tx);
#define SPA_ASYNC_INITIALIZE_RESTART 0x100 #define SPA_ASYNC_INITIALIZE_RESTART 0x100
#define SPA_ASYNC_TRIM_RESTART 0x200 #define SPA_ASYNC_TRIM_RESTART 0x200
#define SPA_ASYNC_AUTOTRIM_RESTART 0x400 #define SPA_ASYNC_AUTOTRIM_RESTART 0x400
#define SPA_ASYNC_L2CACHE_REBUILD 0x800
/* /*
* Controls the behavior of spa_vdev_remove(). * Controls the behavior of spa_vdev_remove().

View File

@ -38,6 +38,7 @@
#include <libzfs.h> #include <libzfs.h>
#include <libzfs_impl.h> #include <libzfs_impl.h>
#include <libzutil.h> #include <libzutil.h>
#include <sys/arc_impl.h>
/* /*
* Returns true if the named pool matches the given GUID. * Returns true if the named pool matches the given GUID.
@ -146,8 +147,10 @@ zpool_clear_label(int fd)
struct stat64 statbuf; struct stat64 statbuf;
int l; int l;
vdev_label_t *label; vdev_label_t *label;
l2arc_dev_hdr_phys_t *l2dhdr;
uint64_t size; uint64_t size;
int labels_cleared = 0; int labels_cleared = 0, header_cleared = 0;
boolean_t clear_l2arc_header = B_FALSE;
if (fstat64_blk(fd, &statbuf) == -1) if (fstat64_blk(fd, &statbuf) == -1)
return (0); return (0);
@ -157,8 +160,13 @@ zpool_clear_label(int fd)
if ((label = calloc(1, sizeof (vdev_label_t))) == NULL) if ((label = calloc(1, sizeof (vdev_label_t))) == NULL)
return (-1); return (-1);
if ((l2dhdr = calloc(1, sizeof (l2arc_dev_hdr_phys_t))) == NULL) {
free(label);
return (-1);
}
for (l = 0; l < VDEV_LABELS; l++) { for (l = 0; l < VDEV_LABELS; l++) {
uint64_t state, guid; uint64_t state, guid, l2cache;
nvlist_t *config; nvlist_t *config;
if (pread64(fd, label, sizeof (vdev_label_t), if (pread64(fd, label, sizeof (vdev_label_t),
@ -185,6 +193,15 @@ zpool_clear_label(int fd)
continue; continue;
} }
/* If the device is a cache device clear the header. */
if (!clear_l2arc_header) {
if (nvlist_lookup_uint64(config,
ZPOOL_CONFIG_POOL_STATE, &l2cache) == 0 &&
l2cache == POOL_STATE_L2CACHE) {
clear_l2arc_header = B_TRUE;
}
}
nvlist_free(config); nvlist_free(config);
/* /*
@ -202,7 +219,17 @@ zpool_clear_label(int fd)
} }
} }
/* Clear the L2ARC header. */
if (clear_l2arc_header) {
memset(l2dhdr, 0, sizeof (l2arc_dev_hdr_phys_t));
if (pwrite64(fd, l2dhdr, sizeof (l2arc_dev_hdr_phys_t),
VDEV_LABEL_START_SIZE) == sizeof (l2arc_dev_hdr_phys_t)) {
header_cleared++;
}
}
free(label); free(label);
free(l2dhdr);
if (labels_cleared == 0) if (labels_cleared == 0)
return (-1); return (-1);

View File

@ -87,7 +87,7 @@ Default value: \fB10\fR%.
.ad .ad
.RS 12n .RS 12n
Set the size of the dbuf cache, \fBdbuf_cache_max_bytes\fR, to a log2 fraction Set the size of the dbuf cache, \fBdbuf_cache_max_bytes\fR, to a log2 fraction
of the target arc size. of the target ARC size.
.sp .sp
Default value: \fB5\fR. Default value: \fB5\fR.
.RE .RE
@ -99,7 +99,7 @@ Default value: \fB5\fR.
.ad .ad
.RS 12n .RS 12n
Set the size of the dbuf metadata cache, \fBdbuf_metadata_cache_max_bytes\fR, Set the size of the dbuf metadata cache, \fBdbuf_metadata_cache_max_bytes\fR,
to a log2 fraction of the target arc size. to a log2 fraction of the target ARC size.
.sp .sp
Default value: \fB6\fR. Default value: \fB6\fR.
.RE .RE
@ -179,7 +179,10 @@ Default value: \fB1\fR.
.ad .ad
.RS 12n .RS 12n
How far through the ARC lists to search for L2ARC cacheable content, expressed How far through the ARC lists to search for L2ARC cacheable content, expressed
as a multiplier of \fBl2arc_write_max\fR as a multiplier of \fBl2arc_write_max\fR.
ARC persistence across reboots can be achieved with persistent L2ARC by setting
this parameter to \fB0\fR allowing the full length of ARC lists to be searched
for cacheable content.
.sp .sp
Default value: \fB2\fR. Default value: \fB2\fR.
.RE .RE
@ -203,7 +206,7 @@ Default value: \fB200\fR%.
.ad .ad
.RS 12n .RS 12n
Do not write buffers to L2ARC if they were prefetched but not used by Do not write buffers to L2ARC if they were prefetched but not used by
applications applications.
.sp .sp
Use \fB1\fR for yes (default) and \fB0\fR to disable. Use \fB1\fR for yes (default) and \fB0\fR to disable.
.RE .RE
@ -214,7 +217,7 @@ Use \fB1\fR for yes (default) and \fB0\fR to disable.
\fBl2arc_norw\fR (int) \fBl2arc_norw\fR (int)
.ad .ad
.RS 12n .RS 12n
No reads during writes No reads during writes.
.sp .sp
Use \fB1\fR for yes and \fB0\fR for no (default). Use \fB1\fR for yes and \fB0\fR for no (default).
.RE .RE
@ -237,11 +240,41 @@ Default value: \fB8,388,608\fR.
\fBl2arc_write_max\fR (ulong) \fBl2arc_write_max\fR (ulong)
.ad .ad
.RS 12n .RS 12n
Max write bytes per interval Max write bytes per interval.
.sp .sp
Default value: \fB8,388,608\fR. Default value: \fB8,388,608\fR.
.RE .RE
.sp
.ne 2
.na
\fBl2arc_rebuild_enabled\fR (int)
.ad
.RS 12n
Rebuild the L2ARC when importing a pool (persistent L2ARC). This can be
disabled if there are problems importing a pool or attaching an L2ARC device
(e.g. the L2ARC device is slow in reading stored log metadata, or the metadata
has become somehow fragmented/unusable).
.sp
Use \fB1\fR for yes (default) and \fB0\fR for no.
.RE
.sp
.ne 2
.na
\fBl2arc_rebuild_blocks_min_l2size\fR (ulong)
.ad
.RS 12n
Min size (in bytes) of an L2ARC device required in order to write log blocks
in it. The log blocks are used upon importing the pool to rebuild
the L2ARC (persistent L2ARC). Rationale: for L2ARC devices less than 1GB, the
amount of data l2arc_evict() evicts is significant compared to the amount of
restored L2ARC data. In this case do not write log blocks in L2ARC in order not
to waste space.
.sp
Default value: \fB1,073,741,824\fR (1GB).
.RE
.sp .sp
.ne 2 .ne 2
.na .na
@ -614,7 +647,7 @@ Default value: \fB1\fR.
.ad .ad
.RS 12n .RS 12n
Sets the maximum number of bytes to consume during pool import to the log2 Sets the maximum number of bytes to consume during pool import to the log2
fraction of the target arc size. fraction of the target ARC size.
.sp .sp
Default value: \fB4\fR. Default value: \fB4\fR.
.RE .RE
@ -963,7 +996,7 @@ Default value: \fB1\fR.
\fBzfs_arc_min\fR (ulong) \fBzfs_arc_min\fR (ulong)
.ad .ad
.RS 12n .RS 12n
Min arc size of ARC in bytes. If set to 0 then arc_c_min will default to Min size of ARC in bytes. If set to 0 then arc_c_min will default to
consuming the larger of 32M or 1/32 of total system memory. consuming the larger of 32M or 1/32 of total system memory.
.sp .sp
Default value: \fB0\fR. Default value: \fB0\fR.
@ -1088,7 +1121,7 @@ Default value: \fB0\fR.
Percent of pagecache to reclaim arc to Percent of pagecache to reclaim arc to
This tunable allows ZFS arc to play more nicely with the kernel's LRU This tunable allows ZFS arc to play more nicely with the kernel's LRU
pagecache. It can guarantee that the arc size won't collapse under scanning pagecache. It can guarantee that the ARC size won't collapse under scanning
pressure on the pagecache, yet still allows arc to be reclaimed down to pressure on the pagecache, yet still allows arc to be reclaimed down to
zfs_arc_min if necessary. This value is specified as percent of pagecache zfs_arc_min if necessary. This value is specified as percent of pagecache
size (as measured by NR_FILE_PAGES) where that percent may exceed 100. This size (as measured by NR_FILE_PAGES) where that percent may exceed 100. This

View File

@ -212,18 +212,24 @@ If specified multiple times, display counts of each intent log transaction type.
Examine the checkpointed state of the pool. Examine the checkpointed state of the pool.
Note, the on disk format of the pool is not reverted to the checkpointed state. Note, the on disk format of the pool is not reverted to the checkpointed state.
.It Fl l Ar device .It Fl l Ar device
Read the vdev labels from the specified device. Read the vdev labels and L2ARC header from the specified device.
.Nm Fl l .Nm Fl l
will return 0 if valid label was found, 1 if error occurred, and 2 if no valid will return 0 if valid label was found, 1 if error occurred, and 2 if no valid
labels were found. Each unique configuration is displayed only once. labels were found. The presence of L2ARC header is indicated by a specific
sequence (L2ARC_DEV_HDR_MAGIC). Each unique configuration is displayed only
once.
.It Fl ll Ar device .It Fl ll Ar device
In addition display label space usage stats. In addition display label space usage stats. If a valid L2ARC header was found
also display the properties of log blocks used for restoring L2ARC contents
(persistent L2ARC).
.It Fl lll Ar device .It Fl lll Ar device
Display every configuration, unique or not. Display every configuration, unique or not. If a valid L2ARC header was found
also display the properties of log entries in log blocks used for restoring
L2ARC contents (persistent L2ARC).
.Pp .Pp
If the If the
.Fl q .Fl q
option is also specified, don't print the labels. option is also specified, don't print the labels or the L2ARC header.
.Pp .Pp
If the If the
.Fl u .Fl u

View File

@ -48,7 +48,10 @@
.Xc .Xc
Removes ZFS label information from the specified Removes ZFS label information from the specified
.Ar device . .Ar device .
The If the
.Ar device
is a cache device, it also removes the L2ARC header
(persistent L2ARC). The
.Ar device .Ar device
must not be part of an active pool configuration. must not be part of an active pool configuration.
.Bl -tag -width Ds .Bl -tag -width Ds

View File

@ -323,8 +323,28 @@ If a read error is encountered on a cache device, that read I/O is reissued to
the original storage pool device, which might be part of a mirrored or raidz the original storage pool device, which might be part of a mirrored or raidz
configuration. configuration.
.Pp .Pp
The content of the cache devices is considered volatile, as is the case with The content of the cache devices is persistent across reboots and restored
other system caches. asynchronously when importing the pool in L2ARC (persistent L2ARC).
This can be disabled by setting
.Sy l2arc_rebuild_enabled = 0 .
For cache devices smaller than 1GB we do not write the metadata structures
required for rebuilding the L2ARC in order not to waste space. This can be
changed with
.Sy l2arc_rebuild_blocks_min_l2size .
The cache device header (512 bytes) is updated even if no metadata structures
are written. Setting
.Sy l2arc_headroom = 0
will result in scanning the full-length ARC lists for cacheable content to be
written in L2ARC (persistent ARC). If a cache device is added with
.Nm zpool Cm add
its label and header will be overwritten and its contents are not going to be
restored in L2ARC, even if the device was previously part of the pool. If a
cache device is onlined with
.Nm zpool Cm online
its contents will be restored in L2ARC. This is useful in case of memory pressure
where the contents of the cache device are not fully restored in L2ARC.
The user can off/online the cache device when there is less memory pressure
in order to fully restore its contents to L2ARC.
.Ss Pool checkpoint .Ss Pool checkpoint
Before starting critical procedures that include destructive actions (e.g Before starting critical procedures that include destructive actions (e.g
.Nm zfs Cm destroy .Nm zfs Cm destroy

View File

@ -353,13 +353,14 @@ pool_property_show(struct kobject *kobj, struct attribute *attr, char *buf)
* This list is intended for kernel features that don't have a pool feature * This list is intended for kernel features that don't have a pool feature
* association or that extend existing user kernel interfaces. * association or that extend existing user kernel interfaces.
* *
* A user processes can easily check if the running zfs kernel module * A user process can easily check if the running zfs kernel module
* supports the new feature. * supports the new feature.
*/ */
static const char *zfs_kernel_features[] = { static const char *zfs_kernel_features[] = {
/* --> Add new kernel features here */ /* --> Add new kernel features here */
"com.delphix:vdev_initialize", "com.delphix:vdev_initialize",
"org.zfsonlinux:vdev_trim", "org.zfsonlinux:vdev_trim",
"org.openzfs:l2arc_persistent",
}; };
#define KERNEL_FEATURE_COUNT ARRAY_SIZE(zfs_kernel_features) #define KERNEL_FEATURE_COUNT ARRAY_SIZE(zfs_kernel_features)

File diff suppressed because it is too large Load Diff

View File

@ -4860,6 +4860,8 @@ spa_load_impl(spa_t *spa, spa_import_type_t type, char **ereport)
} }
spa_import_progress_remove(spa_guid(spa)); spa_import_progress_remove(spa_guid(spa));
spa_async_request(spa, SPA_ASYNC_L2CACHE_REBUILD);
spa_load_note(spa, "LOADED"); spa_load_note(spa, "LOADED");
return (0); return (0);
@ -7985,6 +7987,17 @@ spa_async_thread(void *arg)
mutex_exit(&spa_namespace_lock); mutex_exit(&spa_namespace_lock);
} }
/*
* Kick off L2 cache rebuilding.
*/
if (tasks & SPA_ASYNC_L2CACHE_REBUILD) {
mutex_enter(&spa_namespace_lock);
spa_config_enter(spa, SCL_L2ARC, FTAG, RW_READER);
l2arc_spa_rebuild_start(spa);
spa_config_exit(spa, SCL_L2ARC, FTAG);
mutex_exit(&spa_namespace_lock);
}
/* /*
* Let the world know that we're done. * Let the world know that we're done.
*/ */

View File

@ -2279,9 +2279,22 @@ vdev_reopen(vdev_t *vd)
if (vd->vdev_aux) { if (vd->vdev_aux) {
(void) vdev_validate_aux(vd); (void) vdev_validate_aux(vd);
if (vdev_readable(vd) && vdev_writeable(vd) && if (vdev_readable(vd) && vdev_writeable(vd) &&
vd->vdev_aux == &spa->spa_l2cache && vd->vdev_aux == &spa->spa_l2cache) {
!l2arc_vdev_present(vd)) /*
l2arc_add_vdev(spa, vd); * When reopening we can assume the device label has
* already the attribute l2cache_persistent, since we've
* opened the device in the past and updated the label.
* In case the vdev is present we should evict all ARC
* buffers and pointers to log blocks and reclaim their
* space before restoring its contents to L2ARC.
*/
if (l2arc_vdev_present(vd)) {
l2arc_rebuild_vdev(vd, B_TRUE);
} else {
l2arc_add_vdev(spa, vd);
}
spa_async_request(spa, SPA_ASYNC_L2CACHE_REBUILD);
}
} else { } else {
(void) vdev_validate(vd); (void) vdev_validate(vd);
} }

View File

@ -164,3 +164,9 @@ tags = ['functional', 'user_namespace']
tests = ['groupspace_001_pos', 'groupspace_002_pos', 'groupspace_003_pos', tests = ['groupspace_001_pos', 'groupspace_002_pos', 'groupspace_003_pos',
'userquota_013_pos', 'userspace_003_pos'] 'userquota_013_pos', 'userspace_003_pos']
tags = ['functional', 'userquota'] tags = ['functional', 'userquota']
[tests/functional/persist_l2arc:Linux]
tests = ['persist_l2arc_001_pos', 'persist_l2arc_002_pos',
'persist_l2arc_003_neg', 'persist_l2arc_004_pos', 'persist_l2arc_005_pos',
'persist_l2arc_006_pos', 'persist_l2arc_007_pos', 'persist_l2arc_008_pos']
tags = ['functional', 'persist_l2arc']

View File

@ -36,6 +36,8 @@ INITIALIZE_CHUNK_SIZE initialize_chunk_size zfs_initialize_chunk_size
INITIALIZE_VALUE initialize_value zfs_initialize_value INITIALIZE_VALUE initialize_value zfs_initialize_value
KEEP_LOG_SPACEMAPS_AT_EXPORT keep_log_spacemaps_at_export zfs_keep_log_spacemaps_at_export KEEP_LOG_SPACEMAPS_AT_EXPORT keep_log_spacemaps_at_export zfs_keep_log_spacemaps_at_export
L2ARC_NOPREFETCH l2arc.noprefetch l2arc_noprefetch L2ARC_NOPREFETCH l2arc.noprefetch l2arc_noprefetch
L2ARC_REBUILD_BLOCKS_MIN_L2SIZE UNSUPPORTED l2arc_rebuild_blocks_min_l2size
L2ARC_REBUILD_ENABLED UNSUPPORTED l2arc_rebuild_enabled
L2ARC_WRITE_BOOST l2arc.write_boost l2arc_write_boost L2ARC_WRITE_BOOST l2arc.write_boost l2arc_write_boost
L2ARC_WRITE_MAX l2arc.write_max l2arc_write_max L2ARC_WRITE_MAX l2arc.write_max l2arc_write_max
LIVELIST_CONDENSE_NEW_ALLOC livelist.condense.new_alloc zfs_livelist_condense_new_alloc LIVELIST_CONDENSE_NEW_ALLOC livelist.condense.new_alloc zfs_livelist_condense_new_alloc

View File

@ -45,6 +45,7 @@ SUBDIRS = \
no_space \ no_space \
nopwrite \ nopwrite \
online_offline \ online_offline \
persist_l2arc \
pool_checkpoint \ pool_checkpoint \
pool_names \ pool_names \
poolversion \ poolversion \

View File

@ -0,0 +1,15 @@
pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/persist_l2arc
dist_pkgdata_SCRIPTS = \
cleanup.ksh \
setup.ksh \
persist_l2arc_001_pos.ksh \
persist_l2arc_002_pos.ksh \
persist_l2arc_003_neg.ksh \
persist_l2arc_004_pos.ksh \
persist_l2arc_005_pos.ksh \
persist_l2arc_006_pos.ksh \
persist_l2arc_007_pos.ksh \
persist_l2arc_008_pos.ksh
dist_pkgdata_DATA = \
persist_l2arc.cfg

View File

@ -0,0 +1,31 @@
#!/bin/ksh -p
#
# CDDL HEADER START
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source. A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#
# CDDL HEADER END
#
#
# Copyright (c) 2020, George Amanakis. All rights reserved.
#
. $STF_SUITE/tests/functional/persist_l2arc/persist_l2arc.cfg
verify_runnable "global"
if datasetexists $TESTPOOL ; then
log_must zpool destroy -f $TESTPOOL
fi
log_must rm -rf $VDIR
log_pass

View File

@ -0,0 +1,37 @@
#!/bin/ksh -p
#
# CDDL HEADER START
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source. A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#
# CDDL HEADER END
#
#
# Copyright (c) 2020, George Amanakis. All rights reserved.
#
. $STF_SUITE/include/libtest.shlib
export SIZE=1G
export VDIR=$TESTDIR/disk.persist_l2arc
export VDEV="$VDIR/a"
export VDEV_CACHE="$VDIR/b"
# fio options
export DIRECTORY=/$TESTPOOL
export NUMJOBS=4
export RUNTIME=30
export PERF_RANDSEED=1234
export PERF_COMPPERCENT=66
export PERF_COMPCHUNK=0
export BLOCKSIZE=128K
export SYNC_TYPE=0
export DIRECT=1

View File

@ -0,0 +1,106 @@
#!/bin/ksh -p
#
# CDDL HEADER START
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source. A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#
# CDDL HEADER END
#
#
# Copyright (c) 2020, George Amanakis. All rights reserved.
#
. $STF_SUITE/include/libtest.shlib
. $STF_SUITE/tests/functional/persist_l2arc/persist_l2arc.cfg
#
# DESCRIPTION:
# Persistent L2ARC with an unencrypted ZFS file system succeeds
#
# STRATEGY:
# 1. Create pool with a cache device.
# 2. Export and re-import pool without writing any data.
# 3. Create a random file in that pool and random read for 30 sec.
# 4. Export pool.
# 5. Read the amount of log blocks written from the header of the
# L2ARC device.
# 6. Import pool.
# 7. Read the amount of log blocks rebuilt in arcstats and compare to
# (4).
# 8. Check if the labels of the L2ARC device are intact.
#
# * We can predict the minimum bytes of L2ARC restored if we subtract
# from the effective size of the cache device the bytes l2arc_evict()
# evicts:
# l2: L2ARC device size - VDEV_LABEL_START_SIZE - l2ad_dev_hdr_asize
# wr_sz: l2arc_write_max + l2arc_write_boost (worst case)
# blk_overhead: wr_sz / SPA_MINBLOCKSIZE / (l2 / SPA_MAXBLOCKSIZE) *
# sizeof (l2arc_log_blk_phys_t)
# min restored size: l2 - (wr_sz + blk_overhead)
#
verify_runnable "global"
log_assert "Persistent L2ARC with an unencrypted ZFS file system succeeds."
function cleanup
{
if poolexists $TESTPOOL ; then
destroy_pool $TESTPOOL
fi
log_must set_tunable32 L2ARC_NOPREFETCH $noprefetch
log_must set_tunable32 L2ARC_REBUILD_BLOCKS_MIN_L2SIZE \
$rebuild_blocks_min_l2size
}
log_onexit cleanup
# L2ARC_NOPREFETCH is set to 0 to let L2ARC handle prefetches
typeset noprefetch=$(get_tunable L2ARC_NOPREFETCH)
typeset rebuild_blocks_min_l2size=$(get_tunable L2ARC_REBUILD_BLOCKS_MIN_L2SIZE)
log_must set_tunable32 L2ARC_NOPREFETCH 0
log_must set_tunable32 L2ARC_REBUILD_BLOCKS_MIN_L2SIZE 0
typeset fill_mb=800
typeset cache_sz=$(( floor($fill_mb / 2) ))
export FILE_SIZE=$(( floor($fill_mb / $NUMJOBS) ))M
log_must truncate -s ${cache_sz}M $VDEV_CACHE
log_must zpool create -f $TESTPOOL $VDEV cache $VDEV_CACHE
log_must zpool export $TESTPOOL
log_must zpool import -d $VDIR $TESTPOOL
log_must fio $FIO_SCRIPTS/mkfiles.fio
log_must fio $FIO_SCRIPTS/random_reads.fio
log_must zpool export $TESTPOOL
typeset l2_dh_log_blk=$(zdb -l $VDEV_CACHE | grep log_blk_count | \
awk '{print $2}')
typeset l2_rebuild_log_blk_start=$(get_arcstat l2_rebuild_log_blks)
log_must zpool import -d $VDIR $TESTPOOL
sleep 2
typeset l2_rebuild_log_blk_end=$(get_arcstat l2_rebuild_log_blks)
log_must test $l2_dh_log_blk -eq $(( $l2_rebuild_log_blk_end - $l2_rebuild_log_blk_start ))
log_must test $l2_dh_log_blk -gt 0
log_must zdb -lq $VDEV_CACHE
log_must zpool destroy -f $TESTPOOL
log_pass "Persistent L2ARC with an unencrypted ZFS file system succeeds."

View File

@ -0,0 +1,112 @@
#!/bin/ksh -p
#
# CDDL HEADER START
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source. A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#
# CDDL HEADER END
#
#
# Copyright (c) 2020, George Amanakis. All rights reserved.
#
. $STF_SUITE/include/libtest.shlib
. $STF_SUITE/tests/functional/persist_l2arc/persist_l2arc.cfg
. $STF_SUITE/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib
#
# DESCRIPTION:
# Persistent L2ARC with an encrypted ZFS file system succeeds
#
# STRATEGY:
# 1. Create pool with a cache device.
# 2. Create a an encrypted ZFS file system.
# 3. Create a random file in the encyrpted file system and random
# read for 30 sec.
# 4. Export pool.
# 5. Read the amount of log blocks written from the header of the
# L2ARC device.
# 5. Import pool.
# 6. Mount the encypted ZFS file system.
# 7. Read the amount of log blocks rebuilt in arcstats and compare to
# (5).
# 8. Check if the labels of the L2ARC device are intact.
#
# * We can predict the minimum bytes of L2ARC restored if we subtract
# from the effective size of the cache device the bytes l2arc_evict()
# evicts:
# l2: L2ARC device size - VDEV_LABEL_START_SIZE - l2ad_dev_hdr_asize
# wr_sz: l2arc_write_max + l2arc_write_boost (worst case)
# blk_overhead: wr_sz / SPA_MINBLOCKSIZE / (l2 / SPA_MAXBLOCKSIZE) *
# sizeof (l2arc_log_blk_phys_t)
# min restored size: l2 - (wr_sz + blk_overhead)
#
verify_runnable "global"
log_assert "Persistent L2ARC with an encrypted ZFS file system succeeds."
function cleanup
{
if poolexists $TESTPOOL ; then
destroy_pool $TESTPOOL
fi
log_must set_tunable32 L2ARC_NOPREFETCH $noprefetch
log_must set_tunable32 L2ARC_REBUILD_BLOCKS_MIN_L2SIZE \
$rebuild_blocks_min_l2size
}
log_onexit cleanup
# L2ARC_NOPREFETCH is set to 0 to let L2ARC handle prefetches
typeset noprefetch=$(get_tunable L2ARC_NOPREFETCH)
typeset rebuild_blocks_min_l2size=$(get_tunable L2ARC_REBUILD_BLOCKS_MIN_L2SIZE)
log_must set_tunable32 L2ARC_NOPREFETCH 0
log_must set_tunable32 L2ARC_REBUILD_BLOCKS_MIN_L2SIZE 0
typeset fill_mb=800
typeset cache_sz=$(( floor($fill_mb / 2) ))
export FILE_SIZE=$(( floor($fill_mb / $NUMJOBS) ))M
log_must truncate -s ${cache_sz}M $VDEV_CACHE
log_must zpool create -f $TESTPOOL $VDEV cache $VDEV_CACHE
log_must eval "echo $PASSPHRASE | zfs create -o encryption=on" \
"-o keyformat=passphrase $TESTPOOL/$TESTFS1"
log_must fio $FIO_SCRIPTS/mkfiles.fio
log_must fio $FIO_SCRIPTS/random_reads.fio
log_must zpool export $TESTPOOL
sleep 2
typeset l2_dh_log_blk=$(zdb -l $VDEV_CACHE | grep log_blk_count | \
awk '{print $2}')
typeset l2_rebuild_log_blk_start=$(get_arcstat l2_rebuild_log_blks)
log_must zpool import -d $VDIR $TESTPOOL
log_must eval "echo $PASSPHRASE | zfs mount -l $TESTPOOL/$TESTFS1"
sleep 2
typeset l2_rebuild_log_blk_end=$(get_arcstat l2_rebuild_log_blks)
log_must test $l2_dh_log_blk -eq $(( $l2_rebuild_log_blk_end - $l2_rebuild_log_blk_start ))
log_must test $l2_dh_log_blk -gt 0
log_must zdb -lq $VDEV_CACHE
log_must zpool destroy -f $TESTPOOL
log_pass "Persistent L2ARC with an encrypted ZFS file system succeeds."

View File

@ -0,0 +1,87 @@
#!/bin/ksh -p
#
# CDDL HEADER START
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source. A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#
# CDDL HEADER END
#
#
# Copyright (c) 2020, George Amanakis. All rights reserved.
#
. $STF_SUITE/include/libtest.shlib
. $STF_SUITE/tests/functional/persist_l2arc/persist_l2arc.cfg
#
# DESCRIPTION:
# Persistent L2ARC fails as expected when L2ARC_REBUILD_ENABLED = 0
#
# STRATEGY:
# 1. Set L2ARC_REBUILD_ENABLED = 0
# 2. Create pool with a cache device.
# 3. Create a random file in that pool and random read for 30 sec.
# 4. Export pool.
# 5. Import pool.
# 6. Check in zpool iostat if the cache device has space allocated.
# 7. Read the file written in (2) and check if l2_hits in
# /proc/spl/kstat/zfs/arcstats increased.
#
verify_runnable "global"
log_assert "Persistent L2ARC fails as expected when L2ARC_REBUILD_ENABLED = 0."
function cleanup
{
if poolexists $TESTPOOL ; then
destroy_pool $TESTPOOL
fi
log_must set_tunable32 L2ARC_REBUILD_ENABLED $rebuild_enabled
log_must set_tunable32 L2ARC_NOPREFETCH $noprefetch
}
log_onexit cleanup
# L2ARC_NOPREFETCH is set to 0 to let L2ARC handle prefetches
typeset noprefetch=$(get_tunable L2ARC_NOPREFETCH)
log_must set_tunable32 L2ARC_NOPREFETCH 0
# disable L2ARC rebuild
typeset rebuild_enabled=$(get_tunable L2ARC_REBUILD_ENABLED)
log_must set_tunable32 L2ARC_REBUILD_ENABLED 0
typeset fill_mb=800
typeset cache_sz=$(( 2 * $fill_mb ))
export FILE_SIZE=$(( floor($fill_mb / $NUMJOBS) ))M
log_must truncate -s ${cache_sz}M $VDEV_CACHE
log_must zpool create -f $TESTPOOL $VDEV cache $VDEV_CACHE
log_must fio $FIO_SCRIPTS/mkfiles.fio
log_must fio $FIO_SCRIPTS/random_reads.fio
log_must zpool export $TESTPOOL
typeset l2_success_start=$(get_arcstat l2_rebuild_success)
log_must zpool import -d $VDIR $TESTPOOL
log_mustnot test "$(zpool iostat -Hpv $TESTPOOL $VDEV_CACHE | awk '{print $2}')" -gt 80000000
typeset l2_success_end=$(get_arcstat l2_rebuild_success)
log_mustnot test $l2_success_end -gt $l2_success_start
log_must zpool destroy -f $TESTPOOL
log_must set_tunable32 L2ARC_REBUILD_ENABLED $rebuild_enabled
log_pass "Persistent L2ARC fails as expected when L2ARC_REBUILD_ENABLED = 0."

View File

@ -0,0 +1,101 @@
#!/bin/ksh -p
#
# CDDL HEADER START
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source. A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#
# CDDL HEADER END
#
#
# Copyright (c) 2020, George Amanakis. All rights reserved.
#
. $STF_SUITE/include/libtest.shlib
. $STF_SUITE/tests/functional/persist_l2arc/persist_l2arc.cfg
#
# DESCRIPTION:
# Persistent L2ARC restores all written log blocks
#
# STRATEGY:
# 1. Create pool with a cache device.
# 2. Create a random file in that pool, smaller than the cache device
# and random read for 30 sec.
# 3. Export pool.
# 4. Read amount of log blocks written.
# 5. Import pool.
# 6. Read amount of log blocks built.
# 7. Compare the two amounts
# 8. Read the file written in (2) and check if l2_hits in
# /proc/spl/kstat/zfs/arcstats increased.
# 9. Check if the labels of the L2ARC device are intact.
#
verify_runnable "global"
log_assert "Persistent L2ARC restores all written log blocks."
function cleanup
{
if poolexists $TESTPOOL ; then
destroy_pool $TESTPOOL
fi
log_must set_tunable32 L2ARC_NOPREFETCH $noprefetch
}
log_onexit cleanup
# L2ARC_NOPREFETCH is set to 0 to let L2ARC handle prefetches
typeset noprefetch=$(get_tunable L2ARC_NOPREFETCH)
log_must set_tunable32 L2ARC_NOPREFETCH 0
typeset fill_mb=800
typeset cache_sz=$(( 2 * $fill_mb ))
export FILE_SIZE=$(( floor($fill_mb / $NUMJOBS) ))M
log_must truncate -s ${cache_sz}M $VDEV_CACHE
typeset log_blk_start=$(get_arcstat l2_log_blk_writes)
log_must zpool create -f $TESTPOOL $VDEV cache $VDEV_CACHE
log_must fio $FIO_SCRIPTS/mkfiles.fio
log_must fio $FIO_SCRIPTS/random_reads.fio
log_must zpool export $TESTPOOL
sleep 2
typeset log_blk_end=$(get_arcstat l2_log_blk_writes)
typeset log_blk_rebuild_start=$(get_arcstat l2_rebuild_log_blks)
log_must zpool import -d $VDIR $TESTPOOL
typeset l2_hits_start=$(get_arcstat l2_hits)
export RUNTIME=10
log_must fio $FIO_SCRIPTS/random_reads.fio
typeset l2_hits_end=$(get_arcstat l2_hits)
typeset log_blk_rebuild_end=$(get_arcstat l2_rebuild_log_blks)
log_must test $(( $log_blk_rebuild_end - $log_blk_rebuild_start )) -eq \
$(( $log_blk_end - $log_blk_start ))
log_must test $l2_hits_end -gt $l2_hits_start
log_must zdb -lq $VDEV_CACHE
log_must zpool destroy -f $TESTPOOL
log_pass "Persistent L2ARC restores all written log blocks."

View File

@ -0,0 +1,108 @@
#!/bin/ksh -p
#
# CDDL HEADER START
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source. A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#
# CDDL HEADER END
#
#
# Copyright (c) 2020, George Amanakis. All rights reserved.
#
. $STF_SUITE/include/libtest.shlib
. $STF_SUITE/tests/functional/persist_l2arc/persist_l2arc.cfg
. $STF_SUITE/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib
#
# DESCRIPTION:
# Persistent L2ARC restores all written log blocks with encryption
#
# STRATEGY:
# 1. Create pool with a cache device.
# 2. Create a an encrypted ZFS file system.
# 3. Create a random file in the entrypted file system,
# smaller than the cache device, and random read for 30 sec.
# 4. Export pool.
# 5. Read amount of log blocks written.
# 6. Import pool.
# 7. Mount the encypted ZFS file system.
# 8. Read amount of log blocks built.
# 9. Compare the two amounts
# 10. Read the file written in (3) and check if l2_hits in
# /proc/spl/kstat/zfs/arcstats increased.
# 11. Check if the labels of the L2ARC device are intact.
#
verify_runnable "global"
log_assert "Persistent L2ARC restores all written log blocks with encryption."
function cleanup
{
if poolexists $TESTPOOL ; then
destroy_pool $TESTPOOL
fi
log_must set_tunable32 L2ARC_NOPREFETCH $noprefetch
}
log_onexit cleanup
# L2ARC_NOPREFETCH is set to 0 to let L2ARC handle prefetches
typeset noprefetch=$(get_tunable L2ARC_NOPREFETCH)
log_must set_tunable32 L2ARC_NOPREFETCH 0
typeset fill_mb=800
typeset cache_sz=$(( 2 * $fill_mb ))
export FILE_SIZE=$(( floor($fill_mb / $NUMJOBS) ))M
log_must truncate -s ${cache_sz}M $VDEV_CACHE
typeset log_blk_start=$(get_arcstat l2_log_blk_writes)
log_must zpool create -f $TESTPOOL $VDEV cache $VDEV_CACHE
log_must eval "echo $PASSPHRASE | zfs create -o encryption=on" \
"-o keyformat=passphrase $TESTPOOL/$TESTFS1"
log_must fio $FIO_SCRIPTS/mkfiles.fio
log_must fio $FIO_SCRIPTS/random_reads.fio
log_must zpool export $TESTPOOL
sleep 2
typeset log_blk_end=$(get_arcstat l2_log_blk_writes)
typeset log_blk_rebuild_start=$(get_arcstat l2_rebuild_log_blks)
log_must zpool import -d $VDIR $TESTPOOL
log_must eval "echo $PASSPHRASE | zfs mount -l $TESTPOOL/$TESTFS1"
typeset l2_hits_start=$(get_arcstat l2_hits)
export RUNTIME=10
log_must fio $FIO_SCRIPTS/random_reads.fio
typeset l2_hits_end=$(get_arcstat l2_hits)
typeset log_blk_rebuild_end=$(get_arcstat l2_rebuild_log_blks)
log_must test $(( $log_blk_rebuild_end - $log_blk_rebuild_start )) -eq \
$(( $log_blk_end - $log_blk_start ))
log_must test $l2_hits_end -gt $l2_hits_start
log_must zdb -lq $VDEV_CACHE
log_must zpool destroy -f $TESTPOOL
log_pass "Persistent L2ARC restores all written log blocks with encryption."

View File

@ -0,0 +1,98 @@
#!/bin/ksh -p
#
# CDDL HEADER START
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source. A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#
# CDDL HEADER END
#
#
# Copyright (c) 2020, George Amanakis. All rights reserved.
#
. $STF_SUITE/include/libtest.shlib
. $STF_SUITE/tests/functional/persist_l2arc/persist_l2arc.cfg
#
# DESCRIPTION:
# Off/onlining an L2ARC device results in rebuilding L2ARC, vdev not
# present.
#
# STRATEGY:
# 1. Create pool with a cache device.
# 2. Create a random file in that pool and random read for 30 sec.
# 3. Read the amount of log blocks written from the header of the
# L2ARC device.
# 4. Offline the L2ARC device and export pool.
# 5. Import pool and online the L2ARC device.
# 6. Read the amount of log blocks rebuilt in arcstats and compare to
# (3).
# 7. Check if the labels of the L2ARC device are intact.
#
verify_runnable "global"
log_assert "Off/onlining an L2ARC device results in rebuilding L2ARC, vdev not present."
function cleanup
{
if poolexists $TESTPOOL ; then
destroy_pool $TESTPOOL
fi
log_must set_tunable32 L2ARC_NOPREFETCH $noprefetch
log_must set_tunable32 L2ARC_REBUILD_BLOCKS_MIN_L2SIZE \
$rebuild_blocks_min_l2size
}
log_onexit cleanup
# L2ARC_NOPREFETCH is set to 0 to let L2ARC handle prefetches
typeset noprefetch=$(get_tunable L2ARC_NOPREFETCH)
typeset rebuild_blocks_min_l2size=$(get_tunable L2ARC_REBUILD_BLOCKS_MIN_L2SIZE)
log_must set_tunable32 L2ARC_NOPREFETCH 0
log_must set_tunable32 L2ARC_REBUILD_BLOCKS_MIN_L2SIZE 0
typeset fill_mb=800
typeset cache_sz=$(( floor($fill_mb / 2) ))
export FILE_SIZE=$(( floor($fill_mb / $NUMJOBS) ))M
log_must truncate -s ${cache_sz}M $VDEV_CACHE
log_must zpool create -f $TESTPOOL $VDEV cache $VDEV_CACHE
log_must fio $FIO_SCRIPTS/mkfiles.fio
log_must fio $FIO_SCRIPTS/random_reads.fio
log_must zpool offline $TESTPOOL $VDEV_CACHE
log_must zpool export $TESTPOOL
sleep 5
typeset l2_rebuild_log_blk_start=$(get_arcstat l2_rebuild_log_blks)
typeset l2_dh_log_blk=$(zdb -l $VDEV_CACHE | grep log_blk_count | \
awk '{print $2}')
log_must zpool import -d $VDIR $TESTPOOL
log_must zpool online $TESTPOOL $VDEV_CACHE
sleep 5
typeset l2_rebuild_log_blk_end=$(get_arcstat l2_rebuild_log_blks)
log_must test $l2_dh_log_blk -eq $(( $l2_rebuild_log_blk_end - $l2_rebuild_log_blk_start ))
log_must test $l2_dh_log_blk -gt 0
log_must zdb -lq $VDEV_CACHE
log_must zpool destroy -f $TESTPOOL
log_pass "Off/onlining an L2ARC device results in rebuilding L2ARC, vdev not present."

View File

@ -0,0 +1,95 @@
#!/bin/ksh -p
#
# CDDL HEADER START
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source. A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#
# CDDL HEADER END
#
#
# Copyright (c) 2020, George Amanakis. All rights reserved.
#
. $STF_SUITE/include/libtest.shlib
. $STF_SUITE/tests/functional/persist_l2arc/persist_l2arc.cfg
#
# DESCRIPTION:
# Off/onlining an L2ARC device results in rebuilding L2ARC, vdev present.
#
# STRATEGY:
# 1. Create pool with a cache device.
# 2. Create a random file in that pool and random read for 30 sec.
# 3. Read the amount of log blocks written from the header of the
# L2ARC device.
# 4. Offline the L2ARC device.
# 5. Online the L2ARC device.
# 6. Read the amount of log blocks rebuilt in arcstats and compare to
# (3).
# 7. Check if the labels of the L2ARC device are intact.
#
verify_runnable "global"
log_assert "Off/onlining an L2ARC device results in rebuilding L2ARC, vdev present."
function cleanup
{
if poolexists $TESTPOOL ; then
destroy_pool $TESTPOOL
fi
log_must set_tunable32 L2ARC_NOPREFETCH $noprefetch
log_must set_tunable32 L2ARC_REBUILD_BLOCKS_MIN_L2SIZE \
$rebuild_blocks_min_l2size
}
log_onexit cleanup
# L2ARC_NOPREFETCH is set to 0 to let L2ARC handle prefetches
typeset noprefetch=$(get_tunable L2ARC_NOPREFETCH)
typeset rebuild_blocks_min_l2size=$(get_tunable L2ARC_REBUILD_BLOCKS_MIN_L2SIZE)
log_must set_tunable32 L2ARC_NOPREFETCH 0
log_must set_tunable32 L2ARC_REBUILD_BLOCKS_MIN_L2SIZE 0
typeset fill_mb=800
typeset cache_sz=$(( floor($fill_mb / 2) ))
export FILE_SIZE=$(( floor($fill_mb / $NUMJOBS) ))M
log_must truncate -s ${cache_sz}M $VDEV_CACHE
log_must zpool create -f $TESTPOOL $VDEV cache $VDEV_CACHE
log_must fio $FIO_SCRIPTS/mkfiles.fio
log_must fio $FIO_SCRIPTS/random_reads.fio
log_must zpool offline $TESTPOOL $VDEV_CACHE
sleep 5
typeset l2_rebuild_log_blk_start=$(get_arcstat l2_rebuild_log_blks)
typeset l2_dh_log_blk=$(zdb -l $VDEV_CACHE | grep log_blk_count | \
awk '{print $2}')
log_must zpool online $TESTPOOL $VDEV_CACHE
sleep 5
typeset l2_rebuild_log_blk_end=$(get_arcstat l2_rebuild_log_blks)
log_must test $l2_dh_log_blk -eq $(( $l2_rebuild_log_blk_end - $l2_rebuild_log_blk_start ))
log_must test $l2_dh_log_blk -gt 0
log_must zdb -lq $VDEV_CACHE
log_must zpool destroy -f $TESTPOOL
log_pass "Off/onlining an L2ARC device results in rebuilding L2ARC, vdev present."

View File

@ -0,0 +1,143 @@
#!/bin/ksh -p
#
# CDDL HEADER START
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source. A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#
# CDDL HEADER END
#
#
# Copyright (c) 2020, George Amanakis. All rights reserved.
#
. $STF_SUITE/include/libtest.shlib
. $STF_SUITE/tests/functional/persist_l2arc/persist_l2arc.cfg
#
# DESCRIPTION:
# Off/onlining an L2ARC device restores all written blocks, vdev present.
#
# STRATEGY:
# 1. Create pool with a cache device.
# 2. Create a random file in that pool and random read for 30 sec.
# 3. Read the amount of log blocks written from the header of the
# L2ARC device.
# 4. Offline the L2ARC device.
# 5. Online the L2ARC device.
# 6. Read the amount of log blocks rebuilt in arcstats and compare to
# (3).
# 7. Create another random file in that pool and random read for 30 sec.
# 8. Read the amount of log blocks written from the header of the
# L2ARC device.
# 9. Offline the L2ARC device.
# 10. Online the L2ARC device.
# 11. Read the amount of log blocks rebuilt in arcstats and compare to
# (7).
# 12. Check if the amount of log blocks on the cache device has
# increased.
# 13. Export the pool.
# 14. Read the amount of log blocks on the cache device.
# 15. Import the pool.
# 16. Read the amount of log blocks rebuilt in arcstats and compare to
# (14).
# 17. Check if the labels of the L2ARC device are intact.
#
verify_runnable "global"
log_assert "Off/onlining an L2ARC device restores all written blocks , vdev present."
function cleanup
{
if poolexists $TESTPOOL ; then
destroy_pool $TESTPOOL
fi
log_must set_tunable32 L2ARC_NOPREFETCH $noprefetch
}
log_onexit cleanup
# L2ARC_NOPREFETCH is set to 0 to let L2ARC handle prefetches
typeset noprefetch=$(get_tunable L2ARC_NOPREFETCH)
log_must set_tunable32 L2ARC_NOPREFETCH 0
typeset fill_mb=400
typeset cache_sz=$(( 3 * $fill_mb ))
export FILE_SIZE=$(( floor($fill_mb / $NUMJOBS) ))M
log_must truncate -s ${cache_sz}M $VDEV_CACHE
log_must zpool create -f $TESTPOOL $VDEV cache $VDEV_CACHE
log_must fio $FIO_SCRIPTS/mkfiles.fio
log_must fio $FIO_SCRIPTS/random_reads.fio
log_must zpool offline $TESTPOOL $VDEV_CACHE
sleep 2
typeset l2_dh_log_blk1=$(zdb -l $VDEV_CACHE | grep log_blk_count | \
awk '{print $2}')
typeset l2_rebuild_log_blk_start=$(get_arcstat l2_rebuild_log_blks)
log_must zpool online $TESTPOOL $VDEV_CACHE
sleep 5
typeset l2_rebuild_log_blk_end=$(get_arcstat l2_rebuild_log_blks)
log_must test $l2_dh_log_blk1 -eq $(( $l2_rebuild_log_blk_end - $l2_rebuild_log_blk_start ))
log_must test $l2_dh_log_blk1 -gt 0
log_must fio $FIO_SCRIPTS/mkfiles.fio
log_must fio $FIO_SCRIPTS/random_reads.fio
log_must zpool offline $TESTPOOL $VDEV_CACHE
sleep 2
typeset l2_dh_log_blk2=$(zdb -l $VDEV_CACHE | grep log_blk_count | \
awk '{print $2}')
typeset l2_rebuild_log_blk_start=$(get_arcstat l2_rebuild_log_blks)
log_must zpool online $TESTPOOL $VDEV_CACHE
sleep 5
typeset l2_rebuild_log_blk_end=$(get_arcstat l2_rebuild_log_blks)
log_must test $l2_dh_log_blk2 -eq $(( $l2_rebuild_log_blk_end - $l2_rebuild_log_blk_start ))
log_must test $l2_dh_log_blk2 -gt $l2_dh_log_blk1
log_must zpool export $TESTPOOL
typeset l2_dh_log_blk3=$(zdb -l $VDEV_CACHE | grep log_blk_count | \
awk '{print $2}')
typeset l2_rebuild_log_blk_start=$(get_arcstat l2_rebuild_log_blks)
log_must zpool import -d $VDIR $TESTPOOL
sleep 5
typeset l2_rebuild_log_blk_end=$(get_arcstat l2_rebuild_log_blks)
log_must test $l2_dh_log_blk3 -eq $(( $l2_rebuild_log_blk_end - $l2_rebuild_log_blk_start ))
log_must test $l2_dh_log_blk3 -gt 0
log_must zdb -lq $VDEV_CACHE
log_must zpool destroy -f $TESTPOOL
log_pass "Off/onlining an L2ARC device restores all written blocks, vdev present."

View File

@ -0,0 +1,29 @@
#!/bin/ksh -p
#
# CDDL HEADER START
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source. A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#
# CDDL HEADER END
#
#
# Copyright (c) 2020, George Amanakis. All rights reserved.
#
. $STF_SUITE/tests/functional/persist_l2arc/persist_l2arc.cfg
verify_runnable "global"
log_must rm -rf $VDIR
log_must mkdir -p $VDIR
log_must mkfile $SIZE $VDEV
log_pass