Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Misc uio update #4078

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions include/linux/blkdev_compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,15 @@ get_disk_ro(struct gendisk *disk)
#define BIO_BI_SECTOR(bio) (bio)->bi_iter.bi_sector
#define BIO_BI_SIZE(bio) (bio)->bi_iter.bi_size
#define BIO_BI_IDX(bio) (bio)->bi_iter.bi_idx
#define BIO_BI_SKIP(bio) (bio)->bi_iter.bi_bvec_done
#define bio_for_each_segment4(bv, bvp, b, i) \
bio_for_each_segment((bv), (b), (i))
typedef struct bvec_iter bvec_iterator_t;
#else
#define BIO_BI_SECTOR(bio) (bio)->bi_sector
#define BIO_BI_SIZE(bio) (bio)->bi_size
#define BIO_BI_IDX(bio) (bio)->bi_idx
#define BIO_BI_SKIP(bio) (0)
#define bio_for_each_segment4(bv, bvp, b, i) \
bio_for_each_segment((bvp), (b), (i))
typedef int bvec_iterator_t;
Expand Down
11 changes: 6 additions & 5 deletions module/zcommon/zfs_uio.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ uio_prefaultpages(ssize_t n, struct uio *uio)
caddr_t p;
uint8_t tmp;
int iovcnt;
size_t skip = uio->uio_skip;
size_t skip;

