MFV 316896
7580 ztest failure in dbuf_read_impl
illumos/illumos-gate@1a01181fdc
1a01181fdc
https://www.illumos.org/issues/7580
We need to prevent any reader whenever we're about the zero out all the
blkptrs. To do this we need to grab the dn_struct_rwlock as writer in
dbuf_write_children_ready and free_children just prior to calling bzero.
Reviewed by: Pavel Zakharov <pavel.zakharov@delphix.com>
Reviewed by: Steve Gonczi <steve.gonczi@delphix.com>
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Approved by: Dan McDonald <danmcd@omniti.com>
Author: George Wilson <george.wilson@delphix.com>
This commit is contained in:
parent
2750ce9b17
commit
6911f4a88c
@ -3317,13 +3317,13 @@ dbuf_write_children_ready(zio_t *zio, arc_buf_t *buf, void *vdb)
|
|||||||
dmu_buf_impl_t *db = vdb;
|
dmu_buf_impl_t *db = vdb;
|
||||||
dnode_t *dn;
|
dnode_t *dn;
|
||||||
blkptr_t *bp;
|
blkptr_t *bp;
|
||||||
uint64_t i;
|
unsigned int epbs, i;
|
||||||
int epbs;
|
|
||||||
|
|
||||||
ASSERT3U(db->db_level, >, 0);
|
ASSERT3U(db->db_level, >, 0);
|
||||||
DB_DNODE_ENTER(db);
|
DB_DNODE_ENTER(db);
|
||||||
dn = DB_DNODE(db);
|
dn = DB_DNODE(db);
|
||||||
epbs = dn->dn_phys->dn_indblkshift - SPA_BLKPTRSHIFT;
|
epbs = dn->dn_phys->dn_indblkshift - SPA_BLKPTRSHIFT;
|
||||||
|
ASSERT3U(epbs, <, 31);
|
||||||
|
|
||||||
/* Determine if all our children are holes */
|
/* Determine if all our children are holes */
|
||||||
for (i = 0, bp = db->db.db_data; i < 1 << epbs; i++, bp++) {
|
for (i = 0, bp = db->db.db_data; i < 1 << epbs; i++, bp++) {
|
||||||
@ -3336,8 +3336,14 @@ dbuf_write_children_ready(zio_t *zio, arc_buf_t *buf, void *vdb)
|
|||||||
* we may get compressed away.
|
* we may get compressed away.
|
||||||
*/
|
*/
|
||||||
if (i == 1 << epbs) {
|
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);
|
bzero(db->db.db_data, db->db.db_size);
|
||||||
|
rw_exit(&dn->dn_struct_rwlock);
|
||||||
}
|
}
|
||||||
DB_DNODE_EXIT(db);
|
DB_DNODE_EXIT(db);
|
||||||
}
|
}
|
||||||
|
@ -236,8 +236,8 @@ free_children(dmu_buf_impl_t *db, uint64_t blkid, uint64_t nblks,
|
|||||||
dnode_t *dn;
|
dnode_t *dn;
|
||||||
blkptr_t *bp;
|
blkptr_t *bp;
|
||||||
dmu_buf_impl_t *subdb;
|
dmu_buf_impl_t *subdb;
|
||||||
uint64_t start, end, dbstart, dbend, i;
|
uint64_t start, end, dbstart, dbend;
|
||||||
int epbs, shift;
|
unsigned int epbs, shift, i;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* There is a small possibility that this block will not be cached:
|
* There is a small possibility that this block will not be cached:
|
||||||
@ -254,6 +254,7 @@ free_children(dmu_buf_impl_t *db, uint64_t blkid, uint64_t nblks,
|
|||||||
DB_DNODE_ENTER(db);
|
DB_DNODE_ENTER(db);
|
||||||
dn = DB_DNODE(db);
|
dn = DB_DNODE(db);
|
||||||
epbs = dn->dn_phys->dn_indblkshift - SPA_BLKPTRSHIFT;
|
epbs = dn->dn_phys->dn_indblkshift - SPA_BLKPTRSHIFT;
|
||||||
|
ASSERT3U(epbs, <, 31);
|
||||||
shift = (db->db_level - 1) * epbs;
|
shift = (db->db_level - 1) * epbs;
|
||||||
dbstart = db->db_blkid << epbs;
|
dbstart = db->db_blkid << epbs;
|
||||||
start = blkid >> shift;
|
start = blkid >> shift;
|
||||||
@ -273,12 +274,12 @@ free_children(dmu_buf_impl_t *db, uint64_t blkid, uint64_t nblks,
|
|||||||
FREE_VERIFY(db, start, end, tx);
|
FREE_VERIFY(db, start, end, tx);
|
||||||
free_blocks(dn, bp, end-start+1, tx);
|
free_blocks(dn, bp, end-start+1, tx);
|
||||||
} else {
|
} else {
|
||||||
for (i = start; i <= end; i++, bp++) {
|
for (uint64_t id = start; id <= end; id++, bp++) {
|
||||||
if (BP_IS_HOLE(bp))
|
if (BP_IS_HOLE(bp))
|
||||||
continue;
|
continue;
|
||||||
rw_enter(&dn->dn_struct_rwlock, RW_READER);
|
rw_enter(&dn->dn_struct_rwlock, RW_READER);
|
||||||
VERIFY0(dbuf_hold_impl(dn, db->db_level - 1,
|
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);
|
rw_exit(&dn->dn_struct_rwlock);
|
||||||
ASSERT3P(bp, ==, subdb->db_blkptr);
|
ASSERT3P(bp, ==, subdb->db_blkptr);
|
||||||
|
|
||||||
@ -293,8 +294,14 @@ free_children(dmu_buf_impl_t *db, uint64_t blkid, uint64_t nblks,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (i == 1 << epbs) {
|
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);
|
bzero(db->db.db_data, db->db.db_size);
|
||||||
|
rw_exit(&dn->dn_struct_rwlock);
|
||||||
free_blocks(dn, db->db_blkptr, 1, tx);
|
free_blocks(dn, db->db_blkptr, 1, tx);
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user