Author: kib
Date: Mon Sep 15 12:28:29 2014
New Revision: 271619
URL: http://svnweb.freebsd.org/changeset/base/271619

Log:
  Provide the unique implementation for the VOP_GETPAGES() method used
  by ffs and ext2fs.  Remove duplicated call to vm_page_zero_invalid(),
  done by VOP and by vm_pager_getpages().  Use vm_pager_free_nonreq().
  
  Reviewed by:  alc (previous version)
  Sponsored by: The FreeBSD Foundation
  MFC after:    6 weeks (after r271596)

Modified:
  head/sys/fs/ext2fs/ext2_vnops.c
  head/sys/ufs/ffs/ffs_vnops.c
  head/sys/vm/vnode_pager.c
  head/sys/vm/vnode_pager.h

Modified: head/sys/fs/ext2fs/ext2_vnops.c
==============================================================================
--- head/sys/fs/ext2fs/ext2_vnops.c     Mon Sep 15 11:35:14 2014        
(r271618)
+++ head/sys/fs/ext2fs/ext2_vnops.c     Mon Sep 15 12:28:29 2014        
(r271619)
@@ -97,7 +97,6 @@ static int ext2_chown(struct vnode *, ui
 static vop_close_t     ext2_close;
 static vop_create_t    ext2_create;
 static vop_fsync_t     ext2_fsync;
-static vop_getpages_t  ext2_getpages;
 static vop_getattr_t   ext2_getattr;
 static vop_ioctl_t     ext2_ioctl;
 static vop_link_t      ext2_link;
@@ -128,7 +127,7 @@ struct vop_vector ext2_vnodeops = {
        .vop_close =            ext2_close,
        .vop_create =           ext2_create,
        .vop_fsync =            ext2_fsync,
-       .vop_getpages =         ext2_getpages,
+       .vop_getpages =         vnode_pager_local_getpages,
        .vop_getattr =          ext2_getattr,
        .vop_inactive =         ext2_inactive,
        .vop_ioctl =            ext2_ioctl,
@@ -2063,48 +2062,3 @@ ext2_write(struct vop_write_args *ap)
        }
        return (error);
 }
-
-/*
- * get page routine
- */
-static int
-ext2_getpages(struct vop_getpages_args *ap)
-{
-       int i;
-       vm_page_t mreq;
-       int pcount;
-
-       mreq = ap->a_m[ap->a_reqpage];
-
-       /*
-        * Since the caller has busied the requested page, that page's valid
-        * field will not be changed by other threads.
-        */
-       vm_page_assert_xbusied(mreq);
-
-       /*
-        * if ANY DEV_BSIZE blocks are valid on a large filesystem block,
-        * then the entire page is valid.  Since the page may be mapped,
-        * user programs might reference data beyond the actual end of file
-        * occuring within the page.  We have to zero that data.
-        */
-       if (mreq->valid) {
-               VM_OBJECT_WLOCK(mreq->object);
-               if (mreq->valid != VM_PAGE_BITS_ALL)
-                       vm_page_zero_invalid(mreq, TRUE);
-               pcount = round_page(ap->a_count) / PAGE_SIZE;
-               for (i = 0; i < pcount; i++) {
-                       if (i != ap->a_reqpage) {
-                               vm_page_lock(ap->a_m[i]);
-                               vm_page_free(ap->a_m[i]);
-                               vm_page_unlock(ap->a_m[i]);
-                       }
-               }
-               VM_OBJECT_WUNLOCK(mreq->object);
-               return VM_PAGER_OK;
-       }
-
-       return vnode_pager_generic_getpages(ap->a_vp, ap->a_m,
-                                           ap->a_count,
-                                           ap->a_reqpage);
-}

