Changeset View
Changeset View
Standalone View
Standalone View
sys/contrib/openzfs/module/zfs/dmu.c
Show First 20 Lines • Show All 1,164 Lines • ▼ Show 20 Lines | VERIFY0(dmu_buf_hold_array(os, object, offset, size, FALSE, FTAG, | ||||
&numbufs, &dbp)); | &numbufs, &dbp)); | ||||
for (i = 0; i < numbufs; i++) | for (i = 0; i < numbufs; i++) | ||||
dmu_buf_redact(dbp[i], tx); | dmu_buf_redact(dbp[i], tx); | ||||
dmu_buf_rele_array(dbp, numbufs, FTAG); | dmu_buf_rele_array(dbp, numbufs, FTAG); | ||||
} | } | ||||
#ifdef _KERNEL | #ifdef _KERNEL | ||||
int | int | ||||
dmu_read_uio_dnode(dnode_t *dn, uio_t *uio, uint64_t size) | dmu_read_uio_dnode(dnode_t *dn, zfs_uio_t *uio, uint64_t size) | ||||
{ | { | ||||
dmu_buf_t **dbp; | dmu_buf_t **dbp; | ||||
int numbufs, i, err; | int numbufs, i, err; | ||||
/* | /* | ||||
* NB: we could do this block-at-a-time, but it's nice | * NB: we could do this block-at-a-time, but it's nice | ||||
* to be reading in parallel. | * to be reading in parallel. | ||||
*/ | */ | ||||
err = dmu_buf_hold_array_by_dnode(dn, uio_offset(uio), size, | err = dmu_buf_hold_array_by_dnode(dn, zfs_uio_offset(uio), size, | ||||
TRUE, FTAG, &numbufs, &dbp, 0); | TRUE, FTAG, &numbufs, &dbp, 0); | ||||
if (err) | if (err) | ||||
return (err); | return (err); | ||||
for (i = 0; i < numbufs; i++) { | for (i = 0; i < numbufs; i++) { | ||||
uint64_t tocpy; | uint64_t tocpy; | ||||
int64_t bufoff; | int64_t bufoff; | ||||
dmu_buf_t *db = dbp[i]; | dmu_buf_t *db = dbp[i]; | ||||
ASSERT(size > 0); | ASSERT(size > 0); | ||||
bufoff = uio_offset(uio) - db->db_offset; | bufoff = zfs_uio_offset(uio) - db->db_offset; | ||||
tocpy = MIN(db->db_size - bufoff, size); | tocpy = MIN(db->db_size - bufoff, size); | ||||
#ifdef __FreeBSD__ | err = zfs_uio_fault_move((char *)db->db_data + bufoff, tocpy, | ||||
err = vn_io_fault_uiomove((char *)db->db_data + bufoff, | |||||
tocpy, uio); | |||||
#else | |||||
err = uiomove((char *)db->db_data + bufoff, tocpy, | |||||
UIO_READ, uio); | UIO_READ, uio); | ||||
#endif | |||||
if (err) | if (err) | ||||
break; | break; | ||||
size -= tocpy; | size -= tocpy; | ||||
} | } | ||||
dmu_buf_rele_array(dbp, numbufs, FTAG); | dmu_buf_rele_array(dbp, numbufs, FTAG); | ||||
return (err); | return (err); | ||||
} | } | ||||
/* | /* | ||||
* Read 'size' bytes into the uio buffer. | * Read 'size' bytes into the uio buffer. | ||||
* From object zdb->db_object. | * From object zdb->db_object. | ||||
* Starting at offset uio->uio_loffset. | * Starting at zfs_uio_offset(uio). | ||||
* | * | ||||
* If the caller already has a dbuf in the target object | * If the caller already has a dbuf in the target object | ||||
* (e.g. its bonus buffer), this routine is faster than dmu_read_uio(), | * (e.g. its bonus buffer), this routine is faster than dmu_read_uio(), | ||||
* because we don't have to find the dnode_t for the object. | * because we don't have to find the dnode_t for the object. | ||||
*/ | */ | ||||
int | int | ||||
dmu_read_uio_dbuf(dmu_buf_t *zdb, uio_t *uio, uint64_t size) | dmu_read_uio_dbuf(dmu_buf_t *zdb, zfs_uio_t *uio, uint64_t size) | ||||
{ | { | ||||
dmu_buf_impl_t *db = (dmu_buf_impl_t *)zdb; | dmu_buf_impl_t *db = (dmu_buf_impl_t *)zdb; | ||||
dnode_t *dn; | dnode_t *dn; | ||||
int err; | int err; | ||||
if (size == 0) | if (size == 0) | ||||
return (0); | return (0); | ||||
DB_DNODE_ENTER(db); | DB_DNODE_ENTER(db); | ||||
dn = DB_DNODE(db); | dn = DB_DNODE(db); | ||||
err = dmu_read_uio_dnode(dn, uio, size); | err = dmu_read_uio_dnode(dn, uio, size); | ||||
DB_DNODE_EXIT(db); | DB_DNODE_EXIT(db); | ||||
return (err); | return (err); | ||||
} | } | ||||
/* | /* | ||||
* Read 'size' bytes into the uio buffer. | * Read 'size' bytes into the uio buffer. | ||||
* From the specified object | * From the specified object | ||||
* Starting at offset uio->uio_loffset. | * Starting at offset zfs_uio_offset(uio). | ||||
*/ | */ | ||||
int | int | ||||
dmu_read_uio(objset_t *os, uint64_t object, uio_t *uio, uint64_t size) | dmu_read_uio(objset_t *os, uint64_t object, zfs_uio_t *uio, uint64_t size) | ||||
{ | { | ||||
dnode_t *dn; | dnode_t *dn; | ||||
int err; | int err; | ||||
if (size == 0) | if (size == 0) | ||||
return (0); | return (0); | ||||
err = dnode_hold(os, object, FTAG, &dn); | err = dnode_hold(os, object, FTAG, &dn); | ||||
if (err) | if (err) | ||||
return (err); | return (err); | ||||
err = dmu_read_uio_dnode(dn, uio, size); | err = dmu_read_uio_dnode(dn, uio, size); | ||||
dnode_rele(dn, FTAG); | dnode_rele(dn, FTAG); | ||||
return (err); | return (err); | ||||
} | } | ||||
int | int | ||||
dmu_write_uio_dnode(dnode_t *dn, uio_t *uio, uint64_t size, dmu_tx_t *tx) | dmu_write_uio_dnode(dnode_t *dn, zfs_uio_t *uio, uint64_t size, dmu_tx_t *tx) | ||||
{ | { | ||||
dmu_buf_t **dbp; | dmu_buf_t **dbp; | ||||
int numbufs; | int numbufs; | ||||
int err = 0; | int err = 0; | ||||
int i; | int i; | ||||
err = dmu_buf_hold_array_by_dnode(dn, uio_offset(uio), size, | err = dmu_buf_hold_array_by_dnode(dn, zfs_uio_offset(uio), size, | ||||
FALSE, FTAG, &numbufs, &dbp, DMU_READ_PREFETCH); | FALSE, FTAG, &numbufs, &dbp, DMU_READ_PREFETCH); | ||||
if (err) | if (err) | ||||
return (err); | return (err); | ||||
for (i = 0; i < numbufs; i++) { | for (i = 0; i < numbufs; i++) { | ||||
uint64_t tocpy; | uint64_t tocpy; | ||||
int64_t bufoff; | int64_t bufoff; | ||||
dmu_buf_t *db = dbp[i]; | dmu_buf_t *db = dbp[i]; | ||||
ASSERT(size > 0); | ASSERT(size > 0); | ||||
bufoff = uio_offset(uio) - db->db_offset; | bufoff = zfs_uio_offset(uio) - db->db_offset; | ||||
tocpy = MIN(db->db_size - bufoff, size); | tocpy = MIN(db->db_size - bufoff, size); | ||||
ASSERT(i == 0 || i == numbufs-1 || tocpy == db->db_size); | ASSERT(i == 0 || i == numbufs-1 || tocpy == db->db_size); | ||||
if (tocpy == db->db_size) | if (tocpy == db->db_size) | ||||
dmu_buf_will_fill(db, tx); | dmu_buf_will_fill(db, tx); | ||||
else | else | ||||
dmu_buf_will_dirty(db, tx); | dmu_buf_will_dirty(db, tx); | ||||
/* | /* | ||||
* XXX uiomove could block forever (eg.nfs-backed | * XXX zfs_uiomove could block forever (eg.nfs-backed | ||||
* pages). There needs to be a uiolockdown() function | * pages). There needs to be a uiolockdown() function | ||||
* to lock the pages in memory, so that uiomove won't | * to lock the pages in memory, so that zfs_uiomove won't | ||||
* block. | * block. | ||||
*/ | */ | ||||
#ifdef __FreeBSD__ | err = zfs_uio_fault_move((char *)db->db_data + bufoff, | ||||
err = vn_io_fault_uiomove((char *)db->db_data + bufoff, | tocpy, UIO_WRITE, uio); | ||||
tocpy, uio); | |||||
#else | |||||
err = uiomove((char *)db->db_data + bufoff, tocpy, | |||||
UIO_WRITE, uio); | |||||
#endif | |||||
if (tocpy == db->db_size) | if (tocpy == db->db_size) | ||||
dmu_buf_fill_done(db, tx); | dmu_buf_fill_done(db, tx); | ||||
if (err) | if (err) | ||||
break; | break; | ||||
size -= tocpy; | size -= tocpy; | ||||
} | } | ||||
dmu_buf_rele_array(dbp, numbufs, FTAG); | dmu_buf_rele_array(dbp, numbufs, FTAG); | ||||
return (err); | return (err); | ||||
} | } | ||||
/* | /* | ||||
* Write 'size' bytes from the uio buffer. | * Write 'size' bytes from the uio buffer. | ||||
* To object zdb->db_object. | * To object zdb->db_object. | ||||
* Starting at offset uio->uio_loffset. | * Starting at offset zfs_uio_offset(uio). | ||||
* | * | ||||
* If the caller already has a dbuf in the target object | * If the caller already has a dbuf in the target object | ||||
* (e.g. its bonus buffer), this routine is faster than dmu_write_uio(), | * (e.g. its bonus buffer), this routine is faster than dmu_write_uio(), | ||||
* because we don't have to find the dnode_t for the object. | * because we don't have to find the dnode_t for the object. | ||||
*/ | */ | ||||
int | int | ||||
dmu_write_uio_dbuf(dmu_buf_t *zdb, uio_t *uio, uint64_t size, | dmu_write_uio_dbuf(dmu_buf_t *zdb, zfs_uio_t *uio, uint64_t size, | ||||
dmu_tx_t *tx) | dmu_tx_t *tx) | ||||
{ | { | ||||
dmu_buf_impl_t *db = (dmu_buf_impl_t *)zdb; | dmu_buf_impl_t *db = (dmu_buf_impl_t *)zdb; | ||||
dnode_t *dn; | dnode_t *dn; | ||||
int err; | int err; | ||||
if (size == 0) | if (size == 0) | ||||
return (0); | return (0); | ||||
DB_DNODE_ENTER(db); | DB_DNODE_ENTER(db); | ||||
dn = DB_DNODE(db); | dn = DB_DNODE(db); | ||||
err = dmu_write_uio_dnode(dn, uio, size, tx); | err = dmu_write_uio_dnode(dn, uio, size, tx); | ||||
DB_DNODE_EXIT(db); | DB_DNODE_EXIT(db); | ||||
return (err); | return (err); | ||||
} | } | ||||
/* | /* | ||||
* Write 'size' bytes from the uio buffer. | * Write 'size' bytes from the uio buffer. | ||||
* To the specified object. | * To the specified object. | ||||
* Starting at offset uio->uio_loffset. | * Starting at offset zfs_uio_offset(uio). | ||||
*/ | */ | ||||
int | int | ||||
dmu_write_uio(objset_t *os, uint64_t object, uio_t *uio, uint64_t size, | dmu_write_uio(objset_t *os, uint64_t object, zfs_uio_t *uio, uint64_t size, | ||||
dmu_tx_t *tx) | dmu_tx_t *tx) | ||||
{ | { | ||||
dnode_t *dn; | dnode_t *dn; | ||||
int err; | int err; | ||||
if (size == 0) | if (size == 0) | ||||
return (0); | return (0); | ||||
▲ Show 20 Lines • Show All 230 Lines • ▼ Show 20 Lines | if (!BP_IS_HOLE(bp)) { | ||||
zio_free(zio->io_spa, zio->io_txg, zio->io_bp); | zio_free(zio->io_spa, zio->io_txg, zio->io_bp); | ||||
} | } | ||||
} | } | ||||
dmu_tx_commit(dsa->dsa_tx); | dmu_tx_commit(dsa->dsa_tx); | ||||
dsa->dsa_done(dsa->dsa_zgd, zio->io_error); | dsa->dsa_done(dsa->dsa_zgd, zio->io_error); | ||||
abd_put(zio->io_abd); | abd_free(zio->io_abd); | ||||
kmem_free(dsa, sizeof (*dsa)); | kmem_free(dsa, sizeof (*dsa)); | ||||
} | } | ||||
static int | static int | ||||
dmu_sync_late_arrival(zio_t *pio, objset_t *os, dmu_sync_cb_t *done, zgd_t *zgd, | dmu_sync_late_arrival(zio_t *pio, objset_t *os, dmu_sync_cb_t *done, zgd_t *zgd, | ||||
zio_prop_t *zp, zbookmark_phys_t *zb) | zio_prop_t *zp, zbookmark_phys_t *zb) | ||||
{ | { | ||||
dmu_sync_arg_t *dsa; | dmu_sync_arg_t *dsa; | ||||
▲ Show 20 Lines • Show All 730 Lines • Show Last 20 Lines |