svn commit: r245691 - stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs
Andriy Gapon
avg at FreeBSD.org
Sun Jan 20 16:03:52 UTC 2013
Author: avg
Date: Sun Jan 20 16:03:51 2013
New Revision: 245691
URL: http://svnweb.freebsd.org/changeset/base/245691
Log:
MFC r243517: zfs_getpages: optimize for large block sizes
Modified:
stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
Directory Properties:
stable/9/sys/ (props changed)
stable/9/sys/cddl/contrib/opensolaris/ (props changed)
Modified: stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
==============================================================================
--- stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c Sun Jan 20 14:22:21 2013 (r245690)
+++ stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c Sun Jan 20 16:03:51 2013 (r245691)
@@ -5574,34 +5574,61 @@ zfs_getpages(struct vnode *vp, vm_page_t
znode_t *zp = VTOZ(vp);
zfsvfs_t *zfsvfs = zp->z_zfsvfs;
objset_t *os = zp->z_zfsvfs->z_os;
- vm_page_t mreq;
+ vm_page_t mfirst, mlast, mreq;
vm_object_t object;
caddr_t va;
struct sf_buf *sf;
+ off_t startoff, endoff;
int i, error;
- int pcount, size;
+ vm_pindex_t reqstart, reqend;
+ int pcount, lsize, reqsize, size;
ZFS_ENTER(zfsvfs);
ZFS_VERIFY_ZP(zp);
- pcount = round_page(count) / PAGE_SIZE;
+ pcount = OFF_TO_IDX(round_page(count));
mreq = m[reqpage];
object = mreq->object;
error = 0;
KASSERT(vp->v_object == object, ("mismatching object"));
+ if (pcount > 1 && zp->z_blksz > PAGESIZE) {
+ startoff = rounddown(IDX_TO_OFF(mreq->pindex), zp->z_blksz);
+ reqstart = OFF_TO_IDX(round_page(startoff));
+ if (reqstart < m[0]->pindex)
+ reqstart = 0;
+ else
+ reqstart = reqstart - m[0]->pindex;
+ endoff = roundup(IDX_TO_OFF(mreq->pindex) + PAGE_SIZE,
+ zp->z_blksz);
+ reqend = OFF_TO_IDX(trunc_page(endoff)) - 1;
+ if (reqend > m[pcount - 1]->pindex)
+ reqend = m[pcount - 1]->pindex;
+ reqsize = reqend - m[reqstart]->pindex + 1;
+ KASSERT(reqstart <= reqpage && reqpage < reqstart + reqsize,
+ ("reqpage beyond [reqstart, reqstart + reqsize[ bounds"));
+ } else {
+ reqstart = reqpage;
+ reqsize = 1;
+ }
+ mfirst = m[reqstart];
+ mlast = m[reqstart + reqsize - 1];
+
VM_OBJECT_LOCK(object);
- for (i = 0; i < pcount; i++) {
- if (i != reqpage) {
- vm_page_lock(m[i]);
- vm_page_free(m[i]);
- vm_page_unlock(m[i]);
- }
+ for (i = 0; i < reqstart; i++) {
+ vm_page_lock(m[i]);
+ vm_page_free(m[i]);
+ vm_page_unlock(m[i]);
+ }
+ for (i = reqstart + reqsize; i < pcount; i++) {
+ vm_page_lock(m[i]);
+ vm_page_free(m[i]);
+ vm_page_unlock(m[i]);
}
- if (mreq->valid) {
+ if (mreq->valid && reqsize == 1) {
if (mreq->valid != VM_PAGE_BITS_ALL)
vm_page_zero_invalid(mreq, TRUE);
VM_OBJECT_UNLOCK(object);
@@ -5610,30 +5637,66 @@ zfs_getpages(struct vnode *vp, vm_page_t
}
PCPU_INC(cnt.v_vnodein);
- PCPU_INC(cnt.v_vnodepgsin);
+ PCPU_ADD(cnt.v_vnodepgsin, reqsize);
if (IDX_TO_OFF(mreq->pindex) >= object->un_pager.vnp.vnp_size) {
+ for (i = reqstart; i < reqstart + reqsize; i++) {
+ if (i != reqpage) {
+ vm_page_lock(m[i]);
+ vm_page_free(m[i]);
+ vm_page_unlock(m[i]);
+ }
+ }
VM_OBJECT_UNLOCK(object);
ZFS_EXIT(zfsvfs);
return (VM_PAGER_BAD);
}
- size = PAGE_SIZE;
- if (IDX_TO_OFF(mreq->pindex) + size > object->un_pager.vnp.vnp_size)
- size = object->un_pager.vnp.vnp_size - IDX_TO_OFF(mreq->pindex);
+ lsize = PAGE_SIZE;
+ if (IDX_TO_OFF(mlast->pindex) + lsize > object->un_pager.vnp.vnp_size)
+ lsize = object->un_pager.vnp.vnp_size - IDX_TO_OFF(mlast->pindex);
VM_OBJECT_UNLOCK(object);
- va = zfs_map_page(mreq, &sf);
- error = dmu_read(os, zp->z_id, IDX_TO_OFF(mreq->pindex),
- size, va, DMU_READ_PREFETCH);
- if (size != PAGE_SIZE)
- bzero(va + size, PAGE_SIZE - size);
- zfs_unmap_page(sf);
+
+ for (i = reqstart; i < reqstart + reqsize; i++) {
+ size = PAGE_SIZE;
+ if (i == (reqstart + reqsize - 1))
+ size = lsize;
+ va = zfs_map_page(m[i], &sf);
+ error = dmu_read(os, zp->z_id, IDX_TO_OFF(m[i]->pindex),
+ size, va, DMU_READ_PREFETCH);
+ if (size != PAGE_SIZE)
+ bzero(va + size, PAGE_SIZE - size);
+ zfs_unmap_page(sf);
+ if (error != 0)
+ break;
+ }
+
VM_OBJECT_LOCK(object);
- if (!error)
- mreq->valid = VM_PAGE_BITS_ALL;
- KASSERT(mreq->dirty == 0, ("zfs_getpages: page %p is dirty", mreq));
+ for (i = reqstart; i < reqstart + reqsize; i++) {
+ m[i]->valid = VM_PAGE_BITS_ALL;
+ KASSERT(m[i]->dirty == 0, ("zfs_getpages: page %p is dirty", m[i]));
+ if (i != reqpage) {
+ if (!error) {
+ if (m[i]->oflags & VPO_WANTED) {
+ vm_page_lock(m[i]);
+ vm_page_activate(m[i]);
+ vm_page_unlock(m[i]);
+ } else {
+ vm_page_lock(m[i]);
+ vm_page_deactivate(m[i]);
+ vm_page_unlock(m[i]);
+ }
+ vm_page_wakeup(m[i]);
+ } else {
+ vm_page_lock(m[i]);
+ vm_page_free(m[i]);
+ vm_page_unlock(m[i]);
+ }
+ }
+
+ }
VM_OBJECT_UNLOCK(object);
More information about the svn-src-stable-9
mailing list