Modified: head/sys/ufs/ffs/ffs_vnops.c
==============================================================================
--- head/sys/ufs/ffs/ffs_vnops.c        Mon Sep 15 11:35:14 2014        
(r271618)
+++ head/sys/ufs/ffs/ffs_vnops.c        Mon Sep 15 12:28:29 2014        
(r271619)
@@ -104,7 +104,6 @@ extern int  ffs_rawread(struct vnode *vp,
 #endif
 static vop_fsync_t     ffs_fsync;
 static vop_lock1_t     ffs_lock;
-static vop_getpages_t  ffs_getpages;
 static vop_read_t      ffs_read;
 static vop_write_t     ffs_write;
 static int     ffs_extread(struct vnode *vp, struct uio *uio, int ioflag);
@@ -124,7 +123,7 @@ static vop_vptofh_t ffs_vptofh;
 struct vop_vector ffs_vnodeops1 = {
        .vop_default =          &ufs_vnodeops,
        .vop_fsync =            ffs_fsync,
-       .vop_getpages =         ffs_getpages,
+       .vop_getpages =         vnode_pager_local_getpages,
        .vop_lock1 =            ffs_lock,
        .vop_read =             ffs_read,
        .vop_reallocblks =      ffs_reallocblks,
@@ -143,7 +142,7 @@ struct vop_vector ffs_fifoops1 = {
 struct vop_vector ffs_vnodeops2 = {
        .vop_default =          &ufs_vnodeops,
        .vop_fsync =            ffs_fsync,
-       .vop_getpages =         ffs_getpages,
+       .vop_getpages =         vnode_pager_local_getpages,
        .vop_lock1 =            ffs_lock,
        .vop_read =             ffs_read,
        .vop_reallocblks =      ffs_reallocblks,
@@ -847,53 +846,6 @@ ffs_write(ap)
 }
 
 /*
- * get page routine
- */
-static int
-ffs_getpages(ap)
-       struct vop_getpages_args *ap;
-{
-       int i;
-       vm_page_t mreq;
-       int pcount;
-
-       mreq = ap->a_m[ap->a_reqpage];
-
-       /*
-        * Since the caller has busied the requested page, that page's valid
-        * field will not be changed by other threads.
-        */
-       vm_page_assert_xbusied(mreq);
-
-       /*
-        * if ANY DEV_BSIZE blocks are valid on a large filesystem block,
-        * then the entire page is valid.  Since the page may be mapped,
-        * user programs might reference data beyond the actual end of file
-        * occuring within the page.  We have to zero that data.
-        */
-       if (mreq->valid) {
-               VM_OBJECT_WLOCK(mreq->object);
-               if (mreq->valid != VM_PAGE_BITS_ALL)
-                       vm_page_zero_invalid(mreq, TRUE);
-               pcount = round_page(ap->a_count) / PAGE_SIZE;
-               for (i = 0; i < pcount; i++) {
-                       if (i != ap->a_reqpage) {
-                               vm_page_lock(ap->a_m[i]);
-                               vm_page_free(ap->a_m[i]);
-                               vm_page_unlock(ap->a_m[i]);
-                       }
-               }
-               VM_OBJECT_WUNLOCK(mreq->object);
-               return VM_PAGER_OK;
-       }
-
-       return vnode_pager_generic_getpages(ap->a_vp, ap->a_m,
-                                           ap->a_count,
-                                           ap->a_reqpage);
-}
-
-
-/*
  * Extended attribute area reading.
  */
 static int

Modified: head/sys/vm/vnode_pager.c
==============================================================================
--- head/sys/vm/vnode_pager.c   Mon Sep 15 11:35:14 2014        (r271618)
+++ head/sys/vm/vnode_pager.c   Mon Sep 15 12:28:29 2014        (r271619)
@@ -665,6 +665,39 @@ vnode_pager_getpages(vm_object_t object,
 }
 
 /*
+ * The implementation of VOP_GETPAGES() for local filesystems, where
+ * partially valid pages can only occur at the end of file.
+ */
+int
+vnode_pager_local_getpages(struct vop_getpages_args *ap)
+{
+       vm_page_t mreq;
+
+       mreq = ap->a_m[ap->a_reqpage];
+
+       /*
+        * Since the caller has busied the requested page, that page's valid
+        * field will not be changed by other threads.
+        */
+       vm_page_assert_xbusied(mreq);
+
+       /*
+        * The requested page has valid blocks.  Invalid part can only
+        * exist at the end of file, and the page is made fully valid
+        * by zeroing in vm_pager_getpages().  Free non-requested
+        * pages, since no i/o is done to read its content.
+        */
+       if (mreq->valid != 0) {
+               vm_pager_free_nonreq(mreq->object, ap->a_m, ap->a_reqpage,
+                   round_page(ap->a_count) / PAGE_SIZE);
+               return (VM_PAGER_OK);
+       }
+
+       return (vnode_pager_generic_getpages(ap->a_vp, ap->a_m,
+           ap->a_count, ap->a_reqpage));
+}
+
+/*
  * This is now called from local media FS's to operate against their
  * own vnodes if they fail to implement VOP_GETPAGES.
  */

Modified: head/sys/vm/vnode_pager.h
==============================================================================
--- head/sys/vm/vnode_pager.h   Mon Sep 15 11:35:14 2014        (r271618)
+++ head/sys/vm/vnode_pager.h   Mon Sep 15 12:28:29 2014        (r271619)
@@ -45,6 +45,8 @@ int vnode_pager_generic_getpages(struct 
 int vnode_pager_generic_putpages(struct vnode *vp, vm_page_t *m,
                                          int count, boolean_t sync,
                                          int *rtvals);
+struct vop_getpages_args;
+int vnode_pager_local_getpages(struct vop_getpages_args *ap);
 
 void vnode_pager_release_writecount(vm_object_t object, vm_offset_t start,
     vm_offset_t end);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to