1ea8dc4b6Seschrock /* 2ea8dc4b6Seschrock * CDDL HEADER START 3ea8dc4b6Seschrock * 4ea8dc4b6Seschrock * The contents of this file are subject to the terms of the 5ea8dc4b6Seschrock * Common Development and Distribution License (the "License"). 6ea8dc4b6Seschrock * You may not use this file except in compliance with the License. 7ea8dc4b6Seschrock * 8ea8dc4b6Seschrock * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9ea8dc4b6Seschrock * or http://www.opensolaris.org/os/licensing. 10ea8dc4b6Seschrock * See the License for the specific language governing permissions 11ea8dc4b6Seschrock * and limitations under the License. 12ea8dc4b6Seschrock * 13ea8dc4b6Seschrock * When distributing Covered Code, include this CDDL HEADER in each 14ea8dc4b6Seschrock * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15ea8dc4b6Seschrock * If applicable, add the following below this CDDL HEADER, with the 16ea8dc4b6Seschrock * fields enclosed by brackets "[]" replaced with your own identifying 17ea8dc4b6Seschrock * information: Portions Copyright [yyyy] [name of copyright owner] 18ea8dc4b6Seschrock * 19ea8dc4b6Seschrock * CDDL HEADER END 20ea8dc4b6Seschrock */ 21ea8dc4b6Seschrock /* 2298d1cbfeSGeorge Wilson * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 2397e81309SPrakash Surya * Copyright (c) 2012, 2015 by Delphix. All rights reserved. 24ea8dc4b6Seschrock */ 25ea8dc4b6Seschrock 26ea8dc4b6Seschrock /* 27ea8dc4b6Seschrock * ZFS fault injection 28ea8dc4b6Seschrock * 29ea8dc4b6Seschrock * To handle fault injection, we keep track of a series of zinject_record_t 30ea8dc4b6Seschrock * structures which describe which logical block(s) should be injected with a 31ea8dc4b6Seschrock * fault. These are kept in a global list. Each record corresponds to a given 32ea8dc4b6Seschrock * spa_t and maintains a special hold on the spa_t so that it cannot be deleted 33ea8dc4b6Seschrock * or exported while the injection record exists. 34ea8dc4b6Seschrock * 35ea8dc4b6Seschrock * Device level injection is done using the 'zi_guid' field. If this is set, it 36ea8dc4b6Seschrock * means that the error is destined for a particular device, not a piece of 37ea8dc4b6Seschrock * data. 38ea8dc4b6Seschrock * 39ea8dc4b6Seschrock * This is a rather poor data structure and algorithm, but we don't expect more 40ea8dc4b6Seschrock * than a few faults at any one time, so it should be sufficient for our needs. 41ea8dc4b6Seschrock */ 42ea8dc4b6Seschrock 43ea8dc4b6Seschrock #include <sys/arc.h> 44ea8dc4b6Seschrock #include <sys/zio_impl.h> 45ea8dc4b6Seschrock #include <sys/zfs_ioctl.h> 46ea8dc4b6Seschrock #include <sys/vdev_impl.h> 47b24ab676SJeff Bonwick #include <sys/dmu_objset.h> 48*d8ab6e12SDon Brady #include <sys/dsl_dataset.h> 4921bf64a7Sgw #include <sys/fs/zfs.h> 50ea8dc4b6Seschrock 51*d8ab6e12SDon Brady uint32_t zio_injection_enabled = 0; 52ea8dc4b6Seschrock 5397e81309SPrakash Surya /* 5497e81309SPrakash Surya * Data describing each zinject handler registered on the system, and 5597e81309SPrakash Surya * contains the list node linking the handler in the global zinject 5697e81309SPrakash Surya * handler list. 5797e81309SPrakash Surya */ 58ea8dc4b6Seschrock typedef struct inject_handler { 59ea8dc4b6Seschrock int zi_id; 60ea8dc4b6Seschrock spa_t *zi_spa; 61ea8dc4b6Seschrock zinject_record_t zi_record; 6297e81309SPrakash Surya uint64_t *zi_lanes; 6397e81309SPrakash Surya int zi_next_lane; 64ea8dc4b6Seschrock list_node_t zi_link; 65ea8dc4b6Seschrock } inject_handler_t; 66ea8dc4b6Seschrock 6797e81309SPrakash Surya /* 6897e81309SPrakash Surya * List of all zinject handlers registered on the system, protected by 6997e81309SPrakash Surya * the inject_lock defined below. 7097e81309SPrakash Surya */ 71ea8dc4b6Seschrock static list_t inject_handlers; 7297e81309SPrakash Surya 7397e81309SPrakash Surya /* 7497e81309SPrakash Surya * This protects insertion into, and traversal of, the inject handler 7597e81309SPrakash Surya * list defined above; as well as the inject_delay_count. Any time a 7697e81309SPrakash Surya * handler is inserted or removed from the list, this lock should be 7797e81309SPrakash Surya * taken as a RW_WRITER; and any time traversal is done over the list 7897e81309SPrakash Surya * (without modification to it) this lock should be taken as a RW_READER. 7997e81309SPrakash Surya */ 80ea8dc4b6Seschrock static krwlock_t inject_lock; 8197e81309SPrakash Surya 8297e81309SPrakash Surya /* 8397e81309SPrakash Surya * This holds the number of zinject delay handlers that have been 8497e81309SPrakash Surya * registered on the system. It is protected by the inject_lock defined 8597e81309SPrakash Surya * above. Thus modifications to this count must be a RW_WRITER of the 8697e81309SPrakash Surya * inject_lock, and reads of this count must be (at least) a RW_READER 8797e81309SPrakash Surya * of the lock. 8897e81309SPrakash Surya */ 8997e81309SPrakash Surya static int inject_delay_count = 0; 9097e81309SPrakash Surya 9197e81309SPrakash Surya /* 9297e81309SPrakash Surya * This lock is used only in zio_handle_io_delay(), refer to the comment 9397e81309SPrakash Surya * in that function for more details. 9497e81309SPrakash Surya */ 9597e81309SPrakash Surya static kmutex_t inject_delay_mtx; 9697e81309SPrakash Surya 9797e81309SPrakash Surya /* 9897e81309SPrakash Surya * Used to assign unique identifying numbers to each new zinject handler. 9997e81309SPrakash Surya */ 100ea8dc4b6Seschrock static int inject_next_id = 1; 101ea8dc4b6Seschrock 102ea8dc4b6Seschrock /* 103ea8dc4b6Seschrock * Returns true if the given record matches the I/O in progress. 104ea8dc4b6Seschrock */ 105ea8dc4b6Seschrock static boolean_t 10612a8814cSTom Caputi zio_match_handler(zbookmark_phys_t *zb, uint64_t type, int dva, 107ea8dc4b6Seschrock zinject_record_t *record, int error) 108ea8dc4b6Seschrock { 109ea8dc4b6Seschrock /* 110ea8dc4b6Seschrock * Check for a match against the MOS, which is based on type 111ea8dc4b6Seschrock */ 112b24ab676SJeff Bonwick if (zb->zb_objset == DMU_META_OBJSET && 113b24ab676SJeff Bonwick record->zi_objset == DMU_META_OBJSET && 114b24ab676SJeff Bonwick record->zi_object == DMU_META_DNODE_OBJECT) { 115ea8dc4b6Seschrock if (record->zi_type == DMU_OT_NONE || 116ea8dc4b6Seschrock type == record->zi_type) 117ea8dc4b6Seschrock return (record->zi_freq == 0 || 118ea8dc4b6Seschrock spa_get_random(100) < record->zi_freq); 119ea8dc4b6Seschrock else 120ea8dc4b6Seschrock return (B_FALSE); 121ea8dc4b6Seschrock } 122ea8dc4b6Seschrock 123ea8dc4b6Seschrock /* 124ea8dc4b6Seschrock * Check for an exact match. 125ea8dc4b6Seschrock */ 126ea8dc4b6Seschrock if (zb->zb_objset == record->zi_objset && 127ea8dc4b6Seschrock zb->zb_object == record->zi_object && 128ea8dc4b6Seschrock zb->zb_level == record->zi_level && 129ea8dc4b6Seschrock zb->zb_blkid >= record->zi_start && 130ea8dc4b6Seschrock zb->zb_blkid <= record->zi_end && 13112a8814cSTom Caputi (record->zi_dvas == 0 || (record->zi_dvas & (1ULL << dva))) && 13212a8814cSTom Caputi error == record->zi_error) { 133ea8dc4b6Seschrock return (record->zi_freq == 0 || 134ea8dc4b6Seschrock spa_get_random(100) < record->zi_freq); 13512a8814cSTom Caputi } 136ea8dc4b6Seschrock 137ea8dc4b6Seschrock return (B_FALSE); 138ea8dc4b6Seschrock } 139ea8dc4b6Seschrock 14088ecc943SGeorge Wilson /* 14188ecc943SGeorge Wilson * Panic the system when a config change happens in the function 14288ecc943SGeorge Wilson * specified by tag. 14388ecc943SGeorge Wilson */ 14488ecc943SGeorge Wilson void 1451195e687SMark J Musante zio_handle_panic_injection(spa_t *spa, char *tag, uint64_t type) 14688ecc943SGeorge Wilson { 14788ecc943SGeorge Wilson inject_handler_t *handler; 14888ecc943SGeorge Wilson 14988ecc943SGeorge Wilson rw_enter(&inject_lock, RW_READER); 15088ecc943SGeorge Wilson 15188ecc943SGeorge Wilson for (handler = list_head(&inject_handlers); handler != NULL; 15288ecc943SGeorge Wilson handler = list_next(&inject_handlers, handler)) { 15388ecc943SGeorge Wilson 15488ecc943SGeorge Wilson if (spa != handler->zi_spa) 15588ecc943SGeorge Wilson continue; 15688ecc943SGeorge Wilson 1571195e687SMark J Musante if (handler->zi_record.zi_type == type && 1581195e687SMark J Musante strcmp(tag, handler->zi_record.zi_func) == 0) 15988ecc943SGeorge Wilson panic("Panic requested in function %s\n", tag); 16088ecc943SGeorge Wilson } 16188ecc943SGeorge Wilson 16288ecc943SGeorge Wilson rw_exit(&inject_lock); 16388ecc943SGeorge Wilson } 16488ecc943SGeorge Wilson 16512a8814cSTom Caputi 16612a8814cSTom Caputi /* 16712a8814cSTom Caputi * If this is a physical I/O for a vdev child determine which DVA it is 16812a8814cSTom Caputi * for. We iterate backwards through the DVAs matching on the offset so 16912a8814cSTom Caputi * that we end up with ZI_NO_DVA (-1) if we don't find a match. 17012a8814cSTom Caputi */ 17112a8814cSTom Caputi static int 17212a8814cSTom Caputi zio_match_dva(zio_t *zio) 17312a8814cSTom Caputi { 17412a8814cSTom Caputi int i = ZI_NO_DVA; 17512a8814cSTom Caputi 17612a8814cSTom Caputi if (zio->io_bp != NULL && zio->io_vd != NULL && 17712a8814cSTom Caputi zio->io_child_type == ZIO_CHILD_VDEV) { 17812a8814cSTom Caputi for (i = BP_GET_NDVAS(zio->io_bp) - 1; i >= 0; i--) { 17912a8814cSTom Caputi dva_t *dva = &zio->io_bp->blk_dva[i]; 18012a8814cSTom Caputi uint64_t off = DVA_GET_OFFSET(dva); 18112a8814cSTom Caputi vdev_t *vd = vdev_lookup_top(zio->io_spa, 18212a8814cSTom Caputi DVA_GET_VDEV(dva)); 18312a8814cSTom Caputi 18412a8814cSTom Caputi /* Compensate for vdev label added to leaves */ 18512a8814cSTom Caputi if (zio->io_vd->vdev_ops->vdev_op_leaf) 18612a8814cSTom Caputi off += VDEV_LABEL_START_SIZE; 18712a8814cSTom Caputi 18812a8814cSTom Caputi if (zio->io_vd == vd && zio->io_offset == off) 18912a8814cSTom Caputi break; 19012a8814cSTom Caputi } 19112a8814cSTom Caputi } 19212a8814cSTom Caputi 19312a8814cSTom Caputi return (i); 19412a8814cSTom Caputi } 19512a8814cSTom Caputi 19612a8814cSTom Caputi 197eb633035STom Caputi /* 198eb633035STom Caputi * Inject a decryption failure. Decryption failures can occur in 199eb633035STom Caputi * both the ARC and the ZIO layers. 200eb633035STom Caputi */ 201eb633035STom Caputi int 202eb633035STom Caputi zio_handle_decrypt_injection(spa_t *spa, const zbookmark_phys_t *zb, 203eb633035STom Caputi uint64_t type, int error) 204eb633035STom Caputi { 205eb633035STom Caputi int ret = 0; 206eb633035STom Caputi inject_handler_t *handler; 207eb633035STom Caputi 208eb633035STom Caputi rw_enter(&inject_lock, RW_READER); 209eb633035STom Caputi 210eb633035STom Caputi for (handler = list_head(&inject_handlers); handler != NULL; 211eb633035STom Caputi handler = list_next(&inject_handlers, handler)) { 212eb633035STom Caputi 213eb633035STom Caputi if (spa != handler->zi_spa || 214eb633035STom Caputi handler->zi_record.zi_cmd != ZINJECT_DECRYPT_FAULT) 215eb633035STom Caputi continue; 216eb633035STom Caputi 217eb633035STom Caputi if (zio_match_handler((zbookmark_phys_t *)zb, type, ZI_NO_DVA, 218eb633035STom Caputi &handler->zi_record, error)) { 219eb633035STom Caputi ret = error; 220eb633035STom Caputi break; 221eb633035STom Caputi } 222eb633035STom Caputi } 223eb633035STom Caputi 224eb633035STom Caputi rw_exit(&inject_lock); 225eb633035STom Caputi return (ret); 226eb633035STom Caputi } 227eb633035STom Caputi 228ea8dc4b6Seschrock /* 229ea8dc4b6Seschrock * Determine if the I/O in question should return failure. Returns the errno 230ea8dc4b6Seschrock * to be returned to the caller. 231ea8dc4b6Seschrock */ 232ea8dc4b6Seschrock int 233ea8dc4b6Seschrock zio_handle_fault_injection(zio_t *zio, int error) 234ea8dc4b6Seschrock { 235ea8dc4b6Seschrock int ret = 0; 236ea8dc4b6Seschrock inject_handler_t *handler; 237ea8dc4b6Seschrock 238ea8dc4b6Seschrock /* 239ea8dc4b6Seschrock * Ignore I/O not associated with any logical data. 240ea8dc4b6Seschrock */ 241ea8dc4b6Seschrock if (zio->io_logical == NULL) 242ea8dc4b6Seschrock return (0); 243ea8dc4b6Seschrock 244ea8dc4b6Seschrock /* 245ea8dc4b6Seschrock * Currently, we only support fault injection on reads. 246ea8dc4b6Seschrock */ 247ea8dc4b6Seschrock if (zio->io_type != ZIO_TYPE_READ) 248ea8dc4b6Seschrock return (0); 249ea8dc4b6Seschrock 250ea8dc4b6Seschrock rw_enter(&inject_lock, RW_READER); 251ea8dc4b6Seschrock 252ea8dc4b6Seschrock for (handler = list_head(&inject_handlers); handler != NULL; 253ea8dc4b6Seschrock handler = list_next(&inject_handlers, handler)) { 254ea8dc4b6Seschrock 255283b8460SGeorge.Wilson if (zio->io_spa != handler->zi_spa || 256283b8460SGeorge.Wilson handler->zi_record.zi_cmd != ZINJECT_DATA_FAULT) 257ea8dc4b6Seschrock continue; 258ea8dc4b6Seschrock 25912a8814cSTom Caputi /* If this handler matches, return the specified error */ 260ea8dc4b6Seschrock if (zio_match_handler(&zio->io_logical->io_bookmark, 261ea8dc4b6Seschrock zio->io_bp ? BP_GET_TYPE(zio->io_bp) : DMU_OT_NONE, 26212a8814cSTom Caputi zio_match_dva(zio), &handler->zi_record, error)) { 263ea8dc4b6Seschrock ret = error; 264ea8dc4b6Seschrock break; 265ea8dc4b6Seschrock } 266ea8dc4b6Seschrock } 267ea8dc4b6Seschrock 268ea8dc4b6Seschrock rw_exit(&inject_lock); 269ea8dc4b6Seschrock 270ea8dc4b6Seschrock return (ret); 271ea8dc4b6Seschrock } 272ea8dc4b6Seschrock 27321bf64a7Sgw /* 27421bf64a7Sgw * Determine if the zio is part of a label update and has an injection 27521bf64a7Sgw * handler associated with that portion of the label. Currently, we 27621bf64a7Sgw * allow error injection in either the nvlist or the uberblock region of 27721bf64a7Sgw * of the vdev label. 27821bf64a7Sgw */ 27921bf64a7Sgw int 28021bf64a7Sgw zio_handle_label_injection(zio_t *zio, int error) 28121bf64a7Sgw { 28221bf64a7Sgw inject_handler_t *handler; 28321bf64a7Sgw vdev_t *vd = zio->io_vd; 28421bf64a7Sgw uint64_t offset = zio->io_offset; 28521bf64a7Sgw int label; 28621bf64a7Sgw int ret = 0; 28721bf64a7Sgw 2888f18d1faSGeorge Wilson if (offset >= VDEV_LABEL_START_SIZE && 28921bf64a7Sgw offset < vd->vdev_psize - VDEV_LABEL_END_SIZE) 29021bf64a7Sgw return (0); 29121bf64a7Sgw 29221bf64a7Sgw rw_enter(&inject_lock, RW_READER); 29321bf64a7Sgw 29421bf64a7Sgw for (handler = list_head(&inject_handlers); handler != NULL; 29521bf64a7Sgw handler = list_next(&inject_handlers, handler)) { 29621bf64a7Sgw uint64_t start = handler->zi_record.zi_start; 29721bf64a7Sgw uint64_t end = handler->zi_record.zi_end; 29821bf64a7Sgw 299283b8460SGeorge.Wilson if (handler->zi_record.zi_cmd != ZINJECT_LABEL_FAULT) 30021bf64a7Sgw continue; 30121bf64a7Sgw 30221bf64a7Sgw /* 30321bf64a7Sgw * The injection region is the relative offsets within a 30421bf64a7Sgw * vdev label. We must determine the label which is being 30521bf64a7Sgw * updated and adjust our region accordingly. 30621bf64a7Sgw */ 30721bf64a7Sgw label = vdev_label_number(vd->vdev_psize, offset); 30821bf64a7Sgw start = vdev_label_offset(vd->vdev_psize, label, start); 30921bf64a7Sgw end = vdev_label_offset(vd->vdev_psize, label, end); 31021bf64a7Sgw 31121bf64a7Sgw if (zio->io_vd->vdev_guid == handler->zi_record.zi_guid && 31221bf64a7Sgw (offset >= start && offset <= end)) { 31321bf64a7Sgw ret = error; 31421bf64a7Sgw break; 31521bf64a7Sgw } 31621bf64a7Sgw } 31721bf64a7Sgw rw_exit(&inject_lock); 31821bf64a7Sgw return (ret); 31921bf64a7Sgw } 32021bf64a7Sgw 32121bf64a7Sgw 322ea8dc4b6Seschrock int 3238956713aSEric Schrock zio_handle_device_injection(vdev_t *vd, zio_t *zio, int error) 324ea8dc4b6Seschrock { 325ea8dc4b6Seschrock inject_handler_t *handler; 326ea8dc4b6Seschrock int ret = 0; 327ea8dc4b6Seschrock 3288f18d1faSGeorge Wilson /* 3298f18d1faSGeorge Wilson * We skip over faults in the labels unless it's during 3308f18d1faSGeorge Wilson * device open (i.e. zio == NULL). 3318f18d1faSGeorge Wilson */ 3328f18d1faSGeorge Wilson if (zio != NULL) { 3338f18d1faSGeorge Wilson uint64_t offset = zio->io_offset; 3348f18d1faSGeorge Wilson 3358f18d1faSGeorge Wilson if (offset < VDEV_LABEL_START_SIZE || 3368f18d1faSGeorge Wilson offset >= vd->vdev_psize - VDEV_LABEL_END_SIZE) 3373c708518SMark J Musante return (0); 3388f18d1faSGeorge Wilson } 3398f18d1faSGeorge Wilson 340ea8dc4b6Seschrock rw_enter(&inject_lock, RW_READER); 341ea8dc4b6Seschrock 342ea8dc4b6Seschrock for (handler = list_head(&inject_handlers); handler != NULL; 343ea8dc4b6Seschrock handler = list_next(&inject_handlers, handler)) { 344ea8dc4b6Seschrock 345283b8460SGeorge.Wilson if (handler->zi_record.zi_cmd != ZINJECT_DEVICE_FAULT) 34621bf64a7Sgw continue; 34721bf64a7Sgw 348ea8dc4b6Seschrock if (vd->vdev_guid == handler->zi_record.zi_guid) { 3498956713aSEric Schrock if (handler->zi_record.zi_failfast && 3508956713aSEric Schrock (zio == NULL || (zio->io_flags & 3518956713aSEric Schrock (ZIO_FLAG_IO_RETRY | ZIO_FLAG_TRYHARD)))) { 3528956713aSEric Schrock continue; 3538956713aSEric Schrock } 3548956713aSEric Schrock 3558f18d1faSGeorge Wilson /* Handle type specific I/O failures */ 3568f18d1faSGeorge Wilson if (zio != NULL && 3578f18d1faSGeorge Wilson handler->zi_record.zi_iotype != ZIO_TYPES && 3588f18d1faSGeorge Wilson handler->zi_record.zi_iotype != zio->io_type) 3598f18d1faSGeorge Wilson continue; 3608f18d1faSGeorge Wilson 361ea8dc4b6Seschrock if (handler->zi_record.zi_error == error) { 362ea8dc4b6Seschrock /* 363ea8dc4b6Seschrock * For a failed open, pretend like the device 364ea8dc4b6Seschrock * has gone away. 365ea8dc4b6Seschrock */ 366ea8dc4b6Seschrock if (error == ENXIO) 367ea8dc4b6Seschrock vd->vdev_stat.vs_aux = 368ea8dc4b6Seschrock VDEV_AUX_OPEN_FAILED; 36998d1cbfeSGeorge Wilson 37098d1cbfeSGeorge Wilson /* 37198d1cbfeSGeorge Wilson * Treat these errors as if they had been 37298d1cbfeSGeorge Wilson * retried so that all the appropriate stats 37398d1cbfeSGeorge Wilson * and FMA events are generated. 37498d1cbfeSGeorge Wilson */ 37598d1cbfeSGeorge Wilson if (!handler->zi_record.zi_failfast && 37698d1cbfeSGeorge Wilson zio != NULL) 37798d1cbfeSGeorge Wilson zio->io_flags |= ZIO_FLAG_IO_RETRY; 37898d1cbfeSGeorge Wilson 379ea8dc4b6Seschrock ret = error; 380ea8dc4b6Seschrock break; 381ea8dc4b6Seschrock } 382ea8dc4b6Seschrock if (handler->zi_record.zi_error == ENXIO) { 383be6fd75aSMatthew Ahrens ret = SET_ERROR(EIO); 384ea8dc4b6Seschrock break; 385ea8dc4b6Seschrock } 386ea8dc4b6Seschrock } 387ea8dc4b6Seschrock } 388ea8dc4b6Seschrock 389ea8dc4b6Seschrock rw_exit(&inject_lock); 390ea8dc4b6Seschrock 391ea8dc4b6Seschrock return (ret); 392ea8dc4b6Seschrock } 393ea8dc4b6Seschrock 394468c413aSTim Haley /* 395468c413aSTim Haley * Simulate hardware that ignores cache flushes. For requested number 396468c413aSTim Haley * of seconds nix the actual writing to disk. 397468c413aSTim Haley */ 398468c413aSTim Haley void 399468c413aSTim Haley zio_handle_ignored_writes(zio_t *zio) 400468c413aSTim Haley { 401468c413aSTim Haley inject_handler_t *handler; 402468c413aSTim Haley 403468c413aSTim Haley rw_enter(&inject_lock, RW_READER); 404468c413aSTim Haley 405468c413aSTim Haley for (handler = list_head(&inject_handlers); handler != NULL; 406468c413aSTim Haley handler = list_next(&inject_handlers, handler)) { 407468c413aSTim Haley 408468c413aSTim Haley /* Ignore errors not destined for this pool */ 409283b8460SGeorge.Wilson if (zio->io_spa != handler->zi_spa || 410283b8460SGeorge.Wilson handler->zi_record.zi_cmd != ZINJECT_IGNORED_WRITES) 411468c413aSTim Haley continue; 412468c413aSTim Haley 413468c413aSTim Haley /* 414468c413aSTim Haley * Positive duration implies # of seconds, negative 415468c413aSTim Haley * a number of txgs 416468c413aSTim Haley */ 417468c413aSTim Haley if (handler->zi_record.zi_timer == 0) { 418468c413aSTim Haley if (handler->zi_record.zi_duration > 0) 419d3d50737SRafael Vanoni handler->zi_record.zi_timer = ddi_get_lbolt64(); 420468c413aSTim Haley else 421468c413aSTim Haley handler->zi_record.zi_timer = zio->io_txg; 422468c413aSTim Haley } 423a33cae98STim Haley 424a33cae98STim Haley /* Have a "problem" writing 60% of the time */ 425a33cae98STim Haley if (spa_get_random(100) < 60) 426a33cae98STim Haley zio->io_pipeline &= ~ZIO_VDEV_IO_STAGES; 427468c413aSTim Haley break; 428468c413aSTim Haley } 429468c413aSTim Haley 430468c413aSTim Haley rw_exit(&inject_lock); 431468c413aSTim Haley } 432468c413aSTim Haley 433468c413aSTim Haley void 434468c413aSTim Haley spa_handle_ignored_writes(spa_t *spa) 435468c413aSTim Haley { 436468c413aSTim Haley inject_handler_t *handler; 437468c413aSTim Haley 438468c413aSTim Haley if (zio_injection_enabled == 0) 439468c413aSTim Haley return; 440468c413aSTim Haley 441468c413aSTim Haley rw_enter(&inject_lock, RW_READER); 442468c413aSTim Haley 443468c413aSTim Haley for (handler = list_head(&inject_handlers); handler != NULL; 444468c413aSTim Haley handler = list_next(&inject_handlers, handler)) { 445468c413aSTim Haley 446283b8460SGeorge.Wilson if (spa != handler->zi_spa || 447283b8460SGeorge.Wilson handler->zi_record.zi_cmd != ZINJECT_IGNORED_WRITES) 448468c413aSTim Haley continue; 449468c413aSTim Haley 450468c413aSTim Haley if (handler->zi_record.zi_duration > 0) { 451468c413aSTim Haley VERIFY(handler->zi_record.zi_timer == 0 || 452468c413aSTim Haley handler->zi_record.zi_timer + 453d3d50737SRafael Vanoni handler->zi_record.zi_duration * hz > 454d3d50737SRafael Vanoni ddi_get_lbolt64()); 455468c413aSTim Haley } else { 456468c413aSTim Haley /* duration is negative so the subtraction here adds */ 457468c413aSTim Haley VERIFY(handler->zi_record.zi_timer == 0 || 458468c413aSTim Haley handler->zi_record.zi_timer - 459468c413aSTim Haley handler->zi_record.zi_duration >= 460b24ab676SJeff Bonwick spa_syncing_txg(spa)); 461468c413aSTim Haley } 462468c413aSTim Haley } 463468c413aSTim Haley 464468c413aSTim Haley rw_exit(&inject_lock); 465468c413aSTim Haley } 466468c413aSTim Haley 46797e81309SPrakash Surya hrtime_t 468283b8460SGeorge.Wilson zio_handle_io_delay(zio_t *zio) 469283b8460SGeorge.Wilson { 470283b8460SGeorge.Wilson vdev_t *vd = zio->io_vd; 47197e81309SPrakash Surya inject_handler_t *min_handler = NULL; 47297e81309SPrakash Surya hrtime_t min_target = 0; 473283b8460SGeorge.Wilson 474283b8460SGeorge.Wilson rw_enter(&inject_lock, RW_READER); 475283b8460SGeorge.Wilson 47697e81309SPrakash Surya /* 47797e81309SPrakash Surya * inject_delay_count is a subset of zio_injection_enabled that 47897e81309SPrakash Surya * is only incremented for delay handlers. These checks are 47997e81309SPrakash Surya * mainly added to remind the reader why we're not explicitly 48097e81309SPrakash Surya * checking zio_injection_enabled like the other functions. 48197e81309SPrakash Surya */ 48297e81309SPrakash Surya IMPLY(inject_delay_count > 0, zio_injection_enabled > 0); 48397e81309SPrakash Surya IMPLY(zio_injection_enabled == 0, inject_delay_count == 0); 48497e81309SPrakash Surya 48597e81309SPrakash Surya /* 48697e81309SPrakash Surya * If there aren't any inject delay handlers registered, then we 48797e81309SPrakash Surya * can short circuit and simply return 0 here. A value of zero 48897e81309SPrakash Surya * informs zio_delay_interrupt() that this request should not be 48997e81309SPrakash Surya * delayed. This short circuit keeps us from acquiring the 49097e81309SPrakash Surya * inject_delay_mutex unnecessarily. 49197e81309SPrakash Surya */ 49297e81309SPrakash Surya if (inject_delay_count == 0) { 49397e81309SPrakash Surya rw_exit(&inject_lock); 49497e81309SPrakash Surya return (0); 49597e81309SPrakash Surya } 49697e81309SPrakash Surya 49797e81309SPrakash Surya /* 49897e81309SPrakash Surya * Each inject handler has a number of "lanes" associated with 49997e81309SPrakash Surya * it. Each lane is able to handle requests independently of one 50097e81309SPrakash Surya * another, and at a latency defined by the inject handler 50197e81309SPrakash Surya * record's zi_timer field. Thus if a handler in configured with 50297e81309SPrakash Surya * a single lane with a 10ms latency, it will delay requests 50397e81309SPrakash Surya * such that only a single request is completed every 10ms. So, 50497e81309SPrakash Surya * if more than one request is attempted per each 10ms interval, 50597e81309SPrakash Surya * the average latency of the requests will be greater than 50697e81309SPrakash Surya * 10ms; but if only a single request is submitted each 10ms 50797e81309SPrakash Surya * interval the average latency will be 10ms. 50897e81309SPrakash Surya * 50997e81309SPrakash Surya * We need to acquire this mutex to prevent multiple concurrent 51097e81309SPrakash Surya * threads being assigned to the same lane of a given inject 51197e81309SPrakash Surya * handler. The mutex allows us to perform the following two 51297e81309SPrakash Surya * operations atomically: 51397e81309SPrakash Surya * 51497e81309SPrakash Surya * 1. determine the minimum handler and minimum target 51597e81309SPrakash Surya * value of all the possible handlers 51697e81309SPrakash Surya * 2. update that minimum handler's lane array 51797e81309SPrakash Surya * 51897e81309SPrakash Surya * Without atomicity, two (or more) threads could pick the same 51997e81309SPrakash Surya * lane in step (1), and then conflict with each other in step 52097e81309SPrakash Surya * (2). This could allow a single lane handler to process 52197e81309SPrakash Surya * multiple requests simultaneously, which shouldn't be possible. 52297e81309SPrakash Surya */ 52397e81309SPrakash Surya mutex_enter(&inject_delay_mtx); 524283b8460SGeorge.Wilson 52597e81309SPrakash Surya for (inject_handler_t *handler = list_head(&inject_handlers); 52697e81309SPrakash Surya handler != NULL; handler = list_next(&inject_handlers, handler)) { 527283b8460SGeorge.Wilson if (handler->zi_record.zi_cmd != ZINJECT_DELAY_IO) 528283b8460SGeorge.Wilson continue; 529283b8460SGeorge.Wilson 53097e81309SPrakash Surya if (vd->vdev_guid != handler->zi_record.zi_guid) 53197e81309SPrakash Surya continue; 53297e81309SPrakash Surya 53397e81309SPrakash Surya /* 53497e81309SPrakash Surya * Defensive; should never happen as the array allocation 53597e81309SPrakash Surya * occurs prior to inserting this handler on the list. 53697e81309SPrakash Surya */ 53797e81309SPrakash Surya ASSERT3P(handler->zi_lanes, !=, NULL); 53897e81309SPrakash Surya 53997e81309SPrakash Surya /* 54097e81309SPrakash Surya * This should never happen, the zinject command should 54197e81309SPrakash Surya * prevent a user from setting an IO delay with zero lanes. 54297e81309SPrakash Surya */ 54397e81309SPrakash Surya ASSERT3U(handler->zi_record.zi_nlanes, !=, 0); 54497e81309SPrakash Surya 54597e81309SPrakash Surya ASSERT3U(handler->zi_record.zi_nlanes, >, 54697e81309SPrakash Surya handler->zi_next_lane); 54797e81309SPrakash Surya 54897e81309SPrakash Surya /* 54997e81309SPrakash Surya * We want to issue this IO to the lane that will become 55097e81309SPrakash Surya * idle the soonest, so we compare the soonest this 55197e81309SPrakash Surya * specific handler can complete the IO with all other 55297e81309SPrakash Surya * handlers, to find the lowest value of all possible 55397e81309SPrakash Surya * lanes. We then use this lane to submit the request. 55497e81309SPrakash Surya * 55597e81309SPrakash Surya * Since each handler has a constant value for its 55697e81309SPrakash Surya * delay, we can just use the "next" lane for that 55797e81309SPrakash Surya * handler; as it will always be the lane with the 55897e81309SPrakash Surya * lowest value for that particular handler (i.e. the 55997e81309SPrakash Surya * lane that will become idle the soonest). This saves a 56097e81309SPrakash Surya * scan of each handler's lanes array. 56197e81309SPrakash Surya * 56297e81309SPrakash Surya * There's two cases to consider when determining when 56397e81309SPrakash Surya * this specific IO request should complete. If this 56497e81309SPrakash Surya * lane is idle, we want to "submit" the request now so 56597e81309SPrakash Surya * it will complete after zi_timer milliseconds. Thus, 56697e81309SPrakash Surya * we set the target to now + zi_timer. 56797e81309SPrakash Surya * 56897e81309SPrakash Surya * If the lane is busy, we want this request to complete 56997e81309SPrakash Surya * zi_timer milliseconds after the lane becomes idle. 57097e81309SPrakash Surya * Since the 'zi_lanes' array holds the time at which 57197e81309SPrakash Surya * each lane will become idle, we use that value to 57297e81309SPrakash Surya * determine when this request should complete. 57397e81309SPrakash Surya */ 57497e81309SPrakash Surya hrtime_t idle = handler->zi_record.zi_timer + gethrtime(); 57597e81309SPrakash Surya hrtime_t busy = handler->zi_record.zi_timer + 57697e81309SPrakash Surya handler->zi_lanes[handler->zi_next_lane]; 57797e81309SPrakash Surya hrtime_t target = MAX(idle, busy); 57897e81309SPrakash Surya 57997e81309SPrakash Surya if (min_handler == NULL) { 58097e81309SPrakash Surya min_handler = handler; 58197e81309SPrakash Surya min_target = target; 58297e81309SPrakash Surya continue; 583283b8460SGeorge.Wilson } 584283b8460SGeorge.Wilson 58597e81309SPrakash Surya ASSERT3P(min_handler, !=, NULL); 58697e81309SPrakash Surya ASSERT3U(min_target, !=, 0); 58797e81309SPrakash Surya 58897e81309SPrakash Surya /* 58997e81309SPrakash Surya * We don't yet increment the "next lane" variable since 59097e81309SPrakash Surya * we still might find a lower value lane in another 59197e81309SPrakash Surya * handler during any remaining iterations. Once we're 59297e81309SPrakash Surya * sure we've selected the absolute minimum, we'll claim 59397e81309SPrakash Surya * the lane and increment the handler's "next lane" 59497e81309SPrakash Surya * field below. 59597e81309SPrakash Surya */ 59697e81309SPrakash Surya 59797e81309SPrakash Surya if (target < min_target) { 59897e81309SPrakash Surya min_handler = handler; 59997e81309SPrakash Surya min_target = target; 60097e81309SPrakash Surya } 601283b8460SGeorge.Wilson } 60297e81309SPrakash Surya 60397e81309SPrakash Surya /* 60497e81309SPrakash Surya * 'min_handler' will be NULL if no IO delays are registered for 60597e81309SPrakash Surya * this vdev, otherwise it will point to the handler containing 60697e81309SPrakash Surya * the lane that will become idle the soonest. 60797e81309SPrakash Surya */ 60897e81309SPrakash Surya if (min_handler != NULL) { 60997e81309SPrakash Surya ASSERT3U(min_target, !=, 0); 61097e81309SPrakash Surya min_handler->zi_lanes[min_handler->zi_next_lane] = min_target; 61197e81309SPrakash Surya 61297e81309SPrakash Surya /* 61397e81309SPrakash Surya * If we've used all possible lanes for this handler, 61497e81309SPrakash Surya * loop back and start using the first lane again; 61597e81309SPrakash Surya * otherwise, just increment the lane index. 61697e81309SPrakash Surya */ 61797e81309SPrakash Surya min_handler->zi_next_lane = (min_handler->zi_next_lane + 1) % 61897e81309SPrakash Surya min_handler->zi_record.zi_nlanes; 61997e81309SPrakash Surya } 62097e81309SPrakash Surya 62197e81309SPrakash Surya mutex_exit(&inject_delay_mtx); 622283b8460SGeorge.Wilson rw_exit(&inject_lock); 62397e81309SPrakash Surya 62497e81309SPrakash Surya return (min_target); 625283b8460SGeorge.Wilson } 626283b8460SGeorge.Wilson 627*d8ab6e12SDon Brady static int 628*d8ab6e12SDon Brady zio_calculate_range(const char *pool, zinject_record_t *record) 629*d8ab6e12SDon Brady { 630*d8ab6e12SDon Brady dsl_pool_t *dp; 631*d8ab6e12SDon Brady dsl_dataset_t *ds; 632*d8ab6e12SDon Brady objset_t *os = NULL; 633*d8ab6e12SDon Brady dnode_t *dn = NULL; 634*d8ab6e12SDon Brady int error; 635*d8ab6e12SDon Brady 636*d8ab6e12SDon Brady /* 637*d8ab6e12SDon Brady * Obtain the dnode for object using pool, objset, and object 638*d8ab6e12SDon Brady */ 639*d8ab6e12SDon Brady error = dsl_pool_hold(pool, FTAG, &dp); 640*d8ab6e12SDon Brady if (error) 641*d8ab6e12SDon Brady return (error); 642*d8ab6e12SDon Brady 643*d8ab6e12SDon Brady error = dsl_dataset_hold_obj(dp, record->zi_objset, FTAG, &ds); 644*d8ab6e12SDon Brady dsl_pool_rele(dp, FTAG); 645*d8ab6e12SDon Brady if (error) 646*d8ab6e12SDon Brady return (error); 647*d8ab6e12SDon Brady 648*d8ab6e12SDon Brady error = dmu_objset_from_ds(ds, &os); 649*d8ab6e12SDon Brady dsl_dataset_rele(ds, FTAG); 650*d8ab6e12SDon Brady if (error) 651*d8ab6e12SDon Brady return (error); 652*d8ab6e12SDon Brady 653*d8ab6e12SDon Brady error = dnode_hold(os, record->zi_object, FTAG, &dn); 654*d8ab6e12SDon Brady if (error) 655*d8ab6e12SDon Brady return (error); 656*d8ab6e12SDon Brady 657*d8ab6e12SDon Brady /* 658*d8ab6e12SDon Brady * Translate the range into block IDs 659*d8ab6e12SDon Brady */ 660*d8ab6e12SDon Brady if (record->zi_start != 0 || record->zi_end != -1ULL) { 661*d8ab6e12SDon Brady record->zi_start >>= dn->dn_datablkshift; 662*d8ab6e12SDon Brady record->zi_end >>= dn->dn_datablkshift; 663*d8ab6e12SDon Brady } 664*d8ab6e12SDon Brady if (record->zi_level > 0) { 665*d8ab6e12SDon Brady if (record->zi_level >= dn->dn_nlevels) { 666*d8ab6e12SDon Brady dnode_rele(dn, FTAG); 667*d8ab6e12SDon Brady return (SET_ERROR(EDOM)); 668*d8ab6e12SDon Brady } 669*d8ab6e12SDon Brady 670*d8ab6e12SDon Brady if (record->zi_start != 0 || record->zi_end != 0) { 671*d8ab6e12SDon Brady int shift = dn->dn_indblkshift - SPA_BLKPTRSHIFT; 672*d8ab6e12SDon Brady 673*d8ab6e12SDon Brady for (int level = record->zi_level; level > 0; level--) { 674*d8ab6e12SDon Brady record->zi_start >>= shift; 675*d8ab6e12SDon Brady record->zi_end >>= shift; 676*d8ab6e12SDon Brady } 677*d8ab6e12SDon Brady } 678*d8ab6e12SDon Brady } 679*d8ab6e12SDon Brady 680*d8ab6e12SDon Brady dnode_rele(dn, FTAG); 681*d8ab6e12SDon Brady return (0); 682*d8ab6e12SDon Brady } 683*d8ab6e12SDon Brady 684ea8dc4b6Seschrock /* 685ea8dc4b6Seschrock * Create a new handler for the given record. We add it to the list, adding 686ea8dc4b6Seschrock * a reference to the spa_t in the process. We increment zio_injection_enabled, 687ea8dc4b6Seschrock * which is the switch to trigger all fault injection. 688ea8dc4b6Seschrock */ 689ea8dc4b6Seschrock int 690ea8dc4b6Seschrock zio_inject_fault(char *name, int flags, int *id, zinject_record_t *record) 691ea8dc4b6Seschrock { 692ea8dc4b6Seschrock inject_handler_t *handler; 693ea8dc4b6Seschrock int error; 694ea8dc4b6Seschrock spa_t *spa; 695ea8dc4b6Seschrock 696ea8dc4b6Seschrock /* 697ea8dc4b6Seschrock * If this is pool-wide metadata, make sure we unload the corresponding 698ea8dc4b6Seschrock * spa_t, so that the next attempt to load it will trigger the fault. 699ea8dc4b6Seschrock * We call spa_reset() to unload the pool appropriately. 700ea8dc4b6Seschrock */ 701ea8dc4b6Seschrock if (flags & ZINJECT_UNLOAD_SPA) 702ea8dc4b6Seschrock if ((error = spa_reset(name)) != 0) 703ea8dc4b6Seschrock return (error); 704ea8dc4b6Seschrock 70597e81309SPrakash Surya if (record->zi_cmd == ZINJECT_DELAY_IO) { 70697e81309SPrakash Surya /* 70797e81309SPrakash Surya * A value of zero for the number of lanes or for the 70897e81309SPrakash Surya * delay time doesn't make sense. 70997e81309SPrakash Surya */ 71097e81309SPrakash Surya if (record->zi_timer == 0 || record->zi_nlanes == 0) 71197e81309SPrakash Surya return (SET_ERROR(EINVAL)); 71297e81309SPrakash Surya 71397e81309SPrakash Surya /* 71497e81309SPrakash Surya * The number of lanes is directly mapped to the size of 71597e81309SPrakash Surya * an array used by the handler. Thus, to ensure the 71697e81309SPrakash Surya * user doesn't trigger an allocation that's "too large" 71797e81309SPrakash Surya * we cap the number of lanes here. 71897e81309SPrakash Surya */ 71997e81309SPrakash Surya if (record->zi_nlanes >= UINT16_MAX) 72097e81309SPrakash Surya return (SET_ERROR(EINVAL)); 72197e81309SPrakash Surya } 72297e81309SPrakash Surya 723*d8ab6e12SDon Brady /* 724*d8ab6e12SDon Brady * If the supplied range was in bytes -- calculate the actual blkid 725*d8ab6e12SDon Brady */ 726*d8ab6e12SDon Brady if (flags & ZINJECT_CALC_RANGE) { 727*d8ab6e12SDon Brady error = zio_calculate_range(name, record); 728*d8ab6e12SDon Brady if (error != 0) 729*d8ab6e12SDon Brady return (error); 730*d8ab6e12SDon Brady } 731*d8ab6e12SDon Brady 732ea8dc4b6Seschrock if (!(flags & ZINJECT_NULL)) { 733ea8dc4b6Seschrock /* 734ea8dc4b6Seschrock * spa_inject_ref() will add an injection reference, which will 735ea8dc4b6Seschrock * prevent the pool from being removed from the namespace while 736ea8dc4b6Seschrock * still allowing it to be unloaded. 737ea8dc4b6Seschrock */ 738ea8dc4b6Seschrock if ((spa = spa_inject_addref(name)) == NULL) 739be6fd75aSMatthew Ahrens return (SET_ERROR(ENOENT)); 740ea8dc4b6Seschrock 741ea8dc4b6Seschrock handler = kmem_alloc(sizeof (inject_handler_t), KM_SLEEP); 742ea8dc4b6Seschrock 74397e81309SPrakash Surya handler->zi_spa = spa; 74497e81309SPrakash Surya handler->zi_record = *record; 74597e81309SPrakash Surya 74697e81309SPrakash Surya if (handler->zi_record.zi_cmd == ZINJECT_DELAY_IO) { 74797e81309SPrakash Surya handler->zi_lanes = kmem_zalloc( 74897e81309SPrakash Surya sizeof (*handler->zi_lanes) * 74997e81309SPrakash Surya handler->zi_record.zi_nlanes, KM_SLEEP); 75097e81309SPrakash Surya handler->zi_next_lane = 0; 75197e81309SPrakash Surya } else { 75297e81309SPrakash Surya handler->zi_lanes = NULL; 75397e81309SPrakash Surya handler->zi_next_lane = 0; 75497e81309SPrakash Surya } 75597e81309SPrakash Surya 756ea8dc4b6Seschrock rw_enter(&inject_lock, RW_WRITER); 757ea8dc4b6Seschrock 75897e81309SPrakash Surya /* 75997e81309SPrakash Surya * We can't move this increment into the conditional 76097e81309SPrakash Surya * above because we need to hold the RW_WRITER lock of 76197e81309SPrakash Surya * inject_lock, and we don't want to hold that while 76297e81309SPrakash Surya * allocating the handler's zi_lanes array. 76397e81309SPrakash Surya */ 76497e81309SPrakash Surya if (handler->zi_record.zi_cmd == ZINJECT_DELAY_IO) { 76597e81309SPrakash Surya ASSERT3S(inject_delay_count, >=, 0); 76697e81309SPrakash Surya inject_delay_count++; 76797e81309SPrakash Surya ASSERT3S(inject_delay_count, >, 0); 76897e81309SPrakash Surya } 76997e81309SPrakash Surya 770ea8dc4b6Seschrock *id = handler->zi_id = inject_next_id++; 771ea8dc4b6Seschrock list_insert_tail(&inject_handlers, handler); 7721a5e258fSJosef 'Jeff' Sipek atomic_inc_32(&zio_injection_enabled); 773ea8dc4b6Seschrock 774ea8dc4b6Seschrock rw_exit(&inject_lock); 775ea8dc4b6Seschrock } 776ea8dc4b6Seschrock 777ea8dc4b6Seschrock /* 778ea8dc4b6Seschrock * Flush the ARC, so that any attempts to read this data will end up 779ea8dc4b6Seschrock * going to the ZIO layer. Note that this is a little overkill, but 780ea8dc4b6Seschrock * we don't have the necessary ARC interfaces to do anything else, and 781ea8dc4b6Seschrock * fault injection isn't a performance critical path. 782ea8dc4b6Seschrock */ 783ea8dc4b6Seschrock if (flags & ZINJECT_FLUSH_ARC) 784244781f1SPrakash Surya /* 785244781f1SPrakash Surya * We must use FALSE to ensure arc_flush returns, since 786244781f1SPrakash Surya * we're not preventing concurrent ARC insertions. 787244781f1SPrakash Surya */ 788244781f1SPrakash Surya arc_flush(NULL, FALSE); 789ea8dc4b6Seschrock 790ea8dc4b6Seschrock return (0); 791ea8dc4b6Seschrock } 792ea8dc4b6Seschrock 793ea8dc4b6Seschrock /* 794ea8dc4b6Seschrock * Returns the next record with an ID greater than that supplied to the 795ea8dc4b6Seschrock * function. Used to iterate over all handlers in the system. 796ea8dc4b6Seschrock */ 797ea8dc4b6Seschrock int 798ea8dc4b6Seschrock zio_inject_list_next(int *id, char *name, size_t buflen, 799ea8dc4b6Seschrock zinject_record_t *record) 800ea8dc4b6Seschrock { 801ea8dc4b6Seschrock inject_handler_t *handler; 802ea8dc4b6Seschrock int ret; 803ea8dc4b6Seschrock 804ea8dc4b6Seschrock mutex_enter(&spa_namespace_lock); 805ea8dc4b6Seschrock rw_enter(&inject_lock, RW_READER); 806ea8dc4b6Seschrock 807ea8dc4b6Seschrock for (handler = list_head(&inject_handlers); handler != NULL; 808ea8dc4b6Seschrock handler = list_next(&inject_handlers, handler)) 809ea8dc4b6Seschrock if (handler->zi_id > *id) 810ea8dc4b6Seschrock break; 811ea8dc4b6Seschrock 812ea8dc4b6Seschrock if (handler) { 813ea8dc4b6Seschrock *record = handler->zi_record; 814ea8dc4b6Seschrock *id = handler->zi_id; 815ea8dc4b6Seschrock (void) strncpy(name, spa_name(handler->zi_spa), buflen); 816ea8dc4b6Seschrock ret = 0; 817ea8dc4b6Seschrock } else { 818be6fd75aSMatthew Ahrens ret = SET_ERROR(ENOENT); 819ea8dc4b6Seschrock } 820ea8dc4b6Seschrock 821ea8dc4b6Seschrock rw_exit(&inject_lock); 822ea8dc4b6Seschrock mutex_exit(&spa_namespace_lock); 823ea8dc4b6Seschrock 824ea8dc4b6Seschrock return (ret); 825ea8dc4b6Seschrock } 826ea8dc4b6Seschrock 827ea8dc4b6Seschrock /* 828ea8dc4b6Seschrock * Clear the fault handler with the given identifier, or return ENOENT if none 829ea8dc4b6Seschrock * exists. 830ea8dc4b6Seschrock */ 831ea8dc4b6Seschrock int 832ea8dc4b6Seschrock zio_clear_fault(int id) 833ea8dc4b6Seschrock { 834ea8dc4b6Seschrock inject_handler_t *handler; 835ea8dc4b6Seschrock 836ea8dc4b6Seschrock rw_enter(&inject_lock, RW_WRITER); 837ea8dc4b6Seschrock 838ea8dc4b6Seschrock for (handler = list_head(&inject_handlers); handler != NULL; 839ea8dc4b6Seschrock handler = list_next(&inject_handlers, handler)) 840ea8dc4b6Seschrock if (handler->zi_id == id) 841ea8dc4b6Seschrock break; 842ea8dc4b6Seschrock 843ea8dc4b6Seschrock if (handler == NULL) { 844679b018dSMark J Musante rw_exit(&inject_lock); 845be6fd75aSMatthew Ahrens return (SET_ERROR(ENOENT)); 846ea8dc4b6Seschrock } 847ea8dc4b6Seschrock 84897e81309SPrakash Surya if (handler->zi_record.zi_cmd == ZINJECT_DELAY_IO) { 84997e81309SPrakash Surya ASSERT3S(inject_delay_count, >, 0); 85097e81309SPrakash Surya inject_delay_count--; 85197e81309SPrakash Surya ASSERT3S(inject_delay_count, >=, 0); 85297e81309SPrakash Surya } 85397e81309SPrakash Surya 854679b018dSMark J Musante list_remove(&inject_handlers, handler); 855ea8dc4b6Seschrock rw_exit(&inject_lock); 856ea8dc4b6Seschrock 85797e81309SPrakash Surya if (handler->zi_record.zi_cmd == ZINJECT_DELAY_IO) { 85897e81309SPrakash Surya ASSERT3P(handler->zi_lanes, !=, NULL); 85997e81309SPrakash Surya kmem_free(handler->zi_lanes, sizeof (*handler->zi_lanes) * 86097e81309SPrakash Surya handler->zi_record.zi_nlanes); 86197e81309SPrakash Surya } else { 86297e81309SPrakash Surya ASSERT3P(handler->zi_lanes, ==, NULL); 86397e81309SPrakash Surya } 86497e81309SPrakash Surya 865679b018dSMark J Musante spa_inject_delref(handler->zi_spa); 866679b018dSMark J Musante kmem_free(handler, sizeof (inject_handler_t)); 8671a5e258fSJosef 'Jeff' Sipek atomic_dec_32(&zio_injection_enabled); 868679b018dSMark J Musante 869679b018dSMark J Musante return (0); 870ea8dc4b6Seschrock } 871ea8dc4b6Seschrock 872ea8dc4b6Seschrock void 873ea8dc4b6Seschrock zio_inject_init(void) 874ea8dc4b6Seschrock { 8759b3f6b42SEric Kustarz rw_init(&inject_lock, NULL, RW_DEFAULT, NULL); 87697e81309SPrakash Surya mutex_init(&inject_delay_mtx, NULL, MUTEX_DEFAULT, NULL); 877ea8dc4b6Seschrock list_create(&inject_handlers, sizeof (inject_handler_t), 878ea8dc4b6Seschrock offsetof(inject_handler_t, zi_link)); 879ea8dc4b6Seschrock } 880ea8dc4b6Seschrock 881ea8dc4b6Seschrock void 882ea8dc4b6Seschrock zio_inject_fini(void) 883ea8dc4b6Seschrock { 884ea8dc4b6Seschrock list_destroy(&inject_handlers); 88597e81309SPrakash Surya mutex_destroy(&inject_delay_mtx); 8869b3f6b42SEric Kustarz rw_destroy(&inject_lock); 887ea8dc4b6Seschrock } 888