Deleted Added
full compact
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 ---