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:
parent
36a6e2335c
commit
77f6826b83
229
cmd/zdb/zdb.c
229
cmd/zdb/zdb.c
|
@ -62,6 +62,7 @@
|
|||
#include <sys/zio_compress.h>
|
||||
#include <sys/zfs_fuid.h>
|
||||
#include <sys/arc.h>
|
||||
#include <sys/arc_impl.h>
|
||||
#include <sys/ddt.h>
|
||||
#include <sys/zfeature.h>
|
||||
#include <sys/abd.h>
|
||||
|
@ -3474,6 +3475,216 @@ print_label_header(zdb_label_t *label, int l)
|
|||
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
|
||||
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];
|
||||
zdb_label_t labels[VDEV_LABELS];
|
||||
uint64_t psize, ashift;
|
||||
uint64_t psize, ashift, l2cache;
|
||||
struct stat64 statbuf;
|
||||
boolean_t config_found = B_FALSE;
|
||||
boolean_t error = B_FALSE;
|
||||
boolean_t read_l2arc_header = B_FALSE;
|
||||
avl_tree_t config_tree;
|
||||
avl_tree_t uberblock_tree;
|
||||
void *node, *cookie;
|
||||
|
@ -3735,6 +3947,15 @@ dump_label(const char *dev)
|
|||
if (nvlist_size(config, &size, NV_ENCODE_XDR) != 0)
|
||||
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);
|
||||
rec = cksum_record_insert(&config_tree, &cksum, l);
|
||||
|
||||
|
@ -3785,6 +4006,12 @@ dump_label(const char *dev)
|
|||
nvlist_free(label->config_nv);
|
||||
}
|
||||
|
||||
/*
|
||||
* Dump the L2ARC header, if existent.
|
||||
*/
|
||||
if (read_l2arc_header)
|
||||
dump_l2arc_header(fd);
|
||||
|
||||
cookie = NULL;
|
||||
while ((node = avl_destroy_nodes(&config_tree, &cookie)) != NULL)
|
||||
umem_free(node, sizeof (cksum_record_t));
|
||||
|
|
|
@ -336,6 +336,7 @@ AC_CONFIG_FILES([
|
|||
tests/zfs-tests/tests/functional/no_space/Makefile
|
||||
tests/zfs-tests/tests/functional/nopwrite/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_names/Makefile
|
||||
tests/zfs-tests/tests/functional/poolversion/Makefile
|
||||
|
|
|
@ -310,10 +310,14 @@ void arc_fini(void);
|
|||
void l2arc_add_vdev(spa_t *spa, vdev_t *vd);
|
||||
void l2arc_remove_vdev(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_fini(void);
|
||||
void l2arc_start(void);
|
||||
void l2arc_stop(void);
|
||||
void l2arc_spa_rebuild_start(spa_t *spa);
|
||||
|
||||
#ifndef _KERNEL
|
||||
extern boolean_t arc_watch;
|
||||
|
|
|
@ -20,9 +20,10 @@
|
|||
*/
|
||||
/*
|
||||
* 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.
|
||||
* Copyright 2013 Nexenta Systems, Inc. All rights reserved.
|
||||
* Copyright (c) 2013, Delphix. All rights reserved.
|
||||
* Copyright (c) 2013, Saso Kiselkov. 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
|
||||
|
@ -176,6 +177,218 @@ typedef struct l1arc_buf_hdr {
|
|||
abd_t *b_pabd;
|
||||
} 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
|
||||
* 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];
|
||||
} 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 {
|
||||
/* protected by arc_buf_hdr mutex */
|
||||
l2arc_dev_t *b_dev; /* L2ARC device */
|
||||
uint64_t b_daddr; /* disk address, offset byte */
|
||||
uint32_t b_hits;
|
||||
|
||||
list_node_t b_l2node;
|
||||
} l2arc_buf_hdr_t;
|
||||
|
||||
typedef struct l2arc_write_callback {
|
||||
l2arc_dev_t *l2wcb_dev; /* device info */
|
||||
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;
|
||||
|
||||
struct arc_buf_hdr {
|
||||
|
@ -532,6 +732,71 @@ typedef struct arc_stats {
|
|||
kstat_named_t arcstat_l2_psize;
|
||||
/* Not updated directly; only synced in arc_kstat_update. */
|
||||
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_direct_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_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
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -573,6 +573,11 @@ typedef enum zfs_key_location {
|
|||
#define ZPL_VERSION_USERSPACE ZPL_VERSION_4
|
||||
#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 */
|
||||
#define ZPOOL_NO_REWIND 1 /* No policy - default behavior */
|
||||
#define ZPOOL_NEVER_REWIND 2 /* Do not search for best txg or rewind */
|
||||
|
|
|
@ -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_TRIM_RESTART 0x200
|
||||
#define SPA_ASYNC_AUTOTRIM_RESTART 0x400
|
||||
#define SPA_ASYNC_L2CACHE_REBUILD 0x800
|
||||
|
||||
/*
|
||||
* Controls the behavior of spa_vdev_remove().
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include <libzfs.h>
|
||||
#include <libzfs_impl.h>
|
||||
#include <libzutil.h>
|
||||
#include <sys/arc_impl.h>
|
||||
|
||||
/*
|
||||
* Returns true if the named pool matches the given GUID.
|
||||
|
@ -146,8 +147,10 @@ zpool_clear_label(int fd)
|
|||
struct stat64 statbuf;
|
||||
int l;
|
||||
vdev_label_t *label;
|
||||
l2arc_dev_hdr_phys_t *l2dhdr;
|
||||
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)
|
||||
return (0);
|
||||
|
@ -157,8 +160,13 @@ zpool_clear_label(int fd)
|
|||
if ((label = calloc(1, sizeof (vdev_label_t))) == NULL)
|
||||
return (-1);
|
||||
|
||||
if ((l2dhdr = calloc(1, sizeof (l2arc_dev_hdr_phys_t))) == NULL) {
|
||||
free(label);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
for (l = 0; l < VDEV_LABELS; l++) {
|
||||
uint64_t state, guid;
|
||||
uint64_t state, guid, l2cache;
|
||||
nvlist_t *config;
|
||||
|
||||
if (pread64(fd, label, sizeof (vdev_label_t),
|
||||
|
@ -185,6 +193,15 @@ zpool_clear_label(int fd)
|
|||
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);
|
||||
|
||||
/*
|
||||
|
@ -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(l2dhdr);
|
||||
|
||||
if (labels_cleared == 0)
|
||||
return (-1);
|
||||
|
|
|
@ -87,7 +87,7 @@ Default value: \fB10\fR%.
|
|||
.ad
|
||||
.RS 12n
|
||||
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
|
||||
Default value: \fB5\fR.
|
||||
.RE
|
||||
|
@ -99,7 +99,7 @@ Default value: \fB5\fR.
|
|||
.ad
|
||||
.RS 12n
|
||||
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
|
||||
Default value: \fB6\fR.
|
||||
.RE
|
||||
|
@ -179,7 +179,10 @@ Default value: \fB1\fR.
|
|||
.ad
|
||||
.RS 12n
|
||||
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
|
||||
Default value: \fB2\fR.
|
||||
.RE
|
||||
|
@ -203,7 +206,7 @@ Default value: \fB200\fR%.
|
|||
.ad
|
||||
.RS 12n
|
||||
Do not write buffers to L2ARC if they were prefetched but not used by
|
||||
applications
|
||||
applications.
|
||||
.sp
|
||||
Use \fB1\fR for yes (default) and \fB0\fR to disable.
|
||||
.RE
|
||||
|
@ -214,7 +217,7 @@ Use \fB1\fR for yes (default) and \fB0\fR to disable.
|
|||
\fBl2arc_norw\fR (int)
|
||||
.ad
|
||||
.RS 12n
|
||||
No reads during writes
|
||||
No reads during writes.
|
||||
.sp
|
||||
Use \fB1\fR for yes and \fB0\fR for no (default).
|
||||
.RE
|
||||
|
@ -237,11 +240,41 @@ Default value: \fB8,388,608\fR.
|
|||
\fBl2arc_write_max\fR (ulong)
|
||||
.ad
|
||||
.RS 12n
|
||||
Max write bytes per interval
|
||||
Max write bytes per interval.
|
||||
.sp
|
||||
Default value: \fB8,388,608\fR.
|
||||
.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
|
||||
.ne 2
|
||||
.na
|
||||
|
@ -614,7 +647,7 @@ Default value: \fB1\fR.
|
|||
.ad
|
||||
.RS 12n
|
||||
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
|
||||
Default value: \fB4\fR.
|
||||
.RE
|
||||
|
@ -963,7 +996,7 @@ Default value: \fB1\fR.
|
|||
\fBzfs_arc_min\fR (ulong)
|
||||
.ad
|
||||
.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.
|
||||
.sp
|
||||
Default value: \fB0\fR.
|
||||
|
@ -1088,7 +1121,7 @@ Default value: \fB0\fR.
|
|||
Percent of pagecache to reclaim arc to
|
||||
|
||||
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
|
||||
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
|
||||
|
|
|
@ -212,18 +212,24 @@ If specified multiple times, display counts of each intent log transaction type.
|
|||
Examine the checkpointed state of the pool.
|
||||
Note, the on disk format of the pool is not reverted to the checkpointed state.
|
||||
.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
|
||||
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
|
||||
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
|
||||
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
|
||||
If the
|
||||
.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
|
||||
If the
|
||||
.Fl u
|
||||
|
|
|
@ -48,7 +48,10 @@
|
|||
.Xc
|
||||
Removes ZFS label information from the specified
|
||||
.Ar device .
|
||||
The
|
||||
If the
|
||||
.Ar device
|
||||
is a cache device, it also removes the L2ARC header
|
||||
(persistent L2ARC). The
|
||||
.Ar device
|
||||
must not be part of an active pool configuration.
|
||||
.Bl -tag -width Ds
|
||||
|
|
|
@ -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
|
||||
configuration.
|
||||
.Pp
|
||||
The content of the cache devices is considered volatile, as is the case with
|
||||
other system caches.
|
||||
The content of the cache devices is persistent across reboots and restored
|
||||
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
|
||||
Before starting critical procedures that include destructive actions (e.g
|
||||
.Nm zfs Cm destroy
|
||||
|
|
|
@ -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
|
||||
* 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.
|
||||
*/
|
||||
static const char *zfs_kernel_features[] = {
|
||||
/* --> Add new kernel features here */
|
||||
"com.delphix:vdev_initialize",
|
||||
"org.zfsonlinux:vdev_trim",
|
||||
"org.openzfs:l2arc_persistent",
|
||||
};
|
||||
|
||||
#define KERNEL_FEATURE_COUNT ARRAY_SIZE(zfs_kernel_features)
|
||||
|
|
1400
module/zfs/arc.c
1400
module/zfs/arc.c
File diff suppressed because it is too large
Load Diff
|
@ -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_async_request(spa, SPA_ASYNC_L2CACHE_REBUILD);
|
||||
|
||||
spa_load_note(spa, "LOADED");
|
||||
|
||||
return (0);
|
||||
|
@ -7985,6 +7987,17 @@ spa_async_thread(void *arg)
|
|||
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.
|
||||
*/
|
||||
|
|
|
@ -2279,9 +2279,22 @@ vdev_reopen(vdev_t *vd)
|
|||
if (vd->vdev_aux) {
|
||||
(void) vdev_validate_aux(vd);
|
||||
if (vdev_readable(vd) && vdev_writeable(vd) &&
|
||||
vd->vdev_aux == &spa->spa_l2cache &&
|
||||
!l2arc_vdev_present(vd))
|
||||
vd->vdev_aux == &spa->spa_l2cache) {
|
||||
/*
|
||||
* 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 {
|
||||
(void) vdev_validate(vd);
|
||||
}
|
||||
|
|
|
@ -164,3 +164,9 @@ tags = ['functional', 'user_namespace']
|
|||
tests = ['groupspace_001_pos', 'groupspace_002_pos', 'groupspace_003_pos',
|
||||
'userquota_013_pos', 'userspace_003_pos']
|
||||
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']
|
||||
|
|
|
@ -36,6 +36,8 @@ INITIALIZE_CHUNK_SIZE initialize_chunk_size zfs_initialize_chunk_size
|
|||
INITIALIZE_VALUE initialize_value zfs_initialize_value
|
||||
KEEP_LOG_SPACEMAPS_AT_EXPORT keep_log_spacemaps_at_export zfs_keep_log_spacemaps_at_export
|
||||
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_MAX l2arc.write_max l2arc_write_max
|
||||
LIVELIST_CONDENSE_NEW_ALLOC livelist.condense.new_alloc zfs_livelist_condense_new_alloc
|
||||
|
|
|
@ -45,6 +45,7 @@ SUBDIRS = \
|
|||
no_space \
|
||||
nopwrite \
|
||||
online_offline \
|
||||
persist_l2arc \
|
||||
pool_checkpoint \
|
||||
pool_names \
|
||||
poolversion \
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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."
|
|
@ -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."
|
|
@ -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."
|
|
@ -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."
|
|
@ -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."
|
|
@ -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."
|
|
@ -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."
|
|
@ -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."
|
|
@ -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
|
Loading…
Reference in New Issue