Backport the 'dirtying dbuf' panic fix from newer ZFS version.
Reported by: Thomas Backman <serenity@exscape.org> MFC after: 1 week
This commit is contained in:
parent
612aa2a9b0
commit
26d0605727
@ -19,7 +19,7 @@
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
@ -864,10 +864,11 @@ restore_object(struct restorearg *ra, objset_t *os, struct drr_object *drro)
|
||||
/* currently allocated, want to be allocated */
|
||||
dmu_tx_hold_bonus(tx, drro->drr_object);
|
||||
/*
|
||||
* We may change blocksize, so need to
|
||||
* hold_write
|
||||
* We may change blocksize and delete old content,
|
||||
* so need to hold_write and hold_free.
|
||||
*/
|
||||
dmu_tx_hold_write(tx, drro->drr_object, 0, 1);
|
||||
dmu_tx_hold_free(tx, drro->drr_object, 0, DMU_OBJECT_END);
|
||||
err = dmu_tx_assign(tx, TXG_WAIT);
|
||||
if (err) {
|
||||
dmu_tx_abort(tx);
|
||||
|
@ -415,7 +415,7 @@ void
|
||||
dnode_reallocate(dnode_t *dn, dmu_object_type_t ot, int blocksize,
|
||||
dmu_object_type_t bonustype, int bonuslen, dmu_tx_t *tx)
|
||||
{
|
||||
int i, old_nblkptr;
|
||||
int i, nblkptr;
|
||||
dmu_buf_impl_t *db = NULL;
|
||||
|
||||
ASSERT3U(blocksize, >=, SPA_MINBLOCKSIZE);
|
||||
@ -445,6 +445,8 @@ dnode_reallocate(dnode_t *dn, dmu_object_type_t ot, int blocksize,
|
||||
dnode_free_range(dn, 0, -1ULL, tx);
|
||||
}
|
||||
|
||||
nblkptr = 1 + ((DN_MAX_BONUSLEN - bonuslen) >> SPA_BLKPTRSHIFT);
|
||||
|
||||
/* change blocksize */
|
||||
rw_enter(&dn->dn_struct_rwlock, RW_WRITER);
|
||||
if (blocksize != dn->dn_datablksz &&
|
||||
@ -457,6 +459,8 @@ dnode_reallocate(dnode_t *dn, dmu_object_type_t ot, int blocksize,
|
||||
dnode_setdirty(dn, tx);
|
||||
dn->dn_next_bonuslen[tx->tx_txg&TXG_MASK] = bonuslen;
|
||||
dn->dn_next_blksz[tx->tx_txg&TXG_MASK] = blocksize;
|
||||
if (dn->dn_nblkptr != nblkptr)
|
||||
dn->dn_next_nblkptr[tx->tx_txg&TXG_MASK] = nblkptr;
|
||||
rw_exit(&dn->dn_struct_rwlock);
|
||||
if (db)
|
||||
dbuf_rele(db, FTAG);
|
||||
@ -466,19 +470,15 @@ dnode_reallocate(dnode_t *dn, dmu_object_type_t ot, int blocksize,
|
||||
|
||||
/* change bonus size and type */
|
||||
mutex_enter(&dn->dn_mtx);
|
||||
old_nblkptr = dn->dn_nblkptr;
|
||||
dn->dn_bonustype = bonustype;
|
||||
dn->dn_bonuslen = bonuslen;
|
||||
dn->dn_nblkptr = 1 + ((DN_MAX_BONUSLEN - bonuslen) >> SPA_BLKPTRSHIFT);
|
||||
dn->dn_nblkptr = nblkptr;
|
||||
dn->dn_checksum = ZIO_CHECKSUM_INHERIT;
|
||||
dn->dn_compress = ZIO_COMPRESS_INHERIT;
|
||||
ASSERT3U(dn->dn_nblkptr, <=, DN_MAX_NBLKPTR);
|
||||
|
||||
/* XXX - for now, we can't make nblkptr smaller */
|
||||
ASSERT3U(dn->dn_nblkptr, >=, old_nblkptr);
|
||||
|
||||
/* fix up the bonus db_size if dn_nblkptr has changed */
|
||||
if (dn->dn_bonus && dn->dn_bonuslen != old_nblkptr) {
|
||||
/* fix up the bonus db_size */
|
||||
if (dn->dn_bonus) {
|
||||
dn->dn_bonus->db.db_size =
|
||||
DN_MAX_BONUSLEN - (dn->dn_nblkptr-1) * sizeof (blkptr_t);
|
||||
ASSERT(dn->dn_bonuslen <= dn->dn_bonus->db.db_size);
|
||||
|
@ -19,12 +19,10 @@
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
#include <sys/zfs_context.h>
|
||||
#include <sys/dbuf.h>
|
||||
#include <sys/dnode.h>
|
||||
@ -534,18 +532,12 @@ dnode_sync(dnode_t *dn, dmu_tx_t *tx)
|
||||
/* XXX shouldn't the phys already be zeroed? */
|
||||
bzero(dnp, DNODE_CORE_SIZE);
|
||||
dnp->dn_nlevels = 1;
|
||||
dnp->dn_nblkptr = dn->dn_nblkptr;
|
||||
}
|
||||
|
||||
if (dn->dn_nblkptr > dnp->dn_nblkptr) {
|
||||
/* zero the new blkptrs we are gaining */
|
||||
bzero(dnp->dn_blkptr + dnp->dn_nblkptr,
|
||||
sizeof (blkptr_t) *
|
||||
(dn->dn_nblkptr - dnp->dn_nblkptr));
|
||||
}
|
||||
dnp->dn_type = dn->dn_type;
|
||||
dnp->dn_bonustype = dn->dn_bonustype;
|
||||
dnp->dn_bonuslen = dn->dn_bonuslen;
|
||||
dnp->dn_nblkptr = dn->dn_nblkptr;
|
||||
}
|
||||
|
||||
ASSERT(dnp->dn_nlevels > 1 ||
|
||||
@ -605,6 +597,30 @@ dnode_sync(dnode_t *dn, dmu_tx_t *tx)
|
||||
return;
|
||||
}
|
||||
|
||||
if (dn->dn_next_nblkptr[txgoff]) {
|
||||
/* this should only happen on a realloc */
|
||||
ASSERT(dn->dn_allocated_txg == tx->tx_txg);
|
||||
if (dn->dn_next_nblkptr[txgoff] > dnp->dn_nblkptr) {
|
||||
/* zero the new blkptrs we are gaining */
|
||||
bzero(dnp->dn_blkptr + dnp->dn_nblkptr,
|
||||
sizeof (blkptr_t) *
|
||||
(dn->dn_next_nblkptr[txgoff] - dnp->dn_nblkptr));
|
||||
#ifdef ZFS_DEBUG
|
||||
} else {
|
||||
int i;
|
||||
ASSERT(dn->dn_next_nblkptr[txgoff] < dnp->dn_nblkptr);
|
||||
/* the blkptrs we are losing better be unallocated */
|
||||
for (i = dn->dn_next_nblkptr[txgoff];
|
||||
i < dnp->dn_nblkptr; i++)
|
||||
ASSERT(BP_IS_HOLE(&dnp->dn_blkptr[i]));
|
||||
#endif
|
||||
}
|
||||
mutex_enter(&dn->dn_mtx);
|
||||
dnp->dn_nblkptr = dn->dn_next_nblkptr[txgoff];
|
||||
dn->dn_next_nblkptr[txgoff] = 0;
|
||||
mutex_exit(&dn->dn_mtx);
|
||||
}
|
||||
|
||||
if (dn->dn_next_nlevels[txgoff]) {
|
||||
dnode_increase_indirection(dn, tx);
|
||||
dn->dn_next_nlevels[txgoff] = 0;
|
||||
|
@ -19,7 +19,7 @@
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
@ -160,6 +160,7 @@ typedef struct dnode {
|
||||
uint16_t dn_datablkszsec; /* in 512b sectors */
|
||||
uint32_t dn_datablksz; /* in bytes */
|
||||
uint64_t dn_maxblkid;
|
||||
uint8_t dn_next_nblkptr[TXG_SIZE];
|
||||
uint8_t dn_next_nlevels[TXG_SIZE];
|
||||
uint8_t dn_next_indblkshift[TXG_SIZE];
|
||||
uint16_t dn_next_bonuslen[TXG_SIZE];
|
||||
|
Loading…
Reference in New Issue
Block a user