Date: Mon, 22 Feb 2010 15:35:31 +0000 (UTC) From: Konstantin Belousov <kib@FreeBSD.org> To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r204200 - user/kib/vm6/sys/vm Message-ID: <201002221535.o1MFZV2x084663@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kib Date: Mon Feb 22 15:35:31 2010 New Revision: 204200 URL: http://svn.freebsd.org/changeset/base/204200 Log: Detect sequential writes in vnode_pager_write() and initiate immediate page cleanup for continous regions written sequentially. This allows the buffer clustering and UFS reallocation code to defragment the file. Tested by: pho Modified: user/kib/vm6/sys/vm/vm_object.h user/kib/vm6/sys/vm/vm_readwrite.c user/kib/vm6/sys/vm/vnode_pager.c Modified: user/kib/vm6/sys/vm/vm_object.h ============================================================================== --- user/kib/vm6/sys/vm/vm_object.h Mon Feb 22 15:03:16 2010 (r204199) +++ user/kib/vm6/sys/vm/vm_object.h Mon Feb 22 15:35:31 2010 (r204200) @@ -109,9 +109,13 @@ struct vm_object { * VNode pager * * vnp_size - current size of file + * wpos - start write position for seq write detector + * off - offset from wpos for current write */ struct { off_t vnp_size; + off_t wpos; + ssize_t off; } vnp; /* Modified: user/kib/vm6/sys/vm/vm_readwrite.c ============================================================================== --- user/kib/vm6/sys/vm/vm_readwrite.c Mon Feb 22 15:03:16 2010 (r204199) +++ user/kib/vm6/sys/vm/vm_readwrite.c Mon Feb 22 15:35:31 2010 (r204200) @@ -715,10 +715,10 @@ vnode_pager_write(struct vnode *vp, stru vm_pindex_t idx, clean_start, clean_end; vm_page_t reserv; struct vattr vattr; - ssize_t size, size1, osize, osize1, resid, sresid; - int error, vn_locked, wpmax, wp, i; + ssize_t size, size1, osize, osize1, resid, sresid, written; + int error, vn_locked, wpmax, wp, i, pflags; u_int bits; - boolean_t vnode_locked; + boolean_t vnode_locked, freed, freed1; struct thread *td; if (ioflags & (IO_EXT|IO_INVAL|IO_DIRECT)) @@ -735,6 +735,16 @@ vnode_pager_write(struct vnode *vp, stru vnode_locked = TRUE; error = 0; + /* + * Reversed logic from vnode_generic_putpages(). + */ + if (ioflags & IO_SYNC) + pflags = VM_PAGER_PUT_SYNC; + else if (ioflags & IO_ASYNC) + pflags = 0; + else + pflags = VM_PAGER_CLUSTER_OK; + wpmax = atomic_load_acq_int(&vmio_write_pack); vm_page_t ma[wpmax + 1]; @@ -1002,6 +1012,7 @@ vnode_pager_write(struct vnode *vp, stru error = uiomove_fromphys(ma, off, size, uio); td->td_pflags &= ~TDP_VMIO; + freed = FALSE; VM_OBJECT_LOCK(obj); vm_page_lock_queues(); for (i = 0; i < wp; i++) { @@ -1019,12 +1030,50 @@ vnode_pager_write(struct vnode *vp, stru ma[i]->flags |= PG_WRITEDIRTY; vmio_writedirty++; } + freed1 = FALSE; + if (VM_PAGE_GETQUEUE(ma[i]) == PQ_HOLD) + freed = freed1 = TRUE; vm_page_unhold(ma[i]); - vm_page_activate(ma[i]); + if (!freed1) + vm_page_activate(ma[i]); } - vm_page_unlock_queues(); /* See the comment above about page dirtiness. */ vm_object_set_writeable_dirty(obj); + + /* + * Try to cluster writes. + */ + written = sresid - uio->uio_resid; + if (obj->un_pager.vnp.wpos + obj->un_pager.vnp.off == + uio->uio_offset - written) { + /* + * Sequential writes detected, make a note and + * try to take immediate advantage of it. + */ + if (!freed && OFF_TO_IDX(uio->uio_offset) > + OFF_TO_IDX(uio->uio_offset - written) && + vn_lock(vp, vn_locked | LK_NOWAIT) == 0) { + vm_pageout_flush(ma, wp, pflags); + VOP_UNLOCK(vp, 0); + } +/* printf("seq write, wpos %jd off %jd written %d\n", (intmax_t)obj->un_pager.vnp.wpos, (intmax_t)obj->un_pager.vnp.off, written); */ + obj->un_pager.vnp.off += written; + } else { + /* + * Not a sequential write situation, still + * might be good to not split large write in + * the daemons struggling under pressure. + */ + if (!freed && wp >= vm_pageout_page_count && + vn_lock(vp, vn_locked | LK_NOWAIT) == 0) { + vm_pageout_flush(ma, wp, pflags); + VOP_UNLOCK(vp, 0); + } +/* printf("nonseq write, wpos %jd off %jd wp %d\n", (intmax_t)obj->un_pager.vnp.wpos, (intmax_t)obj->un_pager.vnp.off, wp); */ + obj->un_pager.vnp.wpos = uio->uio_offset; + obj->un_pager.vnp.off = 0; + } + vm_page_unlock_queues(); vm_object_pip_wakeup(obj); VM_OBJECT_UNLOCK(obj); if (error != 0) Modified: user/kib/vm6/sys/vm/vnode_pager.c ============================================================================== --- user/kib/vm6/sys/vm/vnode_pager.c Mon Feb 22 15:03:16 2010 (r204199) +++ user/kib/vm6/sys/vm/vnode_pager.c Mon Feb 22 15:35:31 2010 (r204200) @@ -1017,7 +1017,6 @@ vnode_pager_putpages(object, m, count, s { int rtval; struct vnode *vp; - struct mount *mp; int bytes = count * PAGE_SIZE; /* @@ -1040,8 +1039,6 @@ vnode_pager_putpages(object, m, count, s */ vp = object->handle; VM_OBJECT_UNLOCK(object); - if (vp->v_type != VREG) - mp = NULL; rtval = VOP_PUTPAGES(vp, m, bytes, sync, rtvals, 0); KASSERT(rtval != EOPNOTSUPP, ("vnode_pager: stale FS putpages\n"));
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201002221535.o1MFZV2x084663>