zfs: support force exporting pools
This is primarily of use when a pool has lost its disk, while the user doesn't care about any pending (or otherwise) transactions. Implement various control methods to make this feasible: - txg_wait can now take a NOSUSPEND flag, in which case the caller will be alerted if their txg can't be committed. This is primarily of interest for callers that would normally pass TXG_WAIT, but don't want to wait if the pool becomes suspended, which allows unwinding in some cases, specifically when one is attempting a non-forced export. Without this, the non-forced export would preclude a forced export by virtue of holding the namespace lock indefinitely. - txg_wait also returns failure for TXG_WAIT users if a pool is actually being force exported. Adjust most callers to tolerate this. - spa_config_enter_flags now takes a NOSUSPEND flag to the same effect. - DMU objset initiator which may be set on an objset being forcibly exported / unmounted. - SPA export initiator may be set on a pool being forcibly exported. - DMU send/recv now use an interruption mechanism which relies on the SPA export initiator being able to enumerate datasets and closing any send/recv streams, causing their EINTR paths to be invoked. - ZIO now has a cancel entry point, which tells all suspended zios to fail, and which suppresses the failures for non-CANFAIL users. - metaslab, etc. cleanup, which consists of simply throwing away any changes that were not able to be synced out. - Linux specific: introduce a new tunable, zfs_forced_export_unmount_enabled, which allows the filesystem to remain in a modified 'unmounted' state upon exiting zpl_umount_begin, to achieve parity with FreeBSD and illumos, which have VFS-level support for yanking filesystems out from under users. However, this only helps when the user is actively performing I/O, while not sitting on the filesystem. In particular, this allows test #3 below to pass on Linux. - Add basic logic to zpool to indicate a force-exporting pool, instead of crashing due to lack of config, etc. Add tests which cover the basic use cases: - Force export while a send is in progress - Force export while a recv is in progress - Force export while POSIX I/O is in progress This change modifies the libzfs ABI: - New ZPOOL_STATUS_FORCE_EXPORTING zpool_status_t enum value. - New field libzfs_force_export for libzfs_handle. Signed-off-by: Will Andrews <will@firepipe.net> Signed-off-by: Allan Jude <allan@klarasystems.com> Signed-off-by: Mariusz Zaborski <mariusz.zaborski@klarasystems.com> Signed-off-by: Rob Norris <rob.norris@klarasystems.com> Sponsored-by: Klara, Inc. Sponsored-by: Catalogics, Inc. Sponsored-by: Wasabi Technology, Inc. Closes #3461 (cherry picked from commit 852e633772217d779a63e8c46fe3c5f81dd8960e)
This commit is contained in:
parent
f65b59c5e5
commit
40a9efd0e8
|
@ -357,7 +357,7 @@ get_usage(zpool_help_t idx)
|
|||
case HELP_DETACH:
|
||||
return (gettext("\tdetach <pool> <device>\n"));
|
||||
case HELP_EXPORT:
|
||||
return (gettext("\texport [-af] <pool> ...\n"));
|
||||
return (gettext("\texport [-afF] <pool> ...\n"));
|
||||
case HELP_HISTORY:
|
||||
return (gettext("\thistory [-il] [<pool>] ...\n"));
|
||||
case HELP_IMPORT:
|
||||
|
@ -1830,7 +1830,7 @@ zpool_do_destroy(int argc, char **argv)
|
|||
return (1);
|
||||
}
|
||||
|
||||
if (zpool_disable_datasets(zhp, force) != 0) {
|
||||
if (zpool_disable_datasets(zhp, force, B_FALSE) != 0) {
|
||||
(void) fprintf(stderr, gettext("could not destroy '%s': "
|
||||
"could not unmount datasets\n"), zpool_get_name(zhp));
|
||||
zpool_close(zhp);
|
||||
|
@ -1860,7 +1860,7 @@ zpool_export_one(zpool_handle_t *zhp, void *data)
|
|||
{
|
||||
export_cbdata_t *cb = data;
|
||||
|
||||
if (zpool_disable_datasets(zhp, cb->force) != 0)
|
||||
if (zpool_disable_datasets(zhp, cb->force, cb->hardforce) != 0)
|
||||
return (1);
|
||||
|
||||
/* The history must be logged as part of the export */
|
||||
|
@ -1881,10 +1881,13 @@ zpool_export_one(zpool_handle_t *zhp, void *data)
|
|||
*
|
||||
* -a Export all pools
|
||||
* -f Forcefully unmount datasets
|
||||
* -F Forcefully export, dropping all outstanding dirty data
|
||||
*
|
||||
* Export the given pools. By default, the command will attempt to cleanly
|
||||
* unmount any active datasets within the pool. If the '-f' flag is specified,
|
||||
* then the datasets will be forcefully unmounted.
|
||||
* then the datasets will be forcefully unmounted. If the '-F' flag is
|
||||
* specified, the pool's dirty data, if any, will simply be dropped after a
|
||||
* best-effort attempt to forcibly stop all activity.
|
||||
*/
|
||||
int
|
||||
zpool_do_export(int argc, char **argv)
|
||||
|
|
|
@ -394,6 +394,7 @@ typedef enum {
|
|||
ZPOOL_STATUS_NON_NATIVE_ASHIFT, /* (e.g. 512e dev with ashift of 9) */
|
||||
ZPOOL_STATUS_COMPATIBILITY_ERR, /* bad 'compatibility' property */
|
||||
ZPOOL_STATUS_INCOMPATIBLE_FEAT, /* feature set outside compatibility */
|
||||
ZPOOL_STATUS_FORCE_EXPORTING, /* pool is being force exported */
|
||||
|
||||
/*
|
||||
* Finally, the following indicates a healthy pool.
|
||||
|
@ -917,7 +918,13 @@ int zfs_smb_acl_rename(libzfs_handle_t *, char *, char *, char *, char *);
|
|||
* sharing/unsharing them.
|
||||
*/
|
||||
extern int zpool_enable_datasets(zpool_handle_t *, const char *, int);
|
||||
extern int zpool_disable_datasets(zpool_handle_t *, boolean_t);
|
||||
extern int zpool_disable_datasets(zpool_handle_t *, boolean_t, boolean_t);
|
||||
|
||||
/*
|
||||
* Procedure to inform os that we have started force unmount (linux specific).
|
||||
*/
|
||||
extern void zpool_unmount_mark_hard_force_begin(zpool_handle_t *zhp);
|
||||
extern void zpool_unmount_mark_hard_force_end(zpool_handle_t *zhp);
|
||||
|
||||
/*
|
||||
* Parse a features file for -o compatibility
|
||||
|
|
|
@ -74,6 +74,7 @@ struct libzfs_handle {
|
|||
uint64_t libzfs_max_nvlist;
|
||||
void *libfetch;
|
||||
char *libfetch_load_error;
|
||||
boolean_t libzfs_force_export;
|
||||
};
|
||||
|
||||
struct zfs_handle {
|
||||
|
|
|
@ -31,4 +31,7 @@
|
|||
|
||||
#define getcomm() curthread->td_name
|
||||
#define getpid() curthread->td_tid
|
||||
#define thread_signal spl_kthread_signal
|
||||
extern int spl_kthread_signal(kthread_t *tsk, int sig);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -134,6 +134,8 @@ extern minor_t zfsdev_minor_alloc(void);
|
|||
/* Called on entry to each ZFS vnode and vfs operation */
|
||||
#define ZFS_ENTER(zfsvfs) ZFS_ENTER_ERROR(zfsvfs, EIO)
|
||||
|
||||
#define zfs_enter_unmountok zfs_enter
|
||||
|
||||
/* Must be called before exiting the vop */
|
||||
#define ZFS_EXIT(zfsvfs) ZFS_TEARDOWN_EXIT_READ(zfsvfs, FTAG)
|
||||
|
||||
|
|
|
@ -55,6 +55,7 @@ typedef void (*thread_func_t)(void *);
|
|||
#func, arg, len, pp, state, pri)
|
||||
/* END CSTYLED */
|
||||
|
||||
#define thread_signal(t, s) spl_kthread_signal(t, s)
|
||||
#define thread_exit() __thread_exit()
|
||||
#define thread_join(t) VERIFY(0)
|
||||
#define curthread current
|
||||
|
@ -67,6 +68,7 @@ extern kthread_t *__thread_create(caddr_t stk, size_t stksize,
|
|||
extern void __thread_exit(void);
|
||||
extern struct task_struct *spl_kthread_create(int (*func)(void *),
|
||||
void *data, const char namefmt[], ...);
|
||||
extern int spl_kthread_signal(kthread_t *tsk, int sig);
|
||||
|
||||
extern proc_t p0;
|
||||
|
||||
|
|
|
@ -101,7 +101,8 @@ struct zfsvfs {
|
|||
boolean_t z_utf8; /* utf8-only */
|
||||
int z_norm; /* normalization flags */
|
||||
boolean_t z_relatime; /* enable relatime mount option */
|
||||
boolean_t z_unmounted; /* unmounted */
|
||||
boolean_t z_unmounted; /* mount status */
|
||||
boolean_t z_force_unmounted; /* force-unmounted status */
|
||||
rrmlock_t z_teardown_lock;
|
||||
krwlock_t z_teardown_inactive_lock;
|
||||
list_t z_all_znodes; /* all znodes in the fs */
|
||||
|
|
|
@ -83,11 +83,14 @@ extern "C" {
|
|||
#define zhold(zp) VERIFY3P(igrab(ZTOI((zp))), !=, NULL)
|
||||
#define zrele(zp) iput(ZTOI((zp)))
|
||||
|
||||
#define zfsvfs_is_unmounted(zfsvfs) \
|
||||
((zfsvfs)->z_unmounted || (zfsvfs)->z_force_unmounted)
|
||||
|
||||
/* Called on entry to each ZFS inode and vfs operation. */
|
||||
#define ZFS_ENTER_ERROR(zfsvfs, error) \
|
||||
do { \
|
||||
ZFS_TEARDOWN_ENTER_READ(zfsvfs, FTAG); \
|
||||
if (unlikely((zfsvfs)->z_unmounted)) { \
|
||||
if (zfsvfs_is_unmounted(zfsvfs)) { \
|
||||
ZFS_TEARDOWN_EXIT_READ(zfsvfs, FTAG); \
|
||||
return (error); \
|
||||
} \
|
||||
|
@ -101,12 +104,25 @@ do { \
|
|||
zfs_exit_fs(zfsvfs); \
|
||||
ZFS_TEARDOWN_EXIT_READ(zfsvfs, FTAG); \
|
||||
} while (0)
|
||||
|
||||
#define ZPL_EXIT(zfsvfs) \
|
||||
do { \
|
||||
rrm_exit(&(zfsvfs)->z_teardown_lock, FTAG); \
|
||||
} while (0)
|
||||
|
||||
|
||||
/* ZFS_ENTER but ok with forced unmount having begun */
|
||||
/* ZFS_ENTER but ok with forced unmount having begun */
|
||||
#define _ZFS_ENTER_UNMOUNTOK(zfsvfs, error) \
|
||||
do { \
|
||||
rrm_enter_read(&(zfsvfs)->z_teardown_lock, FTAG); \
|
||||
if ((zfsvfs)->z_unmounted == B_TRUE) { \
|
||||
ZFS_EXIT(zfsvfs); \
|
||||
return (error); \
|
||||
} \
|
||||
} while (0)
|
||||
#define ZFS_ENTER_UNMOUNTOK(zfsvfs) _ZFS_ENTER_UNMOUNTOK(zfsvfs, EIO)
|
||||
#define ZPL_ENTER_UNMOUNTOK(zfsvfs) _ZFS_ENTER_UNMOUNTOK(zfsvfs, -EIO)
|
||||
|
||||
/* Verifies the znode is valid. */
|
||||
#define ZFS_VERIFY_ZP_ERROR(zp, error) \
|
||||
do { \
|
||||
|
|
|
@ -336,6 +336,7 @@ void l2arc_fini(void);
|
|||
void l2arc_start(void);
|
||||
void l2arc_stop(void);
|
||||
void l2arc_spa_rebuild_start(spa_t *spa);
|
||||
void l2arc_spa_rebuild_stop(spa_t *spa);
|
||||
|
||||
#ifndef _KERNEL
|
||||
extern boolean_t arc_watch;
|
||||
|
|
|
@ -276,6 +276,7 @@ typedef enum dmu_object_type {
|
|||
#define TXG_NOWAIT (0ULL)
|
||||
#define TXG_WAIT (1ULL<<0)
|
||||
#define TXG_NOTHROTTLE (1ULL<<1)
|
||||
#define TXG_NOSUSPEND (1ULL<<2)
|
||||
|
||||
void byteswap_uint64_array(void *buf, size_t size);
|
||||
void byteswap_uint32_array(void *buf, size_t size);
|
||||
|
|
|
@ -241,6 +241,7 @@ typedef struct dmu_sendstatus {
|
|||
list_node_t dss_link;
|
||||
int dss_outfd;
|
||||
proc_t *dss_proc;
|
||||
kthread_t *dss_thread;
|
||||
offset_t *dss_off;
|
||||
uint64_t dss_blocks; /* blocks visited during the sending process */
|
||||
} dmu_sendstatus_t;
|
||||
|
|
|
@ -172,6 +172,7 @@ struct objset {
|
|||
|
||||
/* Protected by os_lock */
|
||||
kmutex_t os_lock;
|
||||
kthread_t *os_shutdown_initiator;
|
||||
multilist_t os_dirty_dnodes[TXG_SIZE];
|
||||
list_t os_dnodes;
|
||||
list_t os_downgraded_dbufs;
|
||||
|
@ -263,6 +264,10 @@ int dmu_fsname(const char *snapname, char *buf);
|
|||
void dmu_objset_evict_done(objset_t *os);
|
||||
void dmu_objset_willuse_space(objset_t *os, int64_t space, dmu_tx_t *tx);
|
||||
|
||||
int dmu_objset_shutdown_register(objset_t *os);
|
||||
boolean_t dmu_objset_exiting(objset_t *os);
|
||||
void dmu_objset_shutdown_unregister(objset_t *os);
|
||||
|
||||
void dmu_objset_init(void);
|
||||
void dmu_objset_fini(void);
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ extern const char *recv_clone_name;
|
|||
|
||||
typedef struct dmu_recv_cookie {
|
||||
struct dsl_dataset *drc_ds;
|
||||
kthread_t *drc_initiator;
|
||||
struct dmu_replay_record *drc_drr_begin;
|
||||
struct drr_begin *drc_drrb;
|
||||
const char *drc_tofs;
|
||||
|
@ -55,6 +56,8 @@ typedef struct dmu_recv_cookie {
|
|||
nvlist_t *drc_keynvl;
|
||||
uint64_t drc_fromsnapobj;
|
||||
uint64_t drc_ivset_guid;
|
||||
unsigned int drc_flags;
|
||||
void *drc_rwa;
|
||||
void *drc_owner;
|
||||
cred_t *drc_cred;
|
||||
proc_t *drc_proc;
|
||||
|
@ -81,6 +84,7 @@ int dmu_recv_begin(char *, char *, dmu_replay_record_t *,
|
|||
boolean_t, boolean_t, nvlist_t *, nvlist_t *, char *,
|
||||
dmu_recv_cookie_t *, zfs_file_t *, offset_t *);
|
||||
int dmu_recv_stream(dmu_recv_cookie_t *, offset_t *);
|
||||
int dmu_recv_close(dsl_dataset_t *ds);
|
||||
int dmu_recv_end(dmu_recv_cookie_t *, void *);
|
||||
boolean_t dmu_objset_is_receiving(objset_t *);
|
||||
|
||||
|
|
|
@ -60,6 +60,7 @@ int dmu_send_obj(const char *pool, uint64_t tosnap, uint64_t fromsnap,
|
|||
boolean_t embedok, boolean_t large_block_ok, boolean_t compressok,
|
||||
boolean_t rawok, boolean_t savedok, int outfd, offset_t *off,
|
||||
struct dmu_send_outparams *dso);
|
||||
int dmu_send_close(struct dsl_dataset *ds);
|
||||
|
||||
typedef int (*dmu_send_outfunc_t)(objset_t *os, void *buf, int len, void *arg);
|
||||
typedef struct dmu_send_outparams {
|
||||
|
|
|
@ -243,6 +243,8 @@ typedef struct dsl_dataset {
|
|||
kmutex_t ds_sendstream_lock;
|
||||
list_t ds_sendstreams;
|
||||
|
||||
struct dmu_recv_cookie *ds_receiver;
|
||||
|
||||
/*
|
||||
* When in the middle of a resumable receive, tracks how much
|
||||
* progress we have made.
|
||||
|
@ -317,7 +319,8 @@ typedef struct dsl_dataset_snapshot_arg {
|
|||
/* flags for holding the dataset */
|
||||
typedef enum ds_hold_flags {
|
||||
DS_HOLD_FLAG_NONE = 0 << 0,
|
||||
DS_HOLD_FLAG_DECRYPT = 1 << 0 /* needs access to encrypted data */
|
||||
DS_HOLD_FLAG_DECRYPT = 1 << 0, /* needs access to encrypted data */
|
||||
DS_HOLD_FLAG_MUST_BE_OPEN = 1 << 1, /* dataset must already be open */
|
||||
} ds_hold_flags_t;
|
||||
|
||||
int dsl_dataset_hold(struct dsl_pool *dp, const char *name, void *tag,
|
||||
|
@ -445,6 +448,8 @@ void dsl_dataset_long_hold(dsl_dataset_t *ds, void *tag);
|
|||
void dsl_dataset_long_rele(dsl_dataset_t *ds, void *tag);
|
||||
boolean_t dsl_dataset_long_held(dsl_dataset_t *ds);
|
||||
|
||||
int dsl_dataset_sendrecv_cancel_all(spa_t *spa);
|
||||
|
||||
int dsl_dataset_clone_swap_check_impl(dsl_dataset_t *clone,
|
||||
dsl_dataset_t *origin_head, boolean_t force, void *owner, dmu_tx_t *tx);
|
||||
void dsl_dataset_clone_swap_sync_impl(dsl_dataset_t *clone,
|
||||
|
|
|
@ -172,7 +172,7 @@ int dsl_scan(struct dsl_pool *, pool_scan_func_t);
|
|||
void dsl_scan_assess_vdev(struct dsl_pool *dp, vdev_t *vd);
|
||||
boolean_t dsl_scan_scrubbing(const struct dsl_pool *dp);
|
||||
int dsl_scrub_set_pause_resume(const struct dsl_pool *dp, pool_scrub_cmd_t cmd);
|
||||
void dsl_scan_restart_resilver(struct dsl_pool *, uint64_t txg);
|
||||
int dsl_scan_restart_resilver(struct dsl_pool *, uint64_t txg);
|
||||
boolean_t dsl_scan_resilvering(struct dsl_pool *dp);
|
||||
boolean_t dsl_scan_resilver_scheduled(struct dsl_pool *dp);
|
||||
boolean_t dsl_dataset_unstable(struct dsl_dataset *ds);
|
||||
|
|
|
@ -1367,6 +1367,8 @@ typedef enum zfs_ioc {
|
|||
ZFS_IOC_UNJAIL, /* 0x86 (FreeBSD) */
|
||||
ZFS_IOC_SET_BOOTENV, /* 0x87 */
|
||||
ZFS_IOC_GET_BOOTENV, /* 0x88 */
|
||||
ZFS_IOC_HARD_FORCE_UNMOUNT_BEGIN, /* 0x89 (Linux) */
|
||||
ZFS_IOC_HARD_FORCE_UNMOUNT_END, /* 0x90 (Linux) */
|
||||
ZFS_IOC_LAST
|
||||
} zfs_ioc_t;
|
||||
|
||||
|
|
|
@ -111,6 +111,7 @@ 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);
|
||||
void metaslab_class_force_discard(metaslab_class_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 *);
|
||||
|
|
|
@ -774,6 +774,7 @@ extern int spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
|
|||
extern int spa_import(char *pool, nvlist_t *config, nvlist_t *props,
|
||||
uint64_t flags);
|
||||
extern nvlist_t *spa_tryimport(nvlist_t *tryconfig);
|
||||
extern int spa_set_pre_export_status(const char *pool, boolean_t status);
|
||||
extern int spa_destroy(const char *pool);
|
||||
extern int spa_checkpoint(const char *pool);
|
||||
extern int spa_checkpoint_discard(const char *pool);
|
||||
|
@ -867,7 +868,7 @@ extern nvlist_t *spa_all_configs(uint64_t *);
|
|||
extern void spa_config_set(spa_t *spa, nvlist_t *config);
|
||||
extern nvlist_t *spa_config_generate(spa_t *spa, vdev_t *vd, uint64_t txg,
|
||||
int getstats);
|
||||
extern void spa_config_update(spa_t *spa, int what);
|
||||
extern int spa_config_update_pool(spa_t *spa);
|
||||
extern int spa_config_parse(spa_t *spa, vdev_t **vdp, nvlist_t *nv,
|
||||
vdev_t *parent, uint_t id, int atype);
|
||||
|
||||
|
@ -988,6 +989,13 @@ extern void spa_iostats_trim_add(spa_t *spa, trim_type_t type,
|
|||
uint64_t extents_written, uint64_t bytes_written,
|
||||
uint64_t extents_skipped, uint64_t bytes_skipped,
|
||||
uint64_t extents_failed, uint64_t bytes_failed);
|
||||
|
||||
/* Config lock handling flags */
|
||||
typedef enum {
|
||||
SCL_FLAG_TRYENTER = 1U << 0,
|
||||
SCL_FLAG_NOSUSPEND = 1U << 1,
|
||||
} spa_config_flag_t;
|
||||
|
||||
extern void spa_import_progress_add(spa_t *spa);
|
||||
extern void spa_import_progress_remove(uint64_t spa_guid);
|
||||
extern int spa_import_progress_set_mmp_check(uint64_t pool_guid,
|
||||
|
@ -998,7 +1006,10 @@ extern int spa_import_progress_set_state(uint64_t pool_guid,
|
|||
spa_load_state_t spa_load_state);
|
||||
|
||||
/* Pool configuration locks */
|
||||
extern int spa_config_tryenter(spa_t *spa, int locks, void *tag, krw_t rw);
|
||||
extern int spa_config_tryenter(spa_t *spa, int locks, const void *tag,
|
||||
krw_t rw);
|
||||
extern int spa_config_enter_flags(spa_t *spa, int locks, const void *tag,
|
||||
krw_t rw, spa_config_flag_t flags);
|
||||
extern void spa_config_enter(spa_t *spa, int locks, const void *tag, krw_t rw);
|
||||
extern void spa_config_exit(spa_t *spa, int locks, const void *tag);
|
||||
extern int spa_config_held(spa_t *spa, int locks, krw_t rw);
|
||||
|
@ -1047,6 +1058,7 @@ extern uint64_t spa_last_synced_txg(spa_t *spa);
|
|||
extern uint64_t spa_first_txg(spa_t *spa);
|
||||
extern uint64_t spa_syncing_txg(spa_t *spa);
|
||||
extern uint64_t spa_final_dirty_txg(spa_t *spa);
|
||||
extern void spa_verify_dirty_txg(spa_t *spa, uint64_t txg);
|
||||
extern uint64_t spa_version(spa_t *spa);
|
||||
extern pool_state_t spa_state(spa_t *spa);
|
||||
extern spa_load_state_t spa_load_state(spa_t *spa);
|
||||
|
@ -1066,6 +1078,8 @@ extern metaslab_class_t *spa_dedup_class(spa_t *spa);
|
|||
extern metaslab_class_t *spa_preferred_class(spa_t *spa, uint64_t size,
|
||||
dmu_object_type_t objtype, uint_t level, uint_t special_smallblk);
|
||||
|
||||
extern void spa_evicting_os_lock(spa_t *);
|
||||
extern void spa_evicting_os_unlock(spa_t *);
|
||||
extern void spa_evicting_os_register(spa_t *, objset_t *os);
|
||||
extern void spa_evicting_os_deregister(spa_t *, objset_t *os);
|
||||
extern void spa_evicting_os_wait(spa_t *spa);
|
||||
|
@ -1154,6 +1168,10 @@ extern void spa_history_log_internal_dd(dsl_dir_t *dd, const char *operation,
|
|||
|
||||
extern const char *spa_state_to_name(spa_t *spa);
|
||||
|
||||
extern boolean_t spa_exiting_any(spa_t *spa);
|
||||
extern boolean_t spa_exiting(spa_t *spa);
|
||||
extern int spa_operation_interrupted(spa_t *spa);
|
||||
|
||||
/* error handling */
|
||||
struct zbookmark_phys;
|
||||
extern void spa_log_error(spa_t *spa, const zbookmark_phys_t *zb);
|
||||
|
|
|
@ -244,6 +244,8 @@ struct spa {
|
|||
kmutex_t spa_evicting_os_lock; /* Evicting objset list lock */
|
||||
list_t spa_evicting_os_list; /* Objsets being evicted. */
|
||||
kcondvar_t spa_evicting_os_cv; /* Objset Eviction Completion */
|
||||
kthread_t *spa_export_initiator; /* thread exporting the pool */
|
||||
boolean_t spa_pre_exporting; /* allow fails before export */
|
||||
txg_list_t spa_vdev_txg_list; /* per-txg dirty vdev list */
|
||||
vdev_t *spa_root_vdev; /* top-level vdev container */
|
||||
uint64_t spa_min_ashift; /* of vdevs in normal class */
|
||||
|
|
|
@ -66,11 +66,27 @@ typedef struct txg_list {
|
|||
} txg_list_t;
|
||||
|
||||
struct dsl_pool;
|
||||
struct dmu_tx;
|
||||
|
||||
/*
|
||||
* TXG wait flags, used by txg_wait_synced_tx and callers to indicate
|
||||
* modifications to how they wish to wait for a txg.
|
||||
*/
|
||||
typedef enum {
|
||||
/* No special wait flags. */
|
||||
TXG_WAIT_F_NONE = 0,
|
||||
/* Reject the call with EINTR upon receiving a signal. */
|
||||
TXG_WAIT_F_SIGNAL = (1U << 0),
|
||||
/* Reject the call with EAGAIN upon suspension. */
|
||||
TXG_WAIT_F_NOSUSPEND = (1U << 1),
|
||||
/* Ignore errors and export anyway. */
|
||||
TXG_WAIT_F_FORCE_EXPORT = (1U << 2),
|
||||
} txg_wait_flag_t;
|
||||
|
||||
extern void txg_init(struct dsl_pool *dp, uint64_t txg);
|
||||
extern void txg_fini(struct dsl_pool *dp);
|
||||
extern void txg_sync_start(struct dsl_pool *dp);
|
||||
extern void txg_sync_stop(struct dsl_pool *dp);
|
||||
extern int txg_sync_stop(struct dsl_pool *dp, txg_wait_flag_t txg_how);
|
||||
extern uint64_t txg_hold_open(struct dsl_pool *dp, txg_handle_t *txghp);
|
||||
extern void txg_rele_to_quiesce(txg_handle_t *txghp);
|
||||
extern void txg_rele_to_sync(txg_handle_t *txghp);
|
||||
|
@ -84,14 +100,23 @@ extern void txg_kick(struct dsl_pool *dp);
|
|||
* Wait until the given transaction group has finished syncing.
|
||||
* Try to make this happen as soon as possible (eg. kick off any
|
||||
* necessary syncs immediately). If txg==0, wait for the currently open
|
||||
* txg to finish syncing.
|
||||
* txg to finish syncing. This may be interrupted due to an exiting pool.
|
||||
*
|
||||
* If desired, flags can be specified using txg_wait_synced_tx(), in case
|
||||
* the caller wants to be interruptible.
|
||||
*/
|
||||
extern void txg_wait_synced(struct dsl_pool *dp, uint64_t txg);
|
||||
extern int txg_wait_synced_tx(struct dsl_pool *dp, uint64_t txg,
|
||||
struct dmu_tx *tx, txg_wait_flag_t flags);
|
||||
extern int txg_wait_synced_flags(struct dsl_pool *dp, uint64_t txg,
|
||||
txg_wait_flag_t flags);
|
||||
|
||||
/*
|
||||
* Wait as above. Returns true if the thread was signaled while waiting.
|
||||
* Similar to a txg_wait_synced but it can be interrupted from a signal.
|
||||
* Returns B_TRUE if the thread was signaled while waiting.
|
||||
*/
|
||||
extern boolean_t txg_wait_synced_sig(struct dsl_pool *dp, uint64_t txg);
|
||||
#define txg_wait_synced_sig(dp, txg) \
|
||||
(txg_wait_synced_tx(dp, txg, NULL, TXG_WAIT_F_SIGNAL) == EINTR)
|
||||
|
||||
/*
|
||||
* Wait until the given transaction group, or one after it, is
|
||||
|
@ -102,6 +127,8 @@ extern boolean_t txg_wait_synced_sig(struct dsl_pool *dp, uint64_t txg);
|
|||
extern void txg_wait_open(struct dsl_pool *dp, uint64_t txg,
|
||||
boolean_t should_quiesce);
|
||||
|
||||
void txg_force_export(spa_t *spa);
|
||||
|
||||
/*
|
||||
* Returns TRUE if we are "backed up" waiting for the syncing
|
||||
* transaction to complete; otherwise returns FALSE.
|
||||
|
@ -113,6 +140,8 @@ extern boolean_t txg_sync_waiting(struct dsl_pool *dp);
|
|||
|
||||
extern void txg_verify(spa_t *spa, uint64_t txg);
|
||||
|
||||
extern void txg_completion_notify(struct dsl_pool *dp);
|
||||
|
||||
/*
|
||||
* Wait for pending commit callbacks of already-synced transactions to finish
|
||||
* processing.
|
||||
|
|
|
@ -232,6 +232,7 @@ typedef pthread_t kthread_t;
|
|||
zk_thread_create(func, arg, stksize, state)
|
||||
#define thread_create(stk, stksize, func, arg, len, pp, state, pri) \
|
||||
zk_thread_create(func, arg, stksize, state)
|
||||
#define thread_signal(t, s) pthread_kill((pthread_t)t, s)
|
||||
#define thread_exit() pthread_exit(NULL)
|
||||
#define thread_join(t) pthread_join((pthread_t)(t), NULL)
|
||||
|
||||
|
|
|
@ -74,6 +74,10 @@ typedef struct zfs_ioc_key {
|
|||
|
||||
int zfs_secpolicy_config(zfs_cmd_t *, nvlist_t *, cred_t *);
|
||||
|
||||
void zfs_ioctl_register_pool(zfs_ioc_t ioc, zfs_ioc_legacy_func_t *func,
|
||||
zfs_secpolicy_func_t *secpolicy, boolean_t log_history,
|
||||
zfs_ioc_poolcheck_t pool_check);
|
||||
|
||||
void zfs_ioctl_register_dataset_nolog(zfs_ioc_t, zfs_ioc_legacy_func_t *,
|
||||
zfs_secpolicy_func_t *, zfs_ioc_poolcheck_t);
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ typedef struct refcount {
|
|||
|
||||
/*
|
||||
* Note: zfs_refcount_t must be initialized with
|
||||
* refcount_create[_untracked]()
|
||||
* zfs_refcount_create[_untracked]()
|
||||
*/
|
||||
|
||||
void zfs_refcount_create(zfs_refcount_t *);
|
||||
|
|
|
@ -216,6 +216,43 @@ typedef struct znode {
|
|||
ZNODE_OS_FIELDS;
|
||||
} znode_t;
|
||||
|
||||
/* Verifies the znode is valid. */
|
||||
static inline int
|
||||
zfs_verify_zp(znode_t *zp)
|
||||
{
|
||||
if (unlikely(zp->z_sa_hdl == NULL))
|
||||
return (SET_ERROR(EIO));
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* zfs_enter and zfs_verify_zp together */
|
||||
static inline int
|
||||
zfs_enter_verify_zp(zfsvfs_t *zfsvfs, znode_t *zp, const char *tag)
|
||||
{
|
||||
int error;
|
||||
|
||||
ZFS_ENTER(zfsvfs);
|
||||
if ((error = zfs_verify_zp(zp)) != 0) {
|
||||
ZFS_EXIT(zfsvfs);
|
||||
return (error);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* zfs_enter_unmountok and zfs_verify_zp together */
|
||||
static inline int
|
||||
zfs_enter_unmountok_verify_zp(zfsvfs_t *zfsvfs, znode_t *zp, const char *tag)
|
||||
{
|
||||
int error;
|
||||
|
||||
ZFS_ENTER_UNMOUNTOK(zfsvfs);
|
||||
if ((error = zfs_verify_zp(zp)) != 0) {
|
||||
ZFS_EXIT(zfsvfs);
|
||||
return (error);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
typedef struct znode_hold {
|
||||
uint64_t zh_obj; /* object id */
|
||||
kmutex_t zh_lock; /* lock serializing object access */
|
||||
|
|
|
@ -415,6 +415,7 @@ typedef zio_t *zio_pipe_stage_t(zio_t *zio);
|
|||
*/
|
||||
#define ZIO_REEXECUTE_NOW 0x01
|
||||
#define ZIO_REEXECUTE_SUSPEND 0x02
|
||||
#define ZIO_REEXECUTE_CANCELLED 0x04
|
||||
|
||||
/*
|
||||
* The io_trim flags are used to specify the type of TRIM to perform. They
|
||||
|
@ -640,7 +641,7 @@ extern uint8_t zio_complevel_select(spa_t *spa, enum zio_compress compress,
|
|||
|
||||
extern void zio_suspend(spa_t *spa, zio_t *zio, zio_suspend_reason_t);
|
||||
extern int zio_resume(spa_t *spa);
|
||||
extern void zio_resume_wait(spa_t *spa);
|
||||
extern void zio_cancel(spa_t *spa);
|
||||
|
||||
extern boolean_t zfs_blkptr_verify(spa_t *spa, const blkptr_t *bp,
|
||||
boolean_t config_held, enum blk_verify_flag blk_verify);
|
||||
|
|
|
@ -589,14 +589,6 @@
|
|||
</function-decl>
|
||||
</abi-instr>
|
||||
<abi-instr address-size='64' path='../../module/nvpair/nvpair.c' language='LANG_C99'>
|
||||
<typedef-decl name='__u_short' type-id='8efea9e5' id='46c660f8'/>
|
||||
<typedef-decl name='__u_int' type-id='f0981eeb' id='8ae6822f'/>
|
||||
<typedef-decl name='__quad_t' type-id='bd54fe1a' id='2632227a'/>
|
||||
<typedef-decl name='__u_quad_t' type-id='7359adad' id='5f3d50a6'/>
|
||||
<typedef-decl name='u_short' type-id='46c660f8' id='32580e96'/>
|
||||
<typedef-decl name='u_int' type-id='8ae6822f' id='48f7c3f5'/>
|
||||
<typedef-decl name='quad_t' type-id='2632227a' id='f5ef0660'/>
|
||||
<typedef-decl name='u_quad_t' type-id='5f3d50a6' id='bd226ac0'/>
|
||||
<typedef-decl name='bool_t' type-id='3ff5601b' id='310a70df'/>
|
||||
<enum-decl name='xdr_op' id='6badf1b8'>
|
||||
<underlying-type type-id='9cac1fee'/>
|
||||
|
@ -655,6 +647,14 @@
|
|||
</class-decl>
|
||||
<typedef-decl name='XDR' type-id='755707df' id='bc407f0e'/>
|
||||
<typedef-decl name='xdrproc_t' type-id='94d188f0' id='c28db3e9'/>
|
||||
<typedef-decl name='__u_short' type-id='8efea9e5' id='46c660f8'/>
|
||||
<typedef-decl name='__u_int' type-id='f0981eeb' id='8ae6822f'/>
|
||||
<typedef-decl name='__quad_t' type-id='bd54fe1a' id='2632227a'/>
|
||||
<typedef-decl name='__u_quad_t' type-id='7359adad' id='5f3d50a6'/>
|
||||
<typedef-decl name='u_short' type-id='46c660f8' id='32580e96'/>
|
||||
<typedef-decl name='u_int' type-id='8ae6822f' id='48f7c3f5'/>
|
||||
<typedef-decl name='quad_t' type-id='2632227a' id='f5ef0660'/>
|
||||
<typedef-decl name='u_quad_t' type-id='5f3d50a6' id='bd226ac0'/>
|
||||
<pointer-type-def type-id='bc407f0e' size-in-bits='64' id='17fd1621'/>
|
||||
<pointer-type-def type-id='755707df' size-in-bits='64' id='812c6697'/>
|
||||
<qualified-type-def type-id='26a90f95' const='yes' id='57de658a'/>
|
||||
|
@ -1771,6 +1771,63 @@
|
|||
<var-decl name='nvprt_custops' type-id='7be54adb' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<typedef-decl name='__re_long_size_t' type-id='7359adad' id='ba516949'/>
|
||||
<typedef-decl name='reg_syntax_t' type-id='7359adad' id='1b72c3b3'/>
|
||||
<class-decl name='re_pattern_buffer' size-in-bits='512' is-struct='yes' visibility='default' id='19fc9a8c'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='buffer' type-id='33976309' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='64'>
|
||||
<var-decl name='allocated' type-id='ba516949' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='128'>
|
||||
<var-decl name='used' type-id='ba516949' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='192'>
|
||||
<var-decl name='syntax' type-id='1b72c3b3' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='256'>
|
||||
<var-decl name='fastmap' type-id='26a90f95' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='320'>
|
||||
<var-decl name='translate' type-id='cf536864' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='384'>
|
||||
<var-decl name='re_nsub' type-id='b59d7dce' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='448'>
|
||||
<var-decl name='can_be_null' type-id='f0981eeb' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='449'>
|
||||
<var-decl name='regs_allocated' type-id='f0981eeb' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='451'>
|
||||
<var-decl name='fastmap_accurate' type-id='f0981eeb' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='452'>
|
||||
<var-decl name='no_sub' type-id='f0981eeb' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='453'>
|
||||
<var-decl name='not_bol' type-id='f0981eeb' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='454'>
|
||||
<var-decl name='not_eol' type-id='f0981eeb' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='455'>
|
||||
<var-decl name='newline_anchor' type-id='f0981eeb' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<typedef-decl name='regex_t' type-id='19fc9a8c' id='aca3bac8'/>
|
||||
<typedef-decl name='regoff_t' type-id='95e97e5e' id='54a2a2a8'/>
|
||||
<class-decl name='regmatch_t' size-in-bits='64' is-struct='yes' naming-typedef-id='1b941664' visibility='default' id='4f932615'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='rm_so' type-id='54a2a2a8' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='32'>
|
||||
<var-decl name='rm_eo' type-id='54a2a2a8' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<typedef-decl name='regmatch_t' type-id='4f932615' id='1b941664'/>
|
||||
<typedef-decl name='int8_t' type-id='2171a512' id='ee31ee44'/>
|
||||
<typedef-decl name='int16_t' type-id='03896e23' id='23bd8cb5'/>
|
||||
<typedef-decl name='int32_t' type-id='33f57a65' id='3ff5601b'/>
|
||||
|
@ -1880,63 +1937,6 @@
|
|||
<var-decl name='_unused2' type-id='664ac0b7' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<typedef-decl name='__re_long_size_t' type-id='7359adad' id='ba516949'/>
|
||||
<typedef-decl name='reg_syntax_t' type-id='7359adad' id='1b72c3b3'/>
|
||||
<class-decl name='re_pattern_buffer' size-in-bits='512' is-struct='yes' visibility='default' id='19fc9a8c'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='buffer' type-id='33976309' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='64'>
|
||||
<var-decl name='allocated' type-id='ba516949' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='128'>
|
||||
<var-decl name='used' type-id='ba516949' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='192'>
|
||||
<var-decl name='syntax' type-id='1b72c3b3' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='256'>
|
||||
<var-decl name='fastmap' type-id='26a90f95' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='320'>
|
||||
<var-decl name='translate' type-id='cf536864' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='384'>
|
||||
<var-decl name='re_nsub' type-id='b59d7dce' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='448'>
|
||||
<var-decl name='can_be_null' type-id='f0981eeb' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='449'>
|
||||
<var-decl name='regs_allocated' type-id='f0981eeb' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='451'>
|
||||
<var-decl name='fastmap_accurate' type-id='f0981eeb' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='452'>
|
||||
<var-decl name='no_sub' type-id='f0981eeb' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='453'>
|
||||
<var-decl name='not_bol' type-id='f0981eeb' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='454'>
|
||||
<var-decl name='not_eol' type-id='f0981eeb' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='455'>
|
||||
<var-decl name='newline_anchor' type-id='f0981eeb' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<typedef-decl name='regex_t' type-id='19fc9a8c' id='aca3bac8'/>
|
||||
<typedef-decl name='regoff_t' type-id='95e97e5e' id='54a2a2a8'/>
|
||||
<class-decl name='regmatch_t' size-in-bits='64' is-struct='yes' naming-typedef-id='1b941664' visibility='default' id='4f932615'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='rm_so' type-id='54a2a2a8' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='32'>
|
||||
<var-decl name='rm_eo' type-id='54a2a2a8' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<typedef-decl name='regmatch_t' type-id='4f932615' id='1b941664'/>
|
||||
<typedef-decl name='size_t' type-id='7359adad' id='b59d7dce'/>
|
||||
<pointer-type-def type-id='aa12d1ba' size-in-bits='64' id='822cd80b'/>
|
||||
<qualified-type-def type-id='822cd80b' restrict='yes' id='e75a27e9'/>
|
||||
|
@ -2452,17 +2452,6 @@
|
|||
<parameter type-id='95e97e5e'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='fprintf' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='e75a27e9'/>
|
||||
<parameter type-id='9d26089a'/>
|
||||
<parameter is-variadic='yes'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='printf' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter is-variadic='yes'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='malloc' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<return type-id='eaa32e2f'/>
|
||||
|
@ -2491,6 +2480,19 @@
|
|||
<parameter type-id='80f4b756'/>
|
||||
<return type-id='b59d7dce'/>
|
||||
</function-decl>
|
||||
<function-decl name='__fprintf_chk' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='e75a27e9'/>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='9d26089a'/>
|
||||
<parameter is-variadic='yes'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='__printf_chk' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter is-variadic='yes'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-type size-in-bits='64' id='9f88f76e'>
|
||||
<parameter type-id='196db161'/>
|
||||
<parameter type-id='eaa32e2f'/>
|
||||
|
@ -3124,14 +3126,15 @@
|
|||
</abi-instr>
|
||||
<abi-instr address-size='64' path='assert.c' language='LANG_C99'>
|
||||
<var-decl name='aok' type-id='95e97e5e' mangled-name='aok' visibility='default' elf-symbol-id='aok'/>
|
||||
<function-decl name='vfprintf' visibility='default' binding='global' size-in-bits='64'>
|
||||
<function-decl name='abort' visibility='default' binding='global' size-in-bits='64'>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
<function-decl name='__vfprintf_chk' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='e75a27e9'/>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='9d26089a'/>
|
||||
<parameter type-id='b7f2d5e6'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='abort' visibility='default' binding='global' size-in-bits='64'>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
</abi-instr>
|
||||
</abi-corpus>
|
||||
|
|
|
@ -774,16 +774,23 @@
|
|||
<parameter type-id='b59d7dce'/>
|
||||
<return type-id='eaa32e2f'/>
|
||||
</function-decl>
|
||||
<function-decl name='mbstowcs' visibility='default' binding='global' size-in-bits='64'>
|
||||
<function-decl name='access' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='__mbstowcs_chk' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='f1358bc3'/>
|
||||
<parameter type-id='9d26089a'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<return type-id='b59d7dce'/>
|
||||
</function-decl>
|
||||
<function-decl name='wcstombs' visibility='default' binding='global' size-in-bits='64'>
|
||||
<function-decl name='__wcstombs_chk' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='266fe297'/>
|
||||
<parameter type-id='598aab80'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<return type-id='b59d7dce'/>
|
||||
</function-decl>
|
||||
<function-decl name='mkdir' visibility='default' binding='global' size-in-bits='64'>
|
||||
|
@ -791,17 +798,13 @@
|
|||
<parameter type-id='e1c52942'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='access' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
</abi-instr>
|
||||
<abi-instr address-size='64' path='os/linux/getexecname.c' language='LANG_C99'>
|
||||
<function-decl name='readlink' visibility='default' binding='global' size-in-bits='64'>
|
||||
<function-decl name='__readlink_chk' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='9d26089a'/>
|
||||
<parameter type-id='266fe297'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<return type-id='79a0948f'/>
|
||||
</function-decl>
|
||||
</abi-instr>
|
||||
|
@ -827,10 +830,11 @@
|
|||
<parameter type-id='95e97e5e'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='read' visibility='default' binding='global' size-in-bits='64'>
|
||||
<function-decl name='__read_chk' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='eaa32e2f'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<return type-id='79a0948f'/>
|
||||
</function-decl>
|
||||
<function-decl name='get_system_hostid' mangled-name='get_system_hostid' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='get_system_hostid'>
|
||||
|
@ -879,6 +883,26 @@
|
|||
<var-decl name='mnt_minor' type-id='3502e3ff' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<class-decl name='mntent' size-in-bits='320' is-struct='yes' visibility='default' id='56fe4a37'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='mnt_fsname' type-id='26a90f95' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='64'>
|
||||
<var-decl name='mnt_dir' type-id='26a90f95' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='128'>
|
||||
<var-decl name='mnt_type' type-id='26a90f95' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='192'>
|
||||
<var-decl name='mnt_opts' type-id='26a90f95' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='256'>
|
||||
<var-decl name='mnt_freq' type-id='95e97e5e' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='288'>
|
||||
<var-decl name='mnt_passno' type-id='95e97e5e' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<class-decl name='stat64' size-in-bits='1152' is-struct='yes' visibility='default' id='0bbec9cd'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='st_dev' type-id='35ed8932' visibility='default'/>
|
||||
|
@ -933,26 +957,6 @@
|
|||
<typedef-decl name='__nlink_t' type-id='7359adad' id='80f0b9df'/>
|
||||
<typedef-decl name='__blksize_t' type-id='bd54fe1a' id='d3f10a7f'/>
|
||||
<typedef-decl name='__blkcnt64_t' type-id='bd54fe1a' id='4e711bf1'/>
|
||||
<class-decl name='mntent' size-in-bits='320' is-struct='yes' visibility='default' id='56fe4a37'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='mnt_fsname' type-id='26a90f95' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='64'>
|
||||
<var-decl name='mnt_dir' type-id='26a90f95' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='128'>
|
||||
<var-decl name='mnt_type' type-id='26a90f95' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='192'>
|
||||
<var-decl name='mnt_opts' type-id='26a90f95' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='256'>
|
||||
<var-decl name='mnt_freq' type-id='95e97e5e' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='288'>
|
||||
<var-decl name='mnt_passno' type-id='95e97e5e' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<pointer-type-def type-id='0c544dc0' size-in-bits='64' id='394fc496'/>
|
||||
<pointer-type-def type-id='56fe4a37' size-in-bits='64' id='b6b61d2f'/>
|
||||
<qualified-type-def type-id='b6b61d2f' restrict='yes' id='3cad23cd'/>
|
||||
|
@ -1019,6 +1023,7 @@
|
|||
</function-decl>
|
||||
</abi-instr>
|
||||
<abi-instr address-size='64' path='timestamp.c' language='LANG_C99'>
|
||||
<typedef-decl name='nl_item' type-id='95e97e5e' id='03b79a94'/>
|
||||
<class-decl name='tm' size-in-bits='448' is-struct='yes' visibility='default' id='dddf6ca2'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='tm_sec' type-id='95e97e5e' visibility='default'/>
|
||||
|
@ -1055,7 +1060,6 @@
|
|||
</data-member>
|
||||
</class-decl>
|
||||
<typedef-decl name='time_t' type-id='65eda9c0' id='c9d12d66'/>
|
||||
<typedef-decl name='nl_item' type-id='95e97e5e' id='03b79a94'/>
|
||||
<qualified-type-def type-id='c9d12d66' const='yes' id='588b3216'/>
|
||||
<pointer-type-def type-id='588b3216' size-in-bits='64' id='9f201474'/>
|
||||
<qualified-type-def type-id='dddf6ca2' const='yes' id='e824a34f'/>
|
||||
|
@ -1071,11 +1075,6 @@
|
|||
<parameter type-id='03b79a94'/>
|
||||
<return type-id='26a90f95'/>
|
||||
</function-decl>
|
||||
<function-decl name='printf' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter is-variadic='yes'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='time' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='b2eb2c3f'/>
|
||||
<return type-id='c9d12d66'/>
|
||||
|
@ -1091,31 +1090,21 @@
|
|||
<parameter type-id='9f201474'/>
|
||||
<return type-id='d915a820'/>
|
||||
</function-decl>
|
||||
<function-decl name='__printf_chk' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter is-variadic='yes'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
</abi-instr>
|
||||
<abi-instr address-size='64' path='uu_alloc.c' language='LANG_C99'>
|
||||
<type-decl name='char' size-in-bits='8' id='a84c031d'/>
|
||||
<class-decl name='__va_list_tag' size-in-bits='192' is-struct='yes' visibility='default' id='d5027220'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='gp_offset' type-id='f0981eeb' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='32'>
|
||||
<var-decl name='fp_offset' type-id='f0981eeb' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='64'>
|
||||
<var-decl name='overflow_arg_area' type-id='eaa32e2f' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='128'>
|
||||
<var-decl name='reg_save_area' type-id='eaa32e2f' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<type-decl name='int' size-in-bits='32' id='95e97e5e'/>
|
||||
<type-decl name='unsigned int' size-in-bits='32' id='f0981eeb'/>
|
||||
<type-decl name='unsigned long int' size-in-bits='64' id='7359adad'/>
|
||||
<type-decl name='variadic parameter type' id='2c1145c5'/>
|
||||
<type-decl name='void' id='48b5725f'/>
|
||||
<typedef-decl name='uint_t' type-id='f0981eeb' id='3502e3ff'/>
|
||||
<typedef-decl name='size_t' type-id='7359adad' id='b59d7dce'/>
|
||||
<pointer-type-def type-id='d5027220' size-in-bits='64' id='b7f2d5e6'/>
|
||||
<pointer-type-def type-id='a84c031d' size-in-bits='64' id='26a90f95'/>
|
||||
<qualified-type-def type-id='a84c031d' const='yes' id='9b45d938'/>
|
||||
<pointer-type-def type-id='9b45d938' size-in-bits='64' id='80f4b756'/>
|
||||
|
@ -1151,13 +1140,6 @@
|
|||
<parameter is-variadic='yes'/>
|
||||
<return type-id='26a90f95'/>
|
||||
</function-decl>
|
||||
<function-decl name='vsnprintf' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='26a90f95'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='b7f2d5e6'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='malloc' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<return type-id='eaa32e2f'/>
|
||||
|
@ -1166,18 +1148,6 @@
|
|||
<parameter type-id='eaa32e2f'/>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
<function-decl name='memcpy' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='eaa32e2f'/>
|
||||
<parameter type-id='eaa32e2f'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<return type-id='eaa32e2f'/>
|
||||
</function-decl>
|
||||
<function-decl name='memset' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='eaa32e2f'/>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<return type-id='eaa32e2f'/>
|
||||
</function-decl>
|
||||
<function-decl name='strlen' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<return type-id='b59d7dce'/>
|
||||
|
@ -1201,6 +1171,7 @@
|
|||
<array-type-def dimensions='1' type-id='a84c031d' size-in-bits='512' id='59daf3ef'>
|
||||
<subrange length='64' type-id='7359adad' id='b10be967'/>
|
||||
</array-type-def>
|
||||
<type-decl name='int' size-in-bits='32' id='95e97e5e'/>
|
||||
<type-decl name='long int' size-in-bits='64' id='bd54fe1a'/>
|
||||
<type-decl name='short int' size-in-bits='16' id='a2185560'/>
|
||||
<type-decl name='signed char' size-in-bits='8' id='28577a57'/>
|
||||
|
@ -1326,6 +1297,7 @@
|
|||
</data-member>
|
||||
</class-decl>
|
||||
<typedef-decl name='ulong_t' type-id='7359adad' id='ee1f298e'/>
|
||||
<typedef-decl name='uintptr_t' type-id='7359adad' id='e475ab95'/>
|
||||
<union-decl name='pthread_mutexattr_t' size-in-bits='32' naming-typedef-id='8afd6070' visibility='default' id='7300eb00'>
|
||||
<data-member access='public'>
|
||||
<var-decl name='__size' type-id='8e0573fd' visibility='default'/>
|
||||
|
@ -1388,7 +1360,6 @@
|
|||
<typedef-decl name='__int8_t' type-id='28577a57' id='2171a512'/>
|
||||
<typedef-decl name='__uint8_t' type-id='002ac4a6' id='c51d6389'/>
|
||||
<typedef-decl name='__uint32_t' type-id='f0981eeb' id='62f1140c'/>
|
||||
<typedef-decl name='uintptr_t' type-id='7359adad' id='e475ab95'/>
|
||||
<pointer-type-def type-id='0e01899c' size-in-bits='64' id='4d98cd5a'/>
|
||||
<pointer-type-def type-id='fba6cb51' size-in-bits='64' id='32adbf30'/>
|
||||
<pointer-type-def type-id='428b67b3' size-in-bits='64' id='bf311473'/>
|
||||
|
@ -1633,6 +1604,20 @@
|
|||
<class-decl name='_IO_codecvt' is-struct='yes' visibility='default' is-declaration-only='yes' id='a4036571'/>
|
||||
<class-decl name='_IO_marker' is-struct='yes' visibility='default' is-declaration-only='yes' id='010ae0b9'/>
|
||||
<class-decl name='_IO_wide_data' is-struct='yes' visibility='default' is-declaration-only='yes' id='79bd3751'/>
|
||||
<class-decl name='__va_list_tag' size-in-bits='192' is-struct='yes' visibility='default' id='d5027220'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='gp_offset' type-id='f0981eeb' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='32'>
|
||||
<var-decl name='fp_offset' type-id='f0981eeb' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='64'>
|
||||
<var-decl name='overflow_arg_area' type-id='eaa32e2f' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='128'>
|
||||
<var-decl name='reg_save_area' type-id='eaa32e2f' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<type-decl name='unnamed-enum-underlying-type-32' is-anonymous='yes' size-in-bits='32' alignment-in-bits='32' id='9cac1fee'/>
|
||||
<type-decl name='unsigned short int' size-in-bits='16' id='8efea9e5'/>
|
||||
<typedef-decl name='uu_dprintf_t' type-id='0538fe4f' id='2367d595'/>
|
||||
|
@ -1757,6 +1742,7 @@
|
|||
<pointer-type-def type-id='bb4788fa' size-in-bits='64' id='cecf4ea7'/>
|
||||
<pointer-type-def type-id='010ae0b9' size-in-bits='64' id='e4c6fa61'/>
|
||||
<pointer-type-def type-id='79bd3751' size-in-bits='64' id='c65a1f29'/>
|
||||
<pointer-type-def type-id='d5027220' size-in-bits='64' id='b7f2d5e6'/>
|
||||
<qualified-type-def type-id='80f4b756' restrict='yes' id='9d26089a'/>
|
||||
<pointer-type-def type-id='2367d595' size-in-bits='64' id='ed73b5ca'/>
|
||||
<class-decl name='_IO_codecvt' is-struct='yes' visibility='default' is-declaration-only='yes' id='a4036571'/>
|
||||
|
@ -1789,22 +1775,24 @@
|
|||
<parameter type-id='95e97e5e'/>
|
||||
<return type-id='26a90f95'/>
|
||||
</function-decl>
|
||||
<function-decl name='fprintf' visibility='default' binding='global' size-in-bits='64'>
|
||||
<function-decl name='strdup' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<return type-id='26a90f95'/>
|
||||
</function-decl>
|
||||
<function-decl name='__fprintf_chk' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='e75a27e9'/>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='9d26089a'/>
|
||||
<parameter is-variadic='yes'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='vfprintf' visibility='default' binding='global' size-in-bits='64'>
|
||||
<function-decl name='__vfprintf_chk' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='e75a27e9'/>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='9d26089a'/>
|
||||
<parameter type-id='b7f2d5e6'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='strdup' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<return type-id='26a90f95'/>
|
||||
</function-decl>
|
||||
</abi-instr>
|
||||
<abi-instr address-size='64' path='uu_ident.c' language='LANG_C99'>
|
||||
<function-decl name='strchr' visibility='default' binding='global' size-in-bits='64'>
|
||||
|
@ -2144,13 +2132,6 @@
|
|||
<parameter type-id='3502e3ff' name='uflags'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='snprintf' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='26a90f95'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter is-variadic='yes'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='clock_gettime' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='a1c3b834'/>
|
||||
<parameter type-id='3d83ba87'/>
|
||||
|
@ -2160,6 +2141,12 @@
|
|||
<parameter type-id='80f4b756'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='__open_too_many_args' visibility='default' binding='global' size-in-bits='64'>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
<function-decl name='__open_missing_mode' visibility='default' binding='global' size-in-bits='64'>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
</abi-instr>
|
||||
<abi-instr address-size='64' path='uu_pname.c' language='LANG_C99'>
|
||||
<function-decl name='getexecname' mangled-name='getexecname' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='getexecname'>
|
||||
|
|
|
@ -1,14 +1,10 @@
|
|||
<abi-corpus version='2.0' architecture='elf-amd-x86_64' soname='libzfs.so.4'>
|
||||
<elf-needed>
|
||||
<dependency name='libzfs_core.so.3'/>
|
||||
<dependency name='libuuid.so.1'/>
|
||||
<dependency name='libblkid.so.1'/>
|
||||
<dependency name='libudev.so.1'/>
|
||||
<dependency name='libnvpair.so.3'/>
|
||||
<dependency name='libtirpc.so.3'/>
|
||||
<dependency name='libuutil.so.3'/>
|
||||
<dependency name='libm.so.6'/>
|
||||
<dependency name='libcrypto.so.1.1'/>
|
||||
<dependency name='libcrypto.so.3'/>
|
||||
<dependency name='libz.so.1'/>
|
||||
<dependency name='libc.so.6'/>
|
||||
</elf-needed>
|
||||
|
@ -536,11 +532,6 @@
|
|||
<parameter type-id='80f4b756'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='fputs' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='9d26089a'/>
|
||||
<parameter type-id='e75a27e9'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='flock' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
|
@ -599,8 +590,9 @@
|
|||
<parameter type-id='80f4b756'/>
|
||||
<return type-id='f09217ba'/>
|
||||
</function-decl>
|
||||
<function-decl name='fgets' visibility='default' binding='global' size-in-bits='64'>
|
||||
<function-decl name='__fgets_chk' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='266fe297'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='e75a27e9'/>
|
||||
<return type-id='26a90f95'/>
|
||||
|
@ -1369,7 +1361,7 @@
|
|||
<typedef-decl name='zpool_handle_t' type-id='67002a8a' id='b1efc708'/>
|
||||
<typedef-decl name='libzfs_handle_t' type-id='c8a9d9d8' id='95942d0c'/>
|
||||
<typedef-decl name='zfs_iter_f' type-id='5571cde4' id='d8e49ab9'/>
|
||||
<class-decl name='libzfs_handle' size-in-bits='20352' is-struct='yes' visibility='default' id='c8a9d9d8'>
|
||||
<class-decl name='libzfs_handle' size-in-bits='20416' is-struct='yes' visibility='default' id='c8a9d9d8'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='libzfs_error' type-id='95e97e5e' visibility='default'/>
|
||||
</data-member>
|
||||
|
@ -1436,6 +1428,9 @@
|
|||
<data-member access='public' layout-offset-in-bits='20288'>
|
||||
<var-decl name='libfetch_load_error' type-id='26a90f95' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='20352'>
|
||||
<var-decl name='libzfs_force_export' type-id='c19b74c3' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<class-decl name='zfs_handle' size-in-bits='4928' is-struct='yes' visibility='default' id='f6ee4445'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
|
@ -1760,6 +1755,54 @@
|
|||
<var-decl name='cl_haszonedchild' type-id='c19b74c3' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<typedef-decl name='__re_long_size_t' type-id='7359adad' id='ba516949'/>
|
||||
<typedef-decl name='reg_syntax_t' type-id='7359adad' id='1b72c3b3'/>
|
||||
<class-decl name='re_pattern_buffer' size-in-bits='512' is-struct='yes' visibility='default' id='19fc9a8c'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='buffer' type-id='33976309' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='64'>
|
||||
<var-decl name='allocated' type-id='ba516949' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='128'>
|
||||
<var-decl name='used' type-id='ba516949' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='192'>
|
||||
<var-decl name='syntax' type-id='1b72c3b3' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='256'>
|
||||
<var-decl name='fastmap' type-id='26a90f95' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='320'>
|
||||
<var-decl name='translate' type-id='cf536864' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='384'>
|
||||
<var-decl name='re_nsub' type-id='b59d7dce' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='448'>
|
||||
<var-decl name='can_be_null' type-id='f0981eeb' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='449'>
|
||||
<var-decl name='regs_allocated' type-id='f0981eeb' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='451'>
|
||||
<var-decl name='fastmap_accurate' type-id='f0981eeb' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='452'>
|
||||
<var-decl name='no_sub' type-id='f0981eeb' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='453'>
|
||||
<var-decl name='not_bol' type-id='f0981eeb' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='454'>
|
||||
<var-decl name='not_eol' type-id='f0981eeb' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='455'>
|
||||
<var-decl name='newline_anchor' type-id='f0981eeb' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<typedef-decl name='regex_t' type-id='19fc9a8c' id='aca3bac8'/>
|
||||
<typedef-decl name='uintptr_t' type-id='7359adad' id='e475ab95'/>
|
||||
<union-decl name='pthread_mutex_t' size-in-bits='320' naming-typedef-id='7a6844eb' visibility='default' id='70681f9b'>
|
||||
<data-member access='public'>
|
||||
<var-decl name='__data' type-id='4c734837' visibility='default'/>
|
||||
|
@ -1908,54 +1951,6 @@
|
|||
<var-decl name='_unused2' type-id='664ac0b7' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<typedef-decl name='__re_long_size_t' type-id='7359adad' id='ba516949'/>
|
||||
<typedef-decl name='reg_syntax_t' type-id='7359adad' id='1b72c3b3'/>
|
||||
<class-decl name='re_pattern_buffer' size-in-bits='512' is-struct='yes' visibility='default' id='19fc9a8c'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='buffer' type-id='33976309' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='64'>
|
||||
<var-decl name='allocated' type-id='ba516949' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='128'>
|
||||
<var-decl name='used' type-id='ba516949' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='192'>
|
||||
<var-decl name='syntax' type-id='1b72c3b3' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='256'>
|
||||
<var-decl name='fastmap' type-id='26a90f95' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='320'>
|
||||
<var-decl name='translate' type-id='cf536864' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='384'>
|
||||
<var-decl name='re_nsub' type-id='b59d7dce' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='448'>
|
||||
<var-decl name='can_be_null' type-id='f0981eeb' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='449'>
|
||||
<var-decl name='regs_allocated' type-id='f0981eeb' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='451'>
|
||||
<var-decl name='fastmap_accurate' type-id='f0981eeb' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='452'>
|
||||
<var-decl name='no_sub' type-id='f0981eeb' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='453'>
|
||||
<var-decl name='not_bol' type-id='f0981eeb' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='454'>
|
||||
<var-decl name='not_eol' type-id='f0981eeb' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='455'>
|
||||
<var-decl name='newline_anchor' type-id='f0981eeb' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<typedef-decl name='regex_t' type-id='19fc9a8c' id='aca3bac8'/>
|
||||
<typedef-decl name='uintptr_t' type-id='7359adad' id='e475ab95'/>
|
||||
<typedef-decl name='size_t' type-id='7359adad' id='b59d7dce'/>
|
||||
<pointer-type-def type-id='aa12d1ba' size-in-bits='64' id='822cd80b'/>
|
||||
<pointer-type-def type-id='ec1ed955' size-in-bits='64' id='dca988a5'/>
|
||||
|
@ -2734,11 +2729,6 @@
|
|||
<parameter type-id='80f4b756'/>
|
||||
<return type-id='26a90f95'/>
|
||||
</function-decl>
|
||||
<function-decl name='strcpy' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='26a90f95'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<return type-id='26a90f95'/>
|
||||
</function-decl>
|
||||
<function-decl name='strchr' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
|
@ -2800,6 +2790,18 @@
|
|||
</enum-decl>
|
||||
<typedef-decl name='zpool_prop_t' type-id='af1ba157' id='5d0c23fb'/>
|
||||
<typedef-decl name='uint_t' type-id='f0981eeb' id='3502e3ff'/>
|
||||
<typedef-decl name='regoff_t' type-id='95e97e5e' id='54a2a2a8'/>
|
||||
<class-decl name='regmatch_t' size-in-bits='64' is-struct='yes' naming-typedef-id='1b941664' visibility='default' id='4f932615'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='rm_so' type-id='54a2a2a8' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='32'>
|
||||
<var-decl name='rm_eo' type-id='54a2a2a8' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<typedef-decl name='regmatch_t' type-id='4f932615' id='1b941664'/>
|
||||
<typedef-decl name='__sighandler_t' type-id='03347643' id='8cdd9566'/>
|
||||
<typedef-decl name='ssize_t' type-id='41060289' id='79a0948f'/>
|
||||
<class-decl name='sigaction' size-in-bits='1216' is-struct='yes' visibility='default' id='fe391c48'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='__sigaction_handler' type-id='ac5ab598' visibility='default'/>
|
||||
|
@ -3008,18 +3010,6 @@
|
|||
</class-decl>
|
||||
<typedef-decl name='siginfo_t' type-id='d8149419' id='cb681f62'/>
|
||||
<typedef-decl name='sigset_t' type-id='b9c97942' id='daf33c64'/>
|
||||
<typedef-decl name='regoff_t' type-id='95e97e5e' id='54a2a2a8'/>
|
||||
<class-decl name='regmatch_t' size-in-bits='64' is-struct='yes' naming-typedef-id='1b941664' visibility='default' id='4f932615'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='rm_so' type-id='54a2a2a8' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='32'>
|
||||
<var-decl name='rm_eo' type-id='54a2a2a8' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<typedef-decl name='regmatch_t' type-id='4f932615' id='1b941664'/>
|
||||
<typedef-decl name='__sighandler_t' type-id='03347643' id='8cdd9566'/>
|
||||
<typedef-decl name='ssize_t' type-id='41060289' id='79a0948f'/>
|
||||
<qualified-type-def type-id='822cd80b' restrict='yes' id='e75a27e9'/>
|
||||
<qualified-type-def type-id='9b23c9ad' restrict='yes' id='8c85230f'/>
|
||||
<qualified-type-def type-id='80f4b756' restrict='yes' id='9d26089a'/>
|
||||
|
@ -3251,24 +3241,6 @@
|
|||
<parameter type-id='80f4b756'/>
|
||||
<return type-id='822cd80b'/>
|
||||
</function-decl>
|
||||
<function-decl name='printf' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter is-variadic='yes'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='snprintf' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='26a90f95'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter is-variadic='yes'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='asprintf' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='8c85230f'/>
|
||||
<parameter type-id='9d26089a'/>
|
||||
<parameter is-variadic='yes'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='fputc' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='822cd80b'/>
|
||||
|
@ -3281,13 +3253,6 @@
|
|||
<parameter type-id='e75a27e9'/>
|
||||
<return type-id='41060289'/>
|
||||
</function-decl>
|
||||
<function-decl name='fread' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='1b7446cd'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<parameter type-id='e75a27e9'/>
|
||||
<return type-id='b59d7dce'/>
|
||||
</function-decl>
|
||||
<function-decl name='rewind' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='822cd80b'/>
|
||||
<return type-id='48b5725f'/>
|
||||
|
@ -3309,12 +3274,6 @@
|
|||
<parameter type-id='b59d7dce'/>
|
||||
<return type-id='eaa32e2f'/>
|
||||
</function-decl>
|
||||
<function-decl name='memcpy' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='eaa32e2f'/>
|
||||
<parameter type-id='eaa32e2f'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<return type-id='eaa32e2f'/>
|
||||
</function-decl>
|
||||
<function-decl name='strdup' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<return type-id='26a90f95'/>
|
||||
|
@ -3338,12 +3297,6 @@
|
|||
<parameter type-id='95e97e5e'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='read' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='eaa32e2f'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<return type-id='79a0948f'/>
|
||||
</function-decl>
|
||||
<function-decl name='getpid' visibility='default' binding='global' size-in-bits='64'>
|
||||
<return type-id='3629bad8'/>
|
||||
</function-decl>
|
||||
|
@ -3355,6 +3308,40 @@
|
|||
<parameter type-id='80f4b756'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='__open_too_many_args' visibility='default' binding='global' size-in-bits='64'>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
<function-decl name='__open_missing_mode' visibility='default' binding='global' size-in-bits='64'>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
<function-decl name='__printf_chk' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter is-variadic='yes'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='__asprintf_chk' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='8c85230f'/>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='9d26089a'/>
|
||||
<parameter is-variadic='yes'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='__fread_chk' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='1b7446cd'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<parameter type-id='e75a27e9'/>
|
||||
<return type-id='b59d7dce'/>
|
||||
</function-decl>
|
||||
<function-decl name='__read_chk' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='eaa32e2f'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<return type-id='79a0948f'/>
|
||||
</function-decl>
|
||||
<function-type size-in-bits='64' id='ee076206'>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-type>
|
||||
|
@ -3399,13 +3386,13 @@
|
|||
<typedef-decl name='zprop_list_t' type-id='bd9b4291' id='bdb8ac4f'/>
|
||||
<class-decl name='renameflags' size-in-bits='32' is-struct='yes' visibility='default' id='7aee5792'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='recursive' type-id='95e97e5e' visibility='default'/>
|
||||
<var-decl name='recursive' type-id='f0981eeb' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='1'>
|
||||
<var-decl name='nounmount' type-id='95e97e5e' visibility='default'/>
|
||||
<var-decl name='nounmount' type-id='f0981eeb' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='2'>
|
||||
<var-decl name='forceunmount' type-id='95e97e5e' visibility='default'/>
|
||||
<var-decl name='forceunmount' type-id='f0981eeb' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<typedef-decl name='renameflags_t' type-id='7aee5792' id='067170c2'/>
|
||||
|
@ -3477,55 +3464,6 @@
|
|||
<var-decl name='mnt_mntopts' type-id='26a90f95' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<union-decl name='pthread_mutexattr_t' size-in-bits='32' naming-typedef-id='8afd6070' visibility='default' id='7300eb00'>
|
||||
<data-member access='public'>
|
||||
<var-decl name='__size' type-id='8e0573fd' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public'>
|
||||
<var-decl name='__align' type-id='95e97e5e' visibility='default'/>
|
||||
</data-member>
|
||||
</union-decl>
|
||||
<typedef-decl name='pthread_mutexattr_t' type-id='7300eb00' id='8afd6070'/>
|
||||
<typedef-decl name='int64_t' type-id='0c9942d2' id='9da381c4'/>
|
||||
<typedef-decl name='__int64_t' type-id='bd54fe1a' id='0c9942d2'/>
|
||||
<typedef-decl name='__gid_t' type-id='f0981eeb' id='d94ec6d9'/>
|
||||
<typedef-decl name='__time_t' type-id='bd54fe1a' id='65eda9c0'/>
|
||||
<class-decl name='tm' size-in-bits='448' is-struct='yes' visibility='default' id='dddf6ca2'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='tm_sec' type-id='95e97e5e' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='32'>
|
||||
<var-decl name='tm_min' type-id='95e97e5e' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='64'>
|
||||
<var-decl name='tm_hour' type-id='95e97e5e' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='96'>
|
||||
<var-decl name='tm_mday' type-id='95e97e5e' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='128'>
|
||||
<var-decl name='tm_mon' type-id='95e97e5e' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='160'>
|
||||
<var-decl name='tm_year' type-id='95e97e5e' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='192'>
|
||||
<var-decl name='tm_wday' type-id='95e97e5e' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='224'>
|
||||
<var-decl name='tm_yday' type-id='95e97e5e' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='256'>
|
||||
<var-decl name='tm_isdst' type-id='95e97e5e' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='320'>
|
||||
<var-decl name='tm_gmtoff' type-id='bd54fe1a' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='384'>
|
||||
<var-decl name='tm_zone' type-id='80f4b756' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<typedef-decl name='time_t' type-id='65eda9c0' id='c9d12d66'/>
|
||||
<class-decl name='group' size-in-bits='256' is-struct='yes' visibility='default' id='01a1b934'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='gr_name' type-id='26a90f95' visibility='default'/>
|
||||
|
@ -3583,6 +3521,55 @@
|
|||
<var-decl name='pw_shell' type-id='26a90f95' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<union-decl name='pthread_mutexattr_t' size-in-bits='32' naming-typedef-id='8afd6070' visibility='default' id='7300eb00'>
|
||||
<data-member access='public'>
|
||||
<var-decl name='__size' type-id='8e0573fd' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public'>
|
||||
<var-decl name='__align' type-id='95e97e5e' visibility='default'/>
|
||||
</data-member>
|
||||
</union-decl>
|
||||
<typedef-decl name='pthread_mutexattr_t' type-id='7300eb00' id='8afd6070'/>
|
||||
<typedef-decl name='int64_t' type-id='0c9942d2' id='9da381c4'/>
|
||||
<typedef-decl name='__int64_t' type-id='bd54fe1a' id='0c9942d2'/>
|
||||
<typedef-decl name='__gid_t' type-id='f0981eeb' id='d94ec6d9'/>
|
||||
<typedef-decl name='__time_t' type-id='bd54fe1a' id='65eda9c0'/>
|
||||
<class-decl name='tm' size-in-bits='448' is-struct='yes' visibility='default' id='dddf6ca2'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='tm_sec' type-id='95e97e5e' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='32'>
|
||||
<var-decl name='tm_min' type-id='95e97e5e' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='64'>
|
||||
<var-decl name='tm_hour' type-id='95e97e5e' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='96'>
|
||||
<var-decl name='tm_mday' type-id='95e97e5e' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='128'>
|
||||
<var-decl name='tm_mon' type-id='95e97e5e' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='160'>
|
||||
<var-decl name='tm_year' type-id='95e97e5e' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='192'>
|
||||
<var-decl name='tm_wday' type-id='95e97e5e' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='224'>
|
||||
<var-decl name='tm_yday' type-id='95e97e5e' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='256'>
|
||||
<var-decl name='tm_isdst' type-id='95e97e5e' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='320'>
|
||||
<var-decl name='tm_gmtoff' type-id='bd54fe1a' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='384'>
|
||||
<var-decl name='tm_zone' type-id='80f4b756' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<typedef-decl name='time_t' type-id='65eda9c0' id='c9d12d66'/>
|
||||
<typedef-decl name='uid_t' type-id='cc5fcceb' id='354978ed'/>
|
||||
<pointer-type-def type-id='fba6cb51' size-in-bits='64' id='32adbf30'/>
|
||||
<pointer-type-def type-id='f20fbd51' size-in-bits='64' id='a3681dea'/>
|
||||
|
@ -4457,12 +4444,6 @@
|
|||
<parameter type-id='80f4b756'/>
|
||||
<return type-id='a195f4a3'/>
|
||||
</function-decl>
|
||||
<function-decl name='fprintf' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='e75a27e9'/>
|
||||
<parameter type-id='9d26089a'/>
|
||||
<parameter is-variadic='yes'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='strtol' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='9d26089a'/>
|
||||
<parameter type-id='8c85230f'/>
|
||||
|
@ -4478,12 +4459,6 @@
|
|||
<function-decl name='abort' visibility='default' binding='global' size-in-bits='64'>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
<function-decl name='strncpy' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='26a90f95'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<return type-id='26a90f95'/>
|
||||
</function-decl>
|
||||
<function-decl name='strrchr' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
|
@ -4504,12 +4479,6 @@
|
|||
<parameter type-id='9d26089a'/>
|
||||
<return type-id='26a90f95'/>
|
||||
</function-decl>
|
||||
<function-decl name='ioctl' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='7359adad'/>
|
||||
<parameter is-variadic='yes'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='strftime' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='266fe297'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
|
@ -4522,6 +4491,19 @@
|
|||
<parameter type-id='f099ad08'/>
|
||||
<return type-id='d915a820'/>
|
||||
</function-decl>
|
||||
<function-decl name='__fprintf_chk' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='e75a27e9'/>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='9d26089a'/>
|
||||
<parameter is-variadic='yes'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='ioctl' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='7359adad'/>
|
||||
<parameter is-variadic='yes'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-type size-in-bits='64' id='7e291ce6'>
|
||||
<parameter type-id='eaa32e2f'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
|
@ -4534,7 +4516,7 @@
|
|||
<array-type-def dimensions='1' type-id='a84c031d' size-in-bits='448' id='6093ff7c'>
|
||||
<subrange length='56' type-id='7359adad' id='f8137894'/>
|
||||
</array-type-def>
|
||||
<class-decl name='differ_info' size-in-bits='9024' is-struct='yes' visibility='default' id='d41965ee'>
|
||||
<class-decl name='differ_info' size-in-bits='9088' is-struct='yes' visibility='default' id='d41965ee'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='zhp' type-id='9200a744' visibility='default'/>
|
||||
</data-member>
|
||||
|
@ -4575,18 +4557,21 @@
|
|||
<var-decl name='timestamped' type-id='c19b74c3' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='8832'>
|
||||
<var-decl name='shares' type-id='9c313c2d' visibility='default'/>
|
||||
<var-decl name='no_mangle' type-id='c19b74c3' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='8896'>
|
||||
<var-decl name='zerr' type-id='95e97e5e' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='8928'>
|
||||
<var-decl name='cleanupfd' type-id='95e97e5e' visibility='default'/>
|
||||
<var-decl name='shares' type-id='9c313c2d' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='8960'>
|
||||
<var-decl name='outputfd' type-id='95e97e5e' visibility='default'/>
|
||||
<var-decl name='zerr' type-id='95e97e5e' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='8992'>
|
||||
<var-decl name='cleanupfd' type-id='95e97e5e' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='9024'>
|
||||
<var-decl name='outputfd' type-id='95e97e5e' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='9056'>
|
||||
<var-decl name='datafd' type-id='95e97e5e' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
|
@ -4624,6 +4609,13 @@
|
|||
<parameter type-id='ee78f675'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='color_start' mangled-name='color_start' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='color_start'>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
<function-decl name='color_end' mangled-name='color_end' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='color_end'>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
<function-decl name='zfs_show_diffs' mangled-name='zfs_show_diffs' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_show_diffs'>
|
||||
<parameter type-id='9200a744' name='zhp'/>
|
||||
<parameter type-id='95e97e5e' name='outfd'/>
|
||||
|
@ -4648,6 +4640,11 @@
|
|||
<parameter type-id='4051f5e7'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='fputs' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='9d26089a'/>
|
||||
<parameter type-id='e75a27e9'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='pipe2' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='7292109c'/>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
|
@ -4777,24 +4774,6 @@
|
|||
<parameter type-id='37e3bd22' name='inuse'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='memset' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='eaa32e2f'/>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<return type-id='eaa32e2f'/>
|
||||
</function-decl>
|
||||
<function-decl name='fstat64' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='62f7a03d'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='pread64' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='eaa32e2f'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<parameter type-id='724e4de6'/>
|
||||
<return type-id='79a0948f'/>
|
||||
</function-decl>
|
||||
<function-decl name='pwrite64' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='eaa32e2f'/>
|
||||
|
@ -4802,6 +4781,19 @@
|
|||
<parameter type-id='724e4de6'/>
|
||||
<return type-id='79a0948f'/>
|
||||
</function-decl>
|
||||
<function-decl name='__pread64_chk' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='eaa32e2f'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<parameter type-id='724e4de6'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<return type-id='79a0948f'/>
|
||||
</function-decl>
|
||||
<function-decl name='fstat64' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='62f7a03d'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-type size-in-bits='64' id='baa42fef'>
|
||||
<parameter type-id='eaa32e2f'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
|
@ -4900,6 +4892,9 @@
|
|||
</class-decl>
|
||||
<typedef-decl name='proto_table_t' type-id='f4c8e1ed' id='f1bd64e2'/>
|
||||
<typedef-decl name='tpool_t' type-id='88d1b7f9' id='b1bbf10d'/>
|
||||
<typedef-decl name='DIR' type-id='20cd73f2' id='54a5d683'/>
|
||||
<typedef-decl name='mode_t' type-id='e1c52942' id='d50d396c'/>
|
||||
<typedef-decl name='__compar_fn_t' type-id='585e1de9' id='aba7edd8'/>
|
||||
<class-decl name='dirent64' size-in-bits='2240' is-struct='yes' visibility='default' id='5725d813'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='d_ino' type-id='71288a47' visibility='default'/>
|
||||
|
@ -5013,9 +5008,6 @@
|
|||
<typedef-decl name='__fsblkcnt64_t' type-id='7359adad' id='95fe1a02'/>
|
||||
<typedef-decl name='__fsfilcnt64_t' type-id='7359adad' id='0c3a4dde'/>
|
||||
<typedef-decl name='__fsword_t' type-id='bd54fe1a' id='6028cbfe'/>
|
||||
<typedef-decl name='DIR' type-id='20cd73f2' id='54a5d683'/>
|
||||
<typedef-decl name='mode_t' type-id='e1c52942' id='d50d396c'/>
|
||||
<typedef-decl name='__compar_fn_t' type-id='585e1de9' id='aba7edd8'/>
|
||||
<pointer-type-def type-id='54a5d683' size-in-bits='64' id='f09217ba'/>
|
||||
<pointer-type-def type-id='5725d813' size-in-bits='64' id='07b96073'/>
|
||||
<pointer-type-def type-id='9b293607' size-in-bits='64' id='77bf1784'/>
|
||||
|
@ -5235,15 +5227,21 @@
|
|||
<parameter type-id='aba7edd8'/>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
<function-decl name='rmdir' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='__openat_too_many_args' visibility='default' binding='global' size-in-bits='64'>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
<function-decl name='__openat_missing_mode' visibility='default' binding='global' size-in-bits='64'>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
<function-decl name='statfs64' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='7fd094c8'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='rmdir' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-type size-in-bits='64' id='c5c76c9c'>
|
||||
<parameter type-id='eaa32e2f'/>
|
||||
<return type-id='48b5725f'/>
|
||||
|
@ -5253,10 +5251,10 @@
|
|||
<type-decl name='long long unsigned int' size-in-bits='64' id='3a47d82b'/>
|
||||
<class-decl name='splitflags' size-in-bits='64' is-struct='yes' visibility='default' id='dc01bf52'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='dryrun' type-id='95e97e5e' visibility='default'/>
|
||||
<var-decl name='dryrun' type-id='f0981eeb' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='1'>
|
||||
<var-decl name='import' type-id='95e97e5e' visibility='default'/>
|
||||
<var-decl name='import' type-id='f0981eeb' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='32'>
|
||||
<var-decl name='name_flags' type-id='95e97e5e' visibility='default'/>
|
||||
|
@ -5312,7 +5310,8 @@
|
|||
<enumerator name='ZPOOL_STATUS_NON_NATIVE_ASHIFT' value='29'/>
|
||||
<enumerator name='ZPOOL_STATUS_COMPATIBILITY_ERR' value='30'/>
|
||||
<enumerator name='ZPOOL_STATUS_INCOMPATIBLE_FEAT' value='31'/>
|
||||
<enumerator name='ZPOOL_STATUS_OK' value='32'/>
|
||||
<enumerator name='ZPOOL_STATUS_FORCE_EXPORTING' value='32'/>
|
||||
<enumerator name='ZPOOL_STATUS_OK' value='33'/>
|
||||
</enum-decl>
|
||||
<typedef-decl name='zpool_status_t' type-id='5e770b40' id='d3dd6294'/>
|
||||
<enum-decl name='zpool_compat_status_t' naming-typedef-id='901b78d1' id='20676925'>
|
||||
|
@ -6042,11 +6041,6 @@
|
|||
<parameter type-id='95e97e5e'/>
|
||||
<return type-id='3a47d82b'/>
|
||||
</function-decl>
|
||||
<function-decl name='realpath' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='9d26089a'/>
|
||||
<parameter type-id='266fe297'/>
|
||||
<return type-id='26a90f95'/>
|
||||
</function-decl>
|
||||
<function-decl name='memcmp' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='eaa32e2f'/>
|
||||
<parameter type-id='eaa32e2f'/>
|
||||
|
@ -6065,6 +6059,12 @@
|
|||
<parameter type-id='b59d7dce'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='__realpath_chk' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='9d26089a'/>
|
||||
<parameter type-id='266fe297'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<return type-id='26a90f95'/>
|
||||
</function-decl>
|
||||
<function-decl name='munmap' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='eaa32e2f'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
|
@ -6846,21 +6846,10 @@
|
|||
<parameter type-id='a3681dea' name='stream_avl'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='sprintf' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='26a90f95'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter is-variadic='yes'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='perror' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
<function-decl name='strcat' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='26a90f95'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<return type-id='26a90f95'/>
|
||||
</function-decl>
|
||||
<function-decl name='strndup' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
|
@ -7243,24 +7232,12 @@
|
|||
<function-decl name='zfs_version_print' mangled-name='zfs_version_print' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_version_print'>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='color_start' mangled-name='color_start' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='color_start'>
|
||||
<parameter type-id='26a90f95' name='color'/>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
<function-decl name='color_end' mangled-name='color_end' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='color_end'>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
<function-decl name='printf_color' mangled-name='printf_color' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='printf_color'>
|
||||
<parameter type-id='26a90f95' name='color'/>
|
||||
<parameter type-id='80f4b756' name='color'/>
|
||||
<parameter type-id='26a90f95' name='format'/>
|
||||
<parameter is-variadic='yes'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='pow' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='a0eb0f08'/>
|
||||
<parameter type-id='a0eb0f08'/>
|
||||
<return type-id='a0eb0f08'/>
|
||||
</function-decl>
|
||||
<function-decl name='__ctype_toupper_loc' visibility='default' binding='global' size-in-bits='64'>
|
||||
<return type-id='24f95ba5'/>
|
||||
</function-decl>
|
||||
|
@ -7278,25 +7255,6 @@
|
|||
<parameter type-id='d33f11cb'/>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
<function-decl name='vfprintf' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='e75a27e9'/>
|
||||
<parameter type-id='9d26089a'/>
|
||||
<parameter type-id='b7f2d5e6'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='vsnprintf' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='26a90f95'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='b7f2d5e6'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='vasprintf' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='8c85230f'/>
|
||||
<parameter type-id='9d26089a'/>
|
||||
<parameter type-id='b7f2d5e6'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='strtod' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='9d26089a'/>
|
||||
<parameter type-id='8c85230f'/>
|
||||
|
@ -7316,12 +7274,6 @@
|
|||
<parameter type-id='b59d7dce'/>
|
||||
<return type-id='b59d7dce'/>
|
||||
</function-decl>
|
||||
<function-decl name='waitpid' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='3629bad8'/>
|
||||
<parameter type-id='7292109c'/>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<return type-id='3629bad8'/>
|
||||
</function-decl>
|
||||
<function-decl name='dup2' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
|
@ -7356,6 +7308,31 @@
|
|||
<function-decl name='vfork' visibility='default' binding='global' size-in-bits='64'>
|
||||
<return type-id='3629bad8'/>
|
||||
</function-decl>
|
||||
<function-decl name='pow' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='a0eb0f08'/>
|
||||
<parameter type-id='a0eb0f08'/>
|
||||
<return type-id='a0eb0f08'/>
|
||||
</function-decl>
|
||||
<function-decl name='__vfprintf_chk' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='e75a27e9'/>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='9d26089a'/>
|
||||
<parameter type-id='b7f2d5e6'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='__vasprintf_chk' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='8c85230f'/>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='9d26089a'/>
|
||||
<parameter type-id='b7f2d5e6'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='waitpid' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='3629bad8'/>
|
||||
<parameter type-id='7292109c'/>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<return type-id='3629bad8'/>
|
||||
</function-decl>
|
||||
<function-type size-in-bits='64' id='c70fa2e8'>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='eaa32e2f'/>
|
||||
|
@ -7364,6 +7341,9 @@
|
|||
</abi-instr>
|
||||
<abi-instr address-size='64' path='os/linux/libzfs_mount_os.c' language='LANG_C99'>
|
||||
<pointer-type-def type-id='7359adad' size-in-bits='64' id='1d2c2b85'/>
|
||||
<function-decl name='geteuid' visibility='default' binding='global' size-in-bits='64'>
|
||||
<return type-id='cc5fcceb'/>
|
||||
</function-decl>
|
||||
<function-decl name='mount' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
|
@ -7377,9 +7357,6 @@
|
|||
<parameter type-id='95e97e5e'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='geteuid' visibility='default' binding='global' size-in-bits='64'>
|
||||
<return type-id='cc5fcceb'/>
|
||||
</function-decl>
|
||||
<function-decl name='zfs_parse_mount_options' mangled-name='zfs_parse_mount_options' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_parse_mount_options'>
|
||||
<parameter type-id='26a90f95' name='mntopts'/>
|
||||
<parameter type-id='1d2c2b85' name='mntflags'/>
|
||||
|
|
|
@ -481,8 +481,6 @@ make_dataset_handle_common(zfs_handle_t *zhp, zfs_cmd_t *zc)
|
|||
zfs_handle_t *
|
||||
make_dataset_handle(libzfs_handle_t *hdl, const char *path)
|
||||
{
|
||||
zfs_cmd_t zc = {"\0"};
|
||||
|
||||
zfs_handle_t *zhp = calloc(1, sizeof (zfs_handle_t));
|
||||
|
||||
if (zhp == NULL)
|
||||
|
@ -490,20 +488,33 @@ make_dataset_handle(libzfs_handle_t *hdl, const char *path)
|
|||
|
||||
zhp->zfs_hdl = hdl;
|
||||
(void) strlcpy(zhp->zfs_name, path, sizeof (zhp->zfs_name));
|
||||
if (zcmd_alloc_dst_nvlist(hdl, &zc, 0) != 0) {
|
||||
free(zhp);
|
||||
return (NULL);
|
||||
}
|
||||
if (get_stats_ioctl(zhp, &zc) == -1) {
|
||||
if (!hdl->libzfs_force_export) {
|
||||
zfs_cmd_t zc = {"\0"};
|
||||
|
||||
zcmd_alloc_dst_nvlist(hdl, &zc, 0);
|
||||
if (get_stats_ioctl(zhp, &zc) == -1) {
|
||||
zcmd_free_nvlists(&zc);
|
||||
free(zhp);
|
||||
return (NULL);
|
||||
}
|
||||
if (make_dataset_handle_common(zhp, &zc) == -1) {
|
||||
free(zhp);
|
||||
zhp = NULL;
|
||||
}
|
||||
zcmd_free_nvlists(&zc);
|
||||
free(zhp);
|
||||
return (NULL);
|
||||
} else {
|
||||
/*
|
||||
* Called from zpool_disable_datasets() which sets force
|
||||
* export and uses mount entries, so de facto the dataset
|
||||
* is a ZFS filesystem. Furthermore, we need to avoid
|
||||
* calling get_stats_ioctl() here since it results in
|
||||
* zfs_ioc_objset_stats()->dmu_objset_hold() being called by
|
||||
* the kernel which can potentially cause IO to be issued
|
||||
* depending on what's currently cached in ARC.
|
||||
*/
|
||||
zhp->zfs_dmustats.dds_type = DMU_OST_ZFS;
|
||||
zhp->zfs_type = ZFS_TYPE_FILESYSTEM;
|
||||
}
|
||||
if (make_dataset_handle_common(zhp, &zc) == -1) {
|
||||
free(zhp);
|
||||
zhp = NULL;
|
||||
}
|
||||
zcmd_free_nvlists(&zc);
|
||||
return (zhp);
|
||||
}
|
||||
|
||||
|
|
|
@ -1525,7 +1525,8 @@ mountpoint_compare(const void *a, const void *b)
|
|||
* and gather all the filesystems that are currently mounted.
|
||||
*/
|
||||
int
|
||||
zpool_disable_datasets(zpool_handle_t *zhp, boolean_t force)
|
||||
zpool_disable_datasets(zpool_handle_t *zhp, boolean_t force,
|
||||
boolean_t hardforce)
|
||||
{
|
||||
int used, alloc;
|
||||
struct mnttab entry;
|
||||
|
@ -1535,8 +1536,9 @@ zpool_disable_datasets(zpool_handle_t *zhp, boolean_t force)
|
|||
libzfs_handle_t *hdl = zhp->zpool_hdl;
|
||||
int i;
|
||||
int ret = -1;
|
||||
int flags = (force ? MS_FORCE : 0);
|
||||
int flags = ((hardforce || force) ? MS_FORCE : 0);
|
||||
|
||||
hdl->libzfs_force_export = flags & MS_FORCE;
|
||||
namelen = strlen(zhp->zpool_name);
|
||||
|
||||
/* Reopen MNTTAB to prevent reading stale data from open file */
|
||||
|
@ -1615,6 +1617,10 @@ zpool_disable_datasets(zpool_handle_t *zhp, boolean_t force)
|
|||
*/
|
||||
qsort(mountpoints, used, sizeof (char *), mountpoint_compare);
|
||||
|
||||
if (hardforce) {
|
||||
zpool_unmount_mark_hard_force_begin(zhp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Walk through and first unshare everything.
|
||||
*/
|
||||
|
@ -1639,9 +1645,15 @@ zpool_disable_datasets(zpool_handle_t *zhp, boolean_t force)
|
|||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < used; i++) {
|
||||
if (datasets[i])
|
||||
remove_mountpoint(datasets[i]);
|
||||
/*
|
||||
* Remove mountpoints, unless the pool is being forcibly exported.
|
||||
* In the latter case, avoid potentially initiating I/O on the pool.
|
||||
*/
|
||||
if (!hdl->libzfs_force_export) {
|
||||
for (i = 0; i < used; i++) {
|
||||
if (datasets[i])
|
||||
remove_mountpoint(datasets[i]);
|
||||
}
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
@ -1654,5 +1666,9 @@ out:
|
|||
free(datasets);
|
||||
free(mountpoints);
|
||||
|
||||
if (hardforce) {
|
||||
zpool_unmount_mark_hard_force_end(zhp);
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
|
|
@ -260,7 +260,9 @@ zpool_get_state_str(zpool_handle_t *zhp)
|
|||
|
||||
status = zpool_get_status(zhp, NULL, &errata);
|
||||
|
||||
if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
|
||||
if (status == ZPOOL_STATUS_FORCE_EXPORTING) {
|
||||
str = gettext("FORCE-EXPORTING");
|
||||
} else if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
|
||||
str = gettext("FAULTED");
|
||||
} else if (status == ZPOOL_STATUS_IO_FAILURE_WAIT ||
|
||||
status == ZPOOL_STATUS_IO_FAILURE_MMP) {
|
||||
|
@ -1481,7 +1483,9 @@ zpool_destroy(zpool_handle_t *zhp, const char *log_str)
|
|||
}
|
||||
|
||||
if (zfp) {
|
||||
remove_mountpoint(zfp);
|
||||
/* Avoid initiating I/O during a forced export. */
|
||||
if (!hdl->libzfs_force_export)
|
||||
remove_mountpoint(zfp);
|
||||
zfs_close(zfp);
|
||||
}
|
||||
|
||||
|
|
|
@ -236,6 +236,9 @@ check_status(nvlist_t *config, boolean_t isimport,
|
|||
uint64_t errata = 0;
|
||||
unsigned long system_hostid = get_system_hostid();
|
||||
|
||||
if (config == NULL)
|
||||
return (ZPOOL_STATUS_FORCE_EXPORTING);
|
||||
|
||||
verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
|
||||
&version) == 0);
|
||||
verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
|
||||
|
|
|
@ -133,3 +133,15 @@ zfs_mount_delegation_check(void)
|
|||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
zpool_unmount_mark_hard_force_begin(zpool_handle_t *zhp)
|
||||
{
|
||||
(void) zhp;
|
||||
}
|
||||
|
||||
void
|
||||
zpool_unmount_mark_hard_force_end(zpool_handle_t *zhp)
|
||||
{
|
||||
(void) zhp;
|
||||
}
|
||||
|
|
|
@ -411,3 +411,23 @@ zfs_mount_delegation_check(void)
|
|||
{
|
||||
return ((geteuid() != 0) ? EACCES : 0);
|
||||
}
|
||||
|
||||
void
|
||||
zpool_unmount_mark_hard_force_begin(zpool_handle_t *zhp)
|
||||
{
|
||||
zfs_cmd_t zc = {"\0"};
|
||||
libzfs_handle_t *hdl = zhp->zpool_hdl;
|
||||
|
||||
(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
|
||||
(void) zfs_ioctl(hdl, ZFS_IOC_HARD_FORCE_UNMOUNT_BEGIN, &zc);
|
||||
}
|
||||
|
||||
void
|
||||
zpool_unmount_mark_hard_force_end(zpool_handle_t *zhp)
|
||||
{
|
||||
zfs_cmd_t zc = {"\0"};
|
||||
libzfs_handle_t *hdl = zhp->zpool_hdl;
|
||||
|
||||
(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
|
||||
(void) zfs_ioctl(hdl, ZFS_IOC_HARD_FORCE_UNMOUNT_END, &zc);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
<dependency name='libblkid.so.1'/>
|
||||
<dependency name='libudev.so.1'/>
|
||||
<dependency name='libnvpair.so.3'/>
|
||||
<dependency name='libtirpc.so.3'/>
|
||||
<dependency name='libc.so.6'/>
|
||||
<dependency name='ld-linux-x86-64.so.2'/>
|
||||
</elf-needed>
|
||||
|
@ -405,12 +404,6 @@
|
|||
<parameter type-id='c43b27a6' name='vtoc'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='sprintf' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='26a90f95'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter is-variadic='yes'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='write' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='eaa32e2f'/>
|
||||
|
@ -438,16 +431,32 @@
|
|||
<type-decl name='unsigned long int' size-in-bits='64' id='7359adad'/>
|
||||
</abi-instr>
|
||||
<abi-instr address-size='64' path='assert.c' language='LANG_C99'>
|
||||
<class-decl name='__va_list_tag' size-in-bits='192' is-struct='yes' visibility='default' id='d5027220'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='gp_offset' type-id='f0981eeb' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='32'>
|
||||
<var-decl name='fp_offset' type-id='f0981eeb' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='64'>
|
||||
<var-decl name='overflow_arg_area' type-id='eaa32e2f' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='128'>
|
||||
<var-decl name='reg_save_area' type-id='eaa32e2f' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<pointer-type-def type-id='d5027220' size-in-bits='64' id='b7f2d5e6'/>
|
||||
<var-decl name='aok' type-id='95e97e5e' mangled-name='aok' visibility='default' elf-symbol-id='aok'/>
|
||||
<function-decl name='vfprintf' visibility='default' binding='global' size-in-bits='64'>
|
||||
<function-decl name='abort' visibility='default' binding='global' size-in-bits='64'>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
<function-decl name='__vfprintf_chk' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='e75a27e9'/>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='9d26089a'/>
|
||||
<parameter type-id='b7f2d5e6'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='abort' visibility='default' binding='global' size-in-bits='64'>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
</abi-instr>
|
||||
<abi-instr address-size='64' path='atomic.c' language='LANG_C99'>
|
||||
<typedef-decl name='int8_t' type-id='2171a512' id='ee31ee44'/>
|
||||
|
@ -893,16 +902,18 @@
|
|||
<parameter type-id='d50d396c' name='mode'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='mbstowcs' visibility='default' binding='global' size-in-bits='64'>
|
||||
<function-decl name='__mbstowcs_chk' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='f1358bc3'/>
|
||||
<parameter type-id='9d26089a'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<return type-id='b59d7dce'/>
|
||||
</function-decl>
|
||||
<function-decl name='wcstombs' visibility='default' binding='global' size-in-bits='64'>
|
||||
<function-decl name='__wcstombs_chk' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='266fe297'/>
|
||||
<parameter type-id='598aab80'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<return type-id='b59d7dce'/>
|
||||
</function-decl>
|
||||
<function-decl name='mkdir' visibility='default' binding='global' size-in-bits='64'>
|
||||
|
@ -1022,15 +1033,8 @@
|
|||
<abi-instr address-size='64' path='page.c' language='LANG_C99'>
|
||||
<var-decl name='pagesize' type-id='b59d7dce' mangled-name='pagesize' visibility='default' elf-symbol-id='pagesize'/>
|
||||
</abi-instr>
|
||||
<abi-instr address-size='64' path='strlcat.c' language='LANG_C99'>
|
||||
<function-decl name='memcpy' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='eaa32e2f'/>
|
||||
<parameter type-id='eaa32e2f'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<return type-id='eaa32e2f'/>
|
||||
</function-decl>
|
||||
</abi-instr>
|
||||
<abi-instr address-size='64' path='timestamp.c' language='LANG_C99'>
|
||||
<typedef-decl name='nl_item' type-id='95e97e5e' id='03b79a94'/>
|
||||
<class-decl name='tm' size-in-bits='448' is-struct='yes' visibility='default' id='dddf6ca2'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='tm_sec' type-id='95e97e5e' visibility='default'/>
|
||||
|
@ -1067,7 +1071,6 @@
|
|||
</data-member>
|
||||
</class-decl>
|
||||
<typedef-decl name='time_t' type-id='65eda9c0' id='c9d12d66'/>
|
||||
<typedef-decl name='nl_item' type-id='95e97e5e' id='03b79a94'/>
|
||||
<qualified-type-def type-id='c9d12d66' const='yes' id='588b3216'/>
|
||||
<pointer-type-def type-id='588b3216' size-in-bits='64' id='9f201474'/>
|
||||
<qualified-type-def type-id='dddf6ca2' const='yes' id='e824a34f'/>
|
||||
|
@ -1142,6 +1145,40 @@
|
|||
<var-decl name='tpa_tid' type-id='4051f5e7' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<class-decl name='__cancel_jmp_buf_tag' size-in-bits='576' is-struct='yes' visibility='default' id='8901473c'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='__cancel_jmp_buf' type-id='379a1ab7' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='512'>
|
||||
<var-decl name='__mask_was_saved' type-id='95e97e5e' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<class-decl name='__pthread_unwind_buf_t' size-in-bits='832' is-struct='yes' naming-typedef-id='4423cf7f' visibility='default' id='a0abc656'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='__cancel_jmp_buf' type-id='f5da478b' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='576'>
|
||||
<var-decl name='__pad' type-id='209ef23f' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<typedef-decl name='__pthread_unwind_buf_t' type-id='a0abc656' id='4423cf7f'/>
|
||||
<union-decl name='__atomic_wide_counter' size-in-bits='64' naming-typedef-id='f3b40860' visibility='default' id='613ce450'>
|
||||
<data-member access='public'>
|
||||
<var-decl name='__value64' type-id='3a47d82b' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public'>
|
||||
<var-decl name='__value32' type-id='e7f43f72' visibility='default'/>
|
||||
</data-member>
|
||||
</union-decl>
|
||||
<class-decl name='__anonymous_struct__' size-in-bits='64' is-struct='yes' is-anonymous='yes' visibility='default' id='e7f43f72'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='__low' type-id='f0981eeb' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='32'>
|
||||
<var-decl name='__high' type-id='f0981eeb' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<typedef-decl name='__atomic_wide_counter' type-id='613ce450' id='f3b40860'/>
|
||||
<typedef-decl name='__cpu_mask' type-id='7359adad' id='49ef3ffd'/>
|
||||
<class-decl name='cpu_set_t' size-in-bits='1024' is-struct='yes' naming-typedef-id='8037c762' visibility='default' id='1f20d231'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
|
@ -1174,10 +1211,10 @@
|
|||
<typedef-decl name='__jmp_buf' type-id='5d4efd44' id='379a1ab7'/>
|
||||
<class-decl name='__pthread_cond_s' size-in-bits='384' is-struct='yes' visibility='default' id='c987b47c'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='' type-id='ac5ab595' visibility='default'/>
|
||||
<var-decl name='__wseq' type-id='f3b40860' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='64'>
|
||||
<var-decl name='' type-id='ac5ab596' visibility='default'/>
|
||||
<var-decl name='__g1_start' type-id='f3b40860' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='128'>
|
||||
<var-decl name='__g_refs' type-id='0d532ec1' visibility='default'/>
|
||||
|
@ -1195,30 +1232,6 @@
|
|||
<var-decl name='__g_signals' type-id='0d532ec1' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<union-decl name='__anonymous_union__1' size-in-bits='64' is-anonymous='yes' visibility='default' id='ac5ab595'>
|
||||
<data-member access='public'>
|
||||
<var-decl name='__wseq' type-id='3a47d82b' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public'>
|
||||
<var-decl name='__wseq32' type-id='e7f43f72' visibility='default'/>
|
||||
</data-member>
|
||||
</union-decl>
|
||||
<class-decl name='__anonymous_struct__' size-in-bits='64' is-struct='yes' is-anonymous='yes' visibility='default' id='e7f43f72'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='__low' type-id='f0981eeb' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='32'>
|
||||
<var-decl name='__high' type-id='f0981eeb' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<union-decl name='__anonymous_union__2' size-in-bits='64' is-anonymous='yes' visibility='default' id='ac5ab596'>
|
||||
<data-member access='public'>
|
||||
<var-decl name='__g1_start' type-id='3a47d82b' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public'>
|
||||
<var-decl name='__g1_start32' type-id='e7f43f72' visibility='default'/>
|
||||
</data-member>
|
||||
</union-decl>
|
||||
<class-decl name='__sigset_t' size-in-bits='1024' is-struct='yes' naming-typedef-id='b9c97942' visibility='default' id='2616147f'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='__val' type-id='d2baa450' visibility='default'/>
|
||||
|
@ -1230,23 +1243,6 @@
|
|||
<var-decl name='sched_priority' type-id='95e97e5e' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<class-decl name='__cancel_jmp_buf_tag' size-in-bits='576' is-struct='yes' visibility='default' id='8901473c'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='__cancel_jmp_buf' type-id='379a1ab7' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='512'>
|
||||
<var-decl name='__mask_was_saved' type-id='95e97e5e' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<class-decl name='__pthread_unwind_buf_t' size-in-bits='832' is-struct='yes' naming-typedef-id='4423cf7f' visibility='default' id='a0abc656'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='__cancel_jmp_buf' type-id='f5da478b' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='576'>
|
||||
<var-decl name='__pad' type-id='209ef23f' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<typedef-decl name='__pthread_unwind_buf_t' type-id='a0abc656' id='4423cf7f'/>
|
||||
<pointer-type-def type-id='8901473c' size-in-bits='64' id='eb91b7ea'/>
|
||||
<pointer-type-def type-id='4423cf7f' size-in-bits='64' id='ba7c727c'/>
|
||||
<pointer-type-def type-id='b9c97942' size-in-bits='64' id='bbf06c47'/>
|
||||
|
@ -1304,16 +1300,6 @@
|
|||
<parameter type-id='9cf59a50' name='tpool'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='__sysconf' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<return type-id='bd54fe1a'/>
|
||||
</function-decl>
|
||||
<function-decl name='pthread_sigmask' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='5a8729d0'/>
|
||||
<parameter type-id='65e6ec45'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='pthread_create' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='cc338b26'/>
|
||||
<parameter type-id='e1815e87'/>
|
||||
|
@ -1466,6 +1452,16 @@
|
|||
<parameter type-id='0be2e71c'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='__sysconf' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<return type-id='bd54fe1a'/>
|
||||
</function-decl>
|
||||
<function-decl name='pthread_sigmask' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='5a8729d0'/>
|
||||
<parameter type-id='65e6ec45'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-type size-in-bits='64' id='cd5d79f4'>
|
||||
<parameter type-id='eaa32e2f'/>
|
||||
<return type-id='eaa32e2f'/>
|
||||
|
@ -1863,7 +1859,7 @@
|
|||
<var-decl name='drr_payloadlen' type-id='8f92235e' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='64'>
|
||||
<var-decl name='drr_u' type-id='ac5ab597' visibility='default'/>
|
||||
<var-decl name='drr_u' type-id='ac5ab595' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<enum-decl name='__anonymous_enum__' is-anonymous='yes' id='08f5ca17'>
|
||||
|
@ -1881,7 +1877,7 @@
|
|||
<enumerator name='DRR_REDACT' value='10'/>
|
||||
<enumerator name='DRR_NUMTYPES' value='11'/>
|
||||
</enum-decl>
|
||||
<union-decl name='__anonymous_union__' size-in-bits='2432' is-anonymous='yes' visibility='default' id='ac5ab597'>
|
||||
<union-decl name='__anonymous_union__' size-in-bits='2432' is-anonymous='yes' visibility='default' id='ac5ab595'>
|
||||
<data-member access='public'>
|
||||
<var-decl name='drr_begin' type-id='09fcdc01' visibility='default'/>
|
||||
</data-member>
|
||||
|
@ -2985,10 +2981,17 @@
|
|||
<parameter type-id='95e97e5e'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='read' visibility='default' binding='global' size-in-bits='64'>
|
||||
<function-decl name='__open_too_many_args' visibility='default' binding='global' size-in-bits='64'>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
<function-decl name='__open_missing_mode' visibility='default' binding='global' size-in-bits='64'>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
<function-decl name='__read_chk' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='eaa32e2f'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<return type-id='79a0948f'/>
|
||||
</function-decl>
|
||||
</abi-instr>
|
||||
|
@ -3156,21 +3159,23 @@
|
|||
<parameter type-id='822cd80b'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='fgets' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='266fe297'/>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='e75a27e9'/>
|
||||
<return type-id='26a90f95'/>
|
||||
</function-decl>
|
||||
<function-decl name='strstr' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<return type-id='26a90f95'/>
|
||||
</function-decl>
|
||||
<function-decl name='readlink' visibility='default' binding='global' size-in-bits='64'>
|
||||
<function-decl name='__fgets_chk' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='266fe297'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='e75a27e9'/>
|
||||
<return type-id='26a90f95'/>
|
||||
</function-decl>
|
||||
<function-decl name='__readlink_chk' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='9d26089a'/>
|
||||
<parameter type-id='266fe297'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<return type-id='79a0948f'/>
|
||||
</function-decl>
|
||||
<function-decl name='zfs_strip_partition' mangled-name='zfs_strip_partition' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_strip_partition'>
|
||||
|
@ -3208,12 +3213,12 @@
|
|||
<class-decl name='blkid_struct_dev' is-struct='yes' visibility='default' is-declaration-only='yes' id='86223623'/>
|
||||
<class-decl name='blkid_struct_dev_iterate' is-struct='yes' visibility='default' is-declaration-only='yes' id='d88420d6'/>
|
||||
<class-decl name='udev_list_entry' is-struct='yes' visibility='default' is-declaration-only='yes' id='e7dbdca3'/>
|
||||
<typedef-decl name='__useconds_t' type-id='f0981eeb' id='4e80d4b1'/>
|
||||
<typedef-decl name='__clockid_t' type-id='95e97e5e' id='08f9a87a'/>
|
||||
<typedef-decl name='clockid_t' type-id='08f9a87a' id='a1c3b834'/>
|
||||
<typedef-decl name='blkid_dev' type-id='8433f053' id='f47b023a'/>
|
||||
<typedef-decl name='blkid_cache' type-id='940e3afc' id='0882dfdf'/>
|
||||
<typedef-decl name='blkid_dev_iterate' type-id='b8fa2efc' id='f4760fa7'/>
|
||||
<typedef-decl name='__useconds_t' type-id='f0981eeb' id='4e80d4b1'/>
|
||||
<typedef-decl name='__clockid_t' type-id='95e97e5e' id='08f9a87a'/>
|
||||
<typedef-decl name='clockid_t' type-id='08f9a87a' id='a1c3b834'/>
|
||||
<pointer-type-def type-id='0882dfdf' size-in-bits='64' id='2e3e7caa'/>
|
||||
<pointer-type-def type-id='f47b023a' size-in-bits='64' id='d87f9b75'/>
|
||||
<pointer-type-def type-id='09286066' size-in-bits='64' id='940e3afc'/>
|
||||
|
@ -3304,11 +3309,6 @@
|
|||
<parameter type-id='b59d7dce'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='stat64' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='9d26089a'/>
|
||||
<parameter type-id='f1cadedf'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='clock_gettime' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='a1c3b834'/>
|
||||
<parameter type-id='3d83ba87'/>
|
||||
|
@ -3318,6 +3318,11 @@
|
|||
<parameter type-id='4e80d4b1'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='stat64' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='9d26089a'/>
|
||||
<parameter type-id='f1cadedf'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='zfs_dev_flush' mangled-name='zfs_dev_flush' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zfs_dev_flush'>
|
||||
<parameter type-id='95e97e5e' name='fd'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
|
@ -3372,23 +3377,10 @@
|
|||
<parameter type-id='95e97e5e' name='wholedisk'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='snprintf' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='26a90f95'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter is-variadic='yes'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='getenv' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<return type-id='26a90f95'/>
|
||||
</function-decl>
|
||||
<function-decl name='memset' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='eaa32e2f'/>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<return type-id='eaa32e2f'/>
|
||||
</function-decl>
|
||||
<function-decl name='strcmp' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
|
@ -3442,20 +3434,6 @@
|
|||
<class-decl name='_IO_marker' is-struct='yes' visibility='default' is-declaration-only='yes' id='010ae0b9'/>
|
||||
<class-decl name='_IO_wide_data' is-struct='yes' visibility='default' is-declaration-only='yes' id='79bd3751'/>
|
||||
<class-decl name='__dirstream' is-struct='yes' visibility='default' is-declaration-only='yes' id='20cd73f2'/>
|
||||
<class-decl name='__va_list_tag' size-in-bits='192' is-struct='yes' visibility='default' id='d5027220'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='gp_offset' type-id='f0981eeb' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='32'>
|
||||
<var-decl name='fp_offset' type-id='f0981eeb' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='64'>
|
||||
<var-decl name='overflow_arg_area' type-id='eaa32e2f' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='128'>
|
||||
<var-decl name='reg_save_area' type-id='eaa32e2f' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<class-decl name='tpool' size-in-bits='2496' is-struct='yes' visibility='default' id='88d1b7f9'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='tp_forw' type-id='9cf59a50' visibility='default'/>
|
||||
|
@ -3645,6 +3623,8 @@
|
|||
<var-decl name='__glibc_reserved' type-id='16dc656a' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<typedef-decl name='DIR' type-id='20cd73f2' id='54a5d683'/>
|
||||
<typedef-decl name='uintptr_t' type-id='7359adad' id='e475ab95'/>
|
||||
<class-decl name='dirent64' size-in-bits='2240' is-struct='yes' visibility='default' id='5725d813'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='d_ino' type-id='71288a47' visibility='default'/>
|
||||
|
@ -3810,10 +3790,10 @@
|
|||
<var-decl name='sigev_notify' type-id='95e97e5e' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='128'>
|
||||
<var-decl name='_sigev_un' type-id='ac5ab598' visibility='default'/>
|
||||
<var-decl name='_sigev_un' type-id='ac5ab596' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<union-decl name='__anonymous_union__' size-in-bits='384' is-anonymous='yes' visibility='default' id='ac5ab598'>
|
||||
<union-decl name='__anonymous_union__' size-in-bits='384' is-anonymous='yes' visibility='default' id='ac5ab596'>
|
||||
<data-member access='public'>
|
||||
<var-decl name='_pad' type-id='73b82f0f' visibility='default'/>
|
||||
</data-member>
|
||||
|
@ -3930,8 +3910,6 @@
|
|||
<var-decl name='tv_nsec' type-id='03085adc' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<typedef-decl name='DIR' type-id='20cd73f2' id='54a5d683'/>
|
||||
<typedef-decl name='uintptr_t' type-id='7359adad' id='e475ab95'/>
|
||||
<pointer-type-def type-id='54a5d683' size-in-bits='64' id='f09217ba'/>
|
||||
<pointer-type-def type-id='aa12d1ba' size-in-bits='64' id='822cd80b'/>
|
||||
<qualified-type-def type-id='822cd80b' restrict='yes' id='e75a27e9'/>
|
||||
|
@ -3940,7 +3918,6 @@
|
|||
<pointer-type-def type-id='bb4788fa' size-in-bits='64' id='cecf4ea7'/>
|
||||
<pointer-type-def type-id='010ae0b9' size-in-bits='64' id='e4c6fa61'/>
|
||||
<pointer-type-def type-id='79bd3751' size-in-bits='64' id='c65a1f29'/>
|
||||
<pointer-type-def type-id='d5027220' size-in-bits='64' id='b7f2d5e6'/>
|
||||
<pointer-type-def type-id='e4957c49' size-in-bits='64' id='924bbc81'/>
|
||||
<qualified-type-def type-id='924bbc81' const='yes' id='5499dcde'/>
|
||||
<pointer-type-def type-id='5499dcde' size-in-bits='64' id='2236d41c'/>
|
||||
|
@ -4242,25 +4219,6 @@
|
|||
<parameter type-id='18c91f9e'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='fprintf' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='e75a27e9'/>
|
||||
<parameter type-id='9d26089a'/>
|
||||
<parameter is-variadic='yes'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='vsnprintf' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='26a90f95'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='b7f2d5e6'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='asprintf' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='8c85230f'/>
|
||||
<parameter type-id='9d26089a'/>
|
||||
<parameter is-variadic='yes'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='strtoull' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='9d26089a'/>
|
||||
<parameter type-id='8c85230f'/>
|
||||
|
@ -4282,11 +4240,6 @@
|
|||
<parameter type-id='95e97e5e'/>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
<function-decl name='realpath' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='9d26089a'/>
|
||||
<parameter type-id='266fe297'/>
|
||||
<return type-id='26a90f95'/>
|
||||
</function-decl>
|
||||
<function-decl name='strncmp' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
|
@ -4302,6 +4255,41 @@
|
|||
<parameter type-id='95e97e5e'/>
|
||||
<return type-id='26a90f95'/>
|
||||
</function-decl>
|
||||
<function-decl name='sysconf' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<return type-id='bd54fe1a'/>
|
||||
</function-decl>
|
||||
<function-decl name='geteuid' visibility='default' binding='global' size-in-bits='64'>
|
||||
<return type-id='cc5fcceb'/>
|
||||
</function-decl>
|
||||
<function-decl name='__fprintf_chk' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='e75a27e9'/>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='9d26089a'/>
|
||||
<parameter is-variadic='yes'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='__asprintf_chk' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='8c85230f'/>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='9d26089a'/>
|
||||
<parameter is-variadic='yes'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='__realpath_chk' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='9d26089a'/>
|
||||
<parameter type-id='266fe297'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<return type-id='26a90f95'/>
|
||||
</function-decl>
|
||||
<function-decl name='__pread64_chk' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='eaa32e2f'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<parameter type-id='724e4de6'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<return type-id='79a0948f'/>
|
||||
</function-decl>
|
||||
<function-decl name='ioctl' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='7359adad'/>
|
||||
|
@ -4313,20 +4301,6 @@
|
|||
<parameter type-id='62f7a03d'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='pread64' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='eaa32e2f'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<parameter type-id='724e4de6'/>
|
||||
<return type-id='79a0948f'/>
|
||||
</function-decl>
|
||||
<function-decl name='sysconf' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<return type-id='bd54fe1a'/>
|
||||
</function-decl>
|
||||
<function-decl name='geteuid' visibility='default' binding='global' size-in-bits='64'>
|
||||
<return type-id='cc5fcceb'/>
|
||||
</function-decl>
|
||||
<function-type size-in-bits='64' id='baa42fef'>
|
||||
<parameter type-id='eaa32e2f'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
|
@ -4404,6 +4378,9 @@
|
|||
<parameter type-id='b59d7dce' name='buflen'/>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
<function-decl name='__ctype_b_loc' visibility='default' binding='global' size-in-bits='64'>
|
||||
<return type-id='c59e1ef0'/>
|
||||
</function-decl>
|
||||
<function-decl name='powl' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='e095c704'/>
|
||||
<parameter type-id='e095c704'/>
|
||||
|
@ -4413,9 +4390,6 @@
|
|||
<parameter type-id='a0eb0f08'/>
|
||||
<return type-id='a0eb0f08'/>
|
||||
</function-decl>
|
||||
<function-decl name='__ctype_b_loc' visibility='default' binding='global' size-in-bits='64'>
|
||||
<return type-id='c59e1ef0'/>
|
||||
</function-decl>
|
||||
</abi-instr>
|
||||
<abi-instr address-size='64' path='zutil_pool.c' language='LANG_C99'>
|
||||
<array-type-def dimensions='1' type-id='853fd5dc' size-in-bits='32768' id='b505fc2f'>
|
||||
|
@ -4471,15 +4445,16 @@
|
|||
<parameter type-id='4dd26a40' name='numrecords'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='printf' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter is-variadic='yes'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='realloc' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='eaa32e2f'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<return type-id='eaa32e2f'/>
|
||||
</function-decl>
|
||||
<function-decl name='__printf_chk' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter is-variadic='yes'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
</abi-instr>
|
||||
</abi-corpus>
|
||||
|
|
|
@ -1,16 +1,7 @@
|
|||
<abi-corpus version='2.0' architecture='elf-amd-x86_64' soname='libzfsbootenv.so.1'>
|
||||
<elf-needed>
|
||||
<dependency name='libzfs.so.4'/>
|
||||
<dependency name='libzfs_core.so.3'/>
|
||||
<dependency name='libuuid.so.1'/>
|
||||
<dependency name='libblkid.so.1'/>
|
||||
<dependency name='libudev.so.1'/>
|
||||
<dependency name='libuutil.so.3'/>
|
||||
<dependency name='libm.so.6'/>
|
||||
<dependency name='libcrypto.so.1.1'/>
|
||||
<dependency name='libz.so.1'/>
|
||||
<dependency name='libnvpair.so.3'/>
|
||||
<dependency name='libtirpc.so.3'/>
|
||||
<dependency name='libc.so.6'/>
|
||||
</elf-needed>
|
||||
<elf-function-symbols>
|
||||
|
@ -289,18 +280,6 @@
|
|||
<parameter type-id='9b23c9ad' name='device'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='fprintf' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='e75a27e9'/>
|
||||
<parameter type-id='9d26089a'/>
|
||||
<parameter is-variadic='yes'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='asprintf' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='8c85230f'/>
|
||||
<parameter type-id='9d26089a'/>
|
||||
<parameter is-variadic='yes'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='free' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='eaa32e2f'/>
|
||||
<return type-id='48b5725f'/>
|
||||
|
@ -319,6 +298,20 @@
|
|||
<parameter type-id='80f4b756'/>
|
||||
<return type-id='b59d7dce'/>
|
||||
</function-decl>
|
||||
<function-decl name='__fprintf_chk' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='e75a27e9'/>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='9d26089a'/>
|
||||
<parameter is-variadic='yes'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='__asprintf_chk' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='8c85230f'/>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='9d26089a'/>
|
||||
<parameter is-variadic='yes'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
</abi-instr>
|
||||
<abi-instr address-size='64' path='lzbe_pair.c' language='LANG_C99'>
|
||||
<type-decl name='short int' size-in-bits='16' id='a2185560'/>
|
||||
|
|
|
@ -951,6 +951,18 @@ receive of encrypted datasets.
|
|||
Intended for users whose pools were created with
|
||||
OpenZFS pre-release versions and now have compatibility issues.
|
||||
.
|
||||
.It Sy zfs_forced_export_unmount Ns = Ns Sy 0 Ns | Ns 1 Pq int
|
||||
During forced unmount, leave the filesystem in a disabled mode of operation,
|
||||
in which all new I/Os fail, except for those required to unmount it.
|
||||
Intended for users trying to forcibly export a pool even when I/Os are in
|
||||
progress, without the need to find and stop them.
|
||||
This option does not affect processes that are merely sitting on the
|
||||
filesystem, only those performing active I/O.
|
||||
.Pp
|
||||
This parameter can be set to 1 to enable this behavior.
|
||||
.Pp
|
||||
This parameter only applies on Linux.
|
||||
.
|
||||
.It Sy zfs_key_max_salt_uses Ns = Ns Sy 400000000 Po 4*10^8 Pc Pq ulong
|
||||
Maximum number of uses of a single salt value before generating a new one for
|
||||
encrypted datasets.
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
.\" Copyright 2017 Nexenta Systems, Inc.
|
||||
.\" Copyright (c) 2017 Open-E, Inc. All Rights Reserved.
|
||||
.\"
|
||||
.Dd February 16, 2020
|
||||
.Dd November 1, 2022
|
||||
.Dt ZPOOL-EXPORT 8
|
||||
.Os
|
||||
.
|
||||
|
@ -37,6 +37,7 @@
|
|||
.Nm zpool
|
||||
.Cm export
|
||||
.Op Fl f
|
||||
.Op Fl F
|
||||
.Fl a Ns | Ns Ar pool Ns …
|
||||
.
|
||||
.Sh DESCRIPTION
|
||||
|
@ -66,6 +67,15 @@ Forcefully unmount all datasets, and allow export of pools with active shared sp
|
|||
This command will forcefully export the pool even if it has a shared spare that
|
||||
is currently being used.
|
||||
This may lead to potential data corruption.
|
||||
.It Fl F
|
||||
Forcibly export the pool.
|
||||
.Pp
|
||||
This option allows a pool to be exported even when the underlying disks are
|
||||
offline and the pool is unavailable.
|
||||
When force exporting a pool, any outstanding dirty data will be discarded.
|
||||
This option implies the
|
||||
.Fl f
|
||||
option.
|
||||
.El
|
||||
.
|
||||
.Sh SEE ALSO
|
||||
|
|
|
@ -108,6 +108,16 @@ spl_panic(const char *file, const char *func, int line, const char *fmt, ...)
|
|||
va_end(ap);
|
||||
}
|
||||
|
||||
int
|
||||
spl_kthread_signal(kthread_t *td, int sig)
|
||||
{
|
||||
|
||||
PROC_LOCK(td->td_proc);
|
||||
tdsignal(td, sig);
|
||||
PROC_UNLOCK(td->td_proc);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
SYSINIT(opensolaris_utsname_init, SI_SUB_TUNABLES, SI_ORDER_ANY,
|
||||
opensolaris_utsname_init, NULL);
|
||||
|
|
|
@ -214,3 +214,15 @@ issig(int why)
|
|||
}
|
||||
|
||||
EXPORT_SYMBOL(issig);
|
||||
|
||||
/*
|
||||
* spl_kthread_signal - Wrapper for sending signals to a thread.
|
||||
*/
|
||||
int
|
||||
spl_kthread_signal(kthread_t *tsk, int sig)
|
||||
{
|
||||
|
||||
return (send_sig(sig, tsk, 0));
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(spl_kthread_signal);
|
||||
|
|
|
@ -563,7 +563,6 @@ zfs_unlinked_drain(zfsvfs_t *zfsvfs)
|
|||
void
|
||||
zfs_unlinked_drain_stop_wait(zfsvfs_t *zfsvfs)
|
||||
{
|
||||
ASSERT3B(zfsvfs->z_unmounted, ==, B_FALSE);
|
||||
|
||||
if (zfsvfs->z_draining) {
|
||||
zfsvfs->z_drain_cancel = B_TRUE;
|
||||
|
|
|
@ -218,9 +218,27 @@ zfs_ioctl_update_mount_cache(const char *dsname)
|
|||
{
|
||||
}
|
||||
|
||||
static int
|
||||
zfs_ioc_pool_unmount_begin(zfs_cmd_t *zc)
|
||||
{
|
||||
return (spa_set_pre_export_status(zc->zc_name, true));
|
||||
}
|
||||
|
||||
static int
|
||||
zfs_ioc_pool_unmount_end(zfs_cmd_t *zc)
|
||||
{
|
||||
return (spa_set_pre_export_status(zc->zc_name, false));
|
||||
}
|
||||
|
||||
void
|
||||
zfs_ioctl_init_os(void)
|
||||
{
|
||||
zfs_ioctl_register_pool(ZFS_IOC_HARD_FORCE_UNMOUNT_BEGIN,
|
||||
zfs_ioc_pool_unmount_begin, zfs_secpolicy_config, B_FALSE,
|
||||
POOL_CHECK_NONE);
|
||||
zfs_ioctl_register_pool(ZFS_IOC_HARD_FORCE_UNMOUNT_END,
|
||||
zfs_ioc_pool_unmount_end, zfs_secpolicy_config, B_FALSE,
|
||||
POOL_CHECK_NONE);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
|
|
|
@ -1095,7 +1095,7 @@ zfs_statvfs(struct inode *ip, struct kstatfs *statp)
|
|||
uint64_t refdbytes, availbytes, usedobjs, availobjs;
|
||||
int err = 0;
|
||||
|
||||
ZFS_ENTER(zfsvfs);
|
||||
ZFS_ENTER_UNMOUNTOK(zfsvfs);
|
||||
|
||||
dmu_objset_space(zfsvfs->z_os,
|
||||
&refdbytes, &availbytes, &usedobjs, &availobjs);
|
||||
|
@ -1166,7 +1166,7 @@ zfs_root(zfsvfs_t *zfsvfs, struct inode **ipp)
|
|||
znode_t *rootzp;
|
||||
int error;
|
||||
|
||||
ZFS_ENTER(zfsvfs);
|
||||
ZFS_ENTER_UNMOUNTOK(zfsvfs);
|
||||
|
||||
error = zfs_zget(zfsvfs, zfsvfs->z_root, &rootzp);
|
||||
if (error == 0)
|
||||
|
@ -1310,6 +1310,8 @@ static int
|
|||
zfsvfs_teardown(zfsvfs_t *zfsvfs, boolean_t unmounting)
|
||||
{
|
||||
znode_t *zp;
|
||||
kthread_t *initiator = NULL;
|
||||
uint64_t wait_flags = 0;
|
||||
|
||||
zfs_unlinked_drain_stop_wait(zfsvfs);
|
||||
|
||||
|
@ -1339,6 +1341,15 @@ zfsvfs_teardown(zfsvfs_t *zfsvfs, boolean_t unmounting)
|
|||
if (++round > 1 && !unmounting)
|
||||
break;
|
||||
}
|
||||
initiator = zfsvfs->z_os->os_shutdown_initiator;
|
||||
/*
|
||||
* Although it could be argued that a force unmount in
|
||||
* another thread shouldn't have this apply, once a force
|
||||
* unmount is in effect, it's pointless for the non-forced
|
||||
* unmount to not use this flag.
|
||||
*/
|
||||
if (initiator != NULL)
|
||||
wait_flags |= TXG_WAIT_F_NOSUSPEND;
|
||||
}
|
||||
|
||||
ZFS_TEARDOWN_ENTER_WRITE(zfsvfs, FTAG);
|
||||
|
@ -1371,6 +1382,10 @@ zfsvfs_teardown(zfsvfs_t *zfsvfs, boolean_t unmounting)
|
|||
* or a reopen of z_os failed then just bail out now.
|
||||
*/
|
||||
if (!unmounting && (zfsvfs->z_unmounted || zfsvfs->z_os == NULL)) {
|
||||
if (initiator == curthread) {
|
||||
zfsvfs->z_unmounted = B_FALSE;
|
||||
dmu_objset_shutdown_unregister(zfsvfs->z_os);
|
||||
}
|
||||
rw_exit(&zfsvfs->z_teardown_inactive_lock);
|
||||
ZFS_TEARDOWN_EXIT(zfsvfs, FTAG);
|
||||
return (SET_ERROR(EIO));
|
||||
|
@ -1439,12 +1454,16 @@ zfsvfs_teardown(zfsvfs_t *zfsvfs, boolean_t unmounting)
|
|||
}
|
||||
}
|
||||
if (!zfs_is_readonly(zfsvfs) && os_dirty) {
|
||||
txg_wait_synced(dmu_objset_pool(zfsvfs->z_os), 0);
|
||||
(void) txg_wait_synced_tx(dmu_objset_pool(zfsvfs->z_os), 0,
|
||||
NULL, wait_flags);
|
||||
}
|
||||
dmu_objset_evict_dbufs(zfsvfs->z_os);
|
||||
dsl_dir_t *dd = os->os_dsl_dataset->ds_dir;
|
||||
dsl_dir_cancel_waiters(dd);
|
||||
|
||||
if (initiator == curthread)
|
||||
dmu_objset_shutdown_unregister(zfsvfs->z_os);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
|
|
@ -227,9 +227,10 @@ zfs_close(struct inode *ip, int flag, cred_t *cr)
|
|||
{
|
||||
znode_t *zp = ITOZ(ip);
|
||||
zfsvfs_t *zfsvfs = ITOZSB(ip);
|
||||
int error;
|
||||
|
||||
ZFS_ENTER(zfsvfs);
|
||||
ZFS_VERIFY_ZP(zp);
|
||||
if ((error = zfs_enter_unmountok_verify_zp(zfsvfs, zp, FTAG)) != 0)
|
||||
return (error);
|
||||
|
||||
/* Decrement the synchronous opens in the znode */
|
||||
if (flag & O_SYNC)
|
||||
|
@ -1669,9 +1670,10 @@ zfs_getattr_fast(struct user_namespace *user_ns, struct inode *ip,
|
|||
zfsvfs_t *zfsvfs = ITOZSB(ip);
|
||||
uint32_t blksize;
|
||||
u_longlong_t nblocks;
|
||||
int error;
|
||||
|
||||
ZFS_ENTER(zfsvfs);
|
||||
ZFS_VERIFY_ZP(zp);
|
||||
if ((error = zfs_enter_unmountok_verify_zp(zfsvfs, zp, FTAG)) != 0)
|
||||
return (error);
|
||||
|
||||
mutex_enter(&zp->z_lock);
|
||||
|
||||
|
|
|
@ -28,7 +28,10 @@
|
|||
#include <sys/zfs_vnops.h>
|
||||
#include <sys/zfs_ctldir.h>
|
||||
#include <sys/zpl.h>
|
||||
#include <sys/dmu_objset.h>
|
||||
#include <sys/dsl_dir.h>
|
||||
|
||||
int zfs_forced_export_unmount_enabled = 0;
|
||||
|
||||
static struct inode *
|
||||
zpl_inode_alloc(struct super_block *sb)
|
||||
|
@ -102,6 +105,31 @@ zpl_evict_inode(struct inode *ip)
|
|||
spl_fstrans_unmark(cookie);
|
||||
}
|
||||
|
||||
static void
|
||||
zpl_umount_begin(struct super_block *sb)
|
||||
{
|
||||
zfsvfs_t *zfsvfs = sb->s_fs_info;
|
||||
|
||||
if (zfsvfs) {
|
||||
/*
|
||||
* Flush out all POSIX I/Os. Notify all waiters that they
|
||||
* must end, then wait for all users to drop their holds on
|
||||
* z_teardown_*_lock, and evict buffers.
|
||||
*/
|
||||
if (zfs_forced_export_unmount_enabled)
|
||||
zfsvfs->z_force_unmounted = B_TRUE;
|
||||
(void) dmu_objset_shutdown_register(zfsvfs->z_os);
|
||||
rrm_enter(&zfsvfs->z_teardown_lock, RW_WRITER, FTAG);
|
||||
rw_enter(&zfsvfs->z_teardown_inactive_lock, RW_WRITER);
|
||||
rw_exit(&zfsvfs->z_teardown_inactive_lock);
|
||||
rrm_exit(&zfsvfs->z_teardown_lock, FTAG);
|
||||
dmu_objset_evict_dbufs(zfsvfs->z_os);
|
||||
|
||||
dsl_dir_cancel_waiters(zfsvfs->z_os->os_dsl_dataset->ds_dir);
|
||||
dmu_objset_shutdown_unregister(zfsvfs->z_os);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
zpl_put_super(struct super_block *sb)
|
||||
{
|
||||
|
@ -185,7 +213,8 @@ zpl_remount_fs(struct super_block *sb, int *flags, char *data)
|
|||
static int
|
||||
__zpl_show_devname(struct seq_file *seq, zfsvfs_t *zfsvfs)
|
||||
{
|
||||
ZPL_ENTER(zfsvfs);
|
||||
|
||||
ZFS_ENTER_UNMOUNTOK(zfsvfs);
|
||||
|
||||
char *fsname = kmem_alloc(ZFS_MAX_DATASET_NAME_LEN, KM_SLEEP);
|
||||
dmu_objset_name(zfsvfs->z_os, fsname);
|
||||
|
@ -349,6 +378,7 @@ const struct super_operations zpl_super_operations = {
|
|||
.write_inode = NULL,
|
||||
.evict_inode = zpl_evict_inode,
|
||||
.put_super = zpl_put_super,
|
||||
.umount_begin = zpl_umount_begin,
|
||||
.sync_fs = zpl_sync_fs,
|
||||
.statfs = zpl_statfs,
|
||||
.remount_fs = zpl_remount_fs,
|
||||
|
@ -363,3 +393,8 @@ struct file_system_type zpl_fs_type = {
|
|||
.mount = zpl_mount,
|
||||
.kill_sb = zpl_kill_sb,
|
||||
};
|
||||
|
||||
/* BEGIN CSTYLED */
|
||||
ZFS_MODULE_PARAM(zfs, zfs_, forced_export_unmount_enabled, INT, ZMOD_RW,
|
||||
"Enable forced export unmount to keep POSIX I/O users off");
|
||||
/* END CSTYLED */
|
||||
|
|
|
@ -9997,6 +9997,18 @@ l2arc_rebuild_vdev(vdev_t *vd, boolean_t reopen)
|
|||
l2arc_rebuild_dev(dev, reopen);
|
||||
}
|
||||
|
||||
static void
|
||||
l2arc_dev_rebuild_stop(l2arc_dev_t *l2ad)
|
||||
{
|
||||
mutex_enter(&l2arc_rebuild_thr_lock);
|
||||
if (l2ad->l2ad_rebuild_began == B_TRUE) {
|
||||
l2ad->l2ad_rebuild_cancel = B_TRUE;
|
||||
while (l2ad->l2ad_rebuild == B_TRUE)
|
||||
cv_wait(&l2arc_rebuild_thr_cv, &l2arc_rebuild_thr_lock);
|
||||
}
|
||||
mutex_exit(&l2arc_rebuild_thr_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove a vdev from the L2ARC.
|
||||
*/
|
||||
|
@ -10014,13 +10026,7 @@ l2arc_remove_vdev(vdev_t *vd)
|
|||
/*
|
||||
* Cancel any ongoing or scheduled rebuild.
|
||||
*/
|
||||
mutex_enter(&l2arc_rebuild_thr_lock);
|
||||
if (remdev->l2ad_rebuild_began == B_TRUE) {
|
||||
remdev->l2ad_rebuild_cancel = B_TRUE;
|
||||
while (remdev->l2ad_rebuild == B_TRUE)
|
||||
cv_wait(&l2arc_rebuild_thr_cv, &l2arc_rebuild_thr_lock);
|
||||
}
|
||||
mutex_exit(&l2arc_rebuild_thr_lock);
|
||||
l2arc_dev_rebuild_stop(remdev);
|
||||
|
||||
/*
|
||||
* Remove device from global list
|
||||
|
@ -10136,6 +10142,25 @@ l2arc_spa_rebuild_start(spa_t *spa)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
l2arc_spa_rebuild_stop(spa_t *spa)
|
||||
{
|
||||
ASSERT(MUTEX_HELD(&spa_namespace_lock));
|
||||
|
||||
/*
|
||||
* Locate the spa's l2arc devices and kick off rebuild threads.
|
||||
*/
|
||||
for (int i = 0; i < spa->spa_l2cache.sav_count; i++) {
|
||||
l2arc_dev_t *dev =
|
||||
l2arc_vdev_get(spa->spa_l2cache.sav_vdevs[i]);
|
||||
if (dev == NULL) {
|
||||
/* Don't attempt a rebuild if the vdev is UNAVAIL */
|
||||
continue;
|
||||
}
|
||||
l2arc_dev_rebuild_stop(dev);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Main entry point for L2ARC rebuilding.
|
||||
*/
|
||||
|
|
|
@ -981,11 +981,12 @@ dbuf_verify(dmu_buf_impl_t *db)
|
|||
uint32_t txg_prev;
|
||||
|
||||
ASSERT(MUTEX_HELD(&db->db_mtx));
|
||||
ASSERT(db->db_objset != NULL);
|
||||
|
||||
if (!(zfs_flags & ZFS_DEBUG_DBUF_VERIFY))
|
||||
if (!(zfs_flags & ZFS_DEBUG_DBUF_VERIFY) ||
|
||||
dmu_objset_exiting(db->db_objset))
|
||||
return;
|
||||
|
||||
ASSERT(db->db_objset != NULL);
|
||||
DB_DNODE_ENTER(db);
|
||||
dn = DB_DNODE(db);
|
||||
if (dn == NULL) {
|
||||
|
@ -1069,7 +1070,8 @@ dbuf_verify(dmu_buf_impl_t *db)
|
|||
if ((db->db_blkptr == NULL || BP_IS_HOLE(db->db_blkptr)) &&
|
||||
(db->db_buf == NULL || db->db_buf->b_data) &&
|
||||
db->db.db_data && db->db_blkid != DMU_BONUS_BLKID &&
|
||||
db->db_state != DB_FILL && !dn->dn_free_txg) {
|
||||
db->db_state != DB_FILL && (dn == NULL || !dn->dn_free_txg) &&
|
||||
!dmu_objset_exiting(db->db_objset)) {
|
||||
/*
|
||||
* If the blkptr isn't set but they have nonzero data,
|
||||
* it had better be dirty, otherwise we'll lose that
|
||||
|
@ -2182,7 +2184,7 @@ dbuf_dirty(dmu_buf_impl_t *db, dmu_tx_t *tx)
|
|||
* this assertion only if we're not already dirty.
|
||||
*/
|
||||
os = dn->dn_objset;
|
||||
VERIFY3U(tx->tx_txg, <=, spa_final_dirty_txg(os->os_spa));
|
||||
spa_verify_dirty_txg(os->os_spa, dmu_tx_get_txg(tx));
|
||||
#ifdef ZFS_DEBUG
|
||||
if (dn->dn_objset->os_dsl_dataset != NULL)
|
||||
rrw_enter(&os->os_dsl_dataset->ds_bp_rwlock, RW_READER, FTAG);
|
||||
|
@ -4199,7 +4201,11 @@ dbuf_lightweight_done(zio_t *zio)
|
|||
{
|
||||
dbuf_dirty_record_t *dr = zio->io_private;
|
||||
|
||||
VERIFY0(zio->io_error);
|
||||
if (zio->io_error != 0) {
|
||||
/* If the pool is exiting, only cleanup in-core state. */
|
||||
ASSERT(spa_exiting_any(zio->io_spa));
|
||||
goto out;
|
||||
}
|
||||
|
||||
objset_t *os = dr->dr_dnode->dn_objset;
|
||||
dmu_tx_t *tx = os->os_synctx;
|
||||
|
@ -4223,6 +4229,7 @@ dbuf_lightweight_done(zio_t *zio)
|
|||
dr->dr_accounted % zio->io_phys_children, zio->io_txg);
|
||||
}
|
||||
|
||||
out:
|
||||
abd_free(dr->dt.dll.dr_abd);
|
||||
kmem_free(dr, sizeof (*dr));
|
||||
}
|
||||
|
@ -4624,9 +4631,14 @@ dbuf_write_done(zio_t *zio, arc_buf_t *buf, void *vdb)
|
|||
objset_t *os = db->db_objset;
|
||||
dmu_tx_t *tx = os->os_synctx;
|
||||
|
||||
ASSERT0(zio->io_error);
|
||||
ASSERT(db->db_blkptr == bp);
|
||||
|
||||
if (zio->io_error != 0) {
|
||||
/* If the pool is exiting, only cleanup in-core state. */
|
||||
ASSERT(spa_exiting_any(zio->io_spa));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
* For nopwrites and rewrites we ensure that the bp matches our
|
||||
* original and bypass all the accounting.
|
||||
|
@ -4639,6 +4651,7 @@ dbuf_write_done(zio_t *zio, arc_buf_t *buf, void *vdb)
|
|||
dsl_dataset_block_born(ds, bp, tx);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
mutex_enter(&db->db_mtx);
|
||||
|
||||
DBUF_VERIFY(db);
|
||||
|
|
|
@ -1115,12 +1115,16 @@ dmu_write(objset_t *os, uint64_t object, uint64_t offset, uint64_t size,
|
|||
{
|
||||
dmu_buf_t **dbp;
|
||||
int numbufs;
|
||||
int error;
|
||||
|
||||
if (size == 0)
|
||||
return;
|
||||
|
||||
VERIFY0(dmu_buf_hold_array(os, object, offset, size,
|
||||
FALSE, FTAG, &numbufs, &dbp));
|
||||
error = dmu_buf_hold_array(os, object, offset, size,
|
||||
FALSE, FTAG, &numbufs, &dbp);
|
||||
VERIFY(error == 0 || spa_exiting_any(os->os_spa));
|
||||
if (error != 0)
|
||||
return;
|
||||
dmu_write_impl(dbp, numbufs, offset, size, buf, tx);
|
||||
dmu_buf_rele_array(dbp, numbufs, FTAG);
|
||||
}
|
||||
|
@ -1134,12 +1138,16 @@ dmu_write_by_dnode(dnode_t *dn, uint64_t offset, uint64_t size,
|
|||
{
|
||||
dmu_buf_t **dbp;
|
||||
int numbufs;
|
||||
int error;
|
||||
|
||||
if (size == 0)
|
||||
return;
|
||||
|
||||
VERIFY0(dmu_buf_hold_array_by_dnode(dn, offset, size,
|
||||
FALSE, FTAG, &numbufs, &dbp, DMU_READ_PREFETCH));
|
||||
error = dmu_buf_hold_array_by_dnode(dn, offset, size,
|
||||
FALSE, FTAG, &numbufs, &dbp, DMU_READ_PREFETCH);
|
||||
VERIFY(error == 0 || spa_exiting_any(dn->dn_objset->os_spa));
|
||||
if (error != 0)
|
||||
return;
|
||||
dmu_write_impl(dbp, numbufs, offset, size, buf, tx);
|
||||
dmu_buf_rele_array(dbp, numbufs, FTAG);
|
||||
}
|
||||
|
@ -1171,11 +1179,15 @@ dmu_write_embedded(objset_t *os, uint64_t object, uint64_t offset,
|
|||
int compressed_size, int byteorder, dmu_tx_t *tx)
|
||||
{
|
||||
dmu_buf_t *db;
|
||||
int error;
|
||||
|
||||
ASSERT3U(etype, <, NUM_BP_EMBEDDED_TYPES);
|
||||
ASSERT3U(comp, <, ZIO_COMPRESS_FUNCTIONS);
|
||||
VERIFY0(dmu_buf_hold_noread(os, object, offset,
|
||||
FTAG, &db));
|
||||
error = dmu_buf_hold_noread(os, object, offset,
|
||||
FTAG, &db);
|
||||
VERIFY(error == 0 || spa_exiting_any(os->os_spa));
|
||||
if (error != 0)
|
||||
return;
|
||||
|
||||
dmu_buf_write_embedded(db,
|
||||
data, (bp_embedded_type_t)etype, (enum zio_compress)comp,
|
||||
|
|
|
@ -1572,6 +1572,11 @@ dmu_objset_write_done(zio_t *zio, arc_buf_t *abuf, void *arg)
|
|||
blkptr_t *bp_orig = &zio->io_bp_orig;
|
||||
objset_t *os = arg;
|
||||
|
||||
if (zio->io_error != 0) {
|
||||
ASSERT(spa_exiting_any(zio->io_spa));
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (zio->io_flags & ZIO_FLAG_IO_REWRITE) {
|
||||
ASSERT(BP_EQUAL(bp, bp_orig));
|
||||
} else {
|
||||
|
@ -1581,6 +1586,8 @@ dmu_objset_write_done(zio_t *zio, arc_buf_t *abuf, void *arg)
|
|||
(void) dsl_dataset_block_kill(ds, bp_orig, tx, B_TRUE);
|
||||
dsl_dataset_block_born(ds, bp, tx);
|
||||
}
|
||||
|
||||
done:
|
||||
kmem_free(bp, sizeof (*bp));
|
||||
}
|
||||
|
||||
|
@ -1820,6 +1827,7 @@ do_userquota_cacheflush(objset_t *os, userquota_cache_t *cache, dmu_tx_t *tx)
|
|||
{
|
||||
void *cookie;
|
||||
userquota_node_t *uqn;
|
||||
int error;
|
||||
|
||||
ASSERT(dmu_tx_is_syncing(tx));
|
||||
|
||||
|
@ -1831,10 +1839,13 @@ do_userquota_cacheflush(objset_t *os, userquota_cache_t *cache, dmu_tx_t *tx)
|
|||
* zap_increment_int(). It's needed because zap_increment_int()
|
||||
* is not thread-safe (i.e. not atomic).
|
||||
*/
|
||||
mutex_enter(&os->os_userused_lock);
|
||||
VERIFY0(zap_increment(os, DMU_USERUSED_OBJECT,
|
||||
uqn->uqn_id, uqn->uqn_delta, tx));
|
||||
mutex_exit(&os->os_userused_lock);
|
||||
if (!dmu_objset_exiting(os)) {
|
||||
mutex_enter(&os->os_userused_lock);
|
||||
error = zap_increment(os, DMU_USERUSED_OBJECT,
|
||||
uqn->uqn_id, uqn->uqn_delta, tx);
|
||||
VERIFY(error == 0 || dmu_objset_exiting(os));
|
||||
mutex_exit(&os->os_userused_lock);
|
||||
}
|
||||
kmem_free(uqn, sizeof (*uqn));
|
||||
}
|
||||
avl_destroy(&cache->uqc_user_deltas);
|
||||
|
@ -1842,10 +1853,13 @@ do_userquota_cacheflush(objset_t *os, userquota_cache_t *cache, dmu_tx_t *tx)
|
|||
cookie = NULL;
|
||||
while ((uqn = avl_destroy_nodes(&cache->uqc_group_deltas,
|
||||
&cookie)) != NULL) {
|
||||
mutex_enter(&os->os_userused_lock);
|
||||
VERIFY0(zap_increment(os, DMU_GROUPUSED_OBJECT,
|
||||
uqn->uqn_id, uqn->uqn_delta, tx));
|
||||
mutex_exit(&os->os_userused_lock);
|
||||
if (!dmu_objset_exiting(os)) {
|
||||
mutex_enter(&os->os_userused_lock);
|
||||
error = zap_increment(os, DMU_GROUPUSED_OBJECT,
|
||||
uqn->uqn_id, uqn->uqn_delta, tx);
|
||||
VERIFY(error == 0 || dmu_objset_exiting(os));
|
||||
mutex_exit(&os->os_userused_lock);
|
||||
}
|
||||
kmem_free(uqn, sizeof (*uqn));
|
||||
}
|
||||
avl_destroy(&cache->uqc_group_deltas);
|
||||
|
@ -1855,8 +1869,9 @@ do_userquota_cacheflush(objset_t *os, userquota_cache_t *cache, dmu_tx_t *tx)
|
|||
while ((uqn = avl_destroy_nodes(&cache->uqc_project_deltas,
|
||||
&cookie)) != NULL) {
|
||||
mutex_enter(&os->os_userused_lock);
|
||||
VERIFY0(zap_increment(os, DMU_PROJECTUSED_OBJECT,
|
||||
uqn->uqn_id, uqn->uqn_delta, tx));
|
||||
error = zap_increment(os, DMU_PROJECTUSED_OBJECT,
|
||||
uqn->uqn_id, uqn->uqn_delta, tx);
|
||||
VERIFY(error == 0 || dmu_objset_exiting(os));
|
||||
mutex_exit(&os->os_userused_lock);
|
||||
kmem_free(uqn, sizeof (*uqn));
|
||||
}
|
||||
|
@ -1975,6 +1990,7 @@ userquota_updates_task(void *arg)
|
|||
|
||||
flags = dn->dn_id_flags;
|
||||
ASSERT(flags);
|
||||
|
||||
if (flags & DN_ID_OLD_EXIST) {
|
||||
do_userquota_update(os, &cache, dn->dn_oldused,
|
||||
dn->dn_oldflags, dn->dn_olduid, dn->dn_oldgid,
|
||||
|
@ -2311,8 +2327,9 @@ dmu_objset_space_upgrade(objset_t *os)
|
|||
if (err != 0)
|
||||
return (err);
|
||||
|
||||
if (issig(JUSTLOOKING) && issig(FORREAL))
|
||||
return (SET_ERROR(EINTR));
|
||||
err = spa_operation_interrupted(os->os_spa);
|
||||
if (err != 0)
|
||||
return (err);
|
||||
|
||||
objerr = dmu_bonus_hold(os, obj, FTAG, &db);
|
||||
if (objerr != 0)
|
||||
|
@ -3000,6 +3017,52 @@ dmu_objset_willuse_space(objset_t *os, int64_t space, dmu_tx_t *tx)
|
|||
dsl_pool_dirty_space(dmu_tx_pool(tx), space, tx);
|
||||
}
|
||||
|
||||
/*
|
||||
* Notify the objset that it's being shutdown. This is primarily useful
|
||||
* when attempting to dislodge any references that might be waiting on a txg
|
||||
* or similar.
|
||||
*/
|
||||
int
|
||||
dmu_objset_shutdown_register(objset_t *os)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
mutex_enter(&os->os_lock);
|
||||
if (os->os_shutdown_initiator == NULL) {
|
||||
os->os_shutdown_initiator = curthread;
|
||||
} else {
|
||||
ret = SET_ERROR(EBUSY);
|
||||
}
|
||||
mutex_exit(&os->os_lock);
|
||||
|
||||
/*
|
||||
* Signal things that will check for objset force export. The calling
|
||||
* thread must use a secondary mechanism to check for ref drops,
|
||||
* before calling dmu_objset_shutdown_unregister().
|
||||
*/
|
||||
if (ret == 0) {
|
||||
txg_completion_notify(spa_get_dsl(dmu_objset_spa(os)));
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
boolean_t
|
||||
dmu_objset_exiting(objset_t *os)
|
||||
{
|
||||
|
||||
return (os->os_shutdown_initiator != NULL ||
|
||||
spa_exiting_any(os->os_spa));
|
||||
}
|
||||
|
||||
void
|
||||
dmu_objset_shutdown_unregister(objset_t *os)
|
||||
{
|
||||
|
||||
ASSERT3P(os->os_shutdown_initiator, ==, curthread);
|
||||
os->os_shutdown_initiator = NULL;
|
||||
}
|
||||
|
||||
#if defined(_KERNEL)
|
||||
EXPORT_SYMBOL(dmu_objset_zil);
|
||||
EXPORT_SYMBOL(dmu_objset_pool);
|
||||
|
|
|
@ -68,9 +68,11 @@ int zfs_recv_queue_length = SPA_MAXBLOCKSIZE;
|
|||
int zfs_recv_queue_ff = 20;
|
||||
int zfs_recv_write_batch_size = 1024 * 1024;
|
||||
|
||||
static char *dmu_recv_tag = "dmu_recv_tag";
|
||||
const char *recv_clone_name = "%recv";
|
||||
|
||||
/* The receive was closed by an external call. */
|
||||
#define DRC_CLOSED (1U << 0)
|
||||
|
||||
static int receive_read_payload_and_next_header(dmu_recv_cookie_t *ra, int len,
|
||||
void *buf);
|
||||
|
||||
|
@ -339,6 +341,34 @@ recv_check_large_blocks(dsl_dataset_t *ds, uint64_t featureflags)
|
|||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
recv_own(dsl_pool_t *dp, dmu_tx_t *tx, uint64_t dsobj, ds_hold_flags_t dsflags,
|
||||
dmu_recv_cookie_t *drc, dsl_dataset_t **dsp, objset_t **osp)
|
||||
{
|
||||
dsl_dataset_t *ds;
|
||||
|
||||
/*
|
||||
* The dataset must be marked inconsistent before exit in any event,
|
||||
* so dirty it now. This ensures it's cleaned up if interrupted.
|
||||
*/
|
||||
VERIFY0(dsl_dataset_own_obj_force(dp, dsobj, dsflags, drc, &ds));
|
||||
dmu_buf_will_dirty(ds->ds_dbuf, tx);
|
||||
dsl_dataset_phys(ds)->ds_flags |= DS_FLAG_INCONSISTENT;
|
||||
ds->ds_receiver = drc;
|
||||
*dsp = ds;
|
||||
VERIFY0(dmu_objset_from_ds(ds, osp));
|
||||
}
|
||||
|
||||
static void
|
||||
recv_disown(dsl_dataset_t *ds, dmu_recv_cookie_t *drc)
|
||||
{
|
||||
ds_hold_flags_t dsflags = (drc->drc_raw) ? 0 : DS_HOLD_FLAG_DECRYPT;
|
||||
|
||||
ASSERT3P(ds->ds_receiver, ==, drc);
|
||||
ds->ds_receiver = NULL;
|
||||
dsl_dataset_disown(ds, dsflags, drc);
|
||||
}
|
||||
|
||||
static int
|
||||
recv_begin_check_existing_impl(dmu_recv_begin_arg_t *drba, dsl_dataset_t *ds,
|
||||
uint64_t fromguid, uint64_t featureflags)
|
||||
|
@ -841,8 +871,8 @@ dmu_recv_begin_sync(void *arg, dmu_tx_t *tx)
|
|||
dsl_dir_rele(dd, FTAG);
|
||||
drc->drc_newfs = B_TRUE;
|
||||
}
|
||||
VERIFY0(dsl_dataset_own_obj_force(dp, dsobj, dsflags, dmu_recv_tag,
|
||||
&newds));
|
||||
recv_own(dp, tx, dsobj, dsflags, drba->drba_cookie, &newds, &os);
|
||||
|
||||
if (dsl_dataset_feature_is_active(newds,
|
||||
SPA_FEATURE_REDACTED_DATASETS)) {
|
||||
/*
|
||||
|
@ -922,9 +952,6 @@ dmu_recv_begin_sync(void *arg, dmu_tx_t *tx)
|
|||
numredactsnaps, tx);
|
||||
}
|
||||
|
||||
dmu_buf_will_dirty(newds->ds_dbuf, tx);
|
||||
dsl_dataset_phys(newds)->ds_flags |= DS_FLAG_INCONSISTENT;
|
||||
|
||||
/*
|
||||
* If we actually created a non-clone, we need to create the objset
|
||||
* in our new dataset. If this is a raw send we postpone this until
|
||||
|
@ -1098,8 +1125,9 @@ dmu_recv_resume_begin_sync(void *arg, dmu_tx_t *tx)
|
|||
{
|
||||
dmu_recv_begin_arg_t *drba = arg;
|
||||
dsl_pool_t *dp = dmu_tx_pool(tx);
|
||||
const char *tofs = drba->drba_cookie->drc_tofs;
|
||||
uint64_t featureflags = drba->drba_cookie->drc_featureflags;
|
||||
dmu_recv_cookie_t *drc = drba->drba_cookie;
|
||||
const char *tofs = drc->drc_tofs;
|
||||
uint64_t featureflags = drc->drc_featureflags;
|
||||
dsl_dataset_t *ds;
|
||||
ds_hold_flags_t dsflags = DS_HOLD_FLAG_NONE;
|
||||
/* 6 extra bytes for /%recv */
|
||||
|
@ -1109,28 +1137,26 @@ dmu_recv_resume_begin_sync(void *arg, dmu_tx_t *tx)
|
|||
recv_clone_name);
|
||||
|
||||
if (featureflags & DMU_BACKUP_FEATURE_RAW) {
|
||||
drba->drba_cookie->drc_raw = B_TRUE;
|
||||
drc->drc_raw = B_TRUE;
|
||||
} else {
|
||||
dsflags |= DS_HOLD_FLAG_DECRYPT;
|
||||
}
|
||||
|
||||
if (dsl_dataset_own_force(dp, recvname, dsflags, dmu_recv_tag, &ds)
|
||||
!= 0) {
|
||||
if (dsl_dataset_own_force(dp, recvname, dsflags, drc, &ds) != 0) {
|
||||
/* %recv does not exist; continue in tofs */
|
||||
VERIFY0(dsl_dataset_own_force(dp, tofs, dsflags, dmu_recv_tag,
|
||||
&ds));
|
||||
drba->drba_cookie->drc_newfs = B_TRUE;
|
||||
VERIFY0(dsl_dataset_own_force(dp, tofs, dsflags, drc, &ds));
|
||||
drc->drc_newfs = B_TRUE;
|
||||
}
|
||||
ds->ds_receiver = drc;
|
||||
|
||||
ASSERT(DS_IS_INCONSISTENT(ds));
|
||||
rrw_enter(&ds->ds_bp_rwlock, RW_READER, FTAG);
|
||||
ASSERT(!BP_IS_HOLE(dsl_dataset_get_blkptr(ds)) ||
|
||||
drba->drba_cookie->drc_raw);
|
||||
ASSERT(!BP_IS_HOLE(dsl_dataset_get_blkptr(ds)) || drc->drc_raw);
|
||||
rrw_exit(&ds->ds_bp_rwlock, FTAG);
|
||||
|
||||
drba->drba_cookie->drc_ds = ds;
|
||||
VERIFY0(dmu_objset_from_ds(ds, &drba->drba_cookie->drc_os));
|
||||
drba->drba_cookie->drc_should_save = B_TRUE;
|
||||
drc->drc_ds = ds;
|
||||
VERIFY0(dmu_objset_from_ds(ds, &drc->drc_os));
|
||||
drc->drc_should_save = B_TRUE;
|
||||
|
||||
spa_history_log_internal_ds(ds, "resume receive", tx, " ");
|
||||
}
|
||||
|
@ -1148,7 +1174,8 @@ dmu_recv_begin(char *tofs, char *tosnap, dmu_replay_record_t *drr_begin,
|
|||
dmu_recv_begin_arg_t drba = { 0 };
|
||||
int err;
|
||||
|
||||
bzero(drc, sizeof (dmu_recv_cookie_t));
|
||||
memset(drc, 0, sizeof (dmu_recv_cookie_t));
|
||||
drc->drc_initiator = curthread;
|
||||
drc->drc_drr_begin = drr_begin;
|
||||
drc->drc_drrb = &drr_begin->drr_u.drr_begin;
|
||||
drc->drc_tosnap = tosnap;
|
||||
|
@ -1237,6 +1264,16 @@ dmu_recv_begin(char *tofs, char *tosnap, dmu_replay_record_t *drr_begin,
|
|||
}
|
||||
}
|
||||
|
||||
if (err == 0 && drc->drc_ds == NULL) {
|
||||
/*
|
||||
* Make sure the dataset is destroyed before returning. We
|
||||
* can't do this in the sync task because a dataset can't be
|
||||
* synced and destroyed in the same txg. In this scenario,
|
||||
* it should be flagged as inconsistent so we're ok anyway.
|
||||
*/
|
||||
(void) dsl_destroy_head(tofs);
|
||||
return (SET_ERROR(ENXIO));
|
||||
}
|
||||
if (err != 0) {
|
||||
kmem_free(drc->drc_next_rrd, sizeof (*drc->drc_next_rrd));
|
||||
nvlist_free(drc->drc_begin_nvl);
|
||||
|
@ -2322,29 +2359,37 @@ static void
|
|||
dmu_recv_cleanup_ds(dmu_recv_cookie_t *drc)
|
||||
{
|
||||
dsl_dataset_t *ds = drc->drc_ds;
|
||||
ds_hold_flags_t dsflags;
|
||||
objset_t *os = ds->ds_objset;
|
||||
int error = 0;
|
||||
|
||||
dsflags = (drc->drc_raw) ? DS_HOLD_FLAG_NONE : DS_HOLD_FLAG_DECRYPT;
|
||||
/*
|
||||
* Wait for the txg sync before cleaning up the receive. For
|
||||
* resumable receives, this ensures that our resume state has
|
||||
* been written out to disk. For raw receives, this ensures
|
||||
* that the user accounting code will not attempt to do anything
|
||||
* after we stopped receiving the dataset.
|
||||
*
|
||||
* If this is interrupted due to suspension and the pool is being
|
||||
* force exported, just exit and cleanup.
|
||||
*/
|
||||
txg_wait_synced(ds->ds_dir->dd_pool, 0);
|
||||
for (;;) {
|
||||
error = txg_wait_synced_tx(ds->ds_dir->dd_pool, 0,
|
||||
NULL, TXG_WAIT_F_NOSUSPEND);
|
||||
if (error == 0 || spa_exiting_any(os->os_spa))
|
||||
break;
|
||||
}
|
||||
ds->ds_objset->os_raw_receive = B_FALSE;
|
||||
|
||||
rrw_enter(&ds->ds_bp_rwlock, RW_READER, FTAG);
|
||||
if (drc->drc_resumable && drc->drc_should_save &&
|
||||
!BP_IS_HOLE(dsl_dataset_get_blkptr(ds))) {
|
||||
rrw_exit(&ds->ds_bp_rwlock, FTAG);
|
||||
dsl_dataset_disown(ds, dsflags, dmu_recv_tag);
|
||||
recv_disown(ds, drc);
|
||||
} else {
|
||||
char name[ZFS_MAX_DATASET_NAME_LEN];
|
||||
rrw_exit(&ds->ds_bp_rwlock, FTAG);
|
||||
dsl_dataset_name(ds, name);
|
||||
dsl_dataset_disown(ds, dsflags, dmu_recv_tag);
|
||||
recv_disown(ds, drc);
|
||||
(void) dsl_destroy_head(name);
|
||||
}
|
||||
}
|
||||
|
@ -2882,6 +2927,35 @@ resume_check(dmu_recv_cookie_t *drc, nvlist_t *begin_nvl)
|
|||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Cancel the receive stream for the dataset, if there is one.
|
||||
*/
|
||||
int
|
||||
dmu_recv_close(dsl_dataset_t *ds)
|
||||
{
|
||||
int err = 0;
|
||||
dmu_recv_cookie_t *drc;
|
||||
|
||||
/*
|
||||
* This lock isn't technically for recv, but it's not worth
|
||||
* adding a dedicated one for this purpose.
|
||||
*/
|
||||
mutex_enter(&ds->ds_sendstream_lock);
|
||||
drc = ds->ds_receiver;
|
||||
if (drc != NULL) {
|
||||
drc->drc_flags |= DRC_CLOSED;
|
||||
/*
|
||||
* Send an interrupt to the initiator thread, which will
|
||||
* cause it to end the stream and clean up.
|
||||
*/
|
||||
if (drc->drc_initiator != curthread)
|
||||
thread_signal(drc->drc_initiator, SIGINT);
|
||||
}
|
||||
mutex_exit(&ds->ds_sendstream_lock);
|
||||
|
||||
return (err);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read in the stream's records, one by one, and apply them to the pool. There
|
||||
* are two threads involved; the thread that calls this function will spin up a
|
||||
|
@ -2898,6 +2972,7 @@ int
|
|||
dmu_recv_stream(dmu_recv_cookie_t *drc, offset_t *voffp)
|
||||
{
|
||||
int err = 0;
|
||||
spa_t *spa = dsl_dataset_get_spa(drc->drc_ds);
|
||||
struct receive_writer_arg *rwa = kmem_zalloc(sizeof (*rwa), KM_SLEEP);
|
||||
|
||||
if (dsl_dataset_has_resume_receive_state(drc->drc_ds)) {
|
||||
|
@ -2934,10 +3009,10 @@ dmu_recv_stream(dmu_recv_cookie_t *drc, offset_t *voffp)
|
|||
/*
|
||||
* If this is a new dataset we set the key immediately.
|
||||
* Otherwise we don't want to change the key until we
|
||||
* are sure the rest of the receive succeeded so we stash
|
||||
* the keynvl away until then.
|
||||
* are sure the rest of the receive succeeded so we
|
||||
* stash the keynvl away until then.
|
||||
*/
|
||||
err = dsl_crypto_recv_raw(spa_name(drc->drc_os->os_spa),
|
||||
err = dsl_crypto_recv_raw(spa_name(spa),
|
||||
drc->drc_ds->ds_object, drc->drc_fromsnapobj,
|
||||
drc->drc_drrb->drr_type, keynvl, drc->drc_newfs);
|
||||
if (err != 0)
|
||||
|
@ -2965,6 +3040,12 @@ dmu_recv_stream(dmu_recv_cookie_t *drc, offset_t *voffp)
|
|||
*/
|
||||
drc->drc_should_save = B_TRUE;
|
||||
|
||||
/* Last chance before kicking off. */
|
||||
if (drc->drc_flags & DRC_CLOSED) {
|
||||
err = SET_ERROR(EINTR);
|
||||
goto out;
|
||||
}
|
||||
|
||||
(void) bqueue_init(&rwa->q, zfs_recv_queue_ff,
|
||||
MAX(zfs_recv_queue_length, 2 * zfs_max_recordsize),
|
||||
offsetof(struct receive_record_arg, node));
|
||||
|
@ -2980,8 +3061,17 @@ dmu_recv_stream(dmu_recv_cookie_t *drc, offset_t *voffp)
|
|||
list_create(&rwa->write_batch, sizeof (struct receive_record_arg),
|
||||
offsetof(struct receive_record_arg, node.bqn_node));
|
||||
|
||||
(void) thread_create(NULL, 0, receive_writer_thread, rwa, 0, curproc,
|
||||
TS_RUN, minclsyspri);
|
||||
/*
|
||||
* Register the rwa with the drc so it can be interrupted. This
|
||||
* requires a mutex handshake to ensure validity.
|
||||
*/
|
||||
mutex_enter(&drc->drc_ds->ds_sendstream_lock);
|
||||
drc->drc_rwa = rwa;
|
||||
mutex_exit(&drc->drc_ds->ds_sendstream_lock);
|
||||
|
||||
kthread_t *rw_td = thread_create(NULL, 0, receive_writer_thread,
|
||||
rwa, 0, curproc, TS_RUN, minclsyspri);
|
||||
|
||||
/*
|
||||
* We're reading rwa->err without locks, which is safe since we are the
|
||||
* only reader, and the worker thread is the only writer. It's ok if we
|
||||
|
@ -2997,11 +3087,10 @@ dmu_recv_stream(dmu_recv_cookie_t *drc, offset_t *voffp)
|
|||
* it. Finally, if receive_read_record fails or we're at the end of the
|
||||
* stream, then we free drc->drc_rrd and exit.
|
||||
*/
|
||||
while (rwa->err == 0) {
|
||||
if (issig(JUSTLOOKING) && issig(FORREAL)) {
|
||||
err = SET_ERROR(EINTR);
|
||||
while (rwa->err == 0 && err == 0) {
|
||||
err = spa_operation_interrupted(dmu_objset_spa(rwa->os));
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
|
||||
ASSERT3P(drc->drc_rrd, ==, NULL);
|
||||
drc->drc_rrd = drc->drc_next_rrd;
|
||||
|
@ -3028,9 +3117,22 @@ dmu_recv_stream(dmu_recv_cookie_t *drc, offset_t *voffp)
|
|||
|
||||
mutex_enter(&rwa->mutex);
|
||||
while (!rwa->done) {
|
||||
boolean_t closed = drc->drc_flags & DRC_CLOSED;
|
||||
|
||||
if (!closed) {
|
||||
if (err == 0)
|
||||
err = spa_operation_interrupted(spa);
|
||||
if (err != 0) {
|
||||
drc->drc_flags |= DRC_CLOSED;
|
||||
thread_signal(rw_td, SIGINT);
|
||||
closed = B_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We need to use cv_wait_sig() so that any process that may
|
||||
* be sleeping here can still fork.
|
||||
* be sleeping here can still fork. Also, it allows
|
||||
* dmu_recv_close to cause an eos marker to be injected.
|
||||
*/
|
||||
(void) cv_wait_sig(&rwa->cv, &rwa->mutex);
|
||||
}
|
||||
|
@ -3062,6 +3164,10 @@ dmu_recv_stream(dmu_recv_cookie_t *drc, offset_t *voffp)
|
|||
}
|
||||
}
|
||||
|
||||
mutex_enter(&drc->drc_ds->ds_sendstream_lock);
|
||||
drc->drc_rwa = NULL;
|
||||
mutex_exit(&drc->drc_ds->ds_sendstream_lock);
|
||||
|
||||
cv_destroy(&rwa->cv);
|
||||
mutex_destroy(&rwa->mutex);
|
||||
bqueue_destroy(&rwa->q);
|
||||
|
@ -3110,7 +3216,7 @@ dmu_recv_end_check(void *arg, dmu_tx_t *tx)
|
|||
dsl_pool_t *dp = dmu_tx_pool(tx);
|
||||
int error;
|
||||
|
||||
ASSERT3P(drc->drc_ds->ds_owner, ==, dmu_recv_tag);
|
||||
ASSERT3P(drc->drc_ds->ds_receiver, ==, drc);
|
||||
|
||||
if (!drc->drc_newfs) {
|
||||
dsl_dataset_t *origin_head;
|
||||
|
@ -3328,7 +3434,7 @@ dmu_recv_end_sync(void *arg, dmu_tx_t *tx)
|
|||
(void) spa_keystore_remove_mapping(dmu_tx_pool(tx)->dp_spa,
|
||||
drc->drc_ds->ds_object, drc->drc_ds);
|
||||
}
|
||||
dsl_dataset_disown(drc->drc_ds, 0, dmu_recv_tag);
|
||||
recv_disown(drc->drc_ds, drc);
|
||||
drc->drc_ds = NULL;
|
||||
}
|
||||
|
||||
|
@ -3394,7 +3500,7 @@ boolean_t
|
|||
dmu_objset_is_receiving(objset_t *os)
|
||||
{
|
||||
return (os->os_dsl_dataset != NULL &&
|
||||
os->os_dsl_dataset->ds_owner == dmu_recv_tag);
|
||||
os->os_dsl_dataset->ds_receiver != NULL);
|
||||
}
|
||||
|
||||
/* BEGIN CSTYLED */
|
||||
|
|
|
@ -564,7 +564,14 @@ commit_rl_updates(objset_t *os, struct merge_data *md, uint64_t object,
|
|||
{
|
||||
dmu_tx_t *tx = dmu_tx_create_dd(spa_get_dsl(os->os_spa)->dp_mos_dir);
|
||||
dmu_tx_hold_space(tx, sizeof (struct redact_block_list_node));
|
||||
VERIFY0(dmu_tx_assign(tx, TXG_WAIT));
|
||||
|
||||
int err = dmu_tx_assign(tx, TXG_WAIT);
|
||||
if (err != 0) {
|
||||
ASSERT(spa_exiting_any(os->os_spa));
|
||||
dmu_tx_abort(tx);
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t txg = dmu_tx_get_txg(tx);
|
||||
if (!md->md_synctask_txg[txg & TXG_MASK]) {
|
||||
dsl_sync_task_nowait(dmu_tx_pool(tx),
|
||||
|
|
|
@ -2214,6 +2214,7 @@ setup_send_progress(struct dmu_send_params *dspp)
|
|||
dssp->dss_outfd = dspp->outfd;
|
||||
dssp->dss_off = dspp->off;
|
||||
dssp->dss_proc = curproc;
|
||||
dssp->dss_thread = curthread;
|
||||
mutex_enter(&dspp->to_ds->ds_sendstream_lock);
|
||||
list_insert_head(&dspp->to_ds->ds_sendstreams, dssp);
|
||||
mutex_exit(&dspp->to_ds->ds_sendstream_lock);
|
||||
|
@ -2503,6 +2504,14 @@ dmu_send_impl(struct dmu_send_params *dspp)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Last chance, bail if possible at this point, now that the send is
|
||||
* registered and can be cancelled by signalling this thread.
|
||||
*/
|
||||
err = spa_operation_interrupted(os->os_spa);
|
||||
if (err != 0)
|
||||
goto out;
|
||||
|
||||
if (resuming || book_resuming) {
|
||||
err = setup_resume_points(dspp, to_arg, from_arg,
|
||||
rlt_arg, smt_arg, resuming, os, redact_rl, nvl);
|
||||
|
@ -2550,8 +2559,8 @@ dmu_send_impl(struct dmu_send_params *dspp)
|
|||
while (err == 0 && !range->eos_marker) {
|
||||
err = do_dump(&dsc, range);
|
||||
range = get_next_range(&srt_arg->q, range);
|
||||
if (issig(JUSTLOOKING) && issig(FORREAL))
|
||||
err = SET_ERROR(EINTR);
|
||||
if (err == 0)
|
||||
err = spa_operation_interrupted(os->os_spa);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3086,7 +3095,32 @@ out:
|
|||
return (err);
|
||||
}
|
||||
|
||||
/* Close all send streams on the dataset. */
|
||||
int
|
||||
dmu_send_close(dsl_dataset_t *ds)
|
||||
{
|
||||
int err = 0;
|
||||
dmu_sendstatus_t *dss;
|
||||
|
||||
mutex_enter(&ds->ds_sendstream_lock);
|
||||
dss = list_head(&ds->ds_sendstreams);
|
||||
while (err == 0 && dss != NULL) {
|
||||
/*
|
||||
* Interrupt the initiator thread, which will cause it
|
||||
* to initiate a cleanup error exit. Also send SIGPIPE
|
||||
* because this interrupts pipe writes.
|
||||
*/
|
||||
thread_signal(dss->dss_thread, SIGINT);
|
||||
thread_signal(dss->dss_thread, SIGPIPE);
|
||||
dss = list_next(&ds->ds_sendstreams, dss);
|
||||
}
|
||||
mutex_exit(&ds->ds_sendstream_lock);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* BEGIN CSTYLED */
|
||||
|
||||
ZFS_MODULE_PARAM(zfs_send, zfs_send_, corrupt_data, INT, ZMOD_RW,
|
||||
"Allow sending corrupt data");
|
||||
|
||||
|
|
|
@ -869,6 +869,19 @@ dmu_tx_try_assign(dmu_tx_t *tx, uint64_t txg_how)
|
|||
if (spa_suspended(spa)) {
|
||||
DMU_TX_STAT_BUMP(dmu_tx_suspended);
|
||||
|
||||
if (txg_how & TXG_NOSUSPEND)
|
||||
return (SET_ERROR(EAGAIN));
|
||||
|
||||
/*
|
||||
* If the user is forcibly exporting the pool or the objset,
|
||||
* indicate to the caller that they need to give up.
|
||||
*/
|
||||
if (spa_exiting_any(spa))
|
||||
return (SET_ERROR(EIO));
|
||||
|
||||
if (tx->tx_objset != NULL && dmu_objset_exiting(tx->tx_objset))
|
||||
return (SET_ERROR(EIO));
|
||||
|
||||
/*
|
||||
* If the user has indicated a blocking failure mode
|
||||
* then return ERESTART which will block in dmu_tx_wait().
|
||||
|
@ -995,6 +1008,8 @@ dmu_tx_unassign(dmu_tx_t *tx)
|
|||
tx->tx_txg = 0;
|
||||
}
|
||||
|
||||
static void dmu_tx_wait_flags(dmu_tx_t *, txg_wait_flag_t);
|
||||
|
||||
/*
|
||||
* Assign tx to a transaction group; txg_how is a bitmask:
|
||||
*
|
||||
|
@ -1015,6 +1030,11 @@ dmu_tx_unassign(dmu_tx_t *tx)
|
|||
* they have already called dmu_tx_wait() (though most likely on a
|
||||
* different tx).
|
||||
*
|
||||
* If TXG_NOSUSPEND is set, this indicates that this request must return
|
||||
* EAGAIN if the pool becomes suspended while it is in progress. This
|
||||
* ensures that the request does not inadvertently cause conditions that
|
||||
* cannot be unwound.
|
||||
*
|
||||
* It is guaranteed that subsequent successful calls to dmu_tx_assign()
|
||||
* will assign the tx to monotonically increasing txgs. Of course this is
|
||||
* not strong monotonicity, because the same txg can be returned multiple
|
||||
|
@ -1037,7 +1057,7 @@ dmu_tx_assign(dmu_tx_t *tx, uint64_t txg_how)
|
|||
int err;
|
||||
|
||||
ASSERT(tx->tx_txg == 0);
|
||||
ASSERT0(txg_how & ~(TXG_WAIT | TXG_NOTHROTTLE));
|
||||
ASSERT0(txg_how & ~(TXG_NOSUSPEND | TXG_WAIT | TXG_NOTHROTTLE));
|
||||
ASSERT(!dsl_pool_sync_context(tx->tx_pool));
|
||||
|
||||
/* If we might wait, we must not hold the config lock. */
|
||||
|
@ -1052,7 +1072,8 @@ dmu_tx_assign(dmu_tx_t *tx, uint64_t txg_how)
|
|||
if (err != ERESTART || !(txg_how & TXG_WAIT))
|
||||
return (err);
|
||||
|
||||
dmu_tx_wait(tx);
|
||||
dmu_tx_wait_flags(tx,
|
||||
(txg_how & TXG_NOSUSPEND) ? TXG_WAIT_F_NOSUSPEND : 0);
|
||||
}
|
||||
|
||||
txg_rele_to_quiesce(&tx->tx_txgh);
|
||||
|
@ -1060,8 +1081,8 @@ dmu_tx_assign(dmu_tx_t *tx, uint64_t txg_how)
|
|||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
dmu_tx_wait(dmu_tx_t *tx)
|
||||
static void
|
||||
dmu_tx_wait_flags(dmu_tx_t *tx, txg_wait_flag_t how)
|
||||
{
|
||||
spa_t *spa = tx->tx_pool->dp_spa;
|
||||
dsl_pool_t *dp = tx->tx_pool;
|
||||
|
@ -1106,8 +1127,11 @@ dmu_tx_wait(dmu_tx_t *tx)
|
|||
* has become active after this thread has tried to
|
||||
* obtain a tx. If that's the case then tx_lasttried_txg
|
||||
* would not have been set.
|
||||
*
|
||||
* It's also possible the pool will be force exported, in
|
||||
* which case we'll try again and notice this fact, and exit.
|
||||
*/
|
||||
txg_wait_synced(dp, spa_last_synced_txg(spa) + 1);
|
||||
txg_wait_synced_tx(dp, spa_last_synced_txg(spa) + 1, tx, how);
|
||||
} else if (tx->tx_needassign_txh) {
|
||||
dnode_t *dn = tx->tx_needassign_txh->txh_dnode;
|
||||
|
||||
|
@ -1121,13 +1145,23 @@ dmu_tx_wait(dmu_tx_t *tx)
|
|||
* If we have a lot of dirty data just wait until we sync
|
||||
* out a TXG at which point we'll hopefully have synced
|
||||
* a portion of the changes.
|
||||
*
|
||||
* It's also possible the pool will be force exported, in
|
||||
* which case we'll try again and notice this fact, and exit.
|
||||
*/
|
||||
txg_wait_synced(dp, spa_last_synced_txg(spa) + 1);
|
||||
txg_wait_synced_tx(dp, spa_last_synced_txg(spa) + 1, tx, how);
|
||||
}
|
||||
|
||||
spa_tx_assign_add_nsecs(spa, gethrtime() - before);
|
||||
}
|
||||
|
||||
void
|
||||
dmu_tx_wait(dmu_tx_t *tx)
|
||||
{
|
||||
|
||||
return (dmu_tx_wait_flags(tx, TXG_WAIT_F_NONE));
|
||||
}
|
||||
|
||||
static void
|
||||
dmu_tx_destroy(dmu_tx_t *tx)
|
||||
{
|
||||
|
|
|
@ -44,6 +44,9 @@
|
|||
#include <sys/dmu_traverse.h>
|
||||
#include <sys/dmu_impl.h>
|
||||
#include <sys/dmu_tx.h>
|
||||
#include <sys/dmu.h>
|
||||
#include <sys/dbuf.h>
|
||||
#include <sys/dnode.h>
|
||||
#include <sys/arc.h>
|
||||
#include <sys/zio.h>
|
||||
#include <sys/zap.h>
|
||||
|
@ -557,8 +560,8 @@ dsl_dataset_try_add_ref(dsl_pool_t *dp, dsl_dataset_t *ds, void *tag)
|
|||
}
|
||||
|
||||
int
|
||||
dsl_dataset_hold_obj(dsl_pool_t *dp, uint64_t dsobj, void *tag,
|
||||
dsl_dataset_t **dsp)
|
||||
dsl_dataset_hold_obj_flags(dsl_pool_t *dp, uint64_t dsobj,
|
||||
ds_hold_flags_t flags, void *tag, dsl_dataset_t **dsp)
|
||||
{
|
||||
objset_t *mos = dp->dp_meta_objset;
|
||||
dmu_buf_t *dbuf;
|
||||
|
@ -581,6 +584,11 @@ dsl_dataset_hold_obj(dsl_pool_t *dp, uint64_t dsobj, void *tag,
|
|||
|
||||
ds = dmu_buf_get_user(dbuf);
|
||||
if (ds == NULL) {
|
||||
if (flags & DS_HOLD_FLAG_MUST_BE_OPEN) {
|
||||
dmu_buf_rele(dbuf, tag);
|
||||
return (SET_ERROR(ENXIO));
|
||||
}
|
||||
|
||||
dsl_dataset_t *winner = NULL;
|
||||
|
||||
ds = kmem_zalloc(sizeof (dsl_dataset_t), KM_SLEEP);
|
||||
|
@ -722,6 +730,15 @@ dsl_dataset_hold_obj(dsl_pool_t *dp, uint64_t dsobj, void *tag,
|
|||
}
|
||||
}
|
||||
|
||||
if (err == 0 && (flags & DS_HOLD_FLAG_DECRYPT)) {
|
||||
err = dsl_dataset_create_key_mapping(ds);
|
||||
if (err != 0)
|
||||
dsl_dataset_rele(ds, tag);
|
||||
}
|
||||
|
||||
if (err != 0)
|
||||
return (err);
|
||||
|
||||
ASSERT3P(ds->ds_dbuf, ==, dbuf);
|
||||
ASSERT3P(dsl_dataset_phys(ds), ==, dbuf->db_data);
|
||||
ASSERT(dsl_dataset_phys(ds)->ds_prev_snap_obj != 0 ||
|
||||
|
@ -745,24 +762,10 @@ dsl_dataset_create_key_mapping(dsl_dataset_t *ds)
|
|||
}
|
||||
|
||||
int
|
||||
dsl_dataset_hold_obj_flags(dsl_pool_t *dp, uint64_t dsobj,
|
||||
ds_hold_flags_t flags, void *tag, dsl_dataset_t **dsp)
|
||||
dsl_dataset_hold_obj(dsl_pool_t *dp, uint64_t dsobj, void *tag,
|
||||
dsl_dataset_t **dsp)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = dsl_dataset_hold_obj(dp, dsobj, tag, dsp);
|
||||
if (err != 0)
|
||||
return (err);
|
||||
|
||||
ASSERT3P(*dsp, !=, NULL);
|
||||
|
||||
if (flags & DS_HOLD_FLAG_DECRYPT) {
|
||||
err = dsl_dataset_create_key_mapping(*dsp);
|
||||
if (err != 0)
|
||||
dsl_dataset_rele(*dsp, tag);
|
||||
}
|
||||
|
||||
return (err);
|
||||
return (dsl_dataset_hold_obj_flags(dp, dsobj, 0, tag, dsp));
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -913,6 +916,115 @@ dsl_dataset_long_held(dsl_dataset_t *ds)
|
|||
return (!zfs_refcount_is_zero(&ds->ds_longholds));
|
||||
}
|
||||
|
||||
/*
|
||||
* Enumerate active datasets. This function is intended for use cases that
|
||||
* want to avoid I/O, and only operate on those that have been loaded in
|
||||
* memory. This works by enumerating the objects in the MOS that are known,
|
||||
* and calling back with each dataset's MOS object IDs. It would be nice if
|
||||
* the objset_t's were registered in a spa_t global list, but they're not,
|
||||
* so this implementation is a bit more complex...
|
||||
*/
|
||||
static int
|
||||
dsl_dataset_active_foreach(spa_t *spa, int func(dsl_dataset_t *, void *),
|
||||
void *cl)
|
||||
{
|
||||
dsl_pool_t *dp = spa_get_dsl(spa);
|
||||
objset_t *mos = dp->dp_meta_objset;
|
||||
dnode_t *mdn = DMU_META_DNODE(mos);
|
||||
dmu_buf_impl_t *db;
|
||||
uint64_t blkid, dsobj, i;
|
||||
dnode_children_t *children_dnodes;
|
||||
dnode_handle_t *dnh;
|
||||
dsl_dataset_t *ds;
|
||||
int epb, error;
|
||||
int ret = 0;
|
||||
|
||||
/*
|
||||
* For each block of the MOS's meta-dnode's full size:
|
||||
* - If the block is not cached, skip.
|
||||
* - If the block has no user, skip.
|
||||
* - For each dnode child of the meta-dnode block:
|
||||
* - If not loaded (no dnode pointer), skip.
|
||||
* - Attempt to hold the dataset, skip on failure.
|
||||
* - Call the callback, quit if returns non zero,
|
||||
* - Rele the dataset either way.
|
||||
*/
|
||||
rrw_enter(&dp->dp_config_rwlock, RW_READER, FTAG);
|
||||
rw_enter(&mdn->dn_struct_rwlock, RW_READER);
|
||||
for (blkid = dsobj = 0;
|
||||
ret == 0 && blkid <= mdn->dn_maxblkid;
|
||||
blkid++, dsobj += epb) {
|
||||
epb = DNODES_PER_BLOCK;
|
||||
error = dbuf_hold_impl(mdn, 0, blkid, TRUE, TRUE, FTAG, &db);
|
||||
if (error != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
epb = db->db.db_size >> DNODE_SHIFT;
|
||||
children_dnodes = dmu_buf_get_user(&db->db);
|
||||
if (children_dnodes == NULL) {
|
||||
goto skip;
|
||||
}
|
||||
|
||||
for (i = 0; ret == 0 && i < epb; i++) {
|
||||
dnh = &children_dnodes->dnc_children[i];
|
||||
if (!DN_SLOT_IS_PTR(dnh->dnh_dnode))
|
||||
continue;
|
||||
|
||||
error = dsl_dataset_hold_obj_flags(dp, dsobj + i,
|
||||
DS_HOLD_FLAG_MUST_BE_OPEN, FTAG, &ds);
|
||||
if (error != 0)
|
||||
continue;
|
||||
|
||||
ret = func(ds, cl);
|
||||
dsl_dataset_rele(ds, FTAG);
|
||||
}
|
||||
|
||||
skip:
|
||||
dbuf_rele(db, FTAG);
|
||||
}
|
||||
rw_exit(&mdn->dn_struct_rwlock);
|
||||
rrw_exit(&dp->dp_config_rwlock, FTAG);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* Cancellation interfaces for send/receive streams.
|
||||
*
|
||||
* If a send/recv wins the race with a forced destroy, their pipes will be
|
||||
* interrupted, and the destroy will wait for all ioctl references to drop.
|
||||
*
|
||||
* If a forced destroy wins the race, the send/receive will fail to start.
|
||||
*/
|
||||
|
||||
/* dsl_dataset_sendrecv_cancel_all callback for dsl_dataset_active_foreach. */
|
||||
static int
|
||||
dsl_dataset_sendrecv_cancel_cb(dsl_dataset_t *ds, __maybe_unused void *arg)
|
||||
{
|
||||
(void) arg;
|
||||
int err;
|
||||
|
||||
err = dmu_send_close(ds);
|
||||
if (err == 0)
|
||||
err = dmu_recv_close(ds);
|
||||
|
||||
return (err);
|
||||
}
|
||||
|
||||
/*
|
||||
* Cancel all outstanding sends/receives. Used when the pool is trying to
|
||||
* forcibly exit. Iterates on all datasets in the MOS and cancels any
|
||||
* running sends/receives by interrupting them.
|
||||
*/
|
||||
int
|
||||
dsl_dataset_sendrecv_cancel_all(spa_t *spa)
|
||||
{
|
||||
|
||||
return (dsl_dataset_active_foreach(spa,
|
||||
dsl_dataset_sendrecv_cancel_cb, NULL));
|
||||
}
|
||||
|
||||
void
|
||||
dsl_dataset_name(dsl_dataset_t *ds, char *name)
|
||||
{
|
||||
|
|
|
@ -624,6 +624,7 @@ dsl_pool_sync(dsl_pool_t *dp, uint64_t txg)
|
|||
dsl_dataset_t *ds;
|
||||
objset_t *mos = dp->dp_meta_objset;
|
||||
list_t synced_datasets;
|
||||
int error;
|
||||
|
||||
list_create(&synced_datasets, sizeof (dsl_dataset_t),
|
||||
offsetof(dsl_dataset_t, ds_synced_link));
|
||||
|
@ -661,7 +662,8 @@ dsl_pool_sync(dsl_pool_t *dp, uint64_t txg)
|
|||
list_insert_tail(&synced_datasets, ds);
|
||||
dsl_dataset_sync(ds, zio, tx);
|
||||
}
|
||||
VERIFY0(zio_wait(zio));
|
||||
error = zio_wait(zio);
|
||||
VERIFY(error == 0 || (spa_exiting_any(zio->io_spa) && error == EIO));
|
||||
|
||||
/*
|
||||
* Update the long range free counter after
|
||||
|
|
|
@ -835,8 +835,7 @@ dsl_scan(dsl_pool_t *dp, pool_scan_func_t func)
|
|||
(void) spa_vdev_state_exit(spa, NULL, 0);
|
||||
|
||||
if (func == POOL_SCAN_RESILVER) {
|
||||
dsl_scan_restart_resilver(spa->spa_dsl_pool, 0);
|
||||
return (0);
|
||||
return (dsl_scan_restart_resilver(spa->spa_dsl_pool, 0));
|
||||
}
|
||||
|
||||
if (func == POOL_SCAN_SCRUB && dsl_scan_is_paused_scrub(scn)) {
|
||||
|
@ -1099,13 +1098,20 @@ dsl_scrub_set_pause_resume(const dsl_pool_t *dp, pool_scrub_cmd_t cmd)
|
|||
|
||||
|
||||
/* start a new scan, or restart an existing one. */
|
||||
void
|
||||
int
|
||||
dsl_scan_restart_resilver(dsl_pool_t *dp, uint64_t txg)
|
||||
{
|
||||
int error;
|
||||
|
||||
if (txg == 0) {
|
||||
dmu_tx_t *tx;
|
||||
tx = dmu_tx_create_dd(dp->dp_mos_dir);
|
||||
VERIFY(0 == dmu_tx_assign(tx, TXG_WAIT));
|
||||
error = dmu_tx_assign(tx, TXG_WAIT);
|
||||
if (error != 0) {
|
||||
ASSERT(spa_exiting_any(dp->dp_spa));
|
||||
dmu_tx_abort(tx);
|
||||
return (error);
|
||||
}
|
||||
|
||||
txg = dmu_tx_get_txg(tx);
|
||||
dp->dp_scan->scn_restart_txg = txg;
|
||||
|
@ -1113,7 +1119,10 @@ dsl_scan_restart_resilver(dsl_pool_t *dp, uint64_t txg)
|
|||
} else {
|
||||
dp->dp_scan->scn_restart_txg = txg;
|
||||
}
|
||||
zfs_dbgmsg("restarting resilver txg=%llu", (longlong_t)txg);
|
||||
zfs_dbgmsg("restarting resilver for %s at txg=%llu",
|
||||
dp->dp_spa->spa_name, (longlong_t)txg);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -2746,13 +2755,18 @@ dsl_scan_visit(dsl_scan_t *scn, dmu_tx_t *tx)
|
|||
dsl_dataset_t *ds;
|
||||
uint64_t dsobj = sds->sds_dsobj;
|
||||
uint64_t txg = sds->sds_txg;
|
||||
int error;
|
||||
|
||||
/* dequeue and free the ds from the queue */
|
||||
scan_ds_queue_remove(scn, dsobj);
|
||||
sds = NULL;
|
||||
|
||||
/* set up min / max txg */
|
||||
VERIFY3U(0, ==, dsl_dataset_hold_obj(dp, dsobj, FTAG, &ds));
|
||||
error = dsl_dataset_hold_obj(dp, dsobj, FTAG, &ds);
|
||||
VERIFY(error == 0 ||
|
||||
(spa_exiting_any(dp->dp_spa) && error == EIO));
|
||||
if (error != 0)
|
||||
return;
|
||||
if (txg != 0) {
|
||||
scn->scn_phys.scn_cur_min_txg =
|
||||
MAX(scn->scn_phys.scn_min_txg, txg);
|
||||
|
|
|
@ -57,7 +57,12 @@ dsl_sync_task_common(const char *pool, dsl_checkfunc_t *checkfunc,
|
|||
|
||||
top:
|
||||
tx = dmu_tx_create_dd(dp->dp_mos_dir);
|
||||
VERIFY0(dmu_tx_assign(tx, TXG_WAIT));
|
||||
err = dmu_tx_assign(tx, TXG_WAIT);
|
||||
if (err != 0) {
|
||||
ASSERT(spa_exiting_any(spa));
|
||||
dmu_tx_abort(tx);
|
||||
return (err);
|
||||
}
|
||||
|
||||
dst.dst_pool = dp;
|
||||
dst.dst_txg = dmu_tx_get_txg(tx);
|
||||
|
|
|
@ -508,6 +508,16 @@ metaslab_class_get_dspace(metaslab_class_t *mc)
|
|||
return (spa_deflate(mc->mc_spa) ? mc->mc_dspace : mc->mc_space);
|
||||
}
|
||||
|
||||
void
|
||||
metaslab_class_force_discard(metaslab_class_t *mc)
|
||||
{
|
||||
|
||||
mc->mc_alloc = 0;
|
||||
mc->mc_deferred = 0;
|
||||
mc->mc_space = 0;
|
||||
mc->mc_dspace = 0;
|
||||
}
|
||||
|
||||
void
|
||||
metaslab_class_histogram_verify(metaslab_class_t *mc)
|
||||
{
|
||||
|
@ -2779,6 +2789,19 @@ metaslab_fini(metaslab_t *msp)
|
|||
metaslab_group_remove(mg, msp);
|
||||
|
||||
mutex_enter(&msp->ms_lock);
|
||||
if (spa_exiting_any(mg->mg_vd->vdev_spa)) {
|
||||
/* Catch-all cleanup as required for force export. */
|
||||
range_tree_vacate(msp->ms_allocatable, NULL, NULL);
|
||||
range_tree_vacate(msp->ms_freeing, NULL, NULL);
|
||||
range_tree_vacate(msp->ms_freed, NULL, NULL);
|
||||
range_tree_vacate(msp->ms_checkpointing, NULL, NULL);
|
||||
for (int t = 0; t < TXG_SIZE; t++)
|
||||
range_tree_vacate(msp->ms_allocating[t], NULL, NULL);
|
||||
for (int t = 0; t < TXG_DEFER_SIZE; t++)
|
||||
range_tree_vacate(msp->ms_defer[t], NULL, NULL);
|
||||
msp->ms_deferspace = 0;
|
||||
}
|
||||
|
||||
VERIFY(msp->ms_group == NULL);
|
||||
|
||||
/*
|
||||
|
@ -3951,6 +3974,31 @@ metaslab_sync(metaslab_t *msp, uint64_t txg)
|
|||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* The pool is being forcibly exported. Just discard everything.
|
||||
*/
|
||||
if (spa_exiting_any(spa)) {
|
||||
mutex_enter(&msp->ms_sync_lock);
|
||||
mutex_enter(&msp->ms_lock);
|
||||
range_tree_vacate(alloctree, NULL, NULL);
|
||||
range_tree_vacate(msp->ms_allocatable, NULL, NULL);
|
||||
range_tree_vacate(msp->ms_freeing, NULL, NULL);
|
||||
range_tree_vacate(msp->ms_freed, NULL, NULL);
|
||||
range_tree_vacate(msp->ms_trim, NULL, NULL);
|
||||
range_tree_vacate(msp->ms_checkpointing, NULL, NULL);
|
||||
range_tree_vacate(msp->ms_allocating[txg & TXG_MASK],
|
||||
NULL, NULL);
|
||||
range_tree_vacate(msp->ms_allocating[TXG_CLEAN(txg) & TXG_MASK],
|
||||
NULL, NULL);
|
||||
for (int t = 0; t < TXG_DEFER_SIZE; t++) {
|
||||
range_tree_vacate(msp->ms_defer[t], NULL, NULL);
|
||||
}
|
||||
msp->ms_deferspace = 0;
|
||||
mutex_exit(&msp->ms_lock);
|
||||
mutex_exit(&msp->ms_sync_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Normally, we don't want to process a metaslab if there are no
|
||||
* allocations or frees to perform. However, if the metaslab is being
|
||||
|
@ -3970,7 +4018,7 @@ metaslab_sync(metaslab_t *msp, uint64_t txg)
|
|||
return;
|
||||
|
||||
|
||||
VERIFY3U(txg, <=, spa_final_dirty_txg(spa));
|
||||
spa_verify_dirty_txg(spa, txg);
|
||||
|
||||
/*
|
||||
* The only state that can actually be changing concurrently
|
||||
|
@ -4339,7 +4387,7 @@ metaslab_sync_done(metaslab_t *msp, uint64_t txg)
|
|||
msp->ms_deferspace += defer_delta;
|
||||
ASSERT3S(msp->ms_deferspace, >=, 0);
|
||||
ASSERT3S(msp->ms_deferspace, <=, msp->ms_size);
|
||||
if (msp->ms_deferspace != 0) {
|
||||
if (msp->ms_deferspace != 0 && !spa_exiting_any(spa)) {
|
||||
/*
|
||||
* Keep syncing this metaslab until all deferred frees
|
||||
* are back in circulation.
|
||||
|
@ -6156,7 +6204,9 @@ metaslab_update_ondisk_flush_data(metaslab_t *ms, dmu_tx_t *tx)
|
|||
int err = zap_lookup(mos, vd->vdev_top_zap,
|
||||
VDEV_TOP_ZAP_MS_UNFLUSHED_PHYS_TXGS, sizeof (uint64_t), 1,
|
||||
&object);
|
||||
if (err == ENOENT) {
|
||||
if (err != 0 && spa_exiting_any(spa)) {
|
||||
return;
|
||||
} else if (err == ENOENT) {
|
||||
object = dmu_object_alloc(mos, DMU_OTN_UINT64_METADATA,
|
||||
SPA_OLD_MAXBLOCKSIZE, DMU_OT_NONE, 0, tx);
|
||||
VERIFY0(zap_add(mos, vd->vdev_top_zap,
|
||||
|
|
309
module/zfs/spa.c
309
module/zfs/spa.c
|
@ -1355,6 +1355,8 @@ spa_activate(spa_t *spa, spa_mode_t mode)
|
|||
static void
|
||||
spa_deactivate(spa_t *spa)
|
||||
{
|
||||
int error;
|
||||
|
||||
ASSERT(spa->spa_sync_on == B_FALSE);
|
||||
ASSERT(spa->spa_dsl_pool == NULL);
|
||||
ASSERT(spa->spa_root_vdev == NULL);
|
||||
|
@ -1394,10 +1396,19 @@ spa_deactivate(spa_t *spa)
|
|||
|
||||
for (size_t i = 0; i < TXG_SIZE; i++) {
|
||||
ASSERT3P(spa->spa_txg_zio[i], !=, NULL);
|
||||
VERIFY0(zio_wait(spa->spa_txg_zio[i]));
|
||||
error = zio_wait(spa->spa_txg_zio[i]);
|
||||
VERIFY(error == 0 || (spa_exiting_any(spa) && error == EIO));
|
||||
spa->spa_txg_zio[i] = NULL;
|
||||
}
|
||||
|
||||
if (spa_exiting_any(spa)) {
|
||||
metaslab_class_force_discard(spa->spa_normal_class);
|
||||
metaslab_class_force_discard(spa->spa_log_class);
|
||||
metaslab_class_force_discard(spa->spa_embedded_log_class);
|
||||
metaslab_class_force_discard(spa->spa_special_class);
|
||||
metaslab_class_force_discard(spa->spa_dedup_class);
|
||||
}
|
||||
|
||||
metaslab_class_destroy(spa->spa_normal_class);
|
||||
spa->spa_normal_class = NULL;
|
||||
|
||||
|
@ -1527,7 +1538,12 @@ static void
|
|||
spa_unload_log_sm_flush_all(spa_t *spa)
|
||||
{
|
||||
dmu_tx_t *tx = dmu_tx_create_dd(spa_get_dsl(spa)->dp_mos_dir);
|
||||
VERIFY0(dmu_tx_assign(tx, TXG_WAIT));
|
||||
int txerr = dmu_tx_assign(tx, TXG_WAIT);
|
||||
if (txerr != 0) {
|
||||
ASSERT(spa_exiting_any(spa));
|
||||
dmu_tx_abort(tx);
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT3U(spa->spa_log_flushall_txg, ==, 0);
|
||||
spa->spa_log_flushall_txg = dmu_tx_get_txg(tx);
|
||||
|
@ -1583,9 +1599,13 @@ spa_destroy_aux_threads(spa_t *spa)
|
|||
/*
|
||||
* Opposite of spa_load().
|
||||
*/
|
||||
static void
|
||||
spa_unload(spa_t *spa)
|
||||
static int
|
||||
spa_unload(spa_t *spa, txg_wait_flag_t txg_how)
|
||||
{
|
||||
int err;
|
||||
vdev_t *vd;
|
||||
uint64_t t, txg;
|
||||
|
||||
ASSERT(MUTEX_HELD(&spa_namespace_lock));
|
||||
ASSERT(spa_state(spa) != POOL_STATE_UNINITIALIZED);
|
||||
|
||||
|
@ -1628,10 +1648,45 @@ spa_unload(spa_t *spa)
|
|||
* Stop syncing.
|
||||
*/
|
||||
if (spa->spa_sync_on) {
|
||||
txg_sync_stop(spa->spa_dsl_pool);
|
||||
err = txg_sync_stop(spa->spa_dsl_pool, txg_how);
|
||||
if (err != 0) {
|
||||
spa_async_resume(spa);
|
||||
return (err);
|
||||
}
|
||||
spa->spa_sync_on = B_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the pool is being forcibly exported, it may be necessary to
|
||||
* cleanup again. This normally would be handled by spa_sync(),
|
||||
* except it's possible that followup txg's were skipped, and
|
||||
* thus the opportunity to have performed these operations.
|
||||
*
|
||||
* This is the correct place to perform these operations, as just
|
||||
* now, spa_sync() and vdev activity has been stopped, and after
|
||||
* here, the metaslabs are destroyed.
|
||||
*/
|
||||
if (spa_exiting_any(spa)) {
|
||||
spa_config_enter(spa, SCL_ALL, spa, RW_WRITER);
|
||||
while ((vd = list_head(&spa->spa_config_dirty_list)) != NULL)
|
||||
vdev_config_clean(vd);
|
||||
while ((vd = list_head(&spa->spa_state_dirty_list)) != NULL)
|
||||
vdev_state_clean(vd);
|
||||
/* The only dirty entries should be for spa_syncing_txg + 1. */
|
||||
t = 0;
|
||||
txg = spa_syncing_txg(spa) + 1;
|
||||
while (t < TXG_SIZE) {
|
||||
vd = txg_list_remove(&spa->spa_vdev_txg_list, t);
|
||||
if (vd == NULL) {
|
||||
t++;
|
||||
continue;
|
||||
}
|
||||
VERIFY3U(t, ==, txg & TXG_MASK);
|
||||
vdev_sync_done(vd, txg);
|
||||
}
|
||||
spa_config_exit(spa, SCL_ALL, spa);
|
||||
}
|
||||
|
||||
/*
|
||||
* This ensures that there is no async metaslab prefetching
|
||||
* while we attempt to unload the spa.
|
||||
|
@ -1736,6 +1791,7 @@ spa_unload(spa_t *spa)
|
|||
}
|
||||
|
||||
spa_config_exit(spa, SCL_ALL, spa);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2596,9 +2652,10 @@ spa_livelist_delete_cb(void *arg, zthr_t *z)
|
|||
" livelist %llu, %lld remaining",
|
||||
(u_longlong_t)dle->dle_bpobj.bpo_object,
|
||||
(u_longlong_t)ll_obj, (longlong_t)count - 1);
|
||||
VERIFY0(dsl_sync_task(spa_name(spa), NULL,
|
||||
err = dsl_sync_task(spa_name(spa), NULL,
|
||||
sublist_delete_sync, &sync_arg, 0,
|
||||
ZFS_SPACE_CHECK_DESTROY));
|
||||
ZFS_SPACE_CHECK_DESTROY);
|
||||
VERIFY(err == 0 || spa_exiting_any(spa));
|
||||
} else {
|
||||
VERIFY3U(err, ==, EINTR);
|
||||
}
|
||||
|
@ -2614,8 +2671,10 @@ spa_livelist_delete_cb(void *arg, zthr_t *z)
|
|||
};
|
||||
zfs_dbgmsg("deletion of livelist %llu completed",
|
||||
(u_longlong_t)ll_obj);
|
||||
VERIFY0(dsl_sync_task(spa_name(spa), NULL, livelist_delete_sync,
|
||||
&sync_arg, 0, ZFS_SPACE_CHECK_DESTROY));
|
||||
int err = dsl_sync_task(spa_name(spa), NULL,
|
||||
livelist_delete_sync, &sync_arg, 0,
|
||||
ZFS_SPACE_CHECK_DESTROY);
|
||||
VERIFY(err == 0 || spa_exiting_any(spa));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4474,7 +4533,7 @@ spa_ld_prepare_for_reload(spa_t *spa)
|
|||
spa_mode_t mode = spa->spa_mode;
|
||||
int async_suspended = spa->spa_async_suspended;
|
||||
|
||||
spa_unload(spa);
|
||||
VERIFY0(spa_unload(spa, TXG_WAIT_F_NONE));
|
||||
spa_deactivate(spa);
|
||||
spa_activate(spa, mode);
|
||||
|
||||
|
@ -4990,7 +5049,7 @@ spa_load_retry(spa_t *spa, spa_load_state_t state)
|
|||
{
|
||||
spa_mode_t mode = spa->spa_mode;
|
||||
|
||||
spa_unload(spa);
|
||||
VERIFY0(spa_unload(spa, TXG_WAIT_F_NONE));
|
||||
spa_deactivate(spa);
|
||||
|
||||
spa->spa_load_max_txg = spa->spa_uberblock.ub_txg - 1;
|
||||
|
@ -5152,6 +5211,16 @@ spa_open_common(const char *pool, spa_t **spapp, void *tag, nvlist_t *nvpolicy,
|
|||
return (SET_ERROR(ENOENT));
|
||||
}
|
||||
|
||||
/*
|
||||
* If the pool is exiting, only the thread forcing it to exit may
|
||||
* open new references to it.
|
||||
*/
|
||||
if (spa_exiting(spa)) {
|
||||
if (locked)
|
||||
mutex_exit(&spa_namespace_lock);
|
||||
return (SET_ERROR(ENXIO));
|
||||
}
|
||||
|
||||
if (spa->spa_state == POOL_STATE_UNINITIALIZED) {
|
||||
zpool_load_policy_t policy;
|
||||
|
||||
|
@ -5180,7 +5249,7 @@ spa_open_common(const char *pool, spa_t **spapp, void *tag, nvlist_t *nvpolicy,
|
|||
* this is the case, the config cache is out of sync and
|
||||
* we should remove the pool from the namespace.
|
||||
*/
|
||||
spa_unload(spa);
|
||||
VERIFY0(spa_unload(spa, TXG_WAIT_F_NONE));
|
||||
spa_deactivate(spa);
|
||||
spa_write_cachefile(spa, B_TRUE, B_TRUE);
|
||||
spa_remove(spa);
|
||||
|
@ -5202,7 +5271,7 @@ spa_open_common(const char *pool, spa_t **spapp, void *tag, nvlist_t *nvpolicy,
|
|||
ZPOOL_CONFIG_LOAD_INFO,
|
||||
spa->spa_load_info) == 0);
|
||||
}
|
||||
spa_unload(spa);
|
||||
VERIFY0(spa_unload(spa, TXG_WAIT_F_NONE));
|
||||
spa_deactivate(spa);
|
||||
spa->spa_last_open_failed = error;
|
||||
if (locked)
|
||||
|
@ -5876,7 +5945,7 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
|
|||
spa_config_exit(spa, SCL_ALL, FTAG);
|
||||
|
||||
if (error != 0) {
|
||||
spa_unload(spa);
|
||||
VERIFY0(spa_unload(spa, TXG_WAIT_F_NONE));
|
||||
spa_deactivate(spa);
|
||||
spa_remove(spa);
|
||||
mutex_exit(&spa_namespace_lock);
|
||||
|
@ -6135,15 +6204,13 @@ spa_import(char *pool, nvlist_t *config, nvlist_t *props, uint64_t flags)
|
|||
|
||||
if (error != 0 || (props && spa_writeable(spa) &&
|
||||
(error = spa_prop_set(spa, props)))) {
|
||||
spa_unload(spa);
|
||||
VERIFY0(spa_unload(spa, TXG_WAIT_F_NONE));
|
||||
spa_deactivate(spa);
|
||||
spa_remove(spa);
|
||||
mutex_exit(&spa_namespace_lock);
|
||||
return (error);
|
||||
}
|
||||
|
||||
spa_async_resume(spa);
|
||||
|
||||
/*
|
||||
* Override any spares and level 2 cache devices as specified by
|
||||
* the user, as these may have correct device names/devids, etc.
|
||||
|
@ -6191,9 +6258,21 @@ spa_import(char *pool, nvlist_t *config, nvlist_t *props, uint64_t flags)
|
|||
/*
|
||||
* Update the config cache to include the newly-imported pool.
|
||||
*/
|
||||
spa_config_update(spa, SPA_CONFIG_UPDATE_POOL);
|
||||
mutex_exit(&spa_namespace_lock);
|
||||
error = spa_config_update_pool(spa);
|
||||
if (error != 0) {
|
||||
mutex_enter(&spa_namespace_lock);
|
||||
VERIFY0(spa_unload(spa, TXG_WAIT_F_NONE));
|
||||
spa_deactivate(spa);
|
||||
spa_remove(spa);
|
||||
mutex_exit(&spa_namespace_lock);
|
||||
return (error);
|
||||
}
|
||||
mutex_enter(&spa_namespace_lock);
|
||||
}
|
||||
|
||||
spa_async_resume(spa);
|
||||
|
||||
/*
|
||||
* It's possible that the pool was expanded while it was exported.
|
||||
* We kick off an async task to handle this for us.
|
||||
|
@ -6316,7 +6395,7 @@ spa_tryimport(nvlist_t *tryconfig)
|
|||
spa_config_exit(spa, SCL_CONFIG, FTAG);
|
||||
}
|
||||
|
||||
spa_unload(spa);
|
||||
VERIFY0(spa_unload(spa, TXG_WAIT_F_NONE));
|
||||
spa_deactivate(spa);
|
||||
spa_remove(spa);
|
||||
mutex_exit(&spa_namespace_lock);
|
||||
|
@ -6324,6 +6403,38 @@ spa_tryimport(nvlist_t *tryconfig)
|
|||
return (config);
|
||||
}
|
||||
|
||||
int
|
||||
spa_set_pre_export_status(const char *pool, boolean_t status)
|
||||
{
|
||||
spa_t *spa;
|
||||
|
||||
mutex_enter(&spa_namespace_lock);
|
||||
if ((spa = spa_lookup(pool)) == NULL) {
|
||||
mutex_exit(&spa_namespace_lock);
|
||||
return (SET_ERROR(ENOENT));
|
||||
}
|
||||
|
||||
mutex_enter(&spa->spa_evicting_os_lock);
|
||||
spa->spa_pre_exporting = status;
|
||||
if (status)
|
||||
txg_completion_notify(spa_get_dsl(spa));
|
||||
mutex_exit(&spa->spa_evicting_os_lock);
|
||||
|
||||
mutex_exit(&spa_namespace_lock);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
spa_set_export_initiator(spa_t *spa, void *initiator)
|
||||
{
|
||||
|
||||
mutex_enter(&spa->spa_evicting_os_lock);
|
||||
spa->spa_export_initiator = initiator;
|
||||
if (initiator != NULL)
|
||||
txg_completion_notify(spa_get_dsl(spa));
|
||||
mutex_exit(&spa->spa_evicting_os_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Pool export/destroy
|
||||
*
|
||||
|
@ -6339,6 +6450,7 @@ spa_export_common(const char *pool, int new_state, nvlist_t **oldconfig,
|
|||
{
|
||||
int error;
|
||||
spa_t *spa;
|
||||
boolean_t force_removal, modifying;
|
||||
|
||||
if (oldconfig)
|
||||
*oldconfig = NULL;
|
||||
|
@ -6359,13 +6471,49 @@ spa_export_common(const char *pool, int new_state, nvlist_t **oldconfig,
|
|||
}
|
||||
spa->spa_is_exporting = B_TRUE;
|
||||
|
||||
/* XXX Should this be chained instead of rejected? */
|
||||
if (spa_exiting(spa)) {
|
||||
mutex_exit(&spa_namespace_lock);
|
||||
return (SET_ERROR(EBUSY));
|
||||
}
|
||||
|
||||
modifying = spa->spa_sync_on && (new_state == POOL_STATE_DESTROYED ||
|
||||
new_state == POOL_STATE_EXPORTED);
|
||||
|
||||
/*
|
||||
* Put a hold on the pool, drop the namespace lock, stop async tasks,
|
||||
* reacquire the namespace lock, and see if we can export.
|
||||
*/
|
||||
spa_open_ref(spa, FTAG);
|
||||
|
||||
/*
|
||||
* Mark the pool as facing impending exit if this is a forced
|
||||
* destroy or export.
|
||||
*/
|
||||
force_removal = hardforce && modifying;
|
||||
if (force_removal) {
|
||||
/* Ensure that references see this change after this. */
|
||||
spa_set_export_initiator(spa, curthread);
|
||||
}
|
||||
mutex_exit(&spa_namespace_lock);
|
||||
spa_async_suspend(spa);
|
||||
|
||||
/*
|
||||
* Cancel all sends/receives if necessary, and wait for their holds
|
||||
* to expire. This is done without the namespace lock, since some
|
||||
* operations may require acquiring it (although they will fail).
|
||||
*/
|
||||
if (force_removal && spa->spa_sync_on) {
|
||||
error = dsl_dataset_sendrecv_cancel_all(spa);
|
||||
if (error != 0) {
|
||||
spa_set_export_initiator(spa, NULL);
|
||||
spa_async_resume(spa);
|
||||
return (error);
|
||||
}
|
||||
txg_force_export(spa);
|
||||
spa_evicting_os_wait(spa);
|
||||
}
|
||||
|
||||
if (spa->spa_zvol_taskq) {
|
||||
zvol_remove_minors(spa, spa_name(spa), B_TRUE);
|
||||
taskq_wait(spa->spa_zvol_taskq);
|
||||
|
@ -6375,22 +6523,45 @@ spa_export_common(const char *pool, int new_state, nvlist_t **oldconfig,
|
|||
|
||||
if (spa->spa_state == POOL_STATE_UNINITIALIZED)
|
||||
goto export_spa;
|
||||
|
||||
/*
|
||||
* The pool will be in core if it's openable, in which case we can
|
||||
* modify its state. Objsets may be open only because they're dirty,
|
||||
* so we have to force it to sync before checking spa_refcnt.
|
||||
*/
|
||||
if (spa->spa_sync_on) {
|
||||
txg_wait_synced(spa->spa_dsl_pool, 0);
|
||||
if (!force_removal && spa->spa_sync_on) {
|
||||
error = txg_wait_synced_tx(spa->spa_dsl_pool, 0,
|
||||
NULL, TXG_WAIT_F_NOSUSPEND);
|
||||
if (error != 0)
|
||||
goto fail;
|
||||
spa_evicting_os_wait(spa);
|
||||
}
|
||||
|
||||
/*
|
||||
* For forced removal, wait for refcount to drop to minref. At this
|
||||
* point, all ioctls should be on their way out or getting rejected
|
||||
* at the front door.
|
||||
*/
|
||||
if (force_removal) {
|
||||
mutex_exit(&spa_namespace_lock);
|
||||
mutex_enter(&spa->spa_evicting_os_lock);
|
||||
while (zfs_refcount_count(&spa->spa_refcount) >
|
||||
spa->spa_minref) {
|
||||
zio_cancel(spa);
|
||||
cv_wait(&spa->spa_evicting_os_cv,
|
||||
&spa->spa_evicting_os_lock);
|
||||
}
|
||||
mutex_exit(&spa->spa_evicting_os_lock);
|
||||
mutex_enter(&spa_namespace_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* A pool cannot be exported or destroyed if there are active
|
||||
* references. If we are resetting a pool, allow references by
|
||||
* fault injection handlers.
|
||||
*/
|
||||
if (!spa_refcount_zero(spa) || (spa->spa_inject_ref != 0)) {
|
||||
VERIFY(!force_removal);
|
||||
error = SET_ERROR(EBUSY);
|
||||
goto fail;
|
||||
}
|
||||
|
@ -6421,6 +6592,7 @@ spa_export_common(const char *pool, int new_state, nvlist_t **oldconfig,
|
|||
vdev_trim_stop_all(rvd, VDEV_TRIM_ACTIVE);
|
||||
vdev_autotrim_stop_all(spa);
|
||||
vdev_rebuild_stop_all(spa);
|
||||
l2arc_spa_rebuild_stop(spa);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -6463,7 +6635,14 @@ export_spa:
|
|||
spa_event_notify(spa, NULL, NULL, ESC_ZFS_POOL_EXPORT);
|
||||
|
||||
if (spa->spa_state != POOL_STATE_UNINITIALIZED) {
|
||||
spa_unload(spa);
|
||||
/*
|
||||
* If the pool is not being hard forced, throw an error upon
|
||||
* suspension and abort.
|
||||
*/
|
||||
error = spa_unload(spa, hardforce ?
|
||||
TXG_WAIT_F_FORCE_EXPORT : TXG_WAIT_F_NOSUSPEND);
|
||||
if (error != 0)
|
||||
goto fail;
|
||||
spa_deactivate(spa);
|
||||
}
|
||||
|
||||
|
@ -6471,7 +6650,7 @@ export_spa:
|
|||
VERIFY(nvlist_dup(spa->spa_config, oldconfig, 0) == 0);
|
||||
|
||||
if (new_state != POOL_STATE_UNINITIALIZED) {
|
||||
if (!hardforce)
|
||||
if (!force_removal)
|
||||
spa_write_cachefile(spa, B_TRUE, B_TRUE);
|
||||
spa_remove(spa);
|
||||
} else {
|
||||
|
@ -6487,6 +6666,8 @@ export_spa:
|
|||
return (0);
|
||||
|
||||
fail:
|
||||
if (force_removal)
|
||||
spa_set_export_initiator(spa, NULL);
|
||||
spa->spa_is_exporting = B_FALSE;
|
||||
spa_async_resume(spa);
|
||||
mutex_exit(&spa_namespace_lock);
|
||||
|
@ -6689,10 +6870,8 @@ spa_vdev_add(spa_t *spa, nvlist_t *nvroot)
|
|||
*/
|
||||
(void) spa_vdev_exit(spa, vd, txg, 0);
|
||||
|
||||
mutex_enter(&spa_namespace_lock);
|
||||
spa_config_update(spa, SPA_CONFIG_UPDATE_POOL);
|
||||
spa_config_update_pool(spa);
|
||||
spa_event_notify(spa, NULL, NULL, ESC_ZFS_VDEV_ADD);
|
||||
mutex_exit(&spa_namespace_lock);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
@ -6739,6 +6918,9 @@ spa_vdev_attach(spa_t *spa, uint64_t guid, nvlist_t *nvroot, int replacing,
|
|||
return (spa_vdev_exit(spa, NULL, txg, error));
|
||||
}
|
||||
|
||||
/* If the pool is being force-exported, no vdev changes may occur. */
|
||||
ASSERT(!spa_exiting_any(spa));
|
||||
|
||||
if (rebuild) {
|
||||
if (!spa_feature_is_enabled(spa, SPA_FEATURE_DEVICE_REBUILD))
|
||||
return (spa_vdev_exit(spa, NULL, txg, ENOTSUP));
|
||||
|
@ -6905,8 +7087,8 @@ spa_vdev_attach(spa_t *spa, uint64_t guid, nvlist_t *nvroot, int replacing,
|
|||
vdev_propagate_state(pvd);
|
||||
|
||||
tvd = newvd->vdev_top;
|
||||
ASSERT(pvd->vdev_top == tvd);
|
||||
ASSERT(tvd->vdev_parent == rvd);
|
||||
ASSERT3P(pvd->vdev_top, ==, tvd);
|
||||
ASSERT3P(tvd->vdev_parent, ==, rvd);
|
||||
|
||||
vdev_config_dirty(tvd);
|
||||
|
||||
|
@ -6950,8 +7132,8 @@ spa_vdev_attach(spa_t *spa, uint64_t guid, nvlist_t *nvroot, int replacing,
|
|||
spa_feature_is_enabled(spa, SPA_FEATURE_RESILVER_DEFER)) {
|
||||
vdev_defer_resilver(newvd);
|
||||
} else {
|
||||
dsl_scan_restart_resilver(spa->spa_dsl_pool,
|
||||
dtl_max_txg);
|
||||
VERIFY0(dsl_scan_restart_resilver(spa->spa_dsl_pool,
|
||||
dtl_max_txg));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7811,7 +7993,7 @@ spa_vdev_split_mirror(spa_t *spa, char *newname, nvlist_t *config,
|
|||
return (error);
|
||||
|
||||
out:
|
||||
spa_unload(newspa);
|
||||
VERIFY0(spa_unload(newspa, TXG_WAIT_F_NONE));
|
||||
spa_deactivate(newspa);
|
||||
spa_remove(newspa);
|
||||
|
||||
|
@ -8129,6 +8311,19 @@ spa_async_autoexpand(spa_t *spa, vdev_t *vd)
|
|||
spa_event_notify(vd->vdev_spa, vd, NULL, ESC_ZFS_VDEV_AUTOEXPAND);
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
spa_pool_space(spa_t *spa)
|
||||
{
|
||||
uint64_t space;
|
||||
|
||||
space = metaslab_class_get_space(spa_normal_class(spa));
|
||||
space += metaslab_class_get_space(spa_special_class(spa));
|
||||
space += metaslab_class_get_space(spa_dedup_class(spa));
|
||||
space += metaslab_class_get_space(spa_embedded_log_class(spa));
|
||||
|
||||
return (space);
|
||||
}
|
||||
|
||||
static void
|
||||
spa_async_thread(void *arg)
|
||||
{
|
||||
|
@ -8149,21 +8344,9 @@ spa_async_thread(void *arg)
|
|||
if (tasks & SPA_ASYNC_CONFIG_UPDATE) {
|
||||
uint64_t old_space, new_space;
|
||||
|
||||
mutex_enter(&spa_namespace_lock);
|
||||
old_space = metaslab_class_get_space(spa_normal_class(spa));
|
||||
old_space += metaslab_class_get_space(spa_special_class(spa));
|
||||
old_space += metaslab_class_get_space(spa_dedup_class(spa));
|
||||
old_space += metaslab_class_get_space(
|
||||
spa_embedded_log_class(spa));
|
||||
|
||||
spa_config_update(spa, SPA_CONFIG_UPDATE_POOL);
|
||||
|
||||
new_space = metaslab_class_get_space(spa_normal_class(spa));
|
||||
new_space += metaslab_class_get_space(spa_special_class(spa));
|
||||
new_space += metaslab_class_get_space(spa_dedup_class(spa));
|
||||
new_space += metaslab_class_get_space(
|
||||
spa_embedded_log_class(spa));
|
||||
mutex_exit(&spa_namespace_lock);
|
||||
new_space = old_space = spa_pool_space(spa);
|
||||
if (spa_config_update_pool(spa) == 0)
|
||||
new_space = spa_pool_space(spa);
|
||||
|
||||
/*
|
||||
* If the pool grew as a result of the config update,
|
||||
|
@ -8220,7 +8403,7 @@ spa_async_thread(void *arg)
|
|||
!vdev_rebuild_active(spa->spa_root_vdev) &&
|
||||
(!dsl_scan_resilvering(dp) ||
|
||||
!spa_feature_is_enabled(dp->dp_spa, SPA_FEATURE_RESILVER_DEFER)))
|
||||
dsl_scan_restart_resilver(dp, 0);
|
||||
(void) dsl_scan_restart_resilver(dp, 0);
|
||||
|
||||
if (tasks & SPA_ASYNC_INITIALIZE_RESTART) {
|
||||
mutex_enter(&spa_namespace_lock);
|
||||
|
@ -8473,6 +8656,9 @@ spa_sync_nvlist(spa_t *spa, uint64_t obj, nvlist_t *nv, dmu_tx_t *tx)
|
|||
size_t nvsize = 0;
|
||||
dmu_buf_t *db;
|
||||
|
||||
if (spa_exiting_any(spa))
|
||||
return;
|
||||
|
||||
VERIFY(nvlist_size(nv, &nvsize, NV_ENCODE_XDR) == 0);
|
||||
|
||||
/*
|
||||
|
@ -8949,6 +9135,9 @@ vdev_indirect_state_sync_verify(vdev_t *vd)
|
|||
vdev_indirect_mapping_t *vim __maybe_unused = vd->vdev_indirect_mapping;
|
||||
vdev_indirect_births_t *vib __maybe_unused = vd->vdev_indirect_births;
|
||||
|
||||
if (spa_exiting_any(vd->vdev_spa))
|
||||
return;
|
||||
|
||||
if (vd->vdev_ops == &vdev_indirect_ops) {
|
||||
ASSERT(vim != NULL);
|
||||
ASSERT(vib != NULL);
|
||||
|
@ -9153,10 +9342,10 @@ spa_sync_rewrite_vdev_config(spa_t *spa, dmu_tx_t *tx)
|
|||
{
|
||||
vdev_t *rvd = spa->spa_root_vdev;
|
||||
uint64_t txg = tx->tx_txg;
|
||||
boolean_t exiting = B_FALSE;
|
||||
|
||||
for (;;) {
|
||||
while (exiting == B_FALSE) {
|
||||
int error = 0;
|
||||
|
||||
/*
|
||||
* We hold SCL_STATE to prevent vdev open/close/etc.
|
||||
* while we're attempting to write the vdev labels.
|
||||
|
@ -9200,7 +9389,18 @@ spa_sync_rewrite_vdev_config(spa_t *spa, dmu_tx_t *tx)
|
|||
if (error == 0)
|
||||
break;
|
||||
zio_suspend(spa, NULL, ZIO_SUSPEND_IOERR);
|
||||
zio_resume_wait(spa);
|
||||
|
||||
mutex_enter(&spa->spa_suspend_lock);
|
||||
for (;;) {
|
||||
exiting = spa_exiting(spa);
|
||||
if (exiting || spa_suspended(spa) == B_FALSE)
|
||||
break;
|
||||
cv_wait(&spa->spa_suspend_cv, &spa->spa_suspend_lock);
|
||||
}
|
||||
mutex_exit(&spa->spa_suspend_lock);
|
||||
|
||||
if (exiting)
|
||||
zio_cancel(spa);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9299,7 +9499,8 @@ spa_sync(spa_t *spa, uint64_t txg)
|
|||
spa_sync_iterate_to_convergence(spa, tx);
|
||||
|
||||
#ifdef ZFS_DEBUG
|
||||
if (!list_is_empty(&spa->spa_config_dirty_list)) {
|
||||
if (!list_is_empty(&spa->spa_config_dirty_list) &&
|
||||
!spa_exiting_any(spa)) {
|
||||
/*
|
||||
* Make sure that the number of ZAPs for all the vdevs matches
|
||||
* the number of ZAPs in the per-vdev ZAP list. This only gets
|
||||
|
@ -9409,7 +9610,8 @@ spa_sync_allpools(void)
|
|||
continue;
|
||||
spa_open_ref(spa, FTAG);
|
||||
mutex_exit(&spa_namespace_lock);
|
||||
txg_wait_synced(spa_get_dsl(spa), 0);
|
||||
txg_wait_synced_flags(spa_get_dsl(spa), 0,
|
||||
TXG_WAIT_F_NOSUSPEND);
|
||||
mutex_enter(&spa_namespace_lock);
|
||||
spa_close(spa, FTAG);
|
||||
}
|
||||
|
@ -9448,7 +9650,7 @@ spa_evict_all(void)
|
|||
spa_close(spa, FTAG);
|
||||
|
||||
if (spa->spa_state != POOL_STATE_UNINITIALIZED) {
|
||||
spa_unload(spa);
|
||||
VERIFY0(spa_unload(spa, TXG_WAIT_F_NONE));
|
||||
spa_deactivate(spa);
|
||||
}
|
||||
spa_remove(spa);
|
||||
|
@ -9910,6 +10112,7 @@ EXPORT_SYMBOL(spa_inject_addref);
|
|||
EXPORT_SYMBOL(spa_inject_delref);
|
||||
EXPORT_SYMBOL(spa_scan_stat_init);
|
||||
EXPORT_SYMBOL(spa_scan_get_stats);
|
||||
EXPORT_SYMBOL(spa_set_pre_export_status);
|
||||
|
||||
/* device manipulation */
|
||||
EXPORT_SYMBOL(spa_vdev_add);
|
||||
|
|
|
@ -400,6 +400,7 @@ spa_checkpoint_discard_thread(void *arg, zthr_t *zthr)
|
|||
{
|
||||
spa_t *spa = arg;
|
||||
vdev_t *rvd = spa->spa_root_vdev;
|
||||
int err = 0;
|
||||
|
||||
for (uint64_t c = 0; c < rvd->vdev_children; c++) {
|
||||
vdev_t *vd = rvd->vdev_child[c];
|
||||
|
@ -434,9 +435,10 @@ spa_checkpoint_discard_thread(void *arg, zthr_t *zthr)
|
|||
error, vd->vdev_id);
|
||||
}
|
||||
|
||||
VERIFY0(dsl_sync_task(spa->spa_name, NULL,
|
||||
err = dsl_sync_task(spa->spa_name, NULL,
|
||||
spa_checkpoint_discard_thread_sync, vd,
|
||||
0, ZFS_SPACE_CHECK_NONE));
|
||||
0, ZFS_SPACE_CHECK_NONE);
|
||||
VERIFY(err == 0 || spa_exiting_any(spa));
|
||||
|
||||
dmu_buf_rele_array(dbp, numbufs, FTAG);
|
||||
}
|
||||
|
@ -444,9 +446,10 @@ spa_checkpoint_discard_thread(void *arg, zthr_t *zthr)
|
|||
|
||||
VERIFY(spa_checkpoint_discard_is_done(spa));
|
||||
VERIFY0(spa->spa_checkpoint_info.sci_dspace);
|
||||
VERIFY0(dsl_sync_task(spa->spa_name, NULL,
|
||||
err = dsl_sync_task(spa->spa_name, NULL,
|
||||
spa_checkpoint_discard_complete_sync, spa,
|
||||
0, ZFS_SPACE_CHECK_NONE));
|
||||
0, ZFS_SPACE_CHECK_NONE);
|
||||
VERIFY(err == 0 || spa_exiting_any(spa));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -541,75 +541,115 @@ spa_config_generate(spa_t *spa, vdev_t *vd, uint64_t txg, int getstats)
|
|||
return (config);
|
||||
}
|
||||
|
||||
static int
|
||||
spa_config_update_begin(spa_t *spa, const void *tag)
|
||||
{
|
||||
|
||||
return (spa_config_enter_flags(spa, SCL_ALL, tag, RW_WRITER,
|
||||
SCL_FLAG_NOSUSPEND));
|
||||
}
|
||||
|
||||
/* Complete a label update. */
|
||||
static int
|
||||
spa_config_update_complete(spa_t *spa, uint64_t txg, boolean_t postsysevent,
|
||||
const void *tag)
|
||||
{
|
||||
int error = 0;
|
||||
|
||||
spa_config_exit(spa, SCL_ALL, tag);
|
||||
|
||||
/*
|
||||
* Wait for the mosconfig to be regenerated and synced.
|
||||
*/
|
||||
error = txg_wait_synced_tx(spa->spa_dsl_pool, txg, NULL, 0);
|
||||
if (error == 0 && !spa->spa_is_root) {
|
||||
/*
|
||||
* Update the global config cache to reflect the new mosconfig.
|
||||
* This operation does not perform any pool I/O, so it is
|
||||
* safe even if one or more of them are suspended.
|
||||
*/
|
||||
mutex_enter(&spa_namespace_lock);
|
||||
spa_write_cachefile(spa, B_FALSE, postsysevent);
|
||||
mutex_exit(&spa_namespace_lock);
|
||||
}
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
/* Update any top-level vdevs needing expansion. */
|
||||
static int
|
||||
spa_config_update_vdevs(spa_t *spa)
|
||||
{
|
||||
vdev_t *rvd = spa->spa_root_vdev;
|
||||
uint64_t txg;
|
||||
int c, error;
|
||||
|
||||
error = spa_config_update_begin(spa, FTAG);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
txg = spa_last_synced_txg(spa) + 1;
|
||||
|
||||
/*
|
||||
* If we have top-level vdevs that were added but have
|
||||
* not yet been prepared for allocation, do that now.
|
||||
* (It's safe now because the config cache is up to date,
|
||||
* so it will be able to translate the new DVAs.)
|
||||
* See comments in spa_vdev_add() for full details.
|
||||
*/
|
||||
for (c = 0; c < rvd->vdev_children; c++) {
|
||||
vdev_t *tvd = rvd->vdev_child[c];
|
||||
|
||||
/*
|
||||
* Explicitly skip vdevs that are indirect or
|
||||
* log vdevs that are being removed. The reason
|
||||
* is that both of those can have vdev_ms_array
|
||||
* set to 0 and we wouldn't want to change their
|
||||
* metaslab size nor call vdev_expand() on them.
|
||||
*/
|
||||
if (!vdev_is_concrete(tvd) ||
|
||||
(tvd->vdev_islog && tvd->vdev_removing))
|
||||
continue;
|
||||
|
||||
if (tvd->vdev_ms_array == 0)
|
||||
vdev_metaslab_set_size(tvd);
|
||||
vdev_expand(tvd, txg);
|
||||
}
|
||||
|
||||
return (spa_config_update_complete(spa, txg, B_TRUE, FTAG));
|
||||
}
|
||||
|
||||
/*
|
||||
* Update all disk labels, generate a fresh config based on the current
|
||||
* in-core state, and sync the global config cache (do not sync the config
|
||||
* cache if this is a booting rootpool).
|
||||
*/
|
||||
void
|
||||
spa_config_update(spa_t *spa, int what)
|
||||
int
|
||||
spa_config_update_pool(spa_t *spa)
|
||||
{
|
||||
vdev_t *rvd = spa->spa_root_vdev;
|
||||
uint64_t txg;
|
||||
int c;
|
||||
int error;
|
||||
|
||||
ASSERT(MUTEX_HELD(&spa_namespace_lock));
|
||||
error = spa_config_update_begin(spa, FTAG);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
spa_config_enter(spa, SCL_ALL, FTAG, RW_WRITER);
|
||||
txg = spa_last_synced_txg(spa) + 1;
|
||||
if (what == SPA_CONFIG_UPDATE_POOL) {
|
||||
vdev_config_dirty(rvd);
|
||||
} else {
|
||||
/*
|
||||
* If we have top-level vdevs that were added but have
|
||||
* not yet been prepared for allocation, do that now.
|
||||
* (It's safe now because the config cache is up to date,
|
||||
* so it will be able to translate the new DVAs.)
|
||||
* See comments in spa_vdev_add() for full details.
|
||||
*/
|
||||
for (c = 0; c < rvd->vdev_children; c++) {
|
||||
vdev_t *tvd = rvd->vdev_child[c];
|
||||
vdev_config_dirty(rvd);
|
||||
|
||||
/*
|
||||
* Explicitly skip vdevs that are indirect or
|
||||
* log vdevs that are being removed. The reason
|
||||
* is that both of those can have vdev_ms_array
|
||||
* set to 0 and we wouldn't want to change their
|
||||
* metaslab size nor call vdev_expand() on them.
|
||||
*/
|
||||
if (!vdev_is_concrete(tvd) ||
|
||||
(tvd->vdev_islog && tvd->vdev_removing))
|
||||
continue;
|
||||
error = spa_config_update_complete(spa, txg, B_FALSE, FTAG);
|
||||
if (error == 0)
|
||||
error = spa_config_update_vdevs(spa);
|
||||
|
||||
if (tvd->vdev_ms_array == 0)
|
||||
vdev_metaslab_set_size(tvd);
|
||||
vdev_expand(tvd, txg);
|
||||
}
|
||||
}
|
||||
spa_config_exit(spa, SCL_ALL, FTAG);
|
||||
|
||||
/*
|
||||
* Wait for the mosconfig to be regenerated and synced.
|
||||
*/
|
||||
txg_wait_synced(spa->spa_dsl_pool, txg);
|
||||
|
||||
/*
|
||||
* Update the global config cache to reflect the new mosconfig.
|
||||
*/
|
||||
if (!spa->spa_is_root) {
|
||||
spa_write_cachefile(spa, B_FALSE,
|
||||
what != SPA_CONFIG_UPDATE_POOL);
|
||||
}
|
||||
|
||||
if (what == SPA_CONFIG_UPDATE_POOL)
|
||||
spa_config_update(spa, SPA_CONFIG_UPDATE_VDEVS);
|
||||
return (error);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(spa_config_load);
|
||||
EXPORT_SYMBOL(spa_all_configs);
|
||||
EXPORT_SYMBOL(spa_config_set);
|
||||
EXPORT_SYMBOL(spa_config_generate);
|
||||
EXPORT_SYMBOL(spa_config_update);
|
||||
EXPORT_SYMBOL(spa_config_update_pool);
|
||||
|
||||
/* BEGIN CSTYLED */
|
||||
#ifdef __linux__
|
||||
|
|
|
@ -99,9 +99,9 @@ spa_log_error(spa_t *spa, const zbookmark_phys_t *zb)
|
|||
|
||||
/*
|
||||
* If we are trying to import a pool, ignore any errors, as we won't be
|
||||
* writing to the pool any time soon.
|
||||
* writing to the pool any time soon. Same for force exports.
|
||||
*/
|
||||
if (spa_load_state(spa) == SPA_LOAD_TRYIMPORT)
|
||||
if (spa_exiting_any(spa) || spa_load_state(spa) == SPA_LOAD_TRYIMPORT)
|
||||
return;
|
||||
|
||||
mutex_enter(&spa->spa_errlist_lock);
|
||||
|
@ -307,13 +307,15 @@ sync_error_list(spa_t *spa, avl_tree_t *t, uint64_t *obj, dmu_tx_t *tx)
|
|||
void *cookie;
|
||||
|
||||
if (avl_numnodes(t) != 0) {
|
||||
if (spa_exiting_any(spa))
|
||||
goto done;
|
||||
|
||||
/* create log if necessary */
|
||||
if (*obj == 0)
|
||||
*obj = zap_create(spa->spa_meta_objset,
|
||||
DMU_OT_ERROR_LOG, DMU_OT_NONE,
|
||||
0, tx);
|
||||
|
||||
/* add errors to the current log */
|
||||
for (se = avl_first(t); se != NULL; se = AVL_NEXT(t, se)) {
|
||||
char *name = se->se_name ? se->se_name : "";
|
||||
|
||||
|
@ -323,6 +325,7 @@ sync_error_list(spa_t *spa, avl_tree_t *t, uint64_t *obj, dmu_tx_t *tx)
|
|||
*obj, buf, 1, strlen(name) + 1, name, tx);
|
||||
}
|
||||
|
||||
done:
|
||||
/* purge the error list */
|
||||
cookie = NULL;
|
||||
while ((se = avl_destroy_nodes(t, &cookie)) != NULL)
|
||||
|
|
|
@ -385,7 +385,7 @@ spa_history_log_nvl(spa_t *spa, nvlist_t *nvl)
|
|||
}
|
||||
|
||||
tx = dmu_tx_create_dd(spa_get_dsl(spa)->dp_mos_dir);
|
||||
err = dmu_tx_assign(tx, TXG_WAIT);
|
||||
err = dmu_tx_assign(tx, TXG_WAIT | TXG_NOSUSPEND);
|
||||
if (err) {
|
||||
dmu_tx_abort(tx);
|
||||
return (err);
|
||||
|
@ -521,9 +521,10 @@ log_internal(nvlist_t *nvl, const char *operation, spa_t *spa,
|
|||
/*
|
||||
* If this is part of creating a pool, not everything is
|
||||
* initialized yet, so don't bother logging the internal events.
|
||||
* Likewise if the pool is not writeable.
|
||||
* Likewise if the pool is not writeable, or is being force exported.
|
||||
*/
|
||||
if (spa_is_initializing(spa) || !spa_writeable(spa)) {
|
||||
if (spa_is_initializing(spa) || !spa_writeable(spa) ||
|
||||
spa_exiting_any(spa)) {
|
||||
fnvlist_free(nvl);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -885,7 +885,9 @@ spa_cleanup_old_sm_logs(spa_t *spa, dmu_tx_t *tx)
|
|||
ASSERT(avl_is_empty(&spa->spa_sm_logs_by_txg));
|
||||
return;
|
||||
}
|
||||
VERIFY0(error);
|
||||
VERIFY(error == 0 || spa_exiting_any(spa));
|
||||
if (error != 0)
|
||||
return;
|
||||
|
||||
metaslab_t *oldest = avl_first(&spa->spa_metaslabs_by_flushed);
|
||||
uint64_t oldest_flushed_txg = metaslab_unflushed_txg(oldest);
|
||||
|
@ -938,7 +940,9 @@ spa_generate_syncing_log_sm(spa_t *spa, dmu_tx_t *tx)
|
|||
&spacemap_zap, tx));
|
||||
spa_feature_incr(spa, SPA_FEATURE_LOG_SPACEMAP, tx);
|
||||
}
|
||||
VERIFY0(error);
|
||||
VERIFY(error == 0 || spa_exiting_any(spa));
|
||||
if (error != 0)
|
||||
return;
|
||||
|
||||
uint64_t sm_obj;
|
||||
ASSERT3U(zap_lookup_int_key(mos, spacemap_zap, txg, &sm_obj),
|
||||
|
|
|
@ -463,46 +463,32 @@ spa_config_lock_destroy(spa_t *spa)
|
|||
}
|
||||
}
|
||||
|
||||
int
|
||||
spa_config_tryenter(spa_t *spa, int locks, void *tag, krw_t rw)
|
||||
static int
|
||||
spa_config_eval_flags(spa_t *spa, spa_config_flag_t flags)
|
||||
{
|
||||
for (int i = 0; i < SCL_LOCKS; i++) {
|
||||
spa_config_lock_t *scl = &spa->spa_config_lock[i];
|
||||
if (!(locks & (1 << i)))
|
||||
continue;
|
||||
mutex_enter(&scl->scl_lock);
|
||||
if (rw == RW_READER) {
|
||||
if (scl->scl_writer || scl->scl_write_wanted) {
|
||||
mutex_exit(&scl->scl_lock);
|
||||
spa_config_exit(spa, locks & ((1 << i) - 1),
|
||||
tag);
|
||||
return (0);
|
||||
}
|
||||
} else {
|
||||
ASSERT(scl->scl_writer != curthread);
|
||||
if (!zfs_refcount_is_zero(&scl->scl_count)) {
|
||||
mutex_exit(&scl->scl_lock);
|
||||
spa_config_exit(spa, locks & ((1 << i) - 1),
|
||||
tag);
|
||||
return (0);
|
||||
}
|
||||
scl->scl_writer = curthread;
|
||||
}
|
||||
(void) zfs_refcount_add(&scl->scl_count, tag);
|
||||
mutex_exit(&scl->scl_lock);
|
||||
int error = 0;
|
||||
|
||||
if ((flags & SCL_FLAG_TRYENTER) != 0)
|
||||
error = SET_ERROR(EAGAIN);
|
||||
if (error == 0 && ((flags & SCL_FLAG_NOSUSPEND) != 0)) {
|
||||
/* Notification given by zio_suspend(). */
|
||||
mutex_enter(&spa->spa_suspend_lock);
|
||||
error = spa_suspended(spa) ? SET_ERROR(EAGAIN) : 0;
|
||||
mutex_exit(&spa->spa_suspend_lock);
|
||||
}
|
||||
return (1);
|
||||
return (error);
|
||||
}
|
||||
|
||||
void
|
||||
spa_config_enter(spa_t *spa, int locks, const void *tag, krw_t rw)
|
||||
int
|
||||
spa_config_enter_flags(spa_t *spa, int locks, const void *tag, krw_t rw,
|
||||
spa_config_flag_t flags)
|
||||
{
|
||||
(void) tag;
|
||||
int error = 0;
|
||||
int wlocks_held = 0;
|
||||
|
||||
ASSERT3U(SCL_LOCKS, <, sizeof (wlocks_held) * NBBY);
|
||||
|
||||
for (int i = 0; i < SCL_LOCKS; i++) {
|
||||
for (int i = 0; error == 0 && i < SCL_LOCKS; i++) {
|
||||
spa_config_lock_t *scl = &spa->spa_config_lock[i];
|
||||
if (scl->scl_writer == curthread)
|
||||
wlocks_held |= (1 << i);
|
||||
|
@ -511,21 +497,53 @@ spa_config_enter(spa_t *spa, int locks, const void *tag, krw_t rw)
|
|||
mutex_enter(&scl->scl_lock);
|
||||
if (rw == RW_READER) {
|
||||
while (scl->scl_writer || scl->scl_write_wanted) {
|
||||
error = spa_config_eval_flags(spa, flags);
|
||||
if (error != 0)
|
||||
break;
|
||||
cv_wait(&scl->scl_cv, &scl->scl_lock);
|
||||
}
|
||||
} else {
|
||||
ASSERT(scl->scl_writer != curthread);
|
||||
while (!zfs_refcount_is_zero(&scl->scl_count)) {
|
||||
error = spa_config_eval_flags(spa, flags);
|
||||
if (error != 0)
|
||||
break;
|
||||
scl->scl_write_wanted++;
|
||||
cv_wait(&scl->scl_cv, &scl->scl_lock);
|
||||
scl->scl_write_wanted--;
|
||||
}
|
||||
scl->scl_writer = curthread;
|
||||
if (error == 0)
|
||||
scl->scl_writer = curthread;
|
||||
}
|
||||
(void) zfs_refcount_add(&scl->scl_count, tag);
|
||||
if (error == 0)
|
||||
(void) zfs_refcount_add(&scl->scl_count, tag);
|
||||
mutex_exit(&scl->scl_lock);
|
||||
|
||||
if (error != 0 && i > 0) {
|
||||
/* Should never happen for classic spa_config_enter. */
|
||||
ASSERT3U(flags, !=, 0);
|
||||
spa_config_exit(spa, locks & ((1 << i) - 1), tag);
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT3U(wlocks_held, <=, locks);
|
||||
return (error);
|
||||
}
|
||||
|
||||
void
|
||||
spa_config_enter(spa_t *spa, int locks, const void *tag, krw_t rw)
|
||||
{
|
||||
spa_config_flag_t flags = 0;
|
||||
|
||||
spa_config_enter_flags(spa, locks, tag, rw, flags);
|
||||
}
|
||||
|
||||
int
|
||||
spa_config_tryenter(spa_t *spa, int locks, const void *tag, krw_t rw)
|
||||
{
|
||||
|
||||
return (spa_config_enter_flags(spa, locks, tag, rw,
|
||||
SCL_FLAG_TRYENTER) == 0);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -887,6 +905,20 @@ spa_open_ref(spa_t *spa, void *tag)
|
|||
(void) zfs_refcount_add(&spa->spa_refcount, tag);
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove a reference to a given spa_t. Common routine that also includes
|
||||
* notifying the exporter if one is registered, when minref has been reached.
|
||||
*/
|
||||
static void
|
||||
spa_close_common(spa_t *spa, const void *tag)
|
||||
{
|
||||
if (zfs_refcount_remove(&spa->spa_refcount, tag) == spa->spa_minref) {
|
||||
mutex_enter(&spa->spa_evicting_os_lock);
|
||||
cv_broadcast(&spa->spa_evicting_os_cv);
|
||||
mutex_exit(&spa->spa_evicting_os_lock);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove a reference to the given spa_t. Must have at least one reference, or
|
||||
* have the namespace lock held.
|
||||
|
@ -896,7 +928,7 @@ spa_close(spa_t *spa, void *tag)
|
|||
{
|
||||
ASSERT(zfs_refcount_count(&spa->spa_refcount) > spa->spa_minref ||
|
||||
MUTEX_HELD(&spa_namespace_lock));
|
||||
(void) zfs_refcount_remove(&spa->spa_refcount, tag);
|
||||
spa_close_common(spa, tag);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -910,7 +942,7 @@ spa_close(spa_t *spa, void *tag)
|
|||
void
|
||||
spa_async_close(spa_t *spa, void *tag)
|
||||
{
|
||||
(void) zfs_refcount_remove(&spa->spa_refcount, tag);
|
||||
spa_close_common(spa, tag);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1729,6 +1761,19 @@ spa_syncing_txg(spa_t *spa)
|
|||
return (spa->spa_syncing_txg);
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify that the requesting thread isn't dirtying a txg it's not supposed
|
||||
* to be. Normally, this must be spa_final_dirty_txg(), but if the pool is
|
||||
* being force exported, no data will be written to stable storage anyway.
|
||||
*/
|
||||
void
|
||||
spa_verify_dirty_txg(spa_t *spa, uint64_t txg)
|
||||
{
|
||||
|
||||
if (spa->spa_export_initiator == NULL)
|
||||
VERIFY3U(txg, <=, spa_final_dirty_txg(spa));
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the last txg where data can be dirtied. The final txgs
|
||||
* will be used to just clear out any deferred frees that remain.
|
||||
|
@ -1988,6 +2033,18 @@ spa_preferred_class(spa_t *spa, uint64_t size, dmu_object_type_t objtype,
|
|||
return (spa_normal_class(spa));
|
||||
}
|
||||
|
||||
void
|
||||
spa_evicting_os_lock(spa_t *spa)
|
||||
{
|
||||
mutex_enter(&spa->spa_evicting_os_lock);
|
||||
}
|
||||
|
||||
void
|
||||
spa_evicting_os_unlock(spa_t *spa)
|
||||
{
|
||||
mutex_exit(&spa->spa_evicting_os_lock);
|
||||
}
|
||||
|
||||
void
|
||||
spa_evicting_os_register(spa_t *spa, objset_t *os)
|
||||
{
|
||||
|
@ -2612,6 +2669,31 @@ spa_maxblocksize(spa_t *spa)
|
|||
return (SPA_OLD_MAXBLOCKSIZE);
|
||||
}
|
||||
|
||||
boolean_t
|
||||
spa_exiting_any(spa_t *spa)
|
||||
{
|
||||
return (spa->spa_export_initiator != NULL || spa->spa_pre_exporting);
|
||||
}
|
||||
|
||||
/*
|
||||
* NB: must hold spa_namespace_lock or spa_evicting_os_lock if the result of
|
||||
* this is critical.
|
||||
*/
|
||||
boolean_t
|
||||
spa_exiting(spa_t *spa)
|
||||
{
|
||||
return (spa_exiting_any(spa) && spa->spa_export_initiator != curthread);
|
||||
}
|
||||
|
||||
int
|
||||
spa_operation_interrupted(spa_t *spa)
|
||||
{
|
||||
if (issig(JUSTLOOKING) && issig(FORREAL))
|
||||
return (SET_ERROR(EINTR));
|
||||
if (spa_exiting(spa))
|
||||
return (SET_ERROR(ENXIO));
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the txg that the last device removal completed. No indirect mappings
|
||||
|
@ -2892,6 +2974,8 @@ EXPORT_SYMBOL(spa_delegation);
|
|||
EXPORT_SYMBOL(spa_meta_objset);
|
||||
EXPORT_SYMBOL(spa_maxblocksize);
|
||||
EXPORT_SYMBOL(spa_maxdnodesize);
|
||||
EXPORT_SYMBOL(spa_exiting);
|
||||
EXPORT_SYMBOL(spa_operation_interrupted);
|
||||
|
||||
/* Miscellaneous support routines */
|
||||
EXPORT_SYMBOL(spa_guid_exists);
|
||||
|
|
|
@ -860,7 +860,7 @@ space_map_truncate(space_map_t *sm, int blocksize, dmu_tx_t *tx)
|
|||
|
||||
ASSERT(dsl_pool_sync_context(dmu_objset_pool(os)));
|
||||
ASSERT(dmu_tx_is_syncing(tx));
|
||||
VERIFY3U(dmu_tx_get_txg(tx), <=, spa_final_dirty_txg(spa));
|
||||
spa_verify_dirty_txg(spa, dmu_tx_get_txg(tx));
|
||||
|
||||
dmu_object_info_from_db(sm->sm_dbuf, &doi);
|
||||
|
||||
|
|
155
module/zfs/txg.c
155
module/zfs/txg.c
|
@ -28,6 +28,7 @@
|
|||
#include <sys/txg_impl.h>
|
||||
#include <sys/dmu_impl.h>
|
||||
#include <sys/spa_impl.h>
|
||||
#include <sys/dmu_objset.h>
|
||||
#include <sys/dmu_tx.h>
|
||||
#include <sys/dsl_pool.h>
|
||||
#include <sys/dsl_scan.h>
|
||||
|
@ -255,10 +256,11 @@ txg_thread_wait(tx_state_t *tx, callb_cpr_t *cpr, kcondvar_t *cv, clock_t time)
|
|||
/*
|
||||
* Stop syncing transaction groups.
|
||||
*/
|
||||
void
|
||||
txg_sync_stop(dsl_pool_t *dp)
|
||||
int
|
||||
txg_sync_stop(dsl_pool_t *dp, txg_wait_flag_t txg_how)
|
||||
{
|
||||
tx_state_t *tx = &dp->dp_tx;
|
||||
int err;
|
||||
|
||||
dprintf("pool %p\n", dp);
|
||||
/*
|
||||
|
@ -269,7 +271,10 @@ txg_sync_stop(dsl_pool_t *dp)
|
|||
/*
|
||||
* We need to ensure that we've vacated the deferred metaslab trees.
|
||||
*/
|
||||
txg_wait_synced(dp, tx->tx_open_txg + TXG_DEFER_SIZE);
|
||||
err = txg_wait_synced_tx(dp, tx->tx_open_txg + TXG_DEFER_SIZE,
|
||||
NULL, txg_how);
|
||||
if (err != 0)
|
||||
return (err);
|
||||
|
||||
/*
|
||||
* Wake all sync threads and wait for them to die.
|
||||
|
@ -290,6 +295,7 @@ txg_sync_stop(dsl_pool_t *dp)
|
|||
tx->tx_exiting = 0;
|
||||
|
||||
mutex_exit(&tx->tx_sync_lock);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -522,6 +528,24 @@ txg_has_quiesced_to_sync(dsl_pool_t *dp)
|
|||
return (tx->tx_quiesced_txg != 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Notify of completion. This is usually only called by the sync thread,
|
||||
* but in force-export/unmount scenarios, it can be called by another thread
|
||||
* that has generated an alternative completion scenario.
|
||||
*/
|
||||
void
|
||||
txg_completion_notify(dsl_pool_t *dp)
|
||||
{
|
||||
tx_state_t *tx = &dp->dp_tx;
|
||||
boolean_t locked = MUTEX_HELD(&tx->tx_sync_lock);
|
||||
|
||||
if (!locked)
|
||||
mutex_enter(&tx->tx_sync_lock);
|
||||
cv_broadcast(&tx->tx_sync_done_cv);
|
||||
if (!locked)
|
||||
mutex_exit(&tx->tx_sync_lock);
|
||||
}
|
||||
|
||||
static void
|
||||
txg_sync_thread(void *arg)
|
||||
{
|
||||
|
@ -602,7 +626,7 @@ txg_sync_thread(void *arg)
|
|||
tx->tx_synced_txg = txg;
|
||||
tx->tx_syncing_txg = 0;
|
||||
DTRACE_PROBE2(txg__synced, dsl_pool_t *, dp, uint64_t, txg);
|
||||
cv_broadcast(&tx->tx_sync_done_cv);
|
||||
txg_completion_notify(dp);
|
||||
|
||||
/*
|
||||
* Dispatch commit callbacks to worker threads.
|
||||
|
@ -695,61 +719,88 @@ txg_delay(dsl_pool_t *dp, uint64_t txg, hrtime_t delay, hrtime_t resolution)
|
|||
mutex_exit(&tx->tx_sync_lock);
|
||||
}
|
||||
|
||||
static boolean_t
|
||||
txg_wait_synced_impl(dsl_pool_t *dp, uint64_t txg, boolean_t wait_sig)
|
||||
int
|
||||
txg_wait_synced_tx(dsl_pool_t *dp, uint64_t txg, dmu_tx_t *tx,
|
||||
txg_wait_flag_t flags)
|
||||
{
|
||||
tx_state_t *tx = &dp->dp_tx;
|
||||
tx_state_t *dp_tx = &dp->dp_tx;
|
||||
int error = 0;
|
||||
objset_t *os = NULL;
|
||||
|
||||
ASSERT(!dsl_pool_config_held(dp));
|
||||
|
||||
mutex_enter(&tx->tx_sync_lock);
|
||||
ASSERT3U(tx->tx_threads, ==, 2);
|
||||
mutex_enter(&dp_tx->tx_sync_lock);
|
||||
ASSERT3U(dp_tx->tx_threads, ==, 2);
|
||||
if (txg == 0)
|
||||
txg = tx->tx_open_txg + TXG_DEFER_SIZE;
|
||||
if (tx->tx_sync_txg_waiting < txg)
|
||||
tx->tx_sync_txg_waiting = txg;
|
||||
txg = dp_tx->tx_open_txg + TXG_DEFER_SIZE;
|
||||
if (dp_tx->tx_sync_txg_waiting < txg)
|
||||
dp_tx->tx_sync_txg_waiting = txg;
|
||||
if (tx != NULL && tx->tx_objset != NULL)
|
||||
os = tx->tx_objset;
|
||||
dprintf("txg=%llu quiesce_txg=%llu sync_txg=%llu\n",
|
||||
(u_longlong_t)txg, (u_longlong_t)tx->tx_quiesce_txg_waiting,
|
||||
(u_longlong_t)tx->tx_sync_txg_waiting);
|
||||
while (tx->tx_synced_txg < txg) {
|
||||
(u_longlong_t)txg, (u_longlong_t)dp_tx->tx_quiesce_txg_waiting,
|
||||
(u_longlong_t)dp_tx->tx_sync_txg_waiting);
|
||||
while (error == 0 && dp_tx->tx_synced_txg < txg) {
|
||||
dprintf("broadcasting sync more "
|
||||
"tx_synced=%llu waiting=%llu dp=%px\n",
|
||||
(u_longlong_t)tx->tx_synced_txg,
|
||||
(u_longlong_t)tx->tx_sync_txg_waiting, dp);
|
||||
cv_broadcast(&tx->tx_sync_more_cv);
|
||||
if (wait_sig) {
|
||||
(u_longlong_t)dp_tx->tx_synced_txg,
|
||||
(u_longlong_t)dp_tx->tx_sync_txg_waiting, dp);
|
||||
cv_broadcast(&dp_tx->tx_sync_more_cv);
|
||||
/*
|
||||
* If we are suspending and exiting, give up, because our
|
||||
* data isn't going to be pushed.
|
||||
*/
|
||||
if (spa_suspended(dp->dp_spa)) {
|
||||
if ((flags & TXG_WAIT_F_FORCE_EXPORT)) {
|
||||
error = 0;
|
||||
break;
|
||||
}
|
||||
if ((flags & TXG_WAIT_F_NOSUSPEND) ||
|
||||
spa_exiting_any(dp->dp_spa)) {
|
||||
error = SET_ERROR(EAGAIN);
|
||||
}
|
||||
}
|
||||
if (error == 0 && os != NULL && dmu_objset_exiting(os)) {
|
||||
if ((flags & TXG_WAIT_F_FORCE_EXPORT)) {
|
||||
error = 0;
|
||||
break;
|
||||
}
|
||||
error = SET_ERROR(EAGAIN);
|
||||
}
|
||||
if (error != 0)
|
||||
break;
|
||||
if (flags & TXG_WAIT_F_SIGNAL) {
|
||||
/*
|
||||
* Condition wait here but stop if the thread receives a
|
||||
* signal. The caller may call txg_wait_synced*() again
|
||||
* to resume waiting for this txg.
|
||||
*/
|
||||
if (cv_wait_io_sig(&tx->tx_sync_done_cv,
|
||||
&tx->tx_sync_lock) == 0) {
|
||||
mutex_exit(&tx->tx_sync_lock);
|
||||
return (B_TRUE);
|
||||
if (cv_wait_io_sig(&dp_tx->tx_sync_done_cv,
|
||||
&dp_tx->tx_sync_lock) == 0) {
|
||||
error = SET_ERROR(EINTR);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
cv_wait_io(&tx->tx_sync_done_cv, &tx->tx_sync_lock);
|
||||
cv_wait_io(&dp_tx->tx_sync_done_cv,
|
||||
&dp_tx->tx_sync_lock);
|
||||
}
|
||||
}
|
||||
mutex_exit(&tx->tx_sync_lock);
|
||||
return (B_FALSE);
|
||||
|
||||
mutex_exit(&dp_tx->tx_sync_lock);
|
||||
dprintf("txg=%llu error=%d\n", (u_longlong_t)txg, error);
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
txg_wait_synced_flags(dsl_pool_t *dp, uint64_t txg, txg_wait_flag_t flags)
|
||||
{
|
||||
return (txg_wait_synced_tx(dp, txg, NULL, flags));
|
||||
}
|
||||
|
||||
void
|
||||
txg_wait_synced(dsl_pool_t *dp, uint64_t txg)
|
||||
{
|
||||
VERIFY0(txg_wait_synced_impl(dp, txg, B_FALSE));
|
||||
}
|
||||
|
||||
/*
|
||||
* Similar to a txg_wait_synced but it can be interrupted from a signal.
|
||||
* Returns B_TRUE if the thread was signaled while waiting.
|
||||
*/
|
||||
boolean_t
|
||||
txg_wait_synced_sig(dsl_pool_t *dp, uint64_t txg)
|
||||
{
|
||||
return (txg_wait_synced_impl(dp, txg, B_TRUE));
|
||||
(void) txg_wait_synced_tx(dp, txg, NULL, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -829,6 +880,36 @@ txg_sync_waiting(dsl_pool_t *dp)
|
|||
tx->tx_quiesced_txg != 0);
|
||||
}
|
||||
|
||||
void
|
||||
txg_force_export(spa_t *spa)
|
||||
{
|
||||
dsl_pool_t *dp = spa_get_dsl(spa);
|
||||
tx_state_t *tx = &dp->dp_tx;
|
||||
uint64_t t, txg;
|
||||
|
||||
/*
|
||||
* When forcing removal, push through TXG_SIZE TXGs to ensure that
|
||||
* all state is cleaned up by spa_sync(). While waiting for each
|
||||
* TXG to complete, cancel any suspended zios that appear.
|
||||
*/
|
||||
ASSERT(spa_exiting_any(spa));
|
||||
txg = tx->tx_synced_txg + 1;
|
||||
for (t = 0; t < TXG_SIZE; t++) {
|
||||
txg_wait_open(dp, txg + t, B_TRUE);
|
||||
|
||||
boolean_t complete = B_FALSE;
|
||||
while (!complete) {
|
||||
zio_cancel(spa);
|
||||
mutex_enter(&tx->tx_sync_lock);
|
||||
(void) cv_timedwait(&tx->tx_sync_done_cv,
|
||||
&tx->tx_sync_lock,
|
||||
ddi_get_lbolt() + MSEC_TO_TICK(100));
|
||||
complete = (tx->tx_synced_txg >= (txg + t));
|
||||
mutex_exit(&tx->tx_sync_lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify that this txg is active (open, quiescing, syncing). Non-active
|
||||
* txg's should not be manipulated.
|
||||
|
|
|
@ -973,6 +973,8 @@ void
|
|||
vdev_free(vdev_t *vd)
|
||||
{
|
||||
spa_t *spa = vd->vdev_spa;
|
||||
uint64_t t, txg;
|
||||
metaslab_t *msp;
|
||||
|
||||
ASSERT3P(vd->vdev_initialize_thread, ==, NULL);
|
||||
ASSERT3P(vd->vdev_trim_thread, ==, NULL);
|
||||
|
@ -997,6 +999,19 @@ vdev_free(vdev_t *vd)
|
|||
*/
|
||||
vdev_close(vd);
|
||||
|
||||
/* If the pool is being forcibly exported, clean up any stragglers. */
|
||||
if (spa_exiting_any(spa)) {
|
||||
for (t = 0, txg = spa_syncing_txg(spa) + 1; t < TXG_SIZE; ) {
|
||||
msp = txg_list_remove(&vd->vdev_ms_list, t);
|
||||
if (msp == NULL) {
|
||||
t++;
|
||||
continue;
|
||||
}
|
||||
VERIFY3U(t, ==, txg & TXG_MASK);
|
||||
/* Metaslab already destroyed, nothing to do. */
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT(!list_link_active(&vd->vdev_config_dirty_node));
|
||||
ASSERT(!list_link_active(&vd->vdev_state_dirty_node));
|
||||
|
||||
|
@ -1026,6 +1041,9 @@ vdev_free(vdev_t *vd)
|
|||
vd->vdev_log_mg = NULL;
|
||||
}
|
||||
|
||||
if (spa_exiting_any(spa))
|
||||
vdev_clear_stats(vd);
|
||||
|
||||
ASSERT0(vd->vdev_stat.vs_space);
|
||||
ASSERT0(vd->vdev_stat.vs_dspace);
|
||||
ASSERT0(vd->vdev_stat.vs_alloc);
|
||||
|
@ -3263,6 +3281,16 @@ vdev_dtl_sync(vdev_t *vd, uint64_t txg)
|
|||
dmu_tx_t *tx;
|
||||
uint64_t object = space_map_object(vd->vdev_dtl_sm);
|
||||
|
||||
/*
|
||||
* The pool is being forcibly exported. Just discard everything.
|
||||
*/
|
||||
if (spa_exiting(spa)) {
|
||||
mutex_enter(&vd->vdev_dtl_lock);
|
||||
range_tree_vacate(rt, NULL, NULL);
|
||||
mutex_exit(&vd->vdev_dtl_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT(vdev_is_concrete(vd));
|
||||
ASSERT(vd->vdev_ops->vdev_op_leaf);
|
||||
|
||||
|
@ -4680,6 +4708,11 @@ vdev_stat_update(zio_t *zio, uint64_t psize)
|
|||
if (zio->io_vd == NULL && (zio->io_flags & ZIO_FLAG_DONT_PROPAGATE))
|
||||
return;
|
||||
|
||||
if (vd == NULL && spa_exiting_any(spa)) {
|
||||
/* Forced export resulted in partially constructed I/O. */
|
||||
return;
|
||||
}
|
||||
|
||||
if (type == ZIO_TYPE_WRITE && txg != 0 &&
|
||||
(!(flags & ZIO_FLAG_IO_REPAIR) ||
|
||||
(flags & ZIO_FLAG_SCAN_THREAD) ||
|
||||
|
|
|
@ -563,13 +563,19 @@ spa_condense_indirect_commit_entry(spa_t *spa,
|
|||
vdev_indirect_mapping_entry_phys_t *vimep, uint32_t count)
|
||||
{
|
||||
spa_condensing_indirect_t *sci = spa->spa_condensing_indirect;
|
||||
dmu_tx_t *tx;
|
||||
int txgoff;
|
||||
|
||||
ASSERT3U(count, <, DVA_GET_ASIZE(&vimep->vimep_dst));
|
||||
|
||||
dmu_tx_t *tx = dmu_tx_create_dd(spa_get_dsl(spa)->dp_mos_dir);
|
||||
tx = dmu_tx_create_dd(spa_get_dsl(spa)->dp_mos_dir);
|
||||
dmu_tx_hold_space(tx, sizeof (*vimep) + sizeof (count));
|
||||
VERIFY0(dmu_tx_assign(tx, TXG_WAIT));
|
||||
int txgoff = dmu_tx_get_txg(tx) & TXG_MASK;
|
||||
if (dmu_tx_assign(tx, TXG_WAIT) != 0) {
|
||||
ASSERT(spa_exiting_any(spa));
|
||||
dmu_tx_abort(tx);
|
||||
return;
|
||||
}
|
||||
txgoff = dmu_tx_get_txg(tx) & TXG_MASK;
|
||||
|
||||
/*
|
||||
* If we are the first entry committed this txg, kick off the sync
|
||||
|
@ -651,6 +657,7 @@ spa_condense_indirect_thread(void *arg, zthr_t *zthr)
|
|||
{
|
||||
spa_t *spa = arg;
|
||||
vdev_t *vd;
|
||||
int err = 0;
|
||||
|
||||
ASSERT3P(spa->spa_condensing_indirect, !=, NULL);
|
||||
spa_config_enter(spa, SCL_VDEV, FTAG, RW_READER);
|
||||
|
@ -744,9 +751,10 @@ spa_condense_indirect_thread(void *arg, zthr_t *zthr)
|
|||
if (zthr_iscancelled(zthr))
|
||||
return;
|
||||
|
||||
VERIFY0(dsl_sync_task(spa_name(spa), NULL,
|
||||
err = dsl_sync_task(spa_name(spa), NULL,
|
||||
spa_condense_indirect_complete_sync, sci, 0,
|
||||
ZFS_SPACE_CHECK_EXTRA_RESERVED));
|
||||
ZFS_SPACE_CHECK_EXTRA_RESERVED);
|
||||
VERIFY(err == 0 || spa_exiting_any(spa));
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -125,6 +125,14 @@ vdev_initialize_change_state(vdev_t *vd, vdev_initializing_state_t new_state)
|
|||
vdev_initializing_state_t old_state = vd->vdev_initialize_state;
|
||||
vd->vdev_initialize_state = new_state;
|
||||
|
||||
/*
|
||||
* In this context, a pool vdev is initializing. Usually, we would
|
||||
* want to handle txg failure, but this can only happen if the pool
|
||||
* becomes suspended and then forcibly exported when this occurs. In
|
||||
* which case, the caller here hung while holding the namespace lock,
|
||||
* so there's little that can be done (including attempt a force
|
||||
* export, which requires the namespace lock) to recover.
|
||||
*/
|
||||
dmu_tx_t *tx = dmu_tx_create_dd(spa_get_dsl(spa)->dp_mos_dir);
|
||||
VERIFY0(dmu_tx_assign(tx, TXG_WAIT));
|
||||
dsl_sync_task_nowait(spa_get_dsl(spa), vdev_initialize_zap_update_sync,
|
||||
|
|
|
@ -1884,7 +1884,7 @@ retry:
|
|||
* bailing out and declaring the pool faulted.
|
||||
*/
|
||||
if (error != 0) {
|
||||
if ((flags & ZIO_FLAG_TRYHARD) != 0)
|
||||
if (spa_exiting_any(spa) || (flags & ZIO_FLAG_TRYHARD) != 0)
|
||||
return (error);
|
||||
flags |= ZIO_FLAG_TRYHARD;
|
||||
}
|
||||
|
|
|
@ -283,7 +283,12 @@ vdev_rebuild_initiate(vdev_t *vd)
|
|||
ASSERT(!vd->vdev_rebuilding);
|
||||
|
||||
dmu_tx_t *tx = dmu_tx_create_dd(spa_get_dsl(spa)->dp_mos_dir);
|
||||
VERIFY0(dmu_tx_assign(tx, TXG_WAIT));
|
||||
int err = dmu_tx_assign(tx, TXG_WAIT);
|
||||
if (err != 0) {
|
||||
ASSERT(spa_exiting_any(vd->vdev_spa));
|
||||
dmu_tx_abort(tx);
|
||||
return;
|
||||
}
|
||||
|
||||
vd->vdev_rebuilding = B_TRUE;
|
||||
|
||||
|
@ -571,7 +576,15 @@ vdev_rebuild_range(vdev_rebuild_t *vr, uint64_t start, uint64_t size)
|
|||
mutex_exit(&vr->vr_io_lock);
|
||||
|
||||
dmu_tx_t *tx = dmu_tx_create_dd(spa_get_dsl(spa)->dp_mos_dir);
|
||||
VERIFY0(dmu_tx_assign(tx, TXG_WAIT));
|
||||
int err = dmu_tx_assign(tx, TXG_WAIT);
|
||||
if (err != 0) {
|
||||
ASSERT(spa_exiting_any(spa));
|
||||
dmu_tx_abort(tx);
|
||||
mutex_enter(&vr->vr_io_lock);
|
||||
vr->vr_bytes_inflight -= psize;
|
||||
mutex_exit(&vr->vr_io_lock);
|
||||
return (err);
|
||||
}
|
||||
uint64_t txg = dmu_tx_get_txg(tx);
|
||||
|
||||
spa_config_enter(spa, SCL_STATE_ALL, vd, RW_READER);
|
||||
|
@ -901,9 +914,15 @@ vdev_rebuild_thread(void *arg)
|
|||
|
||||
dsl_pool_t *dp = spa_get_dsl(spa);
|
||||
dmu_tx_t *tx = dmu_tx_create_dd(dp->dp_mos_dir);
|
||||
VERIFY0(dmu_tx_assign(tx, TXG_WAIT));
|
||||
int txerr = dmu_tx_assign(tx, TXG_WAIT);
|
||||
|
||||
mutex_enter(&vd->vdev_rebuild_lock);
|
||||
if (txerr != 0) {
|
||||
ASSERT(spa_exiting_any(vd->vdev_spa));
|
||||
vd->vdev_rebuilding = B_FALSE;
|
||||
dmu_tx_abort(tx);
|
||||
goto done;
|
||||
}
|
||||
if (error == 0) {
|
||||
/*
|
||||
* After a successful rebuild clear the DTLs of all ranges
|
||||
|
@ -942,6 +961,7 @@ vdev_rebuild_thread(void *arg)
|
|||
|
||||
dmu_tx_commit(tx);
|
||||
|
||||
done:
|
||||
vd->vdev_rebuild_thread = NULL;
|
||||
mutex_exit(&vd->vdev_rebuild_lock);
|
||||
spa_config_exit(spa, SCL_CONFIG, FTAG);
|
||||
|
|
|
@ -1531,7 +1531,15 @@ spa_vdev_remove_thread(void *arg)
|
|||
dmu_tx_t *tx =
|
||||
dmu_tx_create_dd(spa_get_dsl(spa)->dp_mos_dir);
|
||||
|
||||
VERIFY0(dmu_tx_assign(tx, TXG_WAIT));
|
||||
/*
|
||||
* If a tx can't be assigned, just punt and wait for
|
||||
* the next round. This must be an exiting spa.
|
||||
*/
|
||||
if (dmu_tx_assign(tx, TXG_WAIT) != 0) {
|
||||
ASSERT(spa_exiting_any(spa));
|
||||
dmu_tx_abort(tx);
|
||||
goto done;
|
||||
}
|
||||
uint64_t txg = dmu_tx_get_txg(tx);
|
||||
|
||||
/*
|
||||
|
@ -1565,6 +1573,7 @@ spa_vdev_remove_thread(void *arg)
|
|||
|
||||
spa_config_exit(spa, SCL_CONFIG, FTAG);
|
||||
|
||||
done:
|
||||
/*
|
||||
* Wait for all copies to finish before cleaning up the vca.
|
||||
*/
|
||||
|
|
|
@ -317,7 +317,14 @@ vdev_trim_change_state(vdev_t *vd, vdev_trim_state_t new_state,
|
|||
vd->vdev_trim_state = new_state;
|
||||
|
||||
dmu_tx_t *tx = dmu_tx_create_dd(spa_get_dsl(spa)->dp_mos_dir);
|
||||
VERIFY0(dmu_tx_assign(tx, TXG_WAIT));
|
||||
int txerr = dmu_tx_assign(tx, TXG_WAIT);
|
||||
if (txerr != 0) {
|
||||
ASSERT(spa_exiting_any(spa));
|
||||
dmu_tx_abort(tx);
|
||||
return;
|
||||
}
|
||||
|
||||
vd->vdev_trim_state = new_state;
|
||||
dsl_sync_task_nowait(spa_get_dsl(spa), vdev_trim_zap_update_sync,
|
||||
guid, tx);
|
||||
|
||||
|
@ -502,7 +509,15 @@ vdev_trim_range(trim_args_t *ta, uint64_t start, uint64_t size)
|
|||
mutex_exit(&vd->vdev_trim_io_lock);
|
||||
|
||||
dmu_tx_t *tx = dmu_tx_create_dd(spa_get_dsl(spa)->dp_mos_dir);
|
||||
VERIFY0(dmu_tx_assign(tx, TXG_WAIT));
|
||||
int err = dmu_tx_assign(tx, TXG_WAIT);
|
||||
if (err != 0) {
|
||||
ASSERT(spa_exiting_any(spa));
|
||||
mutex_enter(&vd->vdev_trim_io_lock);
|
||||
vd->vdev_trim_inflight[ta->trim_type]--;
|
||||
mutex_exit(&vd->vdev_trim_io_lock);
|
||||
dmu_tx_abort(tx);
|
||||
return (err);
|
||||
}
|
||||
uint64_t txg = dmu_tx_get_txg(tx);
|
||||
|
||||
spa_config_enter(spa, SCL_STATE_ALL, vd, RW_READER);
|
||||
|
|
|
@ -545,6 +545,13 @@ zap_get_leaf_byblk(zap_t *zap, uint64_t blkid, dmu_tx_t *tx, krw_t lt,
|
|||
ASSERT3U(db->db_size, ==, 1 << bs);
|
||||
ASSERT(blkid != 0);
|
||||
|
||||
zap_leaf_phys_t *zap_phys = db->db_data;
|
||||
if (zap_phys->l_hdr.lh_block_type != ZBT_LEAF ||
|
||||
zap_phys->l_hdr.lh_magic != ZAP_LEAF_MAGIC) {
|
||||
dmu_buf_rele(db, NULL);
|
||||
return (SET_ERROR(EIO));
|
||||
}
|
||||
|
||||
zap_leaf_t *l = dmu_buf_get_user(db);
|
||||
|
||||
if (l == NULL)
|
||||
|
@ -559,8 +566,6 @@ zap_get_leaf_byblk(zap_t *zap, uint64_t blkid, dmu_tx_t *tx, krw_t lt,
|
|||
dmu_buf_will_dirty(db, tx);
|
||||
ASSERT3U(l->l_blkid, ==, blkid);
|
||||
ASSERT3P(l->l_dbuf, ==, db);
|
||||
ASSERT3U(zap_leaf_phys(l)->l_hdr.lh_block_type, ==, ZBT_LEAF);
|
||||
ASSERT3U(zap_leaf_phys(l)->l_hdr.lh_magic, ==, ZAP_LEAF_MAGIC);
|
||||
|
||||
*lp = l;
|
||||
return (0);
|
||||
|
|
|
@ -1583,7 +1583,9 @@ zfs_ioc_pool_export(zfs_cmd_t *zc)
|
|||
boolean_t force = (boolean_t)zc->zc_cookie;
|
||||
boolean_t hardforce = (boolean_t)zc->zc_guid;
|
||||
|
||||
zfs_log_history(zc);
|
||||
if (!force && !hardforce)
|
||||
zfs_log_history(zc);
|
||||
|
||||
error = spa_export(zc->zc_name, NULL, force, hardforce);
|
||||
|
||||
return (error);
|
||||
|
@ -6899,7 +6901,7 @@ zfs_ioctl_register(const char *name, zfs_ioc_t ioc, zfs_ioc_func_t *func,
|
|||
vec->zvec_nvl_key_count = num_keys;
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
zfs_ioctl_register_pool(zfs_ioc_t ioc, zfs_ioc_legacy_func_t *func,
|
||||
zfs_secpolicy_func_t *secpolicy, boolean_t log_history,
|
||||
zfs_ioc_poolcheck_t pool_check)
|
||||
|
@ -7171,9 +7173,9 @@ zfs_ioctl_init(void)
|
|||
* does the logging of those commands.
|
||||
*/
|
||||
zfs_ioctl_register_pool(ZFS_IOC_POOL_DESTROY, zfs_ioc_pool_destroy,
|
||||
zfs_secpolicy_config, B_FALSE, POOL_CHECK_SUSPENDED);
|
||||
zfs_secpolicy_config, B_FALSE, POOL_CHECK_NONE);
|
||||
zfs_ioctl_register_pool(ZFS_IOC_POOL_EXPORT, zfs_ioc_pool_export,
|
||||
zfs_secpolicy_config, B_FALSE, POOL_CHECK_SUSPENDED);
|
||||
zfs_secpolicy_config, B_FALSE, POOL_CHECK_NONE);
|
||||
|
||||
zfs_ioctl_register_pool(ZFS_IOC_POOL_STATS, zfs_ioc_pool_stats,
|
||||
zfs_secpolicy_read, B_FALSE, POOL_CHECK_NONE);
|
||||
|
@ -7181,10 +7183,10 @@ zfs_ioctl_init(void)
|
|||
zfs_secpolicy_read, B_FALSE, POOL_CHECK_NONE);
|
||||
|
||||
zfs_ioctl_register_pool(ZFS_IOC_ERROR_LOG, zfs_ioc_error_log,
|
||||
zfs_secpolicy_inject, B_FALSE, POOL_CHECK_SUSPENDED);
|
||||
zfs_secpolicy_inject, B_FALSE, POOL_CHECK_NONE);
|
||||
zfs_ioctl_register_pool(ZFS_IOC_DSOBJ_TO_DSNAME,
|
||||
zfs_ioc_dsobj_to_dsname,
|
||||
zfs_secpolicy_diff, B_FALSE, POOL_CHECK_SUSPENDED);
|
||||
zfs_secpolicy_diff, B_FALSE, POOL_CHECK_NONE);
|
||||
zfs_ioctl_register_pool(ZFS_IOC_POOL_GET_HISTORY,
|
||||
zfs_ioc_pool_get_history,
|
||||
zfs_secpolicy_config, B_FALSE, POOL_CHECK_SUSPENDED);
|
||||
|
|
|
@ -695,7 +695,12 @@ zil_create(zilog_t *zilog)
|
|||
*/
|
||||
if (BP_IS_HOLE(&blk) || BP_SHOULD_BYTESWAP(&blk)) {
|
||||
tx = dmu_tx_create(zilog->zl_os);
|
||||
VERIFY0(dmu_tx_assign(tx, TXG_WAIT));
|
||||
error = dmu_tx_assign(tx, TXG_WAIT);
|
||||
if (error != 0) {
|
||||
ASSERT(dmu_objset_exiting(zilog->zl_os));
|
||||
dmu_tx_abort(tx);
|
||||
return (NULL);
|
||||
}
|
||||
dsl_dataset_dirty(dmu_objset_ds(zilog->zl_os), tx);
|
||||
txg = dmu_tx_get_txg(tx);
|
||||
|
||||
|
@ -750,6 +755,7 @@ zil_destroy(zilog_t *zilog, boolean_t keep_first)
|
|||
lwb_t *lwb;
|
||||
dmu_tx_t *tx;
|
||||
uint64_t txg;
|
||||
int error;
|
||||
|
||||
/*
|
||||
* Wait for any previous destroy to complete.
|
||||
|
@ -762,7 +768,12 @@ zil_destroy(zilog_t *zilog, boolean_t keep_first)
|
|||
return;
|
||||
|
||||
tx = dmu_tx_create(zilog->zl_os);
|
||||
VERIFY0(dmu_tx_assign(tx, TXG_WAIT));
|
||||
error = dmu_tx_assign(tx, TXG_WAIT);
|
||||
if (error != 0) {
|
||||
ASSERT(dmu_objset_exiting(zilog->zl_os));
|
||||
dmu_tx_abort(tx);
|
||||
return;
|
||||
}
|
||||
dsl_dataset_dirty(dmu_objset_ds(zilog->zl_os), tx);
|
||||
txg = dmu_tx_get_txg(tx);
|
||||
|
||||
|
@ -1521,7 +1532,11 @@ zil_lwb_write_issue(zilog_t *zilog, lwb_t *lwb)
|
|||
* should not be subject to the dirty data based delays. We
|
||||
* use TXG_NOTHROTTLE to bypass the delay mechanism.
|
||||
*/
|
||||
VERIFY0(dmu_tx_assign(tx, TXG_WAIT | TXG_NOTHROTTLE));
|
||||
if (dmu_tx_assign(tx, TXG_WAIT | TXG_NOTHROTTLE) != 0) {
|
||||
ASSERT(dmu_objset_exiting(zilog->zl_os));
|
||||
dmu_tx_abort(tx);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
dsl_dataset_dirty(dmu_objset_ds(zilog->zl_os), tx);
|
||||
txg = dmu_tx_get_txg(tx);
|
||||
|
@ -2813,7 +2828,12 @@ static void
|
|||
zil_commit_itx_assign(zilog_t *zilog, zil_commit_waiter_t *zcw)
|
||||
{
|
||||
dmu_tx_t *tx = dmu_tx_create(zilog->zl_os);
|
||||
VERIFY0(dmu_tx_assign(tx, TXG_WAIT));
|
||||
|
||||
if (dmu_tx_assign(tx, TXG_WAIT) != 0) {
|
||||
ASSERT(dmu_objset_exiting(zilog->zl_os));
|
||||
dmu_tx_abort(tx);
|
||||
return;
|
||||
}
|
||||
|
||||
itx_t *itx = zil_itx_create(TX_COMMIT, sizeof (lr_t));
|
||||
itx->itx_sync = B_TRUE;
|
||||
|
@ -2975,6 +2995,12 @@ zil_commit(zilog_t *zilog, uint64_t foid)
|
|||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the objset is being forced to exit, there's nothing more to do.
|
||||
*/
|
||||
if (dmu_objset_exiting(zilog->zl_os))
|
||||
return;
|
||||
|
||||
/*
|
||||
* If the ZIL is suspended, we don't want to dirty it by calling
|
||||
* zil_commit_itx_assign() below, nor can we write out
|
||||
|
@ -3318,14 +3344,16 @@ zil_close(zilog_t *zilog)
|
|||
* ZIL to be clean, and to wait for all pending lwbs to be
|
||||
* written out.
|
||||
*/
|
||||
if (txg != 0)
|
||||
txg_wait_synced(zilog->zl_dmu_pool, txg);
|
||||
if (!dmu_objset_exiting(zilog->zl_os)) {
|
||||
if (txg != 0)
|
||||
txg_wait_synced(zilog->zl_dmu_pool, txg);
|
||||
|
||||
if (zilog_is_dirty(zilog))
|
||||
zfs_dbgmsg("zil (%px) is dirty, txg %llu", zilog,
|
||||
(u_longlong_t)txg);
|
||||
if (txg < spa_freeze_txg(zilog->zl_spa))
|
||||
VERIFY(!zilog_is_dirty(zilog));
|
||||
if (zilog_is_dirty(zilog))
|
||||
zfs_dbgmsg("zil (%px) is dirty, txg %llu", zilog,
|
||||
(u_longlong_t)txg);
|
||||
if (txg < spa_freeze_txg(zilog->zl_spa))
|
||||
VERIFY(!zilog_is_dirty(zilog));
|
||||
}
|
||||
|
||||
zilog->zl_get_data = NULL;
|
||||
|
||||
|
@ -3342,7 +3370,15 @@ zil_close(zilog_t *zilog)
|
|||
metaslab_fastwrite_unmark(zilog->zl_spa, &lwb->lwb_blk);
|
||||
|
||||
list_remove(&zilog->zl_lwb_list, lwb);
|
||||
zio_buf_free(lwb->lwb_buf, lwb->lwb_sz);
|
||||
if (lwb->lwb_buf != NULL) {
|
||||
zio_buf_free(lwb->lwb_buf, lwb->lwb_sz);
|
||||
} else {
|
||||
/*
|
||||
* Pool is being force exported, while this lwb was
|
||||
* between zil_lwb_flush_vdevs_done and zil_sync.
|
||||
*/
|
||||
ASSERT(spa_exiting(zilog->zl_spa));
|
||||
}
|
||||
zil_free_lwb(zilog, lwb);
|
||||
}
|
||||
mutex_exit(&zilog->zl_lock);
|
||||
|
|
131
module/zfs/zio.c
131
module/zfs/zio.c
|
@ -2258,6 +2258,9 @@ zio_wait(zio_t *zio)
|
|||
error = cv_timedwait_io(&zio->io_cv, &zio->io_lock,
|
||||
ddi_get_lbolt() + timeout);
|
||||
|
||||
if (error != 0 && spa_exiting_any(zio->io_spa)) {
|
||||
break;
|
||||
}
|
||||
if (zfs_deadman_enabled && error == -1 &&
|
||||
gethrtime() - zio->io_queued_timestamp >
|
||||
spa_deadman_ziotime(zio->io_spa)) {
|
||||
|
@ -2270,6 +2273,14 @@ zio_wait(zio_t *zio)
|
|||
mutex_exit(&zio->io_lock);
|
||||
|
||||
error = zio->io_error;
|
||||
if (error != 0 && (zio->io_flags & ZIO_FLAG_CANFAIL) == 0 &&
|
||||
spa_exiting_any(zio->io_spa)) {
|
||||
/*
|
||||
* Don't report errors to the callers. In this context, the
|
||||
* pool is being forcibly exported, so just throw it away.
|
||||
*/
|
||||
error = 0;
|
||||
}
|
||||
zio_destroy(zio);
|
||||
|
||||
return (error);
|
||||
|
@ -2325,11 +2336,22 @@ zio_reexecute(void *arg)
|
|||
|
||||
pio->io_flags = pio->io_orig_flags;
|
||||
pio->io_stage = pio->io_orig_stage;
|
||||
pio->io_pipeline = pio->io_orig_pipeline;
|
||||
pio->io_reexecute = 0;
|
||||
if (spa_exiting_any(pio->io_spa)) {
|
||||
/*
|
||||
* This pool is being forcibly exported; skip everything and
|
||||
* finish as soon as possible.
|
||||
*/
|
||||
pio->io_pipeline = ZIO_INTERLOCK_PIPELINE;
|
||||
if (pio->io_error == 0)
|
||||
pio->io_error = SET_ERROR(EIO);
|
||||
pio->io_reexecute = ZIO_REEXECUTE_CANCELLED;
|
||||
} else {
|
||||
pio->io_pipeline = pio->io_orig_pipeline;
|
||||
pio->io_error = 0;
|
||||
pio->io_reexecute = 0;
|
||||
}
|
||||
pio->io_flags |= ZIO_FLAG_REEXECUTED;
|
||||
pio->io_pipeline_trace = 0;
|
||||
pio->io_error = 0;
|
||||
for (int w = 0; w < ZIO_WAIT_TYPES; w++)
|
||||
pio->io_state[w] = 0;
|
||||
for (int c = 0; c < ZIO_CHILD_TYPES; c++)
|
||||
|
@ -2371,6 +2393,8 @@ zio_reexecute(void *arg)
|
|||
void
|
||||
zio_suspend(spa_t *spa, zio_t *zio, zio_suspend_reason_t reason)
|
||||
{
|
||||
dsl_pool_t *dp = spa_get_dsl(spa);
|
||||
|
||||
if (spa_get_failmode(spa) == ZIO_FAILURE_MODE_PANIC)
|
||||
fm_panic("Pool '%s' has encountered an uncorrectable I/O "
|
||||
"failure and the failure mode property for this pool "
|
||||
|
@ -2401,6 +2425,48 @@ zio_suspend(spa_t *spa, zio_t *zio, zio_suspend_reason_t reason)
|
|||
}
|
||||
|
||||
mutex_exit(&spa->spa_suspend_lock);
|
||||
|
||||
/* Notify waiters that might care about this state transition. */
|
||||
for (int i = 0; i < SCL_LOCKS; i++)
|
||||
cv_broadcast(&spa->spa_config_lock[i].scl_cv);
|
||||
cv_broadcast(&spa->spa_evicting_os_cv);
|
||||
txg_completion_notify(dp);
|
||||
}
|
||||
|
||||
static zio_t *
|
||||
zio_unsuspend(spa_t *spa)
|
||||
{
|
||||
zio_t *pio;
|
||||
|
||||
mutex_enter(&spa->spa_suspend_lock);
|
||||
spa->spa_suspended = ZIO_SUSPEND_NONE;
|
||||
cv_broadcast(&spa->spa_suspend_cv);
|
||||
pio = spa->spa_suspend_zio_root;
|
||||
spa->spa_suspend_zio_root = NULL;
|
||||
mutex_exit(&spa->spa_suspend_lock);
|
||||
|
||||
return (pio);
|
||||
}
|
||||
|
||||
void
|
||||
zio_cancel(spa_t *spa)
|
||||
{
|
||||
zio_t *pio;
|
||||
|
||||
/*
|
||||
* Interrupt all physical zios.
|
||||
* Only meaningful in the context of a forced export.
|
||||
*/
|
||||
mutex_enter(&spa->spa_suspend_lock);
|
||||
pio = spa->spa_suspend_zio_root;
|
||||
spa->spa_suspend_zio_root = NULL;
|
||||
cv_broadcast(&spa->spa_suspend_cv);
|
||||
mutex_exit(&spa->spa_suspend_lock);
|
||||
if (pio == NULL)
|
||||
return;
|
||||
|
||||
zio_reexecute(pio);
|
||||
(void) zio_wait(pio);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -2408,16 +2474,18 @@ zio_resume(spa_t *spa)
|
|||
{
|
||||
zio_t *pio;
|
||||
|
||||
/*
|
||||
* Issue an async request to update the pool's configuration in case
|
||||
* suspension occurred while such an update was in progress. This
|
||||
* will restart the update process from the beginning. We could
|
||||
* make it conditional, but it's safer not to.
|
||||
*/
|
||||
spa_async_request(spa, SPA_ASYNC_CONFIG_UPDATE);
|
||||
|
||||
/*
|
||||
* Reexecute all previously suspended i/o.
|
||||
*/
|
||||
mutex_enter(&spa->spa_suspend_lock);
|
||||
spa->spa_suspended = ZIO_SUSPEND_NONE;
|
||||
cv_broadcast(&spa->spa_suspend_cv);
|
||||
pio = spa->spa_suspend_zio_root;
|
||||
spa->spa_suspend_zio_root = NULL;
|
||||
mutex_exit(&spa->spa_suspend_lock);
|
||||
|
||||
pio = zio_unsuspend(spa);
|
||||
if (pio == NULL)
|
||||
return (0);
|
||||
|
||||
|
@ -2425,15 +2493,6 @@ zio_resume(spa_t *spa)
|
|||
return (zio_wait(pio));
|
||||
}
|
||||
|
||||
void
|
||||
zio_resume_wait(spa_t *spa)
|
||||
{
|
||||
mutex_enter(&spa->spa_suspend_lock);
|
||||
while (spa_suspended(spa))
|
||||
cv_wait(&spa->spa_suspend_cv, &spa->spa_suspend_lock);
|
||||
mutex_exit(&spa->spa_suspend_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* ==========================================================================
|
||||
* Gang blocks.
|
||||
|
@ -4379,7 +4438,7 @@ zio_ready(zio_t *zio)
|
|||
return (NULL);
|
||||
}
|
||||
|
||||
if (zio->io_ready) {
|
||||
if (zio->io_ready && zio->io_spa->spa_export_initiator == NULL) {
|
||||
ASSERT(IO_IS_ALLOCATING(zio));
|
||||
ASSERT(bp->blk_birth == zio->io_txg || BP_IS_HOLE(bp) ||
|
||||
(zio->io_flags & ZIO_FLAG_NOPWRITE));
|
||||
|
@ -4525,6 +4584,13 @@ zio_done(zio_t *zio)
|
|||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* If the pool is forcibly exporting, make sure everything is
|
||||
* thrown away, as nothing can be trusted now.
|
||||
*/
|
||||
if (spa_exiting_any(zio->io_spa) && zio->io_error == 0)
|
||||
zio->io_error = SET_ERROR(EIO);
|
||||
|
||||
/*
|
||||
* If the allocation throttle is enabled, then update the accounting.
|
||||
* We only track child I/Os that are part of an allocating async
|
||||
|
@ -4644,7 +4710,7 @@ zio_done(zio_t *zio)
|
|||
}
|
||||
}
|
||||
|
||||
if (zio->io_error) {
|
||||
if (zio->io_error && !spa_exiting_any(zio->io_spa)) {
|
||||
/*
|
||||
* If this I/O is attached to a particular vdev,
|
||||
* generate an error message describing the I/O failure
|
||||
|
@ -4783,7 +4849,20 @@ zio_done(zio_t *zio)
|
|||
}
|
||||
}
|
||||
|
||||
if ((pio = zio_unique_parent(zio)) != NULL) {
|
||||
if (zio->io_reexecute & ZIO_REEXECUTE_CANCELLED) {
|
||||
/*
|
||||
* This zio had been marked for reexecute previously,
|
||||
* and upon reexecution, found the pool being forcibly
|
||||
* exported. Nothing to do now but clean up.
|
||||
*
|
||||
* This special flag is used because it allows the
|
||||
* zio pipeline to mark all zios in the tree as
|
||||
* cancelled, before cleaning them up.
|
||||
*/
|
||||
ASSERT3U(zio->io_error, !=, 0);
|
||||
zio->io_reexecute = 0;
|
||||
goto finish;
|
||||
} else if ((pio = zio_unique_parent(zio)) != NULL) {
|
||||
/*
|
||||
* We're not a root i/o, so there's nothing to do
|
||||
* but notify our parent. Don't propagate errors
|
||||
|
@ -4815,9 +4894,11 @@ zio_done(zio_t *zio)
|
|||
return (NULL);
|
||||
}
|
||||
|
||||
ASSERT(zio->io_child_count == 0);
|
||||
ASSERT(zio->io_reexecute == 0);
|
||||
ASSERT(zio->io_error == 0 || (zio->io_flags & ZIO_FLAG_CANFAIL));
|
||||
finish:
|
||||
ASSERT3U(zio->io_child_count, ==, 0);
|
||||
ASSERT3U(zio->io_reexecute, ==, 0);
|
||||
ASSERT(zio->io_error == 0 || (zio->io_flags & ZIO_FLAG_CANFAIL) ||
|
||||
zio->io_spa->spa_export_initiator != NULL);
|
||||
|
||||
/*
|
||||
* Report any checksum errors, since the I/O is complete.
|
||||
|
|
|
@ -375,7 +375,8 @@ tags = ['functional', 'cli_root', 'zpool_events']
|
|||
|
||||
[tests/functional/cli_root/zpool_export]
|
||||
tests = ['zpool_export_001_pos', 'zpool_export_002_pos',
|
||||
'zpool_export_003_neg', 'zpool_export_004_pos']
|
||||
'zpool_export_003_neg', 'zpool_export_004_pos', 'zpool_export_005_pos',
|
||||
'zpool_export_006_pos', 'zpool_export_007_pos']
|
||||
tags = ['functional', 'cli_root', 'zpool_export']
|
||||
|
||||
[tests/functional/cli_root/zpool_get]
|
||||
|
|
|
@ -55,6 +55,7 @@ export SYSTEM_FILES_COMMON='arp
|
|||
logname
|
||||
ls
|
||||
mkdir
|
||||
mkfifo
|
||||
mknod
|
||||
mktemp
|
||||
mount
|
||||
|
@ -73,6 +74,7 @@ export SYSTEM_FILES_COMMON='arp
|
|||
pwd
|
||||
python
|
||||
python2
|
||||
pv
|
||||
python3
|
||||
quotaon
|
||||
readlink
|
||||
|
|
|
@ -34,6 +34,7 @@ DEADMAN_SYNCTIME_MS deadman.synctime_ms zfs_deadman_synctime_ms
|
|||
DEADMAN_ZIOTIME_MS deadman.ziotime_ms zfs_deadman_ziotime_ms
|
||||
DISABLE_IVSET_GUID_CHECK disable_ivset_guid_check zfs_disable_ivset_guid_check
|
||||
DMU_OFFSET_NEXT_SYNC dmu_offset_next_sync zfs_dmu_offset_next_sync
|
||||
FORCED_EXPORT_UNMOUNT UNSUPPORTED zfs_forced_export_unmount_enabled
|
||||
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
|
||||
|
|
|
@ -56,9 +56,7 @@ done
|
|||
zpool_events_settle
|
||||
|
||||
# 4. Verify 'zpool events -f' successfully recorded these new events
|
||||
EVENTS_LOG=$(cat $EVENTS_FILE | wc -l)
|
||||
if [[ $EVENTS_LOG -ne $EVENTS_NUM ]]; then
|
||||
log_fail "Unexpected number of events: $EVENTS_LOG != $EVENTS_NUM"
|
||||
fi
|
||||
EVENTS_LOG=$(wc -l < $EVENTS_FILE)
|
||||
log_must test $EVENTS_LOG -gt 0
|
||||
|
||||
log_pass "'zpool events -f' successfully follows new events."
|
||||
|
|
|
@ -88,6 +88,7 @@ fi
|
|||
|
||||
# online the device so the zpool will use the new space
|
||||
log_must zpool online -e $TESTPOOL1 $SDISK
|
||||
log_must zpool sync $TESTPOOL1
|
||||
|
||||
typeset new_size=$(get_pool_prop size $TESTPOOL1)
|
||||
log_note "new pool size: $new_size"
|
||||
|
|
|
@ -5,7 +5,10 @@ dist_pkgdata_SCRIPTS = \
|
|||
zpool_export_001_pos.ksh \
|
||||
zpool_export_002_pos.ksh \
|
||||
zpool_export_003_neg.ksh \
|
||||
zpool_export_004_pos.ksh
|
||||
zpool_export_004_pos.ksh \
|
||||
zpool_export_005_pos.ksh \
|
||||
zpool_export_006_pos.ksh \
|
||||
zpool_export_007_pos.ksh
|
||||
|
||||
dist_pkgdata_DATA = \
|
||||
zpool_export.cfg \
|
||||
|
|
|
@ -25,6 +25,12 @@
|
|||
|
||||
. $STF_SUITE/tests/functional/cli_root/zpool_export/zpool_export.cfg
|
||||
|
||||
function create_fifo
|
||||
{
|
||||
log_must rm -f $1
|
||||
log_must mkfifo $1
|
||||
}
|
||||
|
||||
function zpool_export_cleanup
|
||||
{
|
||||
[[ -d $TESTDIR0 ]] && log_must rm -rf $TESTDIR0
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
#!/bin/ksh -p
|
||||
#
|
||||
# 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) 2020 by Klara Systems, Inc. All rights reserved.
|
||||
#
|
||||
|
||||
. $STF_SUITE/tests/functional/cli_root/zpool_export/zpool_export.kshlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# A pool should be force exportable, while a send is running from it.
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Initiate a send from pool to a file.
|
||||
# 2. Slow the send using pv, so it blocks a normal pool export.
|
||||
# 3. Check that normal export fails.
|
||||
# 4. Forcibly export pool.
|
||||
# 5. Verify pool is no longer present in the list output.
|
||||
#
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
function cleanup {
|
||||
[[ -n "$sendpid" ]] && kill -9 "$sendpid"
|
||||
[[ -n "$pvpid" ]] && kill -9 $pvpid
|
||||
[[ -n "$snapstream" ]] && rm -f "$snapstream"
|
||||
zpool_export_cleanup
|
||||
}
|
||||
|
||||
log_onexit cleanup
|
||||
|
||||
log_assert "Verify a pool can be forcibly exported while sending."
|
||||
|
||||
snap=$TESTPOOL1/$TESTFS@$TESTSNAP
|
||||
snapstream=$TEST_BASE_DIR/send.$$
|
||||
|
||||
vdev0=$TESTDIR0/$TESTFILE0
|
||||
log_must mkdir -p $TESTDIR0
|
||||
log_must truncate -s 1G $vdev0
|
||||
log_must zpool create -f $TESTPOOL1 $vdev0
|
||||
log_must zfs create $TESTPOOL1/$TESTFS
|
||||
|
||||
mntpnt=$(get_prop mountpoint $TESTPOOL1/$TESTFS)
|
||||
log_must dd if=/dev/urandom of=$mntpnt/$TESTFILE1 bs=1M count=16
|
||||
|
||||
log_must zfs snapshot $snap
|
||||
|
||||
# Create FIFOs for the send, so the processes can be controlled and
|
||||
# monitored individually.
|
||||
create_fifo $TESTDIR0/snapfifo
|
||||
zfs send $snap > $TESTDIR0/snapfifo &
|
||||
sendpid=$!
|
||||
pv -L 1k < $TESTDIR0/snapfifo > $snapstream &
|
||||
pvpid=$!
|
||||
|
||||
log_note "zfs send pid is $sendpid, pv pid is $pvpid"
|
||||
|
||||
log_mustnot zpool export $TESTPOOL1
|
||||
|
||||
# Send should still be running; now try force export.
|
||||
log_must kill -0 $sendpid
|
||||
log_must zpool export -F $TESTPOOL1
|
||||
|
||||
lsout=$(ls -l $snapstream)
|
||||
log_note "snapstream: $lsout"
|
||||
|
||||
# Send should have exited non-zero.
|
||||
log_mustnot wait $sendpid
|
||||
|
||||
poolexists $TESTPOOL1 && \
|
||||
log_fail "$TESTPOOL1 unexpectedly found in 'zpool list' output."
|
||||
|
||||
log_pass "Successfully forcibly exported a pool while sending."
|
|
@ -0,0 +1,112 @@
|
|||
#!/bin/ksh -p
|
||||
#
|
||||
# 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) 2020 by Klara Systems, Inc. All rights reserved.
|
||||
#
|
||||
|
||||
. $STF_SUITE/tests/functional/cli_root/zpool_export/zpool_export.kshlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# A pool should be force exportable, while a send is running from it.
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Initiate a send from pool A to pool B.
|
||||
# 2. Slow the send using pv, so it blocks a normal pool export.
|
||||
# 3. Check that normal export of pool Bfails.
|
||||
# 4. Forcibly export pool B.
|
||||
# 5. Verify pool B is no longer present in the list output.
|
||||
#
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
function cleanup {
|
||||
[[ -n "$sendpid" ]] && kill -9 "$sendpid"
|
||||
[[ -n "$recvpid" ]] && kill -9 "$recvpid"
|
||||
[[ -n "$pvpid" ]] && kill -9 "$pvpid"
|
||||
zpool_export_cleanup
|
||||
}
|
||||
|
||||
log_onexit cleanup
|
||||
|
||||
log_assert "Verify a receiving pool can be forcibly exported."
|
||||
|
||||
srcsnap=$TESTPOOL1/$TESTFS@$TESTSNAP
|
||||
dstsnap=$TESTPOOL2/$TESTFS@$TESTSNAP
|
||||
|
||||
vdev0=$TESTDIR0/$TESTFILE0
|
||||
vdev1=$TESTDIR0/$TESTFILE1
|
||||
log_must mkdir -p $TESTDIR0
|
||||
log_must truncate -s 1G $vdev0 $vdev1
|
||||
log_must zpool create -f $TESTPOOL1 $vdev0
|
||||
log_must zpool create -f $TESTPOOL2 $vdev1
|
||||
log_must zfs create $TESTPOOL1/$TESTFS
|
||||
|
||||
mntpnt=$(get_prop mountpoint $TESTPOOL1/$TESTFS)
|
||||
log_must dd if=/dev/urandom of=$mntpnt/$TESTFILE1 bs=1M count=16
|
||||
|
||||
log_must zfs snapshot $srcsnap
|
||||
|
||||
# Create FIFOs for send and receive, so the processes can be controlled and
|
||||
# monitored individually.
|
||||
create_fifo $TESTDIR0/sendfifo
|
||||
create_fifo $TESTDIR0/recvfifo
|
||||
|
||||
zfs send $srcsnap > $TESTDIR0/sendfifo &
|
||||
sendpid=$!
|
||||
pv -L 1k < $TESTDIR0/sendfifo > $TESTDIR0/recvfifo &
|
||||
pvpid=$!
|
||||
zfs recv $dstsnap < $TESTDIR0/recvfifo &
|
||||
recvpid=$!
|
||||
|
||||
log_note "zfs send pid is $sendpid, recv pid is $recvpid, pv pid is $pvpid"
|
||||
|
||||
log_note "Waiting until zfs receive has a chance to start ..."
|
||||
typeset -i i=0
|
||||
typeset -i timeout=5
|
||||
while (( $i < $timeout )); do
|
||||
zfs list $TESTPOOL2/$TESTFS >/dev/null 2>&1 && break
|
||||
sleep 1
|
||||
((i = i + 1))
|
||||
done
|
||||
[[ $i -lt $timeout ]] || log_fail "receive failed to start"
|
||||
|
||||
log_must zfs list $TESTPOOL2/$TESTFS
|
||||
|
||||
log_mustnot zpool export $TESTPOOL2
|
||||
|
||||
# Send & receive should still be running; now try force export.
|
||||
log_must kill -0 $sendpid
|
||||
log_must kill -0 $recvpid
|
||||
log_must zpool export -F $TESTPOOL2
|
||||
|
||||
# Both zfs send & recv should have exited non-zero.
|
||||
log_mustnot wait $recvpid
|
||||
log_mustnot wait $sendpid
|
||||
|
||||
poolexists $TESTPOOL1 || \
|
||||
log_fail "$TESTPOOL1 should be in 'zpool list' output."
|
||||
poolexists $TESTPOOL2 && \
|
||||
log_fail "$TESTPOOL2 unexpectedly found in 'zpool list' output."
|
||||
|
||||
log_pass "Successfully forcibly exported a pool while receiving."
|
|
@ -0,0 +1,107 @@
|
|||
#!/bin/ksh -p
|
||||
#
|
||||
# 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) 2020 by Klara Systems, Inc. All rights reserved.
|
||||
#
|
||||
|
||||
. $STF_SUITE/tests/functional/cli_root/zpool_export/zpool_export.kshlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# A pool should be force exportable, while POSIX I/O is in flight.
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Write to a file that is held open, slowed using pv, so it blocks a
|
||||
# normal filesystem unmount / pool export.
|
||||
# 2. Check that normal export fails.
|
||||
# 3. Forcibly export pool.
|
||||
# 4. Verify pool is no longer present in the list output.
|
||||
#
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
function cleanup {
|
||||
[[ -n "$ddinpid" ]] && kill -9 "$ddinpid"
|
||||
[[ -n "$ddoutpid" ]] && kill -9 "$ddoutpid"
|
||||
if is_linux; then
|
||||
log_must set_tunable64 FORCED_EXPORT_UNMOUNT 0
|
||||
fi
|
||||
zpool_export_cleanup
|
||||
}
|
||||
|
||||
log_onexit cleanup
|
||||
|
||||
log_assert "Verify a pool can be forcibly exported while writing POSIX I/O"
|
||||
|
||||
snap=$TESTPOOL1/$TESTFS@$TESTSNAP
|
||||
snapstream=$TEST_BASE_DIR/send.$$
|
||||
|
||||
# On Linux, it's necessary to enable a tunable for the test to be able to
|
||||
# kick the POSIX I/O user off.
|
||||
if is_linux; then
|
||||
log_must set_tunable64 FORCED_EXPORT_UNMOUNT 1
|
||||
fi
|
||||
|
||||
vdev0=$TESTDIR0/$TESTFILE0
|
||||
log_must mkdir -p $TESTDIR0
|
||||
log_must truncate -s 1G $vdev0
|
||||
log_must zpool create -f $TESTPOOL1 $vdev0
|
||||
log_must zfs create $TESTPOOL1/$TESTFS
|
||||
|
||||
mntpnt=$(get_prop mountpoint $TESTPOOL1/$TESTFS)
|
||||
|
||||
# Create FIFOs for the writes, so the processes can be controlled and
|
||||
# monitored individually.
|
||||
create_fifo $TESTDIR0/writefifo
|
||||
dd if=/dev/urandom bs=1M count=16 | pv -L 1k > $TESTDIR0/writefifo &
|
||||
ddinpid=$!
|
||||
|
||||
dd of=${mntpnt}/$TESTFILE1 < $TESTDIR0/writefifo &
|
||||
ddoutpid=$!
|
||||
|
||||
log_note "dd input pid is $ddinpid, dd output pid is $ddoutpid"
|
||||
|
||||
log_note "Waiting until output file is filling ..."
|
||||
typeset -i i=0
|
||||
typeset -i timeout=5
|
||||
while (( $i < $timeout )); do
|
||||
test -f ${mntpnt}/$TESTFILE1 && break
|
||||
sleep 1
|
||||
((i = i + 1))
|
||||
done
|
||||
[[ $i -lt $timeout ]] || log_fail "dd failed to start"
|
||||
|
||||
log_mustnot zpool export $TESTPOOL1
|
||||
|
||||
# Write should still be running; now try force export. We must do this
|
||||
# twice so dd dies initially.
|
||||
log_must kill -0 $ddoutpid
|
||||
log_mustnot zpool export -F $TESTPOOL1
|
||||
# Write should have exited non-zero.
|
||||
log_mustnot wait $ddoutpid
|
||||
log_must zpool export -F $TESTPOOL1
|
||||
|
||||
poolexists $TESTPOOL1 && \
|
||||
log_fail "$TESTPOOL1 unexpectedly found in 'zpool list' output."
|
||||
|
||||
log_pass "Successfully forcibly exported a pool while writing POSIX I/O sending."
|
|
@ -105,7 +105,7 @@ log_must mkfile $FSIZE /$TESTPOOL/data
|
|||
|
||||
for offline_disk in $autoonline_disks
|
||||
do
|
||||
log_must zpool export -F $TESTPOOL
|
||||
log_must zpool export -f $TESTPOOL
|
||||
|
||||
host=$(get_scsi_host $offline_disk)
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
export PREV_UBER="$TEST_BASE_DIR/mmp-uber-prev.txt"
|
||||
export CURR_UBER="$TEST_BASE_DIR/mmp-uber-curr.txt"
|
||||
export DISK=${DISKS%% *}
|
||||
export TESTPOOL="testpool.mmp"
|
||||
|
||||
export HOSTID_FILE="/etc/hostid"
|
||||
export HOSTID1=01234567
|
||||
|
|
|
@ -57,19 +57,19 @@ default_setup_noexit $DISK
|
|||
log_must zpool set multihost=off $TESTPOOL
|
||||
|
||||
for opt in "" "-f"; do
|
||||
log_must zpool export -F $TESTPOOL
|
||||
log_must zpool export -f $TESTPOOL
|
||||
log_must import_no_activity_check $TESTPOOL $opt
|
||||
done
|
||||
|
||||
# 3. Verify multihost=off and hostids differ (no activity check)
|
||||
log_must zpool export -F $TESTPOOL
|
||||
log_must zpool export -f $TESTPOOL
|
||||
log_must mmp_clear_hostid
|
||||
log_must mmp_set_hostid $HOSTID2
|
||||
log_mustnot import_no_activity_check $TESTPOOL ""
|
||||
log_must import_no_activity_check $TESTPOOL "-f"
|
||||
|
||||
# 4. Verify multihost=off and hostid zero allowed (no activity check)
|
||||
log_must zpool export -F $TESTPOOL
|
||||
log_must zpool export -f $TESTPOOL
|
||||
log_must mmp_clear_hostid
|
||||
log_mustnot import_no_activity_check $TESTPOOL ""
|
||||
log_must import_no_activity_check $TESTPOOL "-f"
|
||||
|
@ -79,19 +79,19 @@ log_must mmp_pool_set_hostid $TESTPOOL $HOSTID1
|
|||
log_must zpool set multihost=on $TESTPOOL
|
||||
|
||||
for opt in "" "-f"; do
|
||||
log_must zpool export -F $TESTPOOL
|
||||
log_must zpool export -f $TESTPOOL
|
||||
log_must import_no_activity_check $TESTPOOL $opt
|
||||
done
|
||||
|
||||
# 6. Verify multihost=on and hostids differ (activity check)
|
||||
log_must zpool export -F $TESTPOOL
|
||||
log_must zpool export -f $TESTPOOL
|
||||
log_must mmp_clear_hostid
|
||||
log_must mmp_set_hostid $HOSTID2
|
||||
log_mustnot import_activity_check $TESTPOOL ""
|
||||
log_must import_activity_check $TESTPOOL "-f"
|
||||
|
||||
# 7. Verify mmp_write and mmp_fail are set correctly
|
||||
log_must zpool export -F $TESTPOOL
|
||||
log_must zpool export -f $TESTPOOL
|
||||
log_must verify_mmp_write_fail_present ${DISK[0]}
|
||||
|
||||
# 8. Verify multihost=on and hostid zero fails (no activity check)
|
||||
|
|
|
@ -97,15 +97,15 @@ for x in $(seq 10); do
|
|||
log_must mmp_set_hostid $HOSTID1
|
||||
log_must zpool import $TESTPOOL
|
||||
elif [ $action -eq 1 ]; then
|
||||
log_must zpool export -F $TESTPOOL
|
||||
log_must zpool export -f $TESTPOOL
|
||||
log_must zpool import $TESTPOOL
|
||||
elif [ $action -eq 2 ]; then
|
||||
log_must zpool export -F $TESTPOOL
|
||||
log_must zpool export -f $TESTPOOL
|
||||
log_must mmp_clear_hostid
|
||||
log_must mmp_set_hostid $HOSTID2
|
||||
log_must zpool import -f $TESTPOOL
|
||||
elif [ $action -eq 3 ]; then
|
||||
log_must zpool export -F $TESTPOOL
|
||||
log_must zpool export -f $TESTPOOL
|
||||
log_must set_tunable64 MULTIHOST_INTERVAL $MMP_INTERVAL_MIN
|
||||
log_must zpool import $TESTPOOL
|
||||
elif [ $action -eq 4 ]; then
|
||||
|
|
|
@ -48,6 +48,7 @@ log_must zpool checkpoint $NESTEDPOOL
|
|||
log_must truncate -s $EXPSZ $FILEDISK1
|
||||
log_must zpool online -e $NESTEDPOOL $FILEDISK1
|
||||
NEWSZ=$(zpool list -v | grep "$FILEDISK1" | awk '{print $2}')
|
||||
log_must zpool sync $NESTEDPOOL
|
||||
nested_change_state_after_checkpoint
|
||||
log_mustnot [ "$INITSZ" = "$NEWSZ" ]
|
||||
|
||||
|
|
Loading…
Reference in New Issue