Skip to content

Commit 804e050

Browse files
ahrensbehlendorf
authored andcommitted
Illumos 5175 - implement dmu_read_uio_dbuf() to improve cached read performance
5175 implement dmu_read_uio_dbuf() to improve cached read performance Reviewed by: Adam Leventhal <ahl@delphix.com> Reviewed by: Alex Reece <alex.reece@delphix.com> Reviewed by: George Wilson <george@delphix.com> Reviewed by: Richard Elling <richard.elling@gmail.com> Approved by: Robert Mustacchi <rm@joyent.com> References: https://www.illumos.org/issues/5175 illumos/illumos-gate@f8554bb Porting notes: This patch doesn't include the changes for the COMSTAR (Common Multiprotocol SCSI Target) - since it's not available for ZoL. http://thegreyblog.blogspot.co.at/2010/02/setting-up-solaris-comstar-and.html Ported by: kernelOfTruth <kerneloftruth@gmail.com> Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov> Closes #3392
1 parent d6c9ff0 commit 804e050

File tree

3 files changed

+78
-11
lines changed

3 files changed

+78
-11
lines changed

include/sys/dmu.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,7 @@ int dmu_read_req(objset_t *os, uint64_t object, struct request *req);
714714
int dmu_write_req(objset_t *os, uint64_t object, struct request *req,
715715
dmu_tx_t *tx);
716716
int dmu_read_uio(objset_t *os, uint64_t object, struct uio *uio, uint64_t size);
717+
int dmu_read_uio_dbuf(dmu_buf_t *zdb, struct uio *uio, uint64_t size);
717718
int dmu_write_uio(objset_t *os, uint64_t object, struct uio *uio, uint64_t size,
718719
dmu_tx_t *tx);
719720
int dmu_write_uio_dbuf(dmu_buf_t *zdb, struct uio *uio, uint64_t size,

module/zfs/dmu.c

Lines changed: 70 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1199,8 +1199,8 @@ dmu_write_req(objset_t *os, uint64_t object, struct request *req, dmu_tx_t *tx)
11991199
return (err);
12001200
}
12011201

1202-
int
1203-
dmu_read_uio(objset_t *os, uint64_t object, uio_t *uio, uint64_t size)
1202+
static int
1203+
dmu_read_uio_dnode(dnode_t *dn, uio_t *uio, uint64_t size)
12041204
{
12051205
dmu_buf_t **dbp;
12061206
int numbufs, i, err;
@@ -1210,8 +1210,8 @@ dmu_read_uio(objset_t *os, uint64_t object, uio_t *uio, uint64_t size)
12101210
* NB: we could do this block-at-a-time, but it's nice
12111211
* to be reading in parallel.
12121212
*/
1213-
err = dmu_buf_hold_array(os, object, uio->uio_loffset, size, TRUE, FTAG,
1214-
&numbufs, &dbp);
1213+
err = dmu_buf_hold_array_by_dnode(dn, uio->uio_loffset, size,
1214+
TRUE, FTAG, &numbufs, &dbp, 0);
12151215
if (err)
12161216
return (err);
12171217

@@ -1253,6 +1253,58 @@ dmu_read_uio(objset_t *os, uint64_t object, uio_t *uio, uint64_t size)
12531253
return (err);
12541254
}
12551255

1256+
/*
1257+
* Read 'size' bytes into the uio buffer.
1258+
* From object zdb->db_object.
1259+
* Starting at offset uio->uio_loffset.
1260+
*
1261+
* If the caller already has a dbuf in the target object
1262+
* (e.g. its bonus buffer), this routine is faster than dmu_read_uio(),
1263+
* because we don't have to find the dnode_t for the object.
1264+
*/
1265+
int
1266+
dmu_read_uio_dbuf(dmu_buf_t *zdb, uio_t *uio, uint64_t size)
1267+
{
1268+
dmu_buf_impl_t *db = (dmu_buf_impl_t *)zdb;
1269+
dnode_t *dn;
1270+
int err;
1271+
1272+
if (size == 0)
1273+
return (0);
1274+
1275+
DB_DNODE_ENTER(db);
1276+
dn = DB_DNODE(db);
1277+
err = dmu_read_uio_dnode(dn, uio, size);
1278+
DB_DNODE_EXIT(db);
1279+
1280+
return (err);
1281+
}
1282+
1283+
/*
1284+
* Read 'size' bytes into the uio buffer.
1285+
* From the specified object
1286+
* Starting at offset uio->uio_loffset.
1287+
*/
1288+
int
1289+
dmu_read_uio(objset_t *os, uint64_t object, uio_t *uio, uint64_t size)
1290+
{
1291+
dnode_t *dn;
1292+
int err;
1293+
1294+
if (size == 0)
1295+
return (0);
1296+
1297+
err = dnode_hold(os, object, FTAG, &dn);
1298+
if (err)
1299+
return (err);
1300+
1301+
err = dmu_read_uio_dnode(dn, uio, size);
1302+
1303+
dnode_rele(dn, FTAG);
1304+
1305+
return (err);
1306+
}
1307+
12561308
static int
12571309
dmu_write_uio_dnode(dnode_t *dn, uio_t *uio, uint64_t size, dmu_tx_t *tx)
12581310
{
@@ -1305,6 +1357,15 @@ dmu_write_uio_dnode(dnode_t *dn, uio_t *uio, uint64_t size, dmu_tx_t *tx)
13051357
return (err);
13061358
}
13071359

