6774931dfa
Livelists and spacemaps are data structures that are logs of allocations and frees. Livelists entries are block pointers (blkptr_t). Spacemaps entries are ranges of numbers, most often used as to track allocated/freed regions of metaslabs/vdevs. These data structures can become self-inconsistent, for example if a block or range can be "double allocated" (two allocation records without an intervening free) or "double freed" (two free records without an intervening allocation). ZDB (as well as zfs running in the kernel) can detect these inconsistencies when loading livelists and metaslab. However, it generally halts processing when the error is detected. When analyzing an on-disk problem, we often want to know the entire set of inconsistencies, which is not possible with the current behavior. This commit adds a new flag, `zdb -y`, which analyzes the livelist and metaslab data structures and displays all of their inconsistencies. Note that this is different from the leak detection performed by `zdb -b`, which checks for inconsistencies between the spacemaps and the tree of block pointers, but assumes the spacemaps are self-consistent. The specific checks added are: Verify livelists by iterating through each sublivelists and: - report leftover FREEs - report double ALLOCs and double FREEs - record leftover ALLOCs together with their TXG [see Cross Check] Verify spacemaps by iterating over each metaslab and: - iterate over spacemap and then the metaslab's entries in the spacemap log, then report any double FREEs and double ALLOCs Verify that livelists are consistenet with spacemaps. The space referenced by livelists (after using the FREE's to cancel out corresponding ALLOCs) should be allocated, according to the spacemaps. Reviewed-by: Serapheim Dimitropoulos <serapheim@delphix.com> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Co-authored-by: Sara Hartse <sara.hartse@delphix.com> Signed-off-by: Matthew Ahrens <mahrens@delphix.com> External-issue: DLPX-66031 Closes #10515
148 lines
5.5 KiB
C
148 lines
5.5 KiB
C
/*
|
|
* CDDL HEADER START
|
|
*
|
|
* The contents of this file are subject to the terms of the
|
|
* Common Development and Distribution License (the "License").
|
|
* You may not use this file except in compliance with the License.
|
|
*
|
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
|
* or http://www.opensolaris.org/os/licensing.
|
|
* See the License for the specific language governing permissions
|
|
* and limitations under the License.
|
|
*
|
|
* When distributing Covered Code, include this CDDL HEADER in each
|
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
|
* If applicable, add the following below this CDDL HEADER, with the
|
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
|
*
|
|
* CDDL HEADER END
|
|
*/
|
|
/*
|
|
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
|
* Copyright (c) 2011, 2018 by Delphix. All rights reserved.
|
|
* Copyright (c) 2017, Intel Corporation.
|
|
*/
|
|
|
|
#ifndef _SYS_METASLAB_H
|
|
#define _SYS_METASLAB_H
|
|
|
|
#include <sys/spa.h>
|
|
#include <sys/space_map.h>
|
|
#include <sys/txg.h>
|
|
#include <sys/zio.h>
|
|
#include <sys/avl.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
|
|
typedef struct metaslab_ops {
|
|
uint64_t (*msop_alloc)(metaslab_t *, uint64_t);
|
|
} metaslab_ops_t;
|
|
|
|
|
|
extern metaslab_ops_t *zfs_metaslab_ops;
|
|
|
|
int metaslab_init(metaslab_group_t *, uint64_t, uint64_t, uint64_t,
|
|
metaslab_t **);
|
|
void metaslab_fini(metaslab_t *);
|
|
|
|
void metaslab_set_unflushed_txg(metaslab_t *, uint64_t, dmu_tx_t *);
|
|
void metaslab_set_estimated_condensed_size(metaslab_t *, uint64_t, dmu_tx_t *);
|
|
uint64_t metaslab_unflushed_txg(metaslab_t *);
|
|
uint64_t metaslab_estimated_condensed_size(metaslab_t *);
|
|
int metaslab_sort_by_flushed(const void *, const void *);
|
|
uint64_t metaslab_unflushed_changes_memused(metaslab_t *);
|
|
|
|
int metaslab_load(metaslab_t *);
|
|
void metaslab_unload(metaslab_t *);
|
|
boolean_t metaslab_flush(metaslab_t *, dmu_tx_t *);
|
|
|
|
uint64_t metaslab_allocated_space(metaslab_t *);
|
|
|
|
void metaslab_sync(metaslab_t *, uint64_t);
|
|
void metaslab_sync_done(metaslab_t *, uint64_t);
|
|
void metaslab_sync_reassess(metaslab_group_t *);
|
|
uint64_t metaslab_largest_allocatable(metaslab_t *);
|
|
|
|
/*
|
|
* metaslab alloc flags
|
|
*/
|
|
#define METASLAB_HINTBP_FAVOR 0x0
|
|
#define METASLAB_HINTBP_AVOID 0x1
|
|
#define METASLAB_GANG_HEADER 0x2
|
|
#define METASLAB_GANG_CHILD 0x4
|
|
#define METASLAB_ASYNC_ALLOC 0x8
|
|
#define METASLAB_DONT_THROTTLE 0x10
|
|
#define METASLAB_MUST_RESERVE 0x20
|
|
#define METASLAB_FASTWRITE 0x40
|
|
|
|
int metaslab_alloc(spa_t *, metaslab_class_t *, uint64_t,
|
|
blkptr_t *, int, uint64_t, blkptr_t *, int, zio_alloc_list_t *, zio_t *,
|
|
int);
|
|
int metaslab_alloc_dva(spa_t *, metaslab_class_t *, uint64_t,
|
|
dva_t *, int, dva_t *, uint64_t, int, zio_alloc_list_t *, int);
|
|
void metaslab_free(spa_t *, const blkptr_t *, uint64_t, boolean_t);
|
|
void metaslab_free_concrete(vdev_t *, uint64_t, uint64_t, boolean_t);
|
|
void metaslab_free_dva(spa_t *, const dva_t *, boolean_t);
|
|
void metaslab_free_impl_cb(uint64_t, vdev_t *, uint64_t, uint64_t, void *);
|
|
void metaslab_unalloc_dva(spa_t *, const dva_t *, uint64_t);
|
|
int metaslab_claim(spa_t *, const blkptr_t *, uint64_t);
|
|
int metaslab_claim_impl(vdev_t *, uint64_t, uint64_t, uint64_t);
|
|
void metaslab_check_free(spa_t *, const blkptr_t *);
|
|
void metaslab_fastwrite_mark(spa_t *, const blkptr_t *);
|
|
void metaslab_fastwrite_unmark(spa_t *, const blkptr_t *);
|
|
|
|
void metaslab_stat_init(void);
|
|
void metaslab_stat_fini(void);
|
|
void metaslab_trace_init(zio_alloc_list_t *);
|
|
void metaslab_trace_fini(zio_alloc_list_t *);
|
|
|
|
metaslab_class_t *metaslab_class_create(spa_t *, metaslab_ops_t *);
|
|
void metaslab_class_destroy(metaslab_class_t *);
|
|
int metaslab_class_validate(metaslab_class_t *);
|
|
void metaslab_class_histogram_verify(metaslab_class_t *);
|
|
uint64_t metaslab_class_fragmentation(metaslab_class_t *);
|
|
uint64_t metaslab_class_expandable_space(metaslab_class_t *);
|
|
boolean_t metaslab_class_throttle_reserve(metaslab_class_t *, int, int,
|
|
zio_t *, int);
|
|
void metaslab_class_throttle_unreserve(metaslab_class_t *, int, int, zio_t *);
|
|
void metaslab_class_evict_old(metaslab_class_t *, uint64_t);
|
|
uint64_t metaslab_class_get_alloc(metaslab_class_t *);
|
|
uint64_t metaslab_class_get_space(metaslab_class_t *);
|
|
uint64_t metaslab_class_get_dspace(metaslab_class_t *);
|
|
uint64_t metaslab_class_get_deferred(metaslab_class_t *);
|
|
|
|
void metaslab_space_update(vdev_t *, metaslab_class_t *,
|
|
int64_t, int64_t, int64_t);
|
|
|
|
metaslab_group_t *metaslab_group_create(metaslab_class_t *, vdev_t *, int);
|
|
void metaslab_group_destroy(metaslab_group_t *);
|
|
void metaslab_group_activate(metaslab_group_t *);
|
|
void metaslab_group_passivate(metaslab_group_t *);
|
|
boolean_t metaslab_group_initialized(metaslab_group_t *);
|
|
uint64_t metaslab_group_get_space(metaslab_group_t *);
|
|
void metaslab_group_histogram_verify(metaslab_group_t *);
|
|
uint64_t metaslab_group_fragmentation(metaslab_group_t *);
|
|
void metaslab_group_histogram_remove(metaslab_group_t *, metaslab_t *);
|
|
void metaslab_group_alloc_decrement(spa_t *, uint64_t, void *, int, int,
|
|
boolean_t);
|
|
void metaslab_group_alloc_verify(spa_t *, const blkptr_t *, void *, int);
|
|
void metaslab_recalculate_weight_and_sort(metaslab_t *);
|
|
void metaslab_disable(metaslab_t *);
|
|
void metaslab_enable(metaslab_t *, boolean_t, boolean_t);
|
|
void metaslab_set_selected_txg(metaslab_t *, uint64_t);
|
|
|
|
extern int metaslab_debug_load;
|
|
|
|
range_seg_type_t metaslab_calculate_range_tree_type(vdev_t *vdev,
|
|
metaslab_t *msp, uint64_t *start, uint64_t *shift);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* _SYS_METASLAB_H */
|