summaryrefslogtreecommitdiffstats
path: root/module
diff options
context:
space:
mode:
authorDon Brady <[email protected]>2018-11-05 12:22:33 -0700
committerBrian Behlendorf <[email protected]>2018-11-05 11:22:33 -0800
commite89f1295d4faa88bb05a62c8dd5f781657db5955 (patch)
tree8e39dfe33c6849e00813e54ec95c09a24448a43a /module
parent6644e5bb6e1a6c25c5006c819abf93c7bb662e80 (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')
-rw-r--r--module/zfs/zio_inject.c67
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