/* no need to fault in kernel pages */
switch (uio->uio_segflg) {
Expand All @@ -180,9 +180,13 @@ uio_prefaultpages(ssize_t n, struct uio *uio)

iov = uio->uio_iov;
iovcnt = uio->uio_iovcnt;
skip = uio->uio_skip;

while ((n > 0) && (iovcnt > 0)) {
for (; n > 0 && iovcnt > 0; iov++, iovcnt--, skip = 0) {
cnt = MIN(iov->iov_len - skip, n);
/* empty iov */
if (cnt == 0)
continue;
n -= cnt;
/*
* touch each page in this segment.
Expand All @@ -201,9 +205,6 @@ uio_prefaultpages(ssize_t n, struct uio *uio)
p--;
if (fuword8((uint8_t *) p, &tmp))
return;
iov++;
iovcnt--;
skip = 0;
}
}
EXPORT_SYMBOL(uio_prefaultpages);
Expand Down
164 changes: 0 additions & 164 deletions module/zfs/dmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -1041,170 +1041,6 @@ xuio_stat_wbuf_nocopy()
}

#ifdef _KERNEL

/*
* Copy up to size bytes between arg_buf and req based on the data direction
* described by the req. If an entire req's data cannot be transfered in one
* pass, you should pass in @req_offset to indicate where to continue. The
* return value is the number of bytes successfully copied to arg_buf.
*/
static int
dmu_bio_copy(void *arg_buf, int size, struct bio *bio, size_t bio_offset)
{
struct bio_vec bv, *bvp = &bv;
bvec_iterator_t iter;
char *bv_buf;
int tocpy, bv_len, bv_offset;
int offset = 0;

bio_for_each_segment4(bv, bvp, bio, iter) {

/*
* Fully consumed the passed arg_buf. We use goto here because
* rq_for_each_segment is a double loop
*/
ASSERT3S(offset, <=, size);
if (size == offset)
goto out;

/* Skip already copied bvp */
if (bio_offset >= bvp->bv_len) {
bio_offset -= bvp->bv_len;
continue;
}

bv_len = bvp->bv_len - bio_offset;
bv_offset = bvp->bv_offset + bio_offset;
bio_offset = 0;

tocpy = MIN(bv_len, size - offset);
ASSERT3S(tocpy, >=, 0);

bv_buf = page_address(bvp->bv_page) + bv_offset;
ASSERT3P(bv_buf, !=, NULL);

if (bio_data_dir(bio) == WRITE)
memcpy(arg_buf + offset, bv_buf, tocpy);
else
memcpy(bv_buf, arg_buf + offset, tocpy);

offset += tocpy;
}
out:
return (offset);
}

int
dmu_read_bio(objset_t *os, uint64_t object, struct bio *bio)
{
uint64_t offset = BIO_BI_SECTOR(bio) << 9;
uint64_t size = BIO_BI_SIZE(bio);
dmu_buf_t **dbp;
int numbufs, i, err;
size_t bio_offset;

/*
* NB: we could do this block-at-a-time, but it's nice
* to be reading in parallel.
*/
err = dmu_buf_hold_array(os, object, offset, size, TRUE, FTAG,
&numbufs, &dbp);
if (err)
return (err);

bio_offset = 0;
for (i = 0; i < numbufs; i++) {
uint64_t tocpy;
int64_t bufoff;
int didcpy;
dmu_buf_t *db = dbp[i];

bufoff = offset - db->db_offset;
ASSERT3S(bufoff, >=, 0);

tocpy = MIN(db->db_size - bufoff, size);
if (tocpy == 0)
break;

didcpy = dmu_bio_copy(db->db_data + bufoff, tocpy, bio,
bio_offset);

if (didcpy < tocpy)
err = EIO;

if (err)
break;

size -= tocpy;
offset += didcpy;
bio_offset += didcpy;
err = 0;
}
dmu_buf_rele_array(dbp, numbufs, FTAG);

return (err);
}

int
dmu_write_bio(objset_t *os, uint64_t object, struct bio *bio, dmu_tx_t *tx)
{
uint64_t offset = BIO_BI_SECTOR(bio) << 9;
uint64_t size = BIO_BI_SIZE(bio);
dmu_buf_t **dbp;
int numbufs, i, err;
size_t bio_offset;

if (size == 0)
return (0);

err = dmu_buf_hold_array(os, object, offset, size, FALSE, FTAG,
&numbufs, &dbp);
if (err)
return (err);

bio_offset = 0;
for (i = 0; i < numbufs; i++) {
uint64_t tocpy;
int64_t bufoff;
int didcpy;
dmu_buf_t *db = dbp[i];

bufoff = offset - db->db_offset;
ASSERT3S(bufoff, >=, 0);

tocpy = MIN(db->db_size - bufoff, size);
if (tocpy == 0)
break;

ASSERT(i == 0 || i == numbufs-1 || tocpy == db->db_size);

if (tocpy == db->db_size)
dmu_buf_will_fill(db, tx);
else
dmu_buf_will_dirty(db, tx);

didcpy = dmu_bio_copy(db->db_data + bufoff, tocpy, bio,
bio_offset);

if (tocpy == db->db_size)
dmu_buf_fill_done(db, tx);

if (didcpy < tocpy)
err = EIO;

if (err)
break;

size -= tocpy;
offset += didcpy;
bio_offset += didcpy;
err = 0;
}

dmu_buf_rele_array(dbp, numbufs, FTAG);
return (err);
}

static int
dmu_read_uio_dnode(dnode_t *dn, uio_t *uio, uint64_t size)
{
Expand Down
27 changes: 22 additions & 5 deletions module/zfs/zvol.c
Original file line number Diff line number Diff line change
Expand Up @@ -597,6 +597,7 @@ zvol_write(struct bio *bio)
int error = 0;
dmu_tx_t *tx;
rl_t *rl;
uio_t uio;

if (bio->bi_rw & VDEV_REQ_FLUSH)
zil_commit(zv->zv_zilog, ZVOL_OBJ);
Expand All @@ -607,6 +608,14 @@ zvol_write(struct bio *bio)
if (size == 0)
goto out;

uio.uio_bvec = &bio->bi_io_vec[BIO_BI_IDX(bio)];
uio.uio_skip = BIO_BI_SKIP(bio);
uio.uio_resid = size;
uio.uio_iovcnt = bio->bi_vcnt - BIO_BI_IDX(bio);
uio.uio_loffset = offset;
uio.uio_limit = MAXOFFSET_T;
uio.uio_segflg = UIO_BVEC;

rl = zfs_range_lock(&zv->zv_znode, offset, size, RL_WRITER);

tx = dmu_tx_create(zv->zv_objset);
Expand All @@ -620,7 +629,7 @@ zvol_write(struct bio *bio)
goto out;
}

error = dmu_write_bio(zv->zv_objset, ZVOL_OBJ, bio, tx);
error = dmu_write_uio(zv->zv_objset, ZVOL_OBJ, &uio, size, tx);
if (error == 0)
zvol_log_write(zv, tx, offset, size,
!!(bio->bi_rw & VDEV_REQ_FUA));
Expand Down Expand Up @@ -686,17 +695,25 @@ zvol_read(struct bio *bio)
{
zvol_state_t *zv = bio->bi_bdev->bd_disk->private_data;
uint64_t offset = BIO_BI_SECTOR(bio) << 9;
uint64_t len = BIO_BI_SIZE(bio);
uint64_t size = BIO_BI_SIZE(bio);
int error;
rl_t *rl;
uio_t uio;

if (len == 0)
if (size == 0)
return (0);

uio.uio_bvec = &bio->bi_io_vec[BIO_BI_IDX(bio)];
uio.uio_skip = BIO_BI_SKIP(bio);
uio.uio_resid = size;
uio.uio_iovcnt = bio->bi_vcnt - BIO_BI_IDX(bio);
uio.uio_loffset = offset;
uio.uio_limit = MAXOFFSET_T;
uio.uio_segflg = UIO_BVEC;

rl = zfs_range_lock(&zv->zv_znode, offset, len, RL_READER);
rl = zfs_range_lock(&zv->zv_znode, offset, size, RL_READER);

error = dmu_read_bio(zv->zv_objset, ZVOL_OBJ, bio);
error = dmu_read_uio(zv->zv_objset, ZVOL_OBJ, &uio, size);

zfs_range_unlock(rl);

Expand Down