Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 25 Nov 2012 14:53:26 +0000 (UTC)
From:      Andriy Gapon <avg@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r243517 - head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs
Message-ID:  <201211251453.qAPErQ4S078439@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: avg
Date: Sun Nov 25 14:53:26 2012
New Revision: 243517
URL: http://svnweb.freebsd.org/changeset/base/243517

Log:
  zfs_getpages: optimize for large block sizes
  
  MFC after:	6 weeks

Modified:
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c	Sun Nov 25 14:25:08 2012	(r243516)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c	Sun Nov 25 14:53:26 2012	(r243517)
@@ -5556,34 +5556,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);
@@ -5592,30 +5619,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);
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201211251453.qAPErQ4S078439>