FreeBSD ZFS
The Zettabyte File System

zio_inject.c

Go to the documentation of this file.
00001 /*
00002  * CDDL HEADER START
00003  *
00004  * The contents of this file are subject to the terms of the
00005  * Common Development and Distribution License (the "License").
00006  * You may not use this file except in compliance with the License.
00007  *
00008  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
00009  * or http://www.opensolaris.org/os/licensing.
00010  * See the License for the specific language governing permissions
00011  * and limitations under the License.
00012  *
00013  * When distributing Covered Code, include this CDDL HEADER in each
00014  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
00015  * If applicable, add the following below this CDDL HEADER, with the
00016  * fields enclosed by brackets "[]" replaced with your own identifying
00017  * information: Portions Copyright [yyyy] [name of copyright owner]
00018  *
00019  * CDDL HEADER END
00020  */
00021 /*
00022  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
00023  */
00024 
00043 #include <sys/arc.h>
00044 #include <sys/zio_impl.h>
00045 #include <sys/zfs_ioctl.h>
00046 #include <sys/vdev_impl.h>
00047 #include <sys/dmu_objset.h>
00048 #include <sys/fs/zfs.h>
00049 
00050 uint32_t zio_injection_enabled;
00051 
00052 typedef struct inject_handler {
00053         int                     zi_id;
00054         spa_t                   *zi_spa;
00055         zinject_record_t        zi_record;
00056         list_node_t             zi_link;
00057 } inject_handler_t;
00058 
00059 static list_t inject_handlers;
00060 static krwlock_t inject_lock;
00061 static int inject_next_id = 1;
00062 
00066 static boolean_t
00067 zio_match_handler(zbookmark_t *zb, uint64_t type,
00068     zinject_record_t *record, int error)
00069 {
00070         /*
00071          * Check for a match against the MOS, which is based on type
00072          */
00073         if (zb->zb_objset == DMU_META_OBJSET &&
00074             record->zi_objset == DMU_META_OBJSET &&
00075             record->zi_object == DMU_META_DNODE_OBJECT) {
00076                 if (record->zi_type == DMU_OT_NONE ||
00077                     type == record->zi_type)
00078                         return (record->zi_freq == 0 ||
00079                             spa_get_random(100) < record->zi_freq);
00080                 else
00081                         return (B_FALSE);
00082         }
00083 
00084         /*
00085          * Check for an exact match.
00086          */
00087         if (zb->zb_objset == record->zi_objset &&
00088             zb->zb_object == record->zi_object &&
00089             zb->zb_level == record->zi_level &&
00090             zb->zb_blkid >= record->zi_start &&
00091             zb->zb_blkid <= record->zi_end &&
00092             error == record->zi_error)
00093                 return (record->zi_freq == 0 ||
00094                     spa_get_random(100) < record->zi_freq);
00095 
00096         return (B_FALSE);
00097 }
00098 
00103 void
00104 zio_handle_panic_injection(spa_t *spa, char *tag, uint64_t type)
00105 {
00106         inject_handler_t *handler;
00107 
00108         rw_enter(&inject_lock, RW_READER);
00109 
00110         for (handler = list_head(&inject_handlers); handler != NULL;
00111             handler = list_next(&inject_handlers, handler)) {
00112 
00113                 if (spa != handler->zi_spa)
00114                         continue;
00115 
00116                 if (handler->zi_record.zi_type == type &&
00117                     strcmp(tag, handler->zi_record.zi_func) == 0)
00118                         panic("Panic requested in function %s\n", tag);
00119         }
00120 
00121         rw_exit(&inject_lock);
00122 }
00123 
00128 int
00129 zio_handle_fault_injection(zio_t *zio, int error)
00130 {
00131         int ret = 0;
00132         inject_handler_t *handler;
00133 
00134         /*
00135          * Ignore I/O not associated with any logical data.
00136          */
00137         if (zio->io_logical == NULL)
00138                 return (0);
00139 
00140         /*
00141          * Currently, we only support fault injection on reads.
00142          */
00143         if (zio->io_type != ZIO_TYPE_READ)
00144                 return (0);
00145 
00146         rw_enter(&inject_lock, RW_READER);
00147 
00148         for (handler = list_head(&inject_handlers); handler != NULL;
00149             handler = list_next(&inject_handlers, handler)) {
00150 
00151                 /* Ignore errors not destined for this pool */
00152                 if (zio->io_spa != handler->zi_spa)
00153                         continue;
00154 
00155                 /* Ignore device errors and panic injection */
00156                 if (handler->zi_record.zi_guid != 0 ||
00157                     handler->zi_record.zi_func[0] != '\0' ||
00158                     handler->zi_record.zi_duration != 0)
00159                         continue;
00160 
00161                 /* If this handler matches, return EIO */
00162                 if (zio_match_handler(&zio->io_logical->io_bookmark,
00163                     zio->io_bp ? BP_GET_TYPE(zio->io_bp) : DMU_OT_NONE,
00164                     &handler->zi_record, error)) {
00165                         ret = error;
00166                         break;
00167                 }
00168         }
00169 
00170         rw_exit(&inject_lock);
00171 
00172         return (ret);
00173 }
00174 
00181 int
00182 zio_handle_label_injection(zio_t *zio, int error)
00183 {
00184         inject_handler_t *handler;
00185         vdev_t *vd = zio->io_vd;
00186         uint64_t offset = zio->io_offset;
00187         int label;
00188         int ret = 0;
00189 
00190         if (offset >= VDEV_LABEL_START_SIZE &&
00191             offset < vd->vdev_psize - VDEV_LABEL_END_SIZE)
00192                 return (0);
00193 
00194         rw_enter(&inject_lock, RW_READER);
00195 
00196         for (handler = list_head(&inject_handlers); handler != NULL;
00197             handler = list_next(&inject_handlers, handler)) {
00198                 uint64_t start = handler->zi_record.zi_start;
00199                 uint64_t end = handler->zi_record.zi_end;
00200 
00201                 /* Ignore device only faults or panic injection */
00202                 if (handler->zi_record.zi_start == 0 ||
00203                     handler->zi_record.zi_func[0] != '\0' ||
00204                     handler->zi_record.zi_duration != 0)
00205                         continue;
00206 
00207                 /*
00208                  * The injection region is the relative offsets within a
00209                  * vdev label. We must determine the label which is being
00210                  * updated and adjust our region accordingly.
00211                  */
00212                 label = vdev_label_number(vd->vdev_psize, offset);
00213                 start = vdev_label_offset(vd->vdev_psize, label, start);
00214                 end = vdev_label_offset(vd->vdev_psize, label, end);
00215 
00216                 if (zio->io_vd->vdev_guid == handler->zi_record.zi_guid &&
00217                     (offset >= start && offset <= end)) {
00218                         ret = error;
00219                         break;
00220                 }
00221         }
00222         rw_exit(&inject_lock);
00223         return (ret);
00224 }
00225 
00226 
00227 int
00228 zio_handle_device_injection(vdev_t *vd, zio_t *zio, int error)
00229 {
00230         inject_handler_t *handler;
00231         int ret = 0;
00232 
00233         /*
00234          * We skip over faults in the labels unless it's during
00235          * device open (i.e. zio == NULL).
00236          */
00237         if (zio != NULL) {
00238                 uint64_t offset = zio->io_offset;
00239 
00240                 if (offset < VDEV_LABEL_START_SIZE ||
00241                     offset >= vd->vdev_psize - VDEV_LABEL_END_SIZE)
00242                         return (0);
00243         }
00244 
00245         rw_enter(&inject_lock, RW_READER);
00246 
00247         for (handler = list_head(&inject_handlers); handler != NULL;
00248             handler = list_next(&inject_handlers, handler)) {
00249 
00250                 /*
00251                  * Ignore label specific faults, panic injection
00252                  * or fake writes
00253                  */
00254                 if (handler->zi_record.zi_start != 0 ||
00255                     handler->zi_record.zi_func[0] != '\0' ||
00256                     handler->zi_record.zi_duration != 0)
00257                         continue;
00258 
00259                 if (vd->vdev_guid == handler->zi_record.zi_guid) {
00260                         if (handler->zi_record.zi_failfast &&
00261                             (zio == NULL || (zio->io_flags &
00262                             (ZIO_FLAG_IO_RETRY | ZIO_FLAG_TRYHARD)))) {
00263                                 continue;
00264                         }
00265 
00266                         /* Handle type specific I/O failures */
00267                         if (zio != NULL &&
00268                             handler->zi_record.zi_iotype != ZIO_TYPES &&
00269                             handler->zi_record.zi_iotype != zio->io_type)
00270                                 continue;
00271 
00272                         if (handler->zi_record.zi_error == error) {
00273                                 /*
00274                                  * For a failed open, pretend like the device
00275                                  * has gone away.
00276                                  */
00277                                 if (error == ENXIO)
00278                                         vd->vdev_stat.vs_aux =
00279                                             VDEV_AUX_OPEN_FAILED;
00280 
00281                                 /*
00282                                  * Treat these errors as if they had been
00283                                  * retried so that all the appropriate stats
00284                                  * and FMA events are generated.
00285                                  */
00286                                 if (!handler->zi_record.zi_failfast &&
00287                                     zio != NULL)
00288                                         zio->io_flags |= ZIO_FLAG_IO_RETRY;
00289 
00290                                 ret = error;
00291                                 break;
00292                         }
00293                         if (handler->zi_record.zi_error == ENXIO) {
00294                                 ret = EIO;
00295                                 break;
00296                         }
00297                 }
00298         }
00299 
00300         rw_exit(&inject_lock);
00301 
00302         return (ret);
00303 }
00304 
00309 void
00310 zio_handle_ignored_writes(zio_t *zio)
00311 {
00312         inject_handler_t *handler;
00313 
00314         rw_enter(&inject_lock, RW_READER);
00315 
00316         for (handler = list_head(&inject_handlers); handler != NULL;
00317             handler = list_next(&inject_handlers, handler)) {
00318 
00319                 /* Ignore errors not destined for this pool */
00320                 if (zio->io_spa != handler->zi_spa)
00321                         continue;
00322 
00323                 if (handler->zi_record.zi_duration == 0)
00324                         continue;
00325 
00326                 /*
00327                  * Positive duration implies # of seconds, negative
00328                  * a number of txgs
00329                  */
00330                 if (handler->zi_record.zi_timer == 0) {
00331                         if (handler->zi_record.zi_duration > 0)
00332                                 handler->zi_record.zi_timer = ddi_get_lbolt64();
00333                         else
00334                                 handler->zi_record.zi_timer = zio->io_txg;
00335                 }
00336 
00337                 /* Have a "problem" writing 60% of the time */
00338                 if (spa_get_random(100) < 60)
00339                         zio->io_pipeline &= ~ZIO_VDEV_IO_STAGES;
00340                 break;
00341         }
00342 
00343         rw_exit(&inject_lock);
00344 }
00345 
00346 void
00347 spa_handle_ignored_writes(spa_t *spa)
00348 {
00349         inject_handler_t *handler;
00350 
00351         if (zio_injection_enabled == 0)
00352                 return;
00353 
00354         rw_enter(&inject_lock, RW_READER);
00355 
00356         for (handler = list_head(&inject_handlers); handler != NULL;
00357             handler = list_next(&inject_handlers, handler)) {
00358 
00359                 /* Ignore errors not destined for this pool */
00360                 if (spa != handler->zi_spa)
00361                         continue;
00362 
00363                 if (handler->zi_record.zi_duration == 0)
00364                         continue;
00365 
00366                 if (handler->zi_record.zi_duration > 0) {
00367                         VERIFY(handler->zi_record.zi_timer == 0 ||
00368                             handler->zi_record.zi_timer +
00369                             handler->zi_record.zi_duration * hz >
00370                             ddi_get_lbolt64());
00371                 } else {
00372                         /* duration is negative so the subtraction here adds */
00373                         VERIFY(handler->zi_record.zi_timer == 0 ||
00374                             handler->zi_record.zi_timer -
00375                             handler->zi_record.zi_duration >=
00376                             spa_syncing_txg(spa));
00377                 }
00378         }
00379 
00380         rw_exit(&inject_lock);
00381 }
00382 
00388 int
00389 zio_inject_fault(char *name, int flags, int *id, zinject_record_t *record)
00390 {
00391         inject_handler_t *handler;
00392         int error;
00393         spa_t *spa;
00394 
00395         /*
00396          * If this is pool-wide metadata, make sure we unload the corresponding
00397          * spa_t, so that the next attempt to load it will trigger the fault.
00398          * We call spa_reset() to unload the pool appropriately.
00399          */
00400         if (flags & ZINJECT_UNLOAD_SPA)
00401                 if ((error = spa_reset(name)) != 0)
00402                         return (error);
00403 
00404         if (!(flags & ZINJECT_NULL)) {
00405                 /*
00406                  * spa_inject_ref() will add an injection reference, which will
00407                  * prevent the pool from being removed from the namespace while
00408                  * still allowing it to be unloaded.
00409                  */
00410                 if ((spa = spa_inject_addref(name)) == NULL)
00411                         return (ENOENT);
00412 
00413                 handler = kmem_alloc(sizeof (inject_handler_t), KM_SLEEP);
00414 
00415                 rw_enter(&inject_lock, RW_WRITER);
00416 
00417                 *id = handler->zi_id = inject_next_id++;
00418                 handler->zi_spa = spa;
00419                 handler->zi_record = *record;
00420                 list_insert_tail(&inject_handlers, handler);
00421                 atomic_add_32(&zio_injection_enabled, 1);
00422 
00423                 rw_exit(&inject_lock);
00424         }
00425 
00426         /*
00427          * Flush the ARC, so that any attempts to read this data will end up
00428          * going to the ZIO layer.  Note that this is a little overkill, but
00429          * we don't have the necessary ARC interfaces to do anything else, and
00430          * fault injection isn't a performance critical path.
00431          */
00432         if (flags & ZINJECT_FLUSH_ARC)
00433                 arc_flush(NULL);
00434 
00435         return (0);
00436 }
00437 
00442 int
00443 zio_inject_list_next(int *id, char *name, size_t buflen,
00444     zinject_record_t *record)
00445 {
00446         inject_handler_t *handler;
00447         int ret;
00448 
00449         mutex_enter(&spa_namespace_lock);
00450         rw_enter(&inject_lock, RW_READER);
00451 
00452         for (handler = list_head(&inject_handlers); handler != NULL;
00453             handler = list_next(&inject_handlers, handler))
00454                 if (handler->zi_id > *id)
00455                         break;
00456 
00457         if (handler) {
00458                 *record = handler->zi_record;
00459                 *id = handler->zi_id;
00460                 (void) strncpy(name, spa_name(handler->zi_spa), buflen);
00461                 ret = 0;
00462         } else {
00463                 ret = ENOENT;
00464         }
00465 
00466         rw_exit(&inject_lock);
00467         mutex_exit(&spa_namespace_lock);
00468 
00469         return (ret);
00470 }
00471 
00476 int
00477 zio_clear_fault(int id)
00478 {
00479         inject_handler_t *handler;
00480 
00481         rw_enter(&inject_lock, RW_WRITER);
00482 
00483         for (handler = list_head(&inject_handlers); handler != NULL;
00484             handler = list_next(&inject_handlers, handler))
00485                 if (handler->zi_id == id)
00486                         break;
00487 
00488         if (handler == NULL) {
00489                 rw_exit(&inject_lock);
00490                 return (ENOENT);
00491         }
00492 
00493         list_remove(&inject_handlers, handler);
00494         rw_exit(&inject_lock);
00495 
00496         spa_inject_delref(handler->zi_spa);
00497         kmem_free(handler, sizeof (inject_handler_t));
00498         atomic_add_32(&zio_injection_enabled, -1);
00499 
00500         return (0);
00501 }
00502 
00503 void
00504 zio_inject_init(void)
00505 {
00506         rw_init(&inject_lock, NULL, RW_DEFAULT, NULL);
00507         list_create(&inject_handlers, sizeof (inject_handler_t),
00508             offsetof(inject_handler_t, zi_link));
00509 }
00510 
00511 void
00512 zio_inject_fini(void)
00513 {
00514         list_destroy(&inject_handlers);
00515         rw_destroy(&inject_lock);
00516 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines