diff options
author | Don Brady <[email protected]> | 2018-11-05 12:22:33 -0700 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2018-11-05 11:22:33 -0800 |
commit | e89f1295d4faa88bb05a62c8dd5f781657db5955 (patch) | |
tree | 8e39dfe33c6849e00813e54ec95c09a24448a43a /module/zfs/zio_inject.c | |
parent | 6644e5bb6e1a6c25c5006c819abf93c7bb662e80 (diff) |
Add libzutil for libzfs or libzpool consumers
Adds a libzutil for utility functions that are common to libzfs and
libzpool consumers (most of what was in libzfs_import.c). This
removes the need for utilities to link against both libzpool and
libzfs.
Reviewed-by: Matthew Ahrens <[email protected]>
Reviewed-by: Brian Behlendorf <[email protected]>
Signed-off-by: Don Brady <[email protected]>
Closes #8050
Diffstat (limited to 'module/zfs/zio_inject.c')
-rw-r--r-- | module/zfs/zio_inject.c | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/module/zfs/zio_inject.c b/module/zfs/zio_inject.c index 87d32a115..7a7401ecd 100644 --- a/module/zfs/zio_inject.c +++ b/module/zfs/zio_inject.c @@ -46,6 +46,7 @@ #include <sys/zfs_ioctl.h> #include <sys/vdev_impl.h> #include <sys/dmu_objset.h> +#include <sys/dsl_dataset.h> #include <sys/fs/zfs.h> uint32_t zio_injection_enabled = 0; @@ -659,6 +660,63 @@ zio_handle_io_delay(zio_t *zio) return (min_target); } +static int +zio_calculate_range(const char *pool, zinject_record_t *record) +{ + dsl_pool_t *dp; + dsl_dataset_t *ds; + objset_t *os = NULL; + dnode_t *dn = NULL; + int error; + + /* + * Obtain the dnode for object using pool, objset, and object + */ + error = dsl_pool_hold(pool, FTAG, &dp); + if (error) + return (error); + + error = dsl_dataset_hold_obj(dp, record->zi_objset, FTAG, &ds); + dsl_pool_rele(dp, FTAG); + if (error) + return (error); + + error = dmu_objset_from_ds(ds, &os); + dsl_dataset_rele(ds, FTAG); + if (error) + return (error); + + error = dnode_hold(os, record->zi_object, FTAG, &dn); + if (error) + return (error); + + /* + * Translate the range into block IDs + */ + if (record->zi_start != 0 || record->zi_end != -1ULL) { + record->zi_start >>= dn->dn_datablkshift; + record->zi_end >>= dn->dn_datablkshift; + } + if (record->zi_level > 0) { + if (record->zi_level >= dn->dn_nlevels) { + dnode_rele(dn, FTAG); + return (SET_ERROR(EDOM)); + } + + if (record->zi_start != 0 || record->zi_end != 0) { + int shift = dn->dn_indblkshift - SPA_BLKPTRSHIFT; + + for (int level = record->zi_level; level > 0; level--) { + record->zi_start >>= shift; + record->zi_end >>= shift; + } + } + } + + dnode_rele(dn, FTAG); + return (0); +} + /* * Create a new handler for the given record. We add it to the list, adding * a reference to the spa_t in the process. We increment zio_injection_enabled, @@ -698,6 +756,15 @@ zio_inject_fault(char *name, int flags, int *id, zinject_record_t *record) return (SET_ERROR(EINVAL)); } + /* + * If the supplied range was in bytes -- calculate the actual blkid + */ + if (flags & ZINJECT_CALC_RANGE) { + error = zio_calculate_range(name, record); + if (error != 0) + return (error); + } + if (!(flags & ZINJECT_NULL)) { /* * spa_inject_ref() will add an injection reference, which will |