Print this page
5382 pvn_getpages handles lengths <= PAGESIZE just fine


   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 /*
  26  * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
  27  */
  28 
  29 /*
  30  *      Copyright 1983,1984,1985,1986,1987,1988,1989 AT&T.
  31  *      All Rights Reserved
  32  */
  33 
  34 /*
  35  * Copyright (c) 2013, Joyent, Inc. All rights reserved.
  36  */
  37 
  38 #include <sys/param.h>
  39 #include <sys/types.h>
  40 #include <sys/systm.h>
  41 #include <sys/cred.h>
  42 #include <sys/time.h>
  43 #include <sys/vnode.h>
  44 #include <sys/vfs.h>
  45 #include <sys/vfs_opreg.h>
  46 #include <sys/file.h>


9770                     rp->r_gcount > 0)
9771                         cv_wait(&rp->r_cv, &rp->r_statelock);
9772         }
9773 
9774         /*
9775          * If we are getting called as a side effect of an nfs_write()
9776          * operation the local file size might not be extended yet.
9777          * In this case we want to be able to return pages of zeroes.
9778          */
9779         if (off + len > rp->r_size + PAGEOFFSET && seg != segkmap) {
9780                 NFS4_DEBUG(nfs4_pageio_debug,
9781                     (CE_NOTE, "getpage beyond EOF: off=%lld, "
9782                     "len=%llu, size=%llu, attrsize =%llu", off,
9783                     (u_longlong_t)len, rp->r_size, rp->r_attr.va_size));
9784                 mutex_exit(&rp->r_statelock);
9785                 return (EFAULT);                /* beyond EOF */
9786         }
9787 
9788         mutex_exit(&rp->r_statelock);
9789 
9790         if (len <= PAGESIZE) {
9791                 error = nfs4_getapage(vp, off, len, protp, pl, plsz,
9792                     seg, addr, rw, cr);
9793                 NFS4_DEBUG(nfs4_pageio_debug && error,
9794                     (CE_NOTE, "getpage error %d; off=%lld, "
9795                     "len=%lld", error, off, (u_longlong_t)len));
9796         } else {
9797                 error = pvn_getpages(nfs4_getapage, vp, off, len, protp,
9798                     pl, plsz, seg, addr, rw, cr);
9799                 NFS4_DEBUG(nfs4_pageio_debug && error,
9800                     (CE_NOTE, "getpages error %d; off=%lld, "
9801                     "len=%lld", error, off, (u_longlong_t)len));
9802         }
9803 
9804         switch (error) {
9805         case NFS_EOF:
9806                 nfs4_purge_caches(vp, NFS4_NOPURGE_DNLC, cr, FALSE);
9807                 goto retry;
9808         case ESTALE:
9809                 nfs4_purge_stale_fh(error, vp, cr);
9810         }
9811 
9812         return (error);
9813 }
9814 
9815 /*
9816  * Called from pvn_getpages or nfs4_getpage to get a particular page.
9817  */
9818 /* ARGSUSED */
9819 static int
9820 nfs4_getapage(vnode_t *vp, u_offset_t off, size_t len, uint_t *protp,
9821     page_t *pl[], size_t plsz, struct seg *seg, caddr_t addr,
9822     enum seg_rw rw, cred_t *cr)
9823 {
9824         rnode4_t *rp;
9825         uint_t bsize;
9826         struct buf *bp;
9827         page_t *pp;
9828         u_offset_t lbn;
9829         u_offset_t io_off;
9830         u_offset_t blkoff;
9831         u_offset_t rablkoff;
9832         size_t io_len;
9833         uint_t blksize;
9834         int error;
9835         int readahead;
9836         int readahead_issued = 0;




   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 /*
  26  * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
  27  */
  28 
  29 /*
  30  *      Copyright 1983,1984,1985,1986,1987,1988,1989 AT&T.
  31  *      All Rights Reserved
  32  */
  33 
  34 /*
  35  * Copyright (c) 2013, Joyent, Inc. All rights reserved.
  36  */
  37 
  38 #include <sys/param.h>
  39 #include <sys/types.h>
  40 #include <sys/systm.h>
  41 #include <sys/cred.h>
  42 #include <sys/time.h>
  43 #include <sys/vnode.h>
  44 #include <sys/vfs.h>
  45 #include <sys/vfs_opreg.h>
  46 #include <sys/file.h>


9770                     rp->r_gcount > 0)
9771                         cv_wait(&rp->r_cv, &rp->r_statelock);
9772         }
9773 
9774         /*
9775          * If we are getting called as a side effect of an nfs_write()
9776          * operation the local file size might not be extended yet.
9777          * In this case we want to be able to return pages of zeroes.
9778          */
9779         if (off + len > rp->r_size + PAGEOFFSET && seg != segkmap) {
9780                 NFS4_DEBUG(nfs4_pageio_debug,
9781                     (CE_NOTE, "getpage beyond EOF: off=%lld, "
9782                     "len=%llu, size=%llu, attrsize =%llu", off,
9783                     (u_longlong_t)len, rp->r_size, rp->r_attr.va_size));
9784                 mutex_exit(&rp->r_statelock);
9785                 return (EFAULT);                /* beyond EOF */
9786         }
9787 
9788         mutex_exit(&rp->r_statelock);
9789 







9790         error = pvn_getpages(nfs4_getapage, vp, off, len, protp,
9791             pl, plsz, seg, addr, rw, cr);
9792         NFS4_DEBUG(nfs4_pageio_debug && error,
9793             (CE_NOTE, "getpages error %d; off=%lld, len=%lld",
9794             error, off, (u_longlong_t)len));

9795 
9796         switch (error) {
9797         case NFS_EOF:
9798                 nfs4_purge_caches(vp, NFS4_NOPURGE_DNLC, cr, FALSE);
9799                 goto retry;
9800         case ESTALE:
9801                 nfs4_purge_stale_fh(error, vp, cr);
9802         }
9803 
9804         return (error);
9805 }
9806 
9807 /*
9808  * Called from pvn_getpages to get a particular page.
9809  */
9810 /* ARGSUSED */
9811 static int
9812 nfs4_getapage(vnode_t *vp, u_offset_t off, size_t len, uint_t *protp,
9813     page_t *pl[], size_t plsz, struct seg *seg, caddr_t addr,
9814     enum seg_rw rw, cred_t *cr)
9815 {
9816         rnode4_t *rp;
9817         uint_t bsize;
9818         struct buf *bp;
9819         page_t *pp;
9820         u_offset_t lbn;
9821         u_offset_t io_off;
9822         u_offset_t blkoff;
9823         u_offset_t rablkoff;
9824         size_t io_len;
9825         uint_t blksize;
9826         int error;
9827         int readahead;
9828         int readahead_issued = 0;