summaryrefslogtreecommitdiffstats
path: root/lib/libzfs
diff options
context:
space:
mode:
authorGeorge Amanakis <[email protected]>2020-04-10 13:33:35 -0400
committerGitHub <[email protected]>2020-04-10 10:33:35 -0700
commit77f6826b83b7e27f0996f6d192202c36f65e41fd (patch)
treeb9946c99348bf6742cc41739aeff1a2b952d9d2f /lib/libzfs
parent36a6e2335c45212f2609269bcee3004908ac6bcb (diff)
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 <[email protected]> Reviewed-by: George Wilson <[email protected]> Reviewed-by: Ryan Moeller <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Co-authored-by: Saso Kiselkov <[email protected]> Co-authored-by: Jorgen Lundman <[email protected]> Co-authored-by: George Amanakis <[email protected]> Ported-by: Yuxuan Shui <[email protected]> Signed-off-by: George Amanakis <[email protected]> Closes #925 Closes #1823 Closes #2672 Closes #3744 Closes #9582
Diffstat (limited to 'lib/libzfs')
-rw-r--r--lib/libzfs/libzfs_import.c31
1 files changed, 29 insertions, 2 deletions
diff --git a/lib/libzfs/libzfs_import.c b/lib/libzfs/libzfs_import.c
index 88c4c645b..6c5f61836 100644
--- a/lib/libzfs/libzfs_import.c
+++ b/lib/libzfs/libzfs_import.c
@@ -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);