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
|