1360+
/*
1361+
* Write 'size' bytes from the uio buffer.
1362+
* To object zdb->db_object.
1363+
* Starting at offset uio->uio_loffset.
1364+
*
1365+
* If the caller already has a dbuf in the target object
1366+
* (e.g. its bonus buffer), this routine is faster than dmu_write_uio(),
1367+
* because we don't have to find the dnode_t for the object.
1368+
*/
13081369
int
13091370
dmu_write_uio_dbuf(dmu_buf_t *zdb, uio_t *uio, uint64_t size,
13101371
dmu_tx_t *tx)
@@ -1324,6 +1385,11 @@ dmu_write_uio_dbuf(dmu_buf_t *zdb, uio_t *uio, uint64_t size,
13241385
return (err);
13251386
}
13261387

1388+
/*
1389+
* Write 'size' bytes from the uio buffer.
1390+
* To the specified object.
1391+
* Starting at offset uio->uio_loffset.
1392+
*/
13271393
int
13281394
dmu_write_uio(objset_t *os, uint64_t object, uio_t *uio, uint64_t size,
13291395
dmu_tx_t *tx)

module/zfs/zfs_vnops.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,6 @@ mappedread(struct inode *ip, int nbytes, uio_t *uio)
376376
struct address_space *mp = ip->i_mapping;
377377
struct page *pp;
378378
znode_t *zp = ITOZ(ip);
379-
objset_t *os = ITOZSB(ip)->z_os;
380379
int64_t start, off;
381380
uint64_t bytes;
382381
int len = nbytes;
@@ -403,7 +402,8 @@ mappedread(struct inode *ip, int nbytes, uio_t *uio)
403402
unlock_page(pp);
404403
page_cache_release(pp);
405404
} else {
406-
error = dmu_read_uio(os, zp->z_id, uio, bytes);
405+
error = dmu_read_uio_dbuf(sa_get_db(zp->z_sa_hdl),
406+
uio, bytes);
407407
}
408408

409409
len -= bytes;
@@ -440,7 +440,6 @@ zfs_read(struct inode *ip, uio_t *uio, int ioflag, cred_t *cr)
440440
{
441441
znode_t *zp = ITOZ(ip);
442442
zfs_sb_t *zsb = ITOZSB(ip);
443-
objset_t *os;
444443
ssize_t n, nbytes;
445444
int error = 0;
446445
rl_t *rl;
@@ -450,7 +449,6 @@ zfs_read(struct inode *ip, uio_t *uio, int ioflag, cred_t *cr)
450449

451450
ZFS_ENTER(zsb);
452451
ZFS_VERIFY_ZP(zp);
453-
os = zsb->z_os;
454452

455453
if (zp->z_pflags & ZFS_AV_QUARANTINED) {
456454
ZFS_EXIT(zsb);
@@ -531,10 +529,12 @@ zfs_read(struct inode *ip, uio_t *uio, int ioflag, cred_t *cr)
531529
nbytes = MIN(n, zfs_read_chunk_size -
532530
P2PHASE(uio->uio_loffset, zfs_read_chunk_size));
533531

534-
if (zp->z_is_mapped && !(ioflag & O_DIRECT))
532+
if (zp->z_is_mapped && !(ioflag & O_DIRECT)) {
535533
error = mappedread(ip, nbytes, uio);
536-
else
537-
error = dmu_read_uio(os, zp->z_id, uio, nbytes);
534+
} else {
535+
error = dmu_read_uio_dbuf(sa_get_db(zp->z_sa_hdl),
536+
uio, nbytes);
537+
}
538538

539539
if (error) {
540540
/* convert checksum errors into IO errors */

0 commit comments

Comments
 (0)