Bugfix merge from OpenSolaris:
OpenSolaris onnv-revision: 10209:91f47f0e7728 6830541 zfs_get_data_trips on a verify 6696242 multiple zfs_fillpage() zfs: accessing past end of object panics 6785914 zfs fails to drop dn_struct_rwlock in recovery code path Approved by: delphij (mentor) Obtained from: OpenSolaris (Bug ID 6830541, 6696242, 6785914) MFC after: 2 weeks
This commit is contained in:
parent
7d6af40d1c
commit
e25376bdd0
@ -192,7 +192,7 @@ dmu_buf_hold_array_by_dnode(dnode_t *dn, uint64_t offset, uint64_t length,
|
||||
|
||||
ASSERT(length <= DMU_MAX_ACCESS);
|
||||
|
||||
dbuf_flags = DB_RF_CANFAIL | DB_RF_NEVERWAIT;
|
||||
dbuf_flags = DB_RF_CANFAIL | DB_RF_NEVERWAIT | DB_RF_HAVESTRUCT;
|
||||
if (flags & DMU_READ_NO_PREFETCH || length > zfetch_array_rd_sz)
|
||||
dbuf_flags |= DB_RF_NOPREFETCH;
|
||||
|
||||
@ -209,6 +209,7 @@ dmu_buf_hold_array_by_dnode(dnode_t *dn, uint64_t offset, uint64_t length,
|
||||
os_dsl_dataset->ds_object,
|
||||
(longlong_t)dn->dn_object, dn->dn_datablksz,
|
||||
(longlong_t)offset, (longlong_t)length);
|
||||
rw_exit(&dn->dn_struct_rwlock);
|
||||
return (EIO);
|
||||
}
|
||||
nblks = 1;
|
||||
@ -231,9 +232,7 @@ dmu_buf_hold_array_by_dnode(dnode_t *dn, uint64_t offset, uint64_t length,
|
||||
}
|
||||
/* initiate async i/o */
|
||||
if (read) {
|
||||
rw_exit(&dn->dn_struct_rwlock);
|
||||
(void) dbuf_read(db, zio, dbuf_flags);
|
||||
rw_enter(&dn->dn_struct_rwlock, RW_READER);
|
||||
}
|
||||
dbp[i] = &db->db;
|
||||
}
|
||||
@ -540,7 +539,7 @@ dmu_read(objset_t *os, uint64_t object, uint64_t offset, uint64_t size,
|
||||
{
|
||||
dnode_t *dn;
|
||||
dmu_buf_t **dbp;
|
||||
int numbufs, i, err;
|
||||
int numbufs, err;
|
||||
|
||||
err = dnode_hold(os->os, object, FTAG, &dn);
|
||||
if (err)
|
||||
@ -551,7 +550,7 @@ dmu_read(objset_t *os, uint64_t object, uint64_t offset, uint64_t size,
|
||||
* block. If we ever do the tail block optimization, we will need to
|
||||
* handle that here as well.
|
||||
*/
|
||||
if (dn->dn_datablkshift == 0) {
|
||||
if (dn->dn_maxblkid == 0) {
|
||||
int newsz = offset > dn->dn_datablksz ? 0 :
|
||||
MIN(size, dn->dn_datablksz - offset);
|
||||
bzero((char *)buf + newsz, size - newsz);
|
||||
@ -560,6 +559,7 @@ dmu_read(objset_t *os, uint64_t object, uint64_t offset, uint64_t size,
|
||||
|
||||
while (size > 0) {
|
||||
uint64_t mylen = MIN(size, DMU_MAX_ACCESS / 2);
|
||||
int i;
|
||||
|
||||
/*
|
||||
* NB: we could do this block-at-a-time, but it's nice
|
||||
|
@ -1031,6 +1031,10 @@ zfs_get_done(dmu_buf_t *db, void *vzgd)
|
||||
VFS_UNLOCK_GIANT(vfslocked);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static int zil_fault_io = 0;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Get data to generate a TX_WRITE intent log record.
|
||||
*/
|
||||
@ -1112,7 +1116,21 @@ zfs_get_data(void *arg, lr_write_t *lr, char *buf, zio_t *zio)
|
||||
zgd->zgd_rl = rl;
|
||||
zgd->zgd_zilog = zfsvfs->z_log;
|
||||
zgd->zgd_bp = &lr->lr_blkptr;
|
||||
VERIFY(0 == dmu_buf_hold(os, lr->lr_foid, boff, zgd, &db));
|
||||
#ifdef DEBUG
|
||||
if (zil_fault_io) {
|
||||
error = EIO;
|
||||
zil_fault_io = 0;
|
||||
} else {
|
||||
error = dmu_buf_hold(os, lr->lr_foid, boff, zgd, &db);
|
||||
}
|
||||
#else
|
||||
error = dmu_buf_hold(os, lr->lr_foid, boff, zgd, &db);
|
||||
#endif
|
||||
if (error != 0) {
|
||||
kmem_free(zgd, sizeof (zgd_t));
|
||||
goto out;
|
||||
}
|
||||
|
||||
ASSERT(boff == db->db_offset);
|
||||
lr->lr_blkoff = off - boff;
|
||||
error = dmu_sync(zio, db, &lr->lr_blkptr,
|
||||
|
@ -933,6 +933,10 @@ zil_lwb_commit(zilog_t *zilog, itx_t *itx, lwb_t *lwb)
|
||||
}
|
||||
error = zilog->zl_get_data(
|
||||
itx->itx_private, lr, dbuf, lwb->lwb_zio);
|
||||
if (error == EIO) {
|
||||
txg_wait_synced(zilog->zl_dmu_pool, txg);
|
||||
return (lwb);
|
||||
}
|
||||
if (error) {
|
||||
ASSERT(error == ENOENT || error == EEXIST ||
|
||||
error == EALREADY);
|
||||
|
Loading…
x
Reference in New Issue
Block a user