summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordelphij <delphij@FreeBSD.org>2013-01-10 19:26:56 +0000
committerdelphij <delphij@FreeBSD.org>2013-01-10 19:26:56 +0000
commitf8200d9bc4de2e18914c36bbeb76cffced6288c5 (patch)
tree415c6a7431ea475035a36a4e5afd7d7d20091f4b
parent09551b7a87c77dc36b39b368d4148b552c408ea0 (diff)
downloadFreeBSD-src-f8200d9bc4de2e18914c36bbeb76cffced6288c5.zip
FreeBSD-src-f8200d9bc4de2e18914c36bbeb76cffced6288c5.tar.gz
The current ZFS code expects ddt_zap_count to always succeed by asserting
the underlying zap_count() to return no errors. However, it is possible that the pool reaches to such a state where zap_count would return error, leading to panics when a pool is imported. This commit changes the ddt_zap_count to return error returned from zap_count and handle the error appropriately. With this change, it's now possible to let zpool rollback damaged transaction groups and import the pool. Obtained from: ZFS on Linux github (e8fd45a0f975c6b8ae8cd644714fc21f14fac2bf) MFC after: 1 month
-rw-r--r--cddl/contrib/opensolaris/cmd/zdb/zdb.c4
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt.c26
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt_zap.c9
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/ddt.h6
4 files changed, 27 insertions, 18 deletions
diff --git a/cddl/contrib/opensolaris/cmd/zdb/zdb.c b/cddl/contrib/opensolaris/cmd/zdb/zdb.c
index 362a405..82941af 100644
--- a/cddl/contrib/opensolaris/cmd/zdb/zdb.c
+++ b/cddl/contrib/opensolaris/cmd/zdb/zdb.c
@@ -704,7 +704,9 @@ dump_ddt(ddt_t *ddt, enum ddt_type type, enum ddt_class class)
return;
ASSERT(error == 0);
- if ((count = ddt_object_count(ddt, type, class)) == 0)
+ error = ddt_object_count(ddt, type, class, &count);
+ ASSERT(error == 0);
+ if (count == 0)
return;
dspace = doi.doi_physical_blocks_512 << 9;
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt.c
index ef3d0f4..885af95 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt.c
@@ -89,12 +89,13 @@ ddt_object_destroy(ddt_t *ddt, enum ddt_type type, enum ddt_class class,
spa_t *spa = ddt->ddt_spa;
objset_t *os = ddt->ddt_os;
uint64_t *objectp = &ddt->ddt_object[type][class];
+ uint64_t count;
char name[DDT_NAMELEN];
ddt_object_name(ddt, type, class, name);
ASSERT(*objectp != 0);
- ASSERT(ddt_object_count(ddt, type, class) == 0);
+ VERIFY(ddt_object_count(ddt, type, class, &count) == 0 && count == 0);
ASSERT(ddt_histogram_empty(&ddt->ddt_histogram[type][class]));
VERIFY(zap_remove(os, DMU_POOL_DIRECTORY_OBJECT, name, tx) == 0);
VERIFY(zap_remove(os, spa->spa_ddt_stat_object, name, tx) == 0);
@@ -109,6 +110,7 @@ ddt_object_load(ddt_t *ddt, enum ddt_type type, enum ddt_class class)
{
ddt_object_t *ddo = &ddt->ddt_object_stats[type][class];
dmu_object_info_t doi;
+ uint64_t count;
char name[DDT_NAMELEN];
int error;
@@ -129,7 +131,11 @@ ddt_object_load(ddt_t *ddt, enum ddt_type type, enum ddt_class class)
*/
VERIFY(ddt_object_info(ddt, type, class, &doi) == 0);
- ddo->ddo_count = ddt_object_count(ddt, type, class);
+ error = ddt_object_count(ddt, type, class, &count);
+ if (error)
+ return error;
+
+ ddo->ddo_count = count;
ddo->ddo_dspace = doi.doi_physical_blocks_512 << 9;
ddo->ddo_mspace = doi.doi_fill_count * doi.doi_data_block_size;
@@ -143,6 +149,7 @@ ddt_object_sync(ddt_t *ddt, enum ddt_type type, enum ddt_class class,
{
ddt_object_t *ddo = &ddt->ddt_object_stats[type][class];
dmu_object_info_t doi;
+ uint64_t count;
char name[DDT_NAMELEN];
ddt_object_name(ddt, type, class, name);
@@ -155,8 +162,9 @@ ddt_object_sync(ddt_t *ddt, enum ddt_type type, enum ddt_class class,
* Cache DDT statistics; this is the only time they'll change.
*/
VERIFY(ddt_object_info(ddt, type, class, &doi) == 0);
+ VERIFY(ddt_object_count(ddt, type, class, &count) == 0);
- ddo->ddo_count = ddt_object_count(ddt, type, class);
+ ddo->ddo_count = count;
ddo->ddo_dspace = doi.doi_physical_blocks_512 << 9;
ddo->ddo_mspace = doi.doi_fill_count * doi.doi_data_block_size;
}
@@ -213,13 +221,13 @@ ddt_object_walk(ddt_t *ddt, enum ddt_type type, enum ddt_class class,
ddt->ddt_object[type][class], dde, walk));
}
-uint64_t
-ddt_object_count(ddt_t *ddt, enum ddt_type type, enum ddt_class class)
+int
+ddt_object_count(ddt_t *ddt, enum ddt_type type, enum ddt_class class, uint64_t *count)
{
ASSERT(ddt_object_exists(ddt, type, class));
return (ddt_ops[type]->ddt_op_count(ddt->ddt_os,
- ddt->ddt_object[type][class]));
+ ddt->ddt_object[type][class], count));
}
int
@@ -1079,11 +1087,13 @@ ddt_sync_table(ddt_t *ddt, dmu_tx_t *tx, uint64_t txg)
}
for (enum ddt_type type = 0; type < DDT_TYPES; type++) {
- uint64_t count = 0;
+ uint64_t add, count = 0;
for (enum ddt_class class = 0; class < DDT_CLASSES; class++) {
if (ddt_object_exists(ddt, type, class)) {
ddt_object_sync(ddt, type, class, tx);
- count += ddt_object_count(ddt, type, class);
+ VERIFY(ddt_object_count(ddt, type, class,
+ &add) == 0);
+ count += add;
}
}
for (enum ddt_class class = 0; class < DDT_CLASSES; class++) {
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt_zap.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt_zap.c
index 6812aa3..f42b4dd 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt_zap.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt_zap.c
@@ -133,14 +133,11 @@ ddt_zap_walk(objset_t *os, uint64_t object, ddt_entry_t *dde, uint64_t *walk)
return (error);
}
-static uint64_t
-ddt_zap_count(objset_t *os, uint64_t object)
+static int
+ddt_zap_count(objset_t *os, uint64_t object, uint64_t *count)
{
- uint64_t count = 0;
-
- VERIFY(zap_count(os, object, &count) == 0);
- return (count);
+ return (zap_count(os, object, count));
}
const ddt_ops_t ddt_zap_ops = {
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/ddt.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/ddt.h
index 405622b..5d9747b 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/ddt.h
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/ddt.h
@@ -163,7 +163,7 @@ typedef struct ddt_ops {
dmu_tx_t *tx);
int (*ddt_op_walk)(objset_t *os, uint64_t object, ddt_entry_t *dde,
uint64_t *walk);
- uint64_t (*ddt_op_count)(objset_t *os, uint64_t object);
+ int (*ddt_op_count)(objset_t *os, uint64_t object, uint64_t *count);
} ddt_ops_t;
#define DDT_NAMELEN 80
@@ -172,8 +172,8 @@ extern void ddt_object_name(ddt_t *ddt, enum ddt_type type,
enum ddt_class cls, char *name);
extern int ddt_object_walk(ddt_t *ddt, enum ddt_type type,
enum ddt_class cls, uint64_t *walk, ddt_entry_t *dde);
-extern uint64_t ddt_object_count(ddt_t *ddt, enum ddt_type type,
- enum ddt_class cls);
+extern int ddt_object_count(ddt_t *ddt, enum ddt_type type,
+ enum ddt_class class, uint64_t *count);
extern int ddt_object_info(ddt_t *ddt, enum ddt_type type,
enum ddt_class cls, dmu_object_info_t *);
extern boolean_t ddt_object_exists(ddt_t *ddt, enum ddt_type type,
OpenPOWER on IntegriCloud