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


   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   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 (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.

  23  */
  24 
  25 #include <sys/param.h>
  26 #include <sys/types.h>
  27 #include <sys/systm.h>
  28 #include <sys/cred.h>
  29 #include <sys/proc.h>
  30 #include <sys/user.h>
  31 #include <sys/time.h>
  32 #include <sys/vnode.h>
  33 #include <sys/vfs.h>
  34 #include <sys/vfs_opreg.h>
  35 #include <sys/file.h>
  36 #include <sys/filio.h>
  37 #include <sys/uio.h>
  38 #include <sys/buf.h>
  39 #include <sys/mman.h>
  40 #include <sys/tiuser.h>
  41 #include <sys/pathname.h>
  42 #include <sys/dirent.h>


7368                         held = 0;
7369                 }
7370                 error = cachefs_cd_access(fscp, connected, 0);
7371                 if (error)
7372                         break;
7373                 held = 1;
7374 
7375                 /*
7376                  * If we are getting called as a side effect of a
7377                  * cachefs_write()
7378                  * operation the local file size might not be extended yet.
7379                  * In this case we want to be able to return pages of zeroes.
7380                  */
7381                 if ((u_offset_t)off + len >
7382                     ((cp->c_size + PAGEOFFSET) & (offset_t)PAGEMASK)) {
7383                         if (seg != segkmap) {
7384                                 error = EFAULT;
7385                                 break;
7386                         }
7387                 }
7388                 if (len <= PAGESIZE)
7389                         error = cachefs_getapage(vp, (u_offset_t)off, len,
7390                             protp, pl, plsz, seg, addr, rw, cr);
7391                 else
7392                         error = pvn_getpages(cachefs_getapage, vp,
7393                             (u_offset_t)off, len, protp, pl, plsz, seg, addr,
7394                             rw, cr);
7395                 if (error == 0)
7396                         break;
7397 
7398                 if (((cp->c_flags & CN_NOCACHE) && (error == ENOSPC)) ||
7399                     error == EAGAIN) {
7400                         connected = 0;
7401                         continue;
7402                 }
7403                 if (fscp->fs_cdconnected == CFS_CD_CONNECTED) {
7404                         if (CFS_TIMEOUT(fscp, error)) {
7405                                 cachefs_cd_release(fscp);
7406                                 held = 0;
7407                                 cachefs_cd_timedout(fscp);
7408                                 connected = 0;
7409                                 continue;
7410                         }
7411                 } else {
7412                         if (CFS_TIMEOUT(fscp, error)) {
7413                                 if (cachefs_cd_access_miss(fscp)) {
7414                                         if (len <= PAGESIZE)
7415                                                 error = cachefs_getapage_back(
7416                                                     vp, (u_offset_t)off,
7417                                                     len, protp, pl,
7418                                                     plsz, seg, addr, rw, cr);
7419                                         else
7420                                                 error = pvn_getpages(
7421                                                     cachefs_getapage_back, vp,
7422                                                     (u_offset_t)off, len,
7423                                                     protp, pl,
7424                                                     plsz, seg, addr, rw, cr);
7425                                         if (!CFS_TIMEOUT(fscp, error) &&
7426                                             (error != EAGAIN))
7427                                                 break;
7428                                         delay(5*hz);
7429                                         connected = 0;
7430                                         continue;
7431                                 }
7432                                 connected = 1;
7433                                 continue;
7434                         }
7435                 }
7436                 break;
7437         }
7438 
7439         if (CACHEFS_LOG_LOGGING(cachep, CACHEFS_LOG_GETPAGE))
7440                 cachefs_log_getpage(cachep, error, vp->v_vfsp,
7441                     &cp->c_metadata.md_cookie, cp->c_id.cid_fileno,
7442                     crgetuid(cr), off, len);
7443 


7481          * conditions for the getpage operation.
7482          */
7483         CFS_BACKFS_NFSV4_ASSERT_FSCACHE(fscp);
7484         CFS_BACKFS_NFSV4_ASSERT_CNODE(cp);
7485 
7486         /* Call backfs vnode op after extracting backvp */
7487         mutex_enter(&cp->c_statelock);
7488         backvp = cp->c_backvp;
7489         mutex_exit(&cp->c_statelock);
7490 
7491         CFS_DPRINT_BACKFS_NFSV4(fscp,
7492             ("cachefs_getpage_backfs_nfsv4: cnode %p, backvp %p\n",
7493             cp, backvp));
7494         error = VOP_GETPAGE(backvp, off, len, protp, pl, plsz, seg,
7495             addr, rw, cr, NULL);
7496 
7497         return (error);
7498 }
7499 
7500 /*
7501  * Called from pvn_getpages or cachefs_getpage to get a particular page.
7502  */
7503 /*ARGSUSED*/
7504 static int
7505 cachefs_getapage(struct vnode *vp, u_offset_t off, size_t len, uint_t *protp,
7506         struct page *pl[], size_t plsz, struct seg *seg, caddr_t addr,
7507         enum seg_rw rw, cred_t *cr)
7508 {
7509         cnode_t *cp = VTOC(vp);
7510         page_t **ppp, *pp = NULL;
7511         fscache_t *fscp = C_TO_FSCACHE(cp);
7512         cachefscache_t *cachep = fscp->fs_cache;
7513         int error = 0;
7514         struct page **ourpl;
7515         struct page *ourstackpl[17]; /* see ASSERT() below for 17 */
7516         int index = 0;
7517         int downgrade;
7518         int have_statelock = 0;
7519         u_offset_t popoff;
7520         size_t popsize = 0;
7521 




   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   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 (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
  24  */
  25 
  26 #include <sys/param.h>
  27 #include <sys/types.h>
  28 #include <sys/systm.h>
  29 #include <sys/cred.h>
  30 #include <sys/proc.h>
  31 #include <sys/user.h>
  32 #include <sys/time.h>
  33 #include <sys/vnode.h>
  34 #include <sys/vfs.h>
  35 #include <sys/vfs_opreg.h>
  36 #include <sys/file.h>
  37 #include <sys/filio.h>
  38 #include <sys/uio.h>
  39 #include <sys/buf.h>
  40 #include <sys/mman.h>
  41 #include <sys/tiuser.h>
  42 #include <sys/pathname.h>
  43 #include <sys/dirent.h>


7369                         held = 0;
7370                 }
7371                 error = cachefs_cd_access(fscp, connected, 0);
7372                 if (error)
7373                         break;
7374                 held = 1;
7375 
7376                 /*
7377                  * If we are getting called as a side effect of a
7378                  * cachefs_write()
7379                  * operation the local file size might not be extended yet.
7380                  * In this case we want to be able to return pages of zeroes.
7381                  */
7382                 if ((u_offset_t)off + len >
7383                     ((cp->c_size + PAGEOFFSET) & (offset_t)PAGEMASK)) {
7384                         if (seg != segkmap) {
7385                                 error = EFAULT;
7386                                 break;
7387                         }
7388                 }
7389                 error = pvn_getpages(cachefs_getapage, vp, (u_offset_t)off,
7390                     len, protp, pl, plsz, seg, addr, rw, cr);





7391                 if (error == 0)
7392                         break;
7393 
7394                 if (((cp->c_flags & CN_NOCACHE) && (error == ENOSPC)) ||
7395                     error == EAGAIN) {
7396                         connected = 0;
7397                         continue;
7398                 }
7399                 if (fscp->fs_cdconnected == CFS_CD_CONNECTED) {
7400                         if (CFS_TIMEOUT(fscp, error)) {
7401                                 cachefs_cd_release(fscp);
7402                                 held = 0;
7403                                 cachefs_cd_timedout(fscp);
7404                                 connected = 0;
7405                                 continue;
7406                         }
7407                 } else {
7408                         if (CFS_TIMEOUT(fscp, error)) {
7409                                 if (cachefs_cd_access_miss(fscp)) {






7410                                         error = pvn_getpages(
7411                                             cachefs_getapage_back, vp,
7412                                             (u_offset_t)off, len, protp, pl,

7413                                             plsz, seg, addr, rw, cr);
7414                                         if (!CFS_TIMEOUT(fscp, error) &&
7415                                             (error != EAGAIN))
7416                                                 break;
7417                                         delay(5*hz);
7418                                         connected = 0;
7419                                         continue;
7420                                 }
7421                                 connected = 1;
7422                                 continue;
7423                         }
7424                 }
7425                 break;
7426         }
7427 
7428         if (CACHEFS_LOG_LOGGING(cachep, CACHEFS_LOG_GETPAGE))
7429                 cachefs_log_getpage(cachep, error, vp->v_vfsp,
7430                     &cp->c_metadata.md_cookie, cp->c_id.cid_fileno,
7431                     crgetuid(cr), off, len);
7432 


7470          * conditions for the getpage operation.
7471          */
7472         CFS_BACKFS_NFSV4_ASSERT_FSCACHE(fscp);
7473         CFS_BACKFS_NFSV4_ASSERT_CNODE(cp);
7474 
7475         /* Call backfs vnode op after extracting backvp */
7476         mutex_enter(&cp->c_statelock);
7477         backvp = cp->c_backvp;
7478         mutex_exit(&cp->c_statelock);
7479 
7480         CFS_DPRINT_BACKFS_NFSV4(fscp,
7481             ("cachefs_getpage_backfs_nfsv4: cnode %p, backvp %p\n",
7482             cp, backvp));
7483         error = VOP_GETPAGE(backvp, off, len, protp, pl, plsz, seg,
7484             addr, rw, cr, NULL);
7485 
7486         return (error);
7487 }
7488 
7489 /*
7490  * Called from pvn_getpages to get a particular page.
7491  */
7492 /*ARGSUSED*/
7493 static int
7494 cachefs_getapage(struct vnode *vp, u_offset_t off, size_t len, uint_t *protp,
7495         struct page *pl[], size_t plsz, struct seg *seg, caddr_t addr,
7496         enum seg_rw rw, cred_t *cr)
7497 {
7498         cnode_t *cp = VTOC(vp);
7499         page_t **ppp, *pp = NULL;
7500         fscache_t *fscp = C_TO_FSCACHE(cp);
7501         cachefscache_t *cachep = fscp->fs_cache;
7502         int error = 0;
7503         struct page **ourpl;
7504         struct page *ourstackpl[17]; /* see ASSERT() below for 17 */
7505         int index = 0;
7506         int downgrade;
7507         int have_statelock = 0;
7508         u_offset_t popoff;
7509         size_t popsize = 0;
7510