spa_errlog.c (251632) | spa_errlog.c (268123) |
---|---|
1/* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE --- 6 unchanged lines hidden (view full) --- 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21/* 22 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. | 1/* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE --- 6 unchanged lines hidden (view full) --- 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21/* 22 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. |
23 * Copyright (c) 2013 by Delphix. All rights reserved. | 23 * Copyright (c) 2013, 2014 by Delphix. All rights reserved. |
24 */ 25 26/* 27 * Routines to manage the on-disk persistent error log. 28 * 29 * Each pool stores a log of all logical data errors seen during normal 30 * operation. This is actually the union of two distinct logs: the last log, 31 * and the current log. All errors seen are logged to the current log. When a 32 * scrub completes, the current log becomes the last log, the last log is thrown 33 * out, and the current log is reinitialized. This way, if an error is somehow 34 * corrected, a new scrub will show that that it no longer exists, and will be 35 * deleted from the log when the scrub completes. 36 * 37 * The log is stored using a ZAP object whose key is a string form of the | 24 */ 25 26/* 27 * Routines to manage the on-disk persistent error log. 28 * 29 * Each pool stores a log of all logical data errors seen during normal 30 * operation. This is actually the union of two distinct logs: the last log, 31 * and the current log. All errors seen are logged to the current log. When a 32 * scrub completes, the current log becomes the last log, the last log is thrown 33 * out, and the current log is reinitialized. This way, if an error is somehow 34 * corrected, a new scrub will show that that it no longer exists, and will be 35 * deleted from the log when the scrub completes. 36 * 37 * The log is stored using a ZAP object whose key is a string form of the |
38 * zbookmark tuple (objset, object, level, blkid), and whose contents is an | 38 * zbookmark_phys tuple (objset, object, level, blkid), and whose contents is an |
39 * optional 'objset:object' human-readable string describing the data. When an 40 * error is first logged, this string will be empty, indicating that no name is 41 * known. This prevents us from having to issue a potentially large amount of 42 * I/O to discover the object name during an error path. Instead, we do the 43 * calculation when the data is requested, storing the result so future queries 44 * will be faster. 45 * 46 * This log is then shipped into an nvlist where the key is the dataset name and --- 7 unchanged lines hidden (view full) --- 54#include <sys/zap.h> 55#include <sys/zio.h> 56 57 58/* 59 * Convert a bookmark to a string. 60 */ 61static void | 39 * optional 'objset:object' human-readable string describing the data. When an 40 * error is first logged, this string will be empty, indicating that no name is 41 * known. This prevents us from having to issue a potentially large amount of 42 * I/O to discover the object name during an error path. Instead, we do the 43 * calculation when the data is requested, storing the result so future queries 44 * will be faster. 45 * 46 * This log is then shipped into an nvlist where the key is the dataset name and --- 7 unchanged lines hidden (view full) --- 54#include <sys/zap.h> 55#include <sys/zio.h> 56 57 58/* 59 * Convert a bookmark to a string. 60 */ 61static void |
62bookmark_to_name(zbookmark_t *zb, char *buf, size_t len) | 62bookmark_to_name(zbookmark_phys_t *zb, char *buf, size_t len) |
63{ 64 (void) snprintf(buf, len, "%llx:%llx:%llx:%llx", 65 (u_longlong_t)zb->zb_objset, (u_longlong_t)zb->zb_object, 66 (u_longlong_t)zb->zb_level, (u_longlong_t)zb->zb_blkid); 67} 68 69/* 70 * Convert a string to a bookmark 71 */ 72#ifdef _KERNEL 73static void | 63{ 64 (void) snprintf(buf, len, "%llx:%llx:%llx:%llx", 65 (u_longlong_t)zb->zb_objset, (u_longlong_t)zb->zb_object, 66 (u_longlong_t)zb->zb_level, (u_longlong_t)zb->zb_blkid); 67} 68 69/* 70 * Convert a string to a bookmark 71 */ 72#ifdef _KERNEL 73static void |
74name_to_bookmark(char *buf, zbookmark_t *zb) | 74name_to_bookmark(char *buf, zbookmark_phys_t *zb) |
75{ 76 zb->zb_objset = strtonum(buf, &buf); 77 ASSERT(*buf == ':'); 78 zb->zb_object = strtonum(buf + 1, &buf); 79 ASSERT(*buf == ':'); 80 zb->zb_level = (int)strtonum(buf + 1, &buf); 81 ASSERT(*buf == ':'); 82 zb->zb_blkid = strtonum(buf + 1, &buf); --- 4 unchanged lines hidden (view full) --- 87/* 88 * Log an uncorrectable error to the persistent error log. We add it to the 89 * spa's list of pending errors. The changes are actually synced out to disk 90 * during spa_errlog_sync(). 91 */ 92void 93spa_log_error(spa_t *spa, zio_t *zio) 94{ | 75{ 76 zb->zb_objset = strtonum(buf, &buf); 77 ASSERT(*buf == ':'); 78 zb->zb_object = strtonum(buf + 1, &buf); 79 ASSERT(*buf == ':'); 80 zb->zb_level = (int)strtonum(buf + 1, &buf); 81 ASSERT(*buf == ':'); 82 zb->zb_blkid = strtonum(buf + 1, &buf); --- 4 unchanged lines hidden (view full) --- 87/* 88 * Log an uncorrectable error to the persistent error log. We add it to the 89 * spa's list of pending errors. The changes are actually synced out to disk 90 * during spa_errlog_sync(). 91 */ 92void 93spa_log_error(spa_t *spa, zio_t *zio) 94{ |
95 zbookmark_t *zb = &zio->io_logical->io_bookmark; | 95 zbookmark_phys_t *zb = &zio->io_logical->io_bookmark; |
96 spa_error_entry_t search; 97 spa_error_entry_t *new; 98 avl_tree_t *tree; 99 avl_index_t where; 100 101 /* 102 * If we are trying to import a pool, ignore any errors, as we won't be 103 * writing to the pool any time soon. --- 56 unchanged lines hidden (view full) --- 160} 161 162#ifdef _KERNEL 163static int 164process_error_log(spa_t *spa, uint64_t obj, void *addr, size_t *count) 165{ 166 zap_cursor_t zc; 167 zap_attribute_t za; | 96 spa_error_entry_t search; 97 spa_error_entry_t *new; 98 avl_tree_t *tree; 99 avl_index_t where; 100 101 /* 102 * If we are trying to import a pool, ignore any errors, as we won't be 103 * writing to the pool any time soon. --- 56 unchanged lines hidden (view full) --- 160} 161 162#ifdef _KERNEL 163static int 164process_error_log(spa_t *spa, uint64_t obj, void *addr, size_t *count) 165{ 166 zap_cursor_t zc; 167 zap_attribute_t za; |
168 zbookmark_t zb; | 168 zbookmark_phys_t zb; |
169 170 if (obj == 0) 171 return (0); 172 173 for (zap_cursor_init(&zc, spa->spa_meta_objset, obj); 174 zap_cursor_retrieve(&zc, &za) == 0; 175 zap_cursor_advance(&zc)) { 176 177 if (*count == 0) { 178 zap_cursor_fini(&zc); 179 return (SET_ERROR(ENOMEM)); 180 } 181 182 name_to_bookmark(za.za_name, &zb); 183 184 if (copyout(&zb, (char *)addr + | 169 170 if (obj == 0) 171 return (0); 172 173 for (zap_cursor_init(&zc, spa->spa_meta_objset, obj); 174 zap_cursor_retrieve(&zc, &za) == 0; 175 zap_cursor_advance(&zc)) { 176 177 if (*count == 0) { 178 zap_cursor_fini(&zc); 179 return (SET_ERROR(ENOMEM)); 180 } 181 182 name_to_bookmark(za.za_name, &zb); 183 184 if (copyout(&zb, (char *)addr + |
185 (*count - 1) * sizeof (zbookmark_t), 186 sizeof (zbookmark_t)) != 0) { | 185 (*count - 1) * sizeof (zbookmark_phys_t), 186 sizeof (zbookmark_phys_t)) != 0) { |
187 zap_cursor_fini(&zc); 188 return (SET_ERROR(EFAULT)); 189 } 190 191 *count -= 1; 192 } 193 194 zap_cursor_fini(&zc); --- 7 unchanged lines hidden (view full) --- 202 spa_error_entry_t *se; 203 204 for (se = avl_first(list); se != NULL; se = AVL_NEXT(list, se)) { 205 206 if (*count == 0) 207 return (SET_ERROR(ENOMEM)); 208 209 if (copyout(&se->se_bookmark, (char *)addr + | 187 zap_cursor_fini(&zc); 188 return (SET_ERROR(EFAULT)); 189 } 190 191 *count -= 1; 192 } 193 194 zap_cursor_fini(&zc); --- 7 unchanged lines hidden (view full) --- 202 spa_error_entry_t *se; 203 204 for (se = avl_first(list); se != NULL; se = AVL_NEXT(list, se)) { 205 206 if (*count == 0) 207 return (SET_ERROR(ENOMEM)); 208 209 if (copyout(&se->se_bookmark, (char *)addr + |
210 (*count - 1) * sizeof (zbookmark_t), 211 sizeof (zbookmark_t)) != 0) | 210 (*count - 1) * sizeof (zbookmark_phys_t), 211 sizeof (zbookmark_phys_t)) != 0) |
212 return (SET_ERROR(EFAULT)); 213 214 *count -= 1; 215 } 216 217 return (0); 218} 219#endif --- 187 unchanged lines hidden --- | 212 return (SET_ERROR(EFAULT)); 213 214 *count -= 1; 215 } 216 217 return (0); 218} 219#endif --- 187 unchanged lines hidden --- |