}
nblks = 1;
}
- dbp = kmem_zalloc(sizeof (dmu_buf_t *) * nblks, KM_SLEEP | KM_NODEBUG);
+ dbp = kmem_zalloc(sizeof (dmu_buf_t *) * nblks, KM_PUSHPAGE | KM_NODEBUG);
if (dn->dn_objset->os_dsl_dataset)
dp = dn->dn_objset->os_dsl_dataset->ds_dir->dd_pool;
uio_t *uio = &xuio->xu_uio;
uio->uio_iovcnt = nblk;
- uio->uio_iov = kmem_zalloc(nblk * sizeof (iovec_t), KM_SLEEP);
+ uio->uio_iov = kmem_zalloc(nblk * sizeof (iovec_t), KM_PUSHPAGE);
- priv = kmem_zalloc(sizeof (dmu_xuio_t), KM_SLEEP);
+ priv = kmem_zalloc(sizeof (dmu_xuio_t), KM_PUSHPAGE);
priv->cnt = nblk;
- priv->bufs = kmem_zalloc(nblk * sizeof (arc_buf_t *), KM_SLEEP);
+ priv->bufs = kmem_zalloc(nblk * sizeof (arc_buf_t *), KM_PUSHPAGE);
priv->iovp = uio->uio_iov;
XUIO_XUZC_PRIV(xuio) = priv;
return 0;
}
+static void
+dmu_bio_put(struct bio *bio)
+{
+ struct bio *bio_next;
+
+ while (bio) {
+ bio_next = bio->bi_next;
+ bio_put(bio);
+ bio = bio_next;
+ }
+}
+
+static int
+dmu_bio_clone(struct bio *bio, struct bio **bio_copy)
+{
+ struct bio *bio_root = NULL;
+ struct bio *bio_last = NULL;
+ struct bio *bio_new;
+
+ if (bio == NULL)
+ return EINVAL;
+
+ while (bio) {
+ bio_new = bio_clone(bio, GFP_NOIO);
+ if (bio_new == NULL) {
+ dmu_bio_put(bio_root);
+ return ENOMEM;
+ }
+
+ if (bio_last) {
+ bio_last->bi_next = bio_new;
+ bio_last = bio_new;
+ } else {
+ bio_root = bio_new;
+ bio_last = bio_new;
+ }
+
+ bio = bio->bi_next;
+ }
+
+ *bio_copy = bio_root;
+
+ return 0;
+}
+
int
dmu_read_req(objset_t *os, uint64_t object, struct request *req)
{
uint64_t size = blk_rq_bytes(req);
uint64_t offset = blk_rq_pos(req) << 9;
+ struct bio *bio_saved = req->bio;
dmu_buf_t **dbp;
int numbufs, i, err;
if (err)
return (err);
+ /*
+ * Clone the bio list so the bv->bv_offset and bv->bv_len members
+ * can be safely modified. The original bio list is relinked in to
+ * the request when the function exits. This is required because
+ * some file systems blindly assume that these values will remain
+ * constant between bio_submit() and the IO completion callback.
+ */
+ err = dmu_bio_clone(bio_saved, &req->bio);
+ if (err)
+ goto error;
+
for (i = 0; i < numbufs; i++) {
int tocpy, didcpy, bufoff;
dmu_buf_t *db = dbp[i];
offset += didcpy;
err = 0;
}
+
+ dmu_bio_put(req->bio);
+ req->bio = bio_saved;
+error:
dmu_buf_rele_array(dbp, numbufs, FTAG);
return (err);
{
uint64_t size = blk_rq_bytes(req);
uint64_t offset = blk_rq_pos(req) << 9;
+ struct bio *bio_saved = req->bio;
dmu_buf_t **dbp;
int numbufs;
int err = 0;
if (err)
return (err);
+ /*
+ * Clone the bio list so the bv->bv_offset and bv->bv_len members
+ * can be safely modified. The original bio list is relinked in to
+ * the request when the function exits. This is required because
+ * some file systems blindly assume that these values will remain
+ * constant between bio_submit() and the IO completion callback.
+ */
+ err = dmu_bio_clone(bio_saved, &req->bio);
+ if (err)
+ goto error;
+
for (i = 0; i < numbufs; i++) {
int tocpy, didcpy, bufoff;
dmu_buf_t *db = dbp[i];
err = 0;
}
+ dmu_bio_put(req->bio);
+ req->bio = bio_saved;
+error:
dmu_buf_rele_array(dbp, numbufs, FTAG);
+
return (err);
}
return (EIO); /* Make zl_get_data do txg_waited_synced() */
}
- dsa = kmem_alloc(sizeof (dmu_sync_arg_t), KM_SLEEP);
+ dsa = kmem_alloc(sizeof (dmu_sync_arg_t), KM_PUSHPAGE);
dsa->dsa_dr = NULL;
dsa->dsa_done = done;
dsa->dsa_zgd = zgd;
zio_nowait(zio_write(pio, os->os_spa, dmu_tx_get_txg(tx), zgd->zgd_bp,
zgd->zgd_db->db_data, zgd->zgd_db->db_size, zp,
dmu_sync_late_arrival_ready, dmu_sync_late_arrival_done, dsa,
- ZIO_PRIORITY_SYNC_WRITE, ZIO_FLAG_CANFAIL, zb));
+ ZIO_PRIORITY_SYNC_WRITE, ZIO_FLAG_CANFAIL | ZIO_FLAG_FASTWRITE, zb));
return (0);
}
dr->dt.dl.dr_override_state = DR_IN_DMU_SYNC;
mutex_exit(&db->db_mtx);
- dsa = kmem_alloc(sizeof (dmu_sync_arg_t), KM_SLEEP);
+ dsa = kmem_alloc(sizeof (dmu_sync_arg_t), KM_PUSHPAGE);
dsa->dsa_dr = dr;
dsa->dsa_done = done;
dsa->dsa_zgd = zgd;
zio_nowait(arc_write(pio, os->os_spa, txg,
bp, dr->dt.dl.dr_data, DBUF_IS_L2CACHEABLE(db), &zp,
dmu_sync_ready, dmu_sync_done, dsa,
- ZIO_PRIORITY_SYNC_WRITE, ZIO_FLAG_CANFAIL, &zb));
+ ZIO_PRIORITY_SYNC_WRITE, ZIO_FLAG_CANFAIL | ZIO_FLAG_FASTWRITE, &zb));
return (0);
}
dnode_init();
dbuf_init();
zfetch_init();
+ dmu_tx_init();
arc_init();
l2arc_init();
}
{
l2arc_fini();
arc_fini();
+ dmu_tx_fini();
zfetch_fini();
dbuf_fini();
dnode_fini();
#if defined(_KERNEL) && defined(HAVE_SPL)
EXPORT_SYMBOL(dmu_bonus_hold);
+EXPORT_SYMBOL(dmu_buf_hold_array_by_bonus);
+EXPORT_SYMBOL(dmu_buf_rele_array);
EXPORT_SYMBOL(dmu_free_range);
EXPORT_SYMBOL(dmu_read);
EXPORT_SYMBOL(dmu_write);
-
-/* Get information on a DMU object. */
EXPORT_SYMBOL(dmu_object_info);
EXPORT_SYMBOL(dmu_object_info_from_dnode);
EXPORT_SYMBOL(dmu_object_info_from_db);
EXPORT_SYMBOL(dmu_object_size_from_db);
-
EXPORT_SYMBOL(dmu_object_set_blocksize);
EXPORT_SYMBOL(dmu_object_set_checksum);
EXPORT_SYMBOL(dmu_object_set_compress);
-
+EXPORT_SYMBOL(dmu_request_arcbuf);
+EXPORT_SYMBOL(dmu_return_arcbuf);
+EXPORT_SYMBOL(dmu_assign_arcbuf);
+EXPORT_SYMBOL(dmu_buf_hold);
EXPORT_SYMBOL(dmu_ot);
+
+module_param(zfs_mdcomp_disable, int, 0644);
+MODULE_PARM_DESC(zfs_mdcomp_disable, "Disable meta data compression");
#endif