11544Seschrock /* 21544Seschrock * CDDL HEADER START 31544Seschrock * 41544Seschrock * The contents of this file are subject to the terms of the 51544Seschrock * Common Development and Distribution License (the "License"). 61544Seschrock * You may not use this file except in compliance with the License. 71544Seschrock * 81544Seschrock * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 91544Seschrock * or http://www.opensolaris.org/os/licensing. 101544Seschrock * See the License for the specific language governing permissions 111544Seschrock * and limitations under the License. 121544Seschrock * 131544Seschrock * When distributing Covered Code, include this CDDL HEADER in each 141544Seschrock * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 151544Seschrock * If applicable, add the following below this CDDL HEADER, with the 161544Seschrock * fields enclosed by brackets "[]" replaced with your own identifying 171544Seschrock * information: Portions Copyright [yyyy] [name of copyright owner] 181544Seschrock * 191544Seschrock * CDDL HEADER END 201544Seschrock */ 211544Seschrock /* 22*12247SGeorge.Wilson@Sun.COM * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 231544Seschrock */ 241544Seschrock 251544Seschrock /* 261544Seschrock * ZFS fault injection 271544Seschrock * 281544Seschrock * To handle fault injection, we keep track of a series of zinject_record_t 291544Seschrock * structures which describe which logical block(s) should be injected with a 301544Seschrock * fault. These are kept in a global list. Each record corresponds to a given 311544Seschrock * spa_t and maintains a special hold on the spa_t so that it cannot be deleted 321544Seschrock * or exported while the injection record exists. 331544Seschrock * 341544Seschrock * Device level injection is done using the 'zi_guid' field. If this is set, it 351544Seschrock * means that the error is destined for a particular device, not a piece of 361544Seschrock * data. 371544Seschrock * 381544Seschrock * This is a rather poor data structure and algorithm, but we don't expect more 391544Seschrock * than a few faults at any one time, so it should be sufficient for our needs. 401544Seschrock */ 411544Seschrock 421544Seschrock #include <sys/arc.h> 431544Seschrock #include <sys/zio_impl.h> 441544Seschrock #include <sys/zfs_ioctl.h> 451544Seschrock #include <sys/vdev_impl.h> 4610922SJeff.Bonwick@Sun.COM #include <sys/dmu_objset.h> 476615Sgw25295 #include <sys/fs/zfs.h> 481544Seschrock 491544Seschrock uint32_t zio_injection_enabled; 501544Seschrock 511544Seschrock typedef struct inject_handler { 521544Seschrock int zi_id; 531544Seschrock spa_t *zi_spa; 541544Seschrock zinject_record_t zi_record; 551544Seschrock list_node_t zi_link; 561544Seschrock } inject_handler_t; 571544Seschrock 581544Seschrock static list_t inject_handlers; 591544Seschrock static krwlock_t inject_lock; 601544Seschrock static int inject_next_id = 1; 611544Seschrock 621544Seschrock /* 631544Seschrock * Returns true if the given record matches the I/O in progress. 641544Seschrock */ 651544Seschrock static boolean_t 661544Seschrock zio_match_handler(zbookmark_t *zb, uint64_t type, 671544Seschrock zinject_record_t *record, int error) 681544Seschrock { 691544Seschrock /* 701544Seschrock * Check for a match against the MOS, which is based on type 711544Seschrock */ 7210922SJeff.Bonwick@Sun.COM if (zb->zb_objset == DMU_META_OBJSET && 7310922SJeff.Bonwick@Sun.COM record->zi_objset == DMU_META_OBJSET && 7410922SJeff.Bonwick@Sun.COM record->zi_object == DMU_META_DNODE_OBJECT) { 751544Seschrock if (record->zi_type == DMU_OT_NONE || 761544Seschrock type == record->zi_type) 771544Seschrock return (record->zi_freq == 0 || 781544Seschrock spa_get_random(100) < record->zi_freq); 791544Seschrock else 801544Seschrock return (B_FALSE); 811544Seschrock } 821544Seschrock 831544Seschrock /* 841544Seschrock * Check for an exact match. 851544Seschrock */ 861544Seschrock if (zb->zb_objset == record->zi_objset && 871544Seschrock zb->zb_object == record->zi_object && 881544Seschrock zb->zb_level == record->zi_level && 891544Seschrock zb->zb_blkid >= record->zi_start && 901544Seschrock zb->zb_blkid <= record->zi_end && 911544Seschrock error == record->zi_error) 921544Seschrock return (record->zi_freq == 0 || 931544Seschrock spa_get_random(100) < record->zi_freq); 941544Seschrock 951544Seschrock return (B_FALSE); 961544Seschrock } 971544Seschrock 981544Seschrock /* 9910594SGeorge.Wilson@Sun.COM * Panic the system when a config change happens in the function 10010594SGeorge.Wilson@Sun.COM * specified by tag. 10110594SGeorge.Wilson@Sun.COM */ 10210594SGeorge.Wilson@Sun.COM void 10311422SMark.Musante@Sun.COM zio_handle_panic_injection(spa_t *spa, char *tag, uint64_t type) 10410594SGeorge.Wilson@Sun.COM { 10510594SGeorge.Wilson@Sun.COM inject_handler_t *handler; 10610594SGeorge.Wilson@Sun.COM 10710594SGeorge.Wilson@Sun.COM rw_enter(&inject_lock, RW_READER); 10810594SGeorge.Wilson@Sun.COM 10910594SGeorge.Wilson@Sun.COM for (handler = list_head(&inject_handlers); handler != NULL; 11010594SGeorge.Wilson@Sun.COM handler = list_next(&inject_handlers, handler)) { 11110594SGeorge.Wilson@Sun.COM 11210594SGeorge.Wilson@Sun.COM if (spa != handler->zi_spa) 11310594SGeorge.Wilson@Sun.COM continue; 11410594SGeorge.Wilson@Sun.COM 11511422SMark.Musante@Sun.COM if (handler->zi_record.zi_type == type && 11611422SMark.Musante@Sun.COM strcmp(tag, handler->zi_record.zi_func) == 0) 11710594SGeorge.Wilson@Sun.COM panic("Panic requested in function %s\n", tag); 11810594SGeorge.Wilson@Sun.COM } 11910594SGeorge.Wilson@Sun.COM 12010594SGeorge.Wilson@Sun.COM rw_exit(&inject_lock); 12110594SGeorge.Wilson@Sun.COM } 12210594SGeorge.Wilson@Sun.COM 12310594SGeorge.Wilson@Sun.COM /* 1241544Seschrock * Determine if the I/O in question should return failure. Returns the errno 1251544Seschrock * to be returned to the caller. 1261544Seschrock */ 1271544Seschrock int 1281544Seschrock zio_handle_fault_injection(zio_t *zio, int error) 1291544Seschrock { 1301544Seschrock int ret = 0; 1311544Seschrock inject_handler_t *handler; 1321544Seschrock 1331544Seschrock /* 1341544Seschrock * Ignore I/O not associated with any logical data. 1351544Seschrock */ 1361544Seschrock if (zio->io_logical == NULL) 1371544Seschrock return (0); 1381544Seschrock 1391544Seschrock /* 1401544Seschrock * Currently, we only support fault injection on reads. 1411544Seschrock */ 1421544Seschrock if (zio->io_type != ZIO_TYPE_READ) 1431544Seschrock return (0); 1441544Seschrock 1451544Seschrock rw_enter(&inject_lock, RW_READER); 1461544Seschrock 1471544Seschrock for (handler = list_head(&inject_handlers); handler != NULL; 1481544Seschrock handler = list_next(&inject_handlers, handler)) { 1491544Seschrock 1501544Seschrock /* Ignore errors not destined for this pool */ 1511544Seschrock if (zio->io_spa != handler->zi_spa) 1521544Seschrock continue; 1531544Seschrock 15410594SGeorge.Wilson@Sun.COM /* Ignore device errors and panic injection */ 15510594SGeorge.Wilson@Sun.COM if (handler->zi_record.zi_guid != 0 || 15610921STim.Haley@Sun.COM handler->zi_record.zi_func[0] != '\0' || 15710921STim.Haley@Sun.COM handler->zi_record.zi_duration != 0) 1581544Seschrock continue; 1591544Seschrock 1601544Seschrock /* If this handler matches, return EIO */ 1611544Seschrock if (zio_match_handler(&zio->io_logical->io_bookmark, 1621544Seschrock zio->io_bp ? BP_GET_TYPE(zio->io_bp) : DMU_OT_NONE, 1631544Seschrock &handler->zi_record, error)) { 1641544Seschrock ret = error; 1651544Seschrock break; 1661544Seschrock } 1671544Seschrock } 1681544Seschrock 1691544Seschrock rw_exit(&inject_lock); 1701544Seschrock 1711544Seschrock return (ret); 1721544Seschrock } 1731544Seschrock 1746615Sgw25295 /* 1756615Sgw25295 * Determine if the zio is part of a label update and has an injection 1766615Sgw25295 * handler associated with that portion of the label. Currently, we 1776615Sgw25295 * allow error injection in either the nvlist or the uberblock region of 1786615Sgw25295 * of the vdev label. 1796615Sgw25295 */ 1806615Sgw25295 int 1816615Sgw25295 zio_handle_label_injection(zio_t *zio, int error) 1826615Sgw25295 { 1836615Sgw25295 inject_handler_t *handler; 1846615Sgw25295 vdev_t *vd = zio->io_vd; 1856615Sgw25295 uint64_t offset = zio->io_offset; 1866615Sgw25295 int label; 1876615Sgw25295 int ret = 0; 1886615Sgw25295 18910685SGeorge.Wilson@Sun.COM if (offset >= VDEV_LABEL_START_SIZE && 1906615Sgw25295 offset < vd->vdev_psize - VDEV_LABEL_END_SIZE) 1916615Sgw25295 return (0); 1926615Sgw25295 1936615Sgw25295 rw_enter(&inject_lock, RW_READER); 1946615Sgw25295 1956615Sgw25295 for (handler = list_head(&inject_handlers); handler != NULL; 1966615Sgw25295 handler = list_next(&inject_handlers, handler)) { 1976615Sgw25295 uint64_t start = handler->zi_record.zi_start; 1986615Sgw25295 uint64_t end = handler->zi_record.zi_end; 1996615Sgw25295 20010594SGeorge.Wilson@Sun.COM /* Ignore device only faults or panic injection */ 20110594SGeorge.Wilson@Sun.COM if (handler->zi_record.zi_start == 0 || 20210921STim.Haley@Sun.COM handler->zi_record.zi_func[0] != '\0' || 20310921STim.Haley@Sun.COM handler->zi_record.zi_duration != 0) 2046615Sgw25295 continue; 2056615Sgw25295 2066615Sgw25295 /* 2076615Sgw25295 * The injection region is the relative offsets within a 2086615Sgw25295 * vdev label. We must determine the label which is being 2096615Sgw25295 * updated and adjust our region accordingly. 2106615Sgw25295 */ 2116615Sgw25295 label = vdev_label_number(vd->vdev_psize, offset); 2126615Sgw25295 start = vdev_label_offset(vd->vdev_psize, label, start); 2136615Sgw25295 end = vdev_label_offset(vd->vdev_psize, label, end); 2146615Sgw25295 2156615Sgw25295 if (zio->io_vd->vdev_guid == handler->zi_record.zi_guid && 2166615Sgw25295 (offset >= start && offset <= end)) { 2176615Sgw25295 ret = error; 2186615Sgw25295 break; 2196615Sgw25295 } 2206615Sgw25295 } 2216615Sgw25295 rw_exit(&inject_lock); 2226615Sgw25295 return (ret); 2236615Sgw25295 } 2246615Sgw25295 2256615Sgw25295 2261544Seschrock int 2279725SEric.Schrock@Sun.COM zio_handle_device_injection(vdev_t *vd, zio_t *zio, int error) 2281544Seschrock { 2291544Seschrock inject_handler_t *handler; 2301544Seschrock int ret = 0; 2311544Seschrock 23210685SGeorge.Wilson@Sun.COM /* 23310685SGeorge.Wilson@Sun.COM * We skip over faults in the labels unless it's during 23410685SGeorge.Wilson@Sun.COM * device open (i.e. zio == NULL). 23510685SGeorge.Wilson@Sun.COM */ 23610685SGeorge.Wilson@Sun.COM if (zio != NULL) { 23710685SGeorge.Wilson@Sun.COM uint64_t offset = zio->io_offset; 23810685SGeorge.Wilson@Sun.COM 23910685SGeorge.Wilson@Sun.COM if (offset < VDEV_LABEL_START_SIZE || 24010685SGeorge.Wilson@Sun.COM offset >= vd->vdev_psize - VDEV_LABEL_END_SIZE) 24111937SMark.Musante@Sun.COM return (0); 24210685SGeorge.Wilson@Sun.COM } 24310685SGeorge.Wilson@Sun.COM 2441544Seschrock rw_enter(&inject_lock, RW_READER); 2451544Seschrock 2461544Seschrock for (handler = list_head(&inject_handlers); handler != NULL; 2471544Seschrock handler = list_next(&inject_handlers, handler)) { 2481544Seschrock 24910921STim.Haley@Sun.COM /* 25010921STim.Haley@Sun.COM * Ignore label specific faults, panic injection 25110921STim.Haley@Sun.COM * or fake writes 25210921STim.Haley@Sun.COM */ 25310594SGeorge.Wilson@Sun.COM if (handler->zi_record.zi_start != 0 || 25410921STim.Haley@Sun.COM handler->zi_record.zi_func[0] != '\0' || 25510921STim.Haley@Sun.COM handler->zi_record.zi_duration != 0) 2566615Sgw25295 continue; 2576615Sgw25295 2581544Seschrock if (vd->vdev_guid == handler->zi_record.zi_guid) { 2599725SEric.Schrock@Sun.COM if (handler->zi_record.zi_failfast && 2609725SEric.Schrock@Sun.COM (zio == NULL || (zio->io_flags & 2619725SEric.Schrock@Sun.COM (ZIO_FLAG_IO_RETRY | ZIO_FLAG_TRYHARD)))) { 2629725SEric.Schrock@Sun.COM continue; 2639725SEric.Schrock@Sun.COM } 2649725SEric.Schrock@Sun.COM 26510685SGeorge.Wilson@Sun.COM /* Handle type specific I/O failures */ 26610685SGeorge.Wilson@Sun.COM if (zio != NULL && 26710685SGeorge.Wilson@Sun.COM handler->zi_record.zi_iotype != ZIO_TYPES && 26810685SGeorge.Wilson@Sun.COM handler->zi_record.zi_iotype != zio->io_type) 26910685SGeorge.Wilson@Sun.COM continue; 27010685SGeorge.Wilson@Sun.COM 2711544Seschrock if (handler->zi_record.zi_error == error) { 2721544Seschrock /* 2731544Seschrock * For a failed open, pretend like the device 2741544Seschrock * has gone away. 2751544Seschrock */ 2761544Seschrock if (error == ENXIO) 2771544Seschrock vd->vdev_stat.vs_aux = 2781544Seschrock VDEV_AUX_OPEN_FAILED; 279*12247SGeorge.Wilson@Sun.COM 280*12247SGeorge.Wilson@Sun.COM /* 281*12247SGeorge.Wilson@Sun.COM * Treat these errors as if they had been 282*12247SGeorge.Wilson@Sun.COM * retried so that all the appropriate stats 283*12247SGeorge.Wilson@Sun.COM * and FMA events are generated. 284*12247SGeorge.Wilson@Sun.COM */ 285*12247SGeorge.Wilson@Sun.COM if (!handler->zi_record.zi_failfast && 286*12247SGeorge.Wilson@Sun.COM zio != NULL) 287*12247SGeorge.Wilson@Sun.COM zio->io_flags |= ZIO_FLAG_IO_RETRY; 288*12247SGeorge.Wilson@Sun.COM 2891544Seschrock ret = error; 2901544Seschrock break; 2911544Seschrock } 2921544Seschrock if (handler->zi_record.zi_error == ENXIO) { 2931544Seschrock ret = EIO; 2941544Seschrock break; 2951544Seschrock } 2961544Seschrock } 2971544Seschrock } 2981544Seschrock 2991544Seschrock rw_exit(&inject_lock); 3001544Seschrock 3011544Seschrock return (ret); 3021544Seschrock } 3031544Seschrock 3041544Seschrock /* 30510921STim.Haley@Sun.COM * Simulate hardware that ignores cache flushes. For requested number 30610921STim.Haley@Sun.COM * of seconds nix the actual writing to disk. 30710921STim.Haley@Sun.COM */ 30810921STim.Haley@Sun.COM void 30910921STim.Haley@Sun.COM zio_handle_ignored_writes(zio_t *zio) 31010921STim.Haley@Sun.COM { 31110921STim.Haley@Sun.COM inject_handler_t *handler; 31210921STim.Haley@Sun.COM 31310921STim.Haley@Sun.COM rw_enter(&inject_lock, RW_READER); 31410921STim.Haley@Sun.COM 31510921STim.Haley@Sun.COM for (handler = list_head(&inject_handlers); handler != NULL; 31610921STim.Haley@Sun.COM handler = list_next(&inject_handlers, handler)) { 31710921STim.Haley@Sun.COM 31810921STim.Haley@Sun.COM /* Ignore errors not destined for this pool */ 31910921STim.Haley@Sun.COM if (zio->io_spa != handler->zi_spa) 32010921STim.Haley@Sun.COM continue; 32110921STim.Haley@Sun.COM 32210921STim.Haley@Sun.COM if (handler->zi_record.zi_duration == 0) 32310921STim.Haley@Sun.COM continue; 32410921STim.Haley@Sun.COM 32510921STim.Haley@Sun.COM /* 32610921STim.Haley@Sun.COM * Positive duration implies # of seconds, negative 32710921STim.Haley@Sun.COM * a number of txgs 32810921STim.Haley@Sun.COM */ 32910921STim.Haley@Sun.COM if (handler->zi_record.zi_timer == 0) { 33010921STim.Haley@Sun.COM if (handler->zi_record.zi_duration > 0) 33111066Srafael.vanoni@sun.com handler->zi_record.zi_timer = ddi_get_lbolt64(); 33210921STim.Haley@Sun.COM else 33310921STim.Haley@Sun.COM handler->zi_record.zi_timer = zio->io_txg; 33410921STim.Haley@Sun.COM } 33511026STim.Haley@Sun.COM 33611026STim.Haley@Sun.COM /* Have a "problem" writing 60% of the time */ 33711026STim.Haley@Sun.COM if (spa_get_random(100) < 60) 33811026STim.Haley@Sun.COM zio->io_pipeline &= ~ZIO_VDEV_IO_STAGES; 33910921STim.Haley@Sun.COM break; 34010921STim.Haley@Sun.COM } 34110921STim.Haley@Sun.COM 34210921STim.Haley@Sun.COM rw_exit(&inject_lock); 34310921STim.Haley@Sun.COM } 34410921STim.Haley@Sun.COM 34510921STim.Haley@Sun.COM void 34610921STim.Haley@Sun.COM spa_handle_ignored_writes(spa_t *spa) 34710921STim.Haley@Sun.COM { 34810921STim.Haley@Sun.COM inject_handler_t *handler; 34910921STim.Haley@Sun.COM 35010921STim.Haley@Sun.COM if (zio_injection_enabled == 0) 35110921STim.Haley@Sun.COM return; 35210921STim.Haley@Sun.COM 35310921STim.Haley@Sun.COM rw_enter(&inject_lock, RW_READER); 35410921STim.Haley@Sun.COM 35510921STim.Haley@Sun.COM for (handler = list_head(&inject_handlers); handler != NULL; 35610921STim.Haley@Sun.COM handler = list_next(&inject_handlers, handler)) { 35710921STim.Haley@Sun.COM 35810921STim.Haley@Sun.COM /* Ignore errors not destined for this pool */ 35910921STim.Haley@Sun.COM if (spa != handler->zi_spa) 36010921STim.Haley@Sun.COM continue; 36110921STim.Haley@Sun.COM 36210921STim.Haley@Sun.COM if (handler->zi_record.zi_duration == 0) 36310921STim.Haley@Sun.COM continue; 36410921STim.Haley@Sun.COM 36510921STim.Haley@Sun.COM if (handler->zi_record.zi_duration > 0) { 36610921STim.Haley@Sun.COM VERIFY(handler->zi_record.zi_timer == 0 || 36710921STim.Haley@Sun.COM handler->zi_record.zi_timer + 36811066Srafael.vanoni@sun.com handler->zi_record.zi_duration * hz > 36911066Srafael.vanoni@sun.com ddi_get_lbolt64()); 37010921STim.Haley@Sun.COM } else { 37110921STim.Haley@Sun.COM /* duration is negative so the subtraction here adds */ 37210921STim.Haley@Sun.COM VERIFY(handler->zi_record.zi_timer == 0 || 37310921STim.Haley@Sun.COM handler->zi_record.zi_timer - 37410921STim.Haley@Sun.COM handler->zi_record.zi_duration >= 37510922SJeff.Bonwick@Sun.COM spa_syncing_txg(spa)); 37610921STim.Haley@Sun.COM } 37710921STim.Haley@Sun.COM } 37810921STim.Haley@Sun.COM 37910921STim.Haley@Sun.COM rw_exit(&inject_lock); 38010921STim.Haley@Sun.COM } 38110921STim.Haley@Sun.COM 38210921STim.Haley@Sun.COM /* 3831544Seschrock * Create a new handler for the given record. We add it to the list, adding 3841544Seschrock * a reference to the spa_t in the process. We increment zio_injection_enabled, 3851544Seschrock * which is the switch to trigger all fault injection. 3861544Seschrock */ 3871544Seschrock int 3881544Seschrock zio_inject_fault(char *name, int flags, int *id, zinject_record_t *record) 3891544Seschrock { 3901544Seschrock inject_handler_t *handler; 3911544Seschrock int error; 3921544Seschrock spa_t *spa; 3931544Seschrock 3941544Seschrock /* 3951544Seschrock * If this is pool-wide metadata, make sure we unload the corresponding 3961544Seschrock * spa_t, so that the next attempt to load it will trigger the fault. 3971544Seschrock * We call spa_reset() to unload the pool appropriately. 3981544Seschrock */ 3991544Seschrock if (flags & ZINJECT_UNLOAD_SPA) 4001544Seschrock if ((error = spa_reset(name)) != 0) 4011544Seschrock return (error); 4021544Seschrock 4031544Seschrock if (!(flags & ZINJECT_NULL)) { 4041544Seschrock /* 4051544Seschrock * spa_inject_ref() will add an injection reference, which will 4061544Seschrock * prevent the pool from being removed from the namespace while 4071544Seschrock * still allowing it to be unloaded. 4081544Seschrock */ 4091544Seschrock if ((spa = spa_inject_addref(name)) == NULL) 4101544Seschrock return (ENOENT); 4111544Seschrock 4121544Seschrock handler = kmem_alloc(sizeof (inject_handler_t), KM_SLEEP); 4131544Seschrock 4141544Seschrock rw_enter(&inject_lock, RW_WRITER); 4151544Seschrock 4161544Seschrock *id = handler->zi_id = inject_next_id++; 4171544Seschrock handler->zi_spa = spa; 4181544Seschrock handler->zi_record = *record; 4191544Seschrock list_insert_tail(&inject_handlers, handler); 4201544Seschrock atomic_add_32(&zio_injection_enabled, 1); 4211544Seschrock 4221544Seschrock rw_exit(&inject_lock); 4231544Seschrock } 4241544Seschrock 4251544Seschrock /* 4261544Seschrock * Flush the ARC, so that any attempts to read this data will end up 4271544Seschrock * going to the ZIO layer. Note that this is a little overkill, but 4281544Seschrock * we don't have the necessary ARC interfaces to do anything else, and 4291544Seschrock * fault injection isn't a performance critical path. 4301544Seschrock */ 4311544Seschrock if (flags & ZINJECT_FLUSH_ARC) 4325642Smaybee arc_flush(NULL); 4331544Seschrock 4341544Seschrock return (0); 4351544Seschrock } 4361544Seschrock 4371544Seschrock /* 4381544Seschrock * Returns the next record with an ID greater than that supplied to the 4391544Seschrock * function. Used to iterate over all handlers in the system. 4401544Seschrock */ 4411544Seschrock int 4421544Seschrock zio_inject_list_next(int *id, char *name, size_t buflen, 4431544Seschrock zinject_record_t *record) 4441544Seschrock { 4451544Seschrock inject_handler_t *handler; 4461544Seschrock int ret; 4471544Seschrock 4481544Seschrock mutex_enter(&spa_namespace_lock); 4491544Seschrock rw_enter(&inject_lock, RW_READER); 4501544Seschrock 4511544Seschrock for (handler = list_head(&inject_handlers); handler != NULL; 4521544Seschrock handler = list_next(&inject_handlers, handler)) 4531544Seschrock if (handler->zi_id > *id) 4541544Seschrock break; 4551544Seschrock 4561544Seschrock if (handler) { 4571544Seschrock *record = handler->zi_record; 4581544Seschrock *id = handler->zi_id; 4591544Seschrock (void) strncpy(name, spa_name(handler->zi_spa), buflen); 4601544Seschrock ret = 0; 4611544Seschrock } else { 4621544Seschrock ret = ENOENT; 4631544Seschrock } 4641544Seschrock 4651544Seschrock rw_exit(&inject_lock); 4661544Seschrock mutex_exit(&spa_namespace_lock); 4671544Seschrock 4681544Seschrock return (ret); 4691544Seschrock } 4701544Seschrock 4711544Seschrock /* 4721544Seschrock * Clear the fault handler with the given identifier, or return ENOENT if none 4731544Seschrock * exists. 4741544Seschrock */ 4751544Seschrock int 4761544Seschrock zio_clear_fault(int id) 4771544Seschrock { 4781544Seschrock inject_handler_t *handler; 4791544Seschrock int ret; 4801544Seschrock 4811544Seschrock rw_enter(&inject_lock, RW_WRITER); 4821544Seschrock 4831544Seschrock for (handler = list_head(&inject_handlers); handler != NULL; 4841544Seschrock handler = list_next(&inject_handlers, handler)) 4851544Seschrock if (handler->zi_id == id) 4861544Seschrock break; 4871544Seschrock 4881544Seschrock if (handler == NULL) { 4891544Seschrock ret = ENOENT; 4901544Seschrock } else { 4911544Seschrock list_remove(&inject_handlers, handler); 4921544Seschrock spa_inject_delref(handler->zi_spa); 4931544Seschrock kmem_free(handler, sizeof (inject_handler_t)); 4941544Seschrock atomic_add_32(&zio_injection_enabled, -1); 4951544Seschrock ret = 0; 4961544Seschrock } 4971544Seschrock 4981544Seschrock rw_exit(&inject_lock); 4991544Seschrock 5001544Seschrock return (ret); 5011544Seschrock } 5021544Seschrock 5031544Seschrock void 5041544Seschrock zio_inject_init(void) 5051544Seschrock { 5067313SEric.Kustarz@Sun.COM rw_init(&inject_lock, NULL, RW_DEFAULT, NULL); 5071544Seschrock list_create(&inject_handlers, sizeof (inject_handler_t), 5081544Seschrock offsetof(inject_handler_t, zi_link)); 5091544Seschrock } 5101544Seschrock 5111544Seschrock void 5121544Seschrock zio_inject_fini(void) 5131544Seschrock { 5141544Seschrock list_destroy(&inject_handlers); 5157313SEric.Kustarz@Sun.COM rw_destroy(&inject_lock); 5161544Seschrock } 517