summaryrefslogtreecommitdiffstats
path: root/module
diff options
context:
space:
mode:
authorGeorge Melikov <[email protected]>2017-01-28 23:11:09 +0300
committerBrian Behlendorf <[email protected]>2017-01-28 12:11:09 -0800
commit721ed0ee86463cb3e4a562d86783fd1372182367 (patch)
tree43ed94a78c0fd358cb48f2129e528162f109ccb1 /module
parent160af771081bc21313ad0c111d66b348932fe5d2 (diff)
OpenZFS 7580 - ztest failure in dbuf_read_impl
Authored by: George Wilson <[email protected]> Reviewed by: Pavel Zakharov <[email protected]> Reviewed by: Steve Gonczi <[email protected]> Reviewed by: Matthew Ahrens <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Ported-by: George Melikov <[email protected]> OpenZFS-issue: https://www.illumos.org/issues/7580 OpenZFS-commit: https://github.com/openzfs/openzfs/commit/3105d95 Closes #5678
Diffstat (limited to 'module')
-rw-r--r--module/zfs/dbuf.c12
-rw-r--r--module/zfs/dnode_sync.c18
2 files changed, 22 insertions, 8 deletions
diff --git a/module/zfs/dbuf.c b/module/zfs/dbuf.c
index 01a761091..d2e65dd9c 100644
--- a/module/zfs/dbuf.c
+++ b/module/zfs/dbuf.c
@@ -3537,13 +3537,13 @@ dbuf_write_children_ready(zio_t *zio, arc_buf_t *buf, void *vdb)
dmu_buf_impl_t *db = vdb;
dnode_t *dn;
blkptr_t *bp;
- uint64_t i;
- int epbs;
+ unsigned int epbs, i;
ASSERT3U(db->db_level, >, 0);
DB_DNODE_ENTER(db);
dn = DB_DNODE(db);
epbs = dn->dn_phys->dn_indblkshift - SPA_BLKPTRSHIFT;
+ ASSERT3U(epbs, <, 31);
/* Determine if all our children are holes */
for (i = 0, bp = db->db.db_data; i < 1ULL << epbs; i++, bp++) {
@@ -3556,8 +3556,14 @@ dbuf_write_children_ready(zio_t *zio, arc_buf_t *buf, void *vdb)
* we may get compressed away.
*/
if (i == 1ULL << epbs) {
- /* didn't find any non-holes */
+ /*
+ * We only found holes. Grab the rwlock to prevent
+ * anybody from reading the blocks we're about to
+ * zero out.
+ */
+ rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
bzero(db->db.db_data, db->db.db_size);
+ rw_exit(&dn->dn_struct_rwlock);
}
DB_DNODE_EXIT(db);
}
diff --git a/module/zfs/dnode_sync.c b/module/zfs/dnode_sync.c
index d8527528a..9f3c6a2c7 100644
--- a/module/zfs/dnode_sync.c
+++ b/module/zfs/dnode_sync.c
@@ -240,8 +240,9 @@ free_children(dmu_buf_impl_t *db, uint64_t blkid, uint64_t nblks,
dnode_t *dn;
blkptr_t *bp;
dmu_buf_impl_t *subdb;
- uint64_t start, end, dbstart, dbend, i;
- int epbs, shift;
+ uint64_t start, end, dbstart, dbend;
+ unsigned int epbs, shift, i;
+ uint64_t id;
/*
* There is a small possibility that this block will not be cached:
@@ -258,6 +259,7 @@ free_children(dmu_buf_impl_t *db, uint64_t blkid, uint64_t nblks,
DB_DNODE_ENTER(db);
dn = DB_DNODE(db);
epbs = dn->dn_phys->dn_indblkshift - SPA_BLKPTRSHIFT;
+ ASSERT3U(epbs, <, 31);
shift = (db->db_level - 1) * epbs;
dbstart = db->db_blkid << epbs;
start = blkid >> shift;
@@ -277,12 +279,12 @@ free_children(dmu_buf_impl_t *db, uint64_t blkid, uint64_t nblks,
FREE_VERIFY(db, start, end, tx);
free_blocks(dn, bp, end-start+1, tx);
} else {
- for (i = start; i <= end; i++, bp++) {
+ for (id = start; id <= end; id++, bp++) {
if (BP_IS_HOLE(bp))
continue;
rw_enter(&dn->dn_struct_rwlock, RW_READER);
VERIFY0(dbuf_hold_impl(dn, db->db_level - 1,
- i, TRUE, FALSE, FTAG, &subdb));
+ id, TRUE, FALSE, FTAG, &subdb));
rw_exit(&dn->dn_struct_rwlock);
ASSERT3P(bp, ==, subdb->db_blkptr);
@@ -297,8 +299,14 @@ free_children(dmu_buf_impl_t *db, uint64_t blkid, uint64_t nblks,
break;
}
if (i == 1 << epbs) {
- /* didn't find any non-holes */
+ /*
+ * We only found holes. Grab the rwlock to prevent
+ * anybody from reading the blocks we're about to
+ * zero out.
+ */
+ rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
bzero(db->db.db_data, db->db.db_size);
+ rw_exit(&dn->dn_struct_rwlock);
free_blocks(dn, db->db_blkptr, 1, tx);
} else {
/*