1 /* 2 * CDDL HEADER START 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) 1991, 2010, Oracle and/or its affiliates. All rights reserved. 23 * Copyright 2015 Nexenta Systems, Inc. All rights reserved. 24 */ 25 26 #include <sys/types.h> 27 #include <sys/param.h> 28 #include <sys/systm.h> 29 #include <sys/buf.h> 30 #include <sys/cred.h> 31 #include <sys/errno.h> 32 #include <sys/vnode.h> 33 #include <sys/vfs_opreg.h> 34 #include <sys/cmn_err.h> 35 #include <sys/swap.h> 36 #include <sys/mman.h> 37 #include <sys/vmsystm.h> 38 #include <sys/vtrace.h> 39 #include <sys/debug.h> 40 #include <sys/sysmacros.h> 41 #include <sys/vm.h> 42 43 #include <sys/fs/swapnode.h> 44 45 #include <vm/seg.h> 46 #include <vm/page.h> 47 #include <vm/pvn.h> 48 #include <fs/fs_subr.h> 49 50 #include <vm/seg_kp.h> 51 52 /* 53 * Define the routines within this file. 54 */ 55 static int swap_getpage(struct vnode *vp, offset_t off, size_t len, 56 uint_t *protp, struct page **plarr, size_t plsz, struct seg *seg, 57 caddr_t addr, enum seg_rw rw, struct cred *cr, caller_context_t *ct); 58 static int swap_putpage(struct vnode *vp, offset_t off, size_t len, 59 int flags, struct cred *cr, caller_context_t *ct); 60 static void swap_inactive(struct vnode *vp, struct cred *cr, 61 caller_context_t *ct); 62 static void swap_dispose(vnode_t *vp, page_t *pp, int fl, int dn, 63 cred_t *cr, caller_context_t *ct); 64 65 static int swap_getapage(struct vnode *vp, u_offset_t off, size_t len, 66 uint_t *protp, page_t **plarr, size_t plsz, 67 struct seg *seg, caddr_t addr, enum seg_rw rw, struct cred *cr); 68 69 int swap_getconpage(struct vnode *vp, u_offset_t off, size_t len, 70 uint_t *protp, page_t **plarr, size_t plsz, page_t *conpp, 71 uint_t *pszc, spgcnt_t *nreloc, struct seg *seg, caddr_t addr, 72 enum seg_rw rw, struct cred *cr); 73 74 static int swap_putapage(struct vnode *vp, page_t *pp, u_offset_t *off, 75 size_t *lenp, int flags, struct cred *cr); 76 77 const fs_operation_def_t swap_vnodeops_template[] = { 78 VOPNAME_INACTIVE, { .vop_inactive = swap_inactive }, 79 VOPNAME_GETPAGE, { .vop_getpage = swap_getpage }, 80 VOPNAME_PUTPAGE, { .vop_putpage = swap_putpage }, 81 VOPNAME_DISPOSE, { .vop_dispose = swap_dispose }, 82 VOPNAME_SETFL, { .error = fs_error }, 83 VOPNAME_POLL, { .error = fs_error }, 84 VOPNAME_PATHCONF, { .error = fs_error }, 85 VOPNAME_GETSECATTR, { .error = fs_error }, 86 VOPNAME_SHRLOCK, { .error = fs_error }, 87 NULL, NULL 88 }; 89 90 vnodeops_t *swap_vnodeops; 91 92 /* ARGSUSED */ 93 static void 94 swap_inactive( 95 struct vnode *vp, 96 struct cred *cr, 97 caller_context_t *ct) 98 { 99 SWAPFS_PRINT(SWAP_VOPS, "swap_inactive: vp %x\n", vp, 0, 0, 0, 0); 100 } 101 102 /* 103 * Return all the pages from [off..off+len] in given file 104 */ 105 /*ARGSUSED*/ 106 static int 107 swap_getpage( 108 struct vnode *vp, 109 offset_t off, 110 size_t len, 111 uint_t *protp, 112 page_t *pl[], 113 size_t plsz, 114 struct seg *seg, 115 caddr_t addr, 116 enum seg_rw rw, 117 struct cred *cr, 118 caller_context_t *ct) 119 { 120 SWAPFS_PRINT(SWAP_VOPS, "swap_getpage: vp %p, off %llx, len %lx\n", 121 (void *)vp, off, len, 0, 0); 122 123 TRACE_3(TR_FAC_SWAPFS, TR_SWAPFS_GETPAGE, 124 "swapfs getpage:vp %p off %llx len %ld", 125 (void *)vp, off, len); 126 127 return (pvn_getpages(swap_getapage, vp, (u_offset_t)off, len, protp, 128 pl, plsz, seg, addr, rw, cr)); 129 } 130 131 /* 132 * Called from pvn_getpages to get a particular page. 133 */ 134 /*ARGSUSED*/ 135 static int 136 swap_getapage( 137 struct vnode *vp, 138 u_offset_t off, 139 size_t len, 140 uint_t *protp, 141 page_t *pl[], 142 size_t plsz, 143 struct seg *seg, 144 caddr_t addr, 145 enum seg_rw rw, 146 struct cred *cr) 147 { 148 struct page *pp, *rpp; 149 int flags; 150 int err = 0; 151 struct vnode *pvp = NULL; 152 u_offset_t poff; 153 int flag_noreloc; 154 se_t lock; 155 extern int kcage_on; 156 int upgrade = 0; 157 158 SWAPFS_PRINT(SWAP_VOPS, "swap_getapage: vp %p, off %llx, len %lx\n", 159 vp, off, len, 0, 0); 160 161 /* 162 * Until there is a call-back mechanism to cause SEGKP 163 * pages to be unlocked, make them non-relocatable. 164 */ 165 if (SEG_IS_SEGKP(seg)) 166 flag_noreloc = PG_NORELOC; 167 else 168 flag_noreloc = 0; 169 170 if (protp != NULL) 171 *protp = PROT_ALL; 172 173 lock = (rw == S_CREATE ? SE_EXCL : SE_SHARED); 174 175 again: 176 if (pp = page_lookup(vp, off, lock)) { 177 /* 178 * In very rare instances, a segkp page may have been 179 * relocated outside of the kernel by the kernel cage 180 * due to the window between page_unlock() and 181 * VOP_PUTPAGE() in segkp_unlock(). Due to the 182 * rareness of these occurances, the solution is to 183 * relocate the page to a P_NORELOC page. 184 */ 185 if (flag_noreloc != 0) { 186 if (!PP_ISNORELOC(pp) && kcage_on) { 187 if (lock != SE_EXCL) { 188 upgrade = 1; 189 if (!page_tryupgrade(pp)) { 190 page_unlock(pp); 191 lock = SE_EXCL; 192 goto again; 193 } 194 } 195 196 if (page_relocate_cage(&pp, &rpp) != 0) 197 panic("swap_getapage: " 198 "page_relocate_cage failed"); 199 200 pp = rpp; 201 } 202 } 203 204 if (pl) { 205 if (upgrade) 206 page_downgrade(pp); 207 208 pl[0] = pp; 209 pl[1] = NULL; 210 } else { 211 page_unlock(pp); 212 } 213 } else { 214 pp = page_create_va(vp, off, PAGESIZE, 215 PG_WAIT | PG_EXCL | flag_noreloc, 216 seg, addr); 217 /* 218 * Someone raced in and created the page after we did the 219 * lookup but before we did the create, so go back and 220 * try to look it up again. 221 */ 222 if (pp == NULL) 223 goto again; 224 if (rw != S_CREATE) { 225 err = swap_getphysname(vp, off, &pvp, &poff); 226 if (pvp) { 227 struct anon *ap; 228 kmutex_t *ahm; 229 230 flags = (pl == NULL ? B_ASYNC|B_READ : B_READ); 231 err = VOP_PAGEIO(pvp, pp, poff, 232 PAGESIZE, flags, cr, NULL); 233 234 if (!err) { 235 ahm = AH_MUTEX(vp, off); 236 mutex_enter(ahm); 237 238 ap = swap_anon(vp, off); 239 if (ap == NULL) { 240 panic("swap_getapage:" 241 " null anon"); 242 } 243 244 if (ap->an_pvp == pvp && 245 ap->an_poff == poff) { 246 swap_phys_free(pvp, poff, 247 PAGESIZE); 248 ap->an_pvp = NULL; 249 ap->an_poff = NULL; 250 hat_setmod(pp); 251 } 252 253 mutex_exit(ahm); 254 } 255 } else { 256 if (!err) 257 pagezero(pp, 0, PAGESIZE); 258 259 /* 260 * If it's a fault ahead, release page_io_lock 261 * and SE_EXCL we grabbed in page_create_va 262 * 263 * If we are here, we haven't called VOP_PAGEIO 264 * and thus calling pvn_read_done(pp, B_READ) 265 * below may mislead that we tried i/o. Besides, 266 * in case of async, pvn_read_done() should 267 * not be called by *getpage() 268 */ 269 if (pl == NULL) { 270 /* 271 * swap_getphysname can return error 272 * only when we are getting called from 273 * swapslot_free which passes non-NULL 274 * pl to VOP_GETPAGE. 275 */ 276 ASSERT(err == 0); 277 page_io_unlock(pp); 278 page_unlock(pp); 279 } 280 } 281 } 282 283 ASSERT(pp != NULL); 284 285 if (err && pl) 286 pvn_read_done(pp, B_ERROR); 287 288 if (!err && pl) 289 pvn_plist_init(pp, pl, plsz, off, PAGESIZE, rw); 290 } 291 TRACE_3(TR_FAC_SWAPFS, TR_SWAPFS_GETAPAGE, 292 "swapfs getapage:pp %p vp %p off %llx", pp, vp, off); 293 return (err); 294 } 295 296 /* 297 * Called from large page anon routines only! This is an ugly hack where 298 * the anon layer directly calls into swapfs with a preallocated large page. 299 * Another method would have been to change to VOP and add an extra arg for 300 * the preallocated large page. This all could be cleaned up later when we 301 * solve the anonymous naming problem and no longer need to loop across of 302 * the VOP in PAGESIZE increments to fill in or initialize a large page as 303 * is done today. I think the latter is better since it avoid a change to 304 * the VOP interface that could later be avoided. 305 */ 306 int 307 swap_getconpage( 308 struct vnode *vp, 309 u_offset_t off, 310 size_t len, 311 uint_t *protp, 312 page_t *pl[], 313 size_t plsz, 314 page_t *conpp, 315 uint_t *pszc, 316 spgcnt_t *nreloc, 317 struct seg *seg, 318 caddr_t addr, 319 enum seg_rw rw, 320 struct cred *cr) 321 { 322 struct page *pp; 323 int err = 0; 324 struct vnode *pvp = NULL; 325 u_offset_t poff; 326 327 ASSERT(len == PAGESIZE); 328 ASSERT(pl != NULL); 329 ASSERT(plsz == PAGESIZE); 330 ASSERT(protp == NULL); 331 ASSERT(nreloc != NULL); 332 ASSERT(!SEG_IS_SEGKP(seg)); /* XXX for now not supported */ 333 SWAPFS_PRINT(SWAP_VOPS, "swap_getconpage: vp %p, off %llx, len %lx\n", 334 vp, off, len, 0, 0); 335 336 /* 337 * If we are not using a preallocated page then we know one already 338 * exists. So just let the old code handle it. 339 */ 340 if (conpp == NULL) { 341 err = swap_getapage(vp, (u_offset_t)off, len, protp, pl, plsz, 342 seg, addr, rw, cr); 343 return (err); 344 } 345 ASSERT(conpp->p_szc != 0); 346 ASSERT(PAGE_EXCL(conpp)); 347 348 349 ASSERT(conpp->p_next == conpp); 350 ASSERT(conpp->p_prev == conpp); 351 ASSERT(!PP_ISAGED(conpp)); 352 ASSERT(!PP_ISFREE(conpp)); 353 354 *nreloc = 0; 355 pp = page_lookup_create(vp, off, SE_SHARED, conpp, nreloc, 0); 356 357 /* 358 * If existing page is found we may need to relocate. 359 */ 360 if (pp != conpp) { 361 ASSERT(rw != S_CREATE); 362 ASSERT(pszc != NULL); 363 ASSERT(PAGE_SHARED(pp)); 364 if (pp->p_szc < conpp->p_szc) { 365 *pszc = pp->p_szc; 366 page_unlock(pp); 367 err = -1; 368 } else if (pp->p_szc > conpp->p_szc && 369 seg->s_szc > conpp->p_szc) { 370 *pszc = MIN(pp->p_szc, seg->s_szc); 371 page_unlock(pp); 372 err = -2; 373 } else { 374 pl[0] = pp; 375 pl[1] = NULL; 376 if (page_pptonum(pp) & 377 (page_get_pagecnt(conpp->p_szc) - 1)) 378 cmn_err(CE_PANIC, "swap_getconpage: no root"); 379 } 380 return (err); 381 } 382 383 ASSERT(PAGE_EXCL(pp)); 384 385 if (*nreloc != 0) { 386 ASSERT(rw != S_CREATE); 387 pl[0] = pp; 388 pl[1] = NULL; 389 return (0); 390 } 391 392 *nreloc = 1; 393 394 /* 395 * If necessary do the page io. 396 */ 397 if (rw != S_CREATE) { 398 /* 399 * Since we are only called now on behalf of an 400 * address space operation it's impossible for 401 * us to fail unlike swap_getapge() which 402 * also gets called from swapslot_free(). 403 */ 404 if (swap_getphysname(vp, off, &pvp, &poff)) { 405 cmn_err(CE_PANIC, 406 "swap_getconpage: swap_getphysname failed!"); 407 } 408 409 if (pvp != NULL) { 410 err = VOP_PAGEIO(pvp, pp, poff, PAGESIZE, B_READ, 411 cr, NULL); 412 if (err == 0) { 413 struct anon *ap; 414 kmutex_t *ahm; 415 416 ahm = AH_MUTEX(vp, off); 417 mutex_enter(ahm); 418 ap = swap_anon(vp, off); 419 if (ap == NULL) 420 panic("swap_getconpage: null anon"); 421 if (ap->an_pvp != pvp || ap->an_poff != poff) 422 panic("swap_getconpage: bad anon"); 423 424 swap_phys_free(pvp, poff, PAGESIZE); 425 ap->an_pvp = NULL; 426 ap->an_poff = NULL; 427 hat_setmod(pp); 428 mutex_exit(ahm); 429 } 430 } else { 431 pagezero(pp, 0, PAGESIZE); 432 } 433 } 434 435 /* 436 * Normally we would let pvn_read_done() destroy 437 * the page on IO error. But since this is a preallocated 438 * page we'll let the anon layer handle it. 439 */ 440 page_io_unlock(pp); 441 if (err != 0) 442 page_hashout(pp, NULL); 443 ASSERT(pp->p_next == pp); 444 ASSERT(pp->p_prev == pp); 445 446 TRACE_3(TR_FAC_SWAPFS, TR_SWAPFS_GETAPAGE, 447 "swapfs getconpage:pp %p vp %p off %llx", pp, vp, off); 448 449 pl[0] = pp; 450 pl[1] = NULL; 451 return (err); 452 } 453 454 /* Async putpage klustering stuff */ 455 int sw_pending_size; 456 extern int klustsize; 457 extern struct async_reqs *sw_getreq(); 458 extern void sw_putreq(struct async_reqs *); 459 extern void sw_putbackreq(struct async_reqs *); 460 extern struct async_reqs *sw_getfree(); 461 extern void sw_putfree(struct async_reqs *); 462 463 static size_t swap_putpagecnt, swap_pagespushed; 464 static size_t swap_otherfail, swap_otherpages; 465 static size_t swap_klustfail, swap_klustpages; 466 static size_t swap_getiofail, swap_getiopages; 467 468 /* 469 * Flags are composed of {B_INVAL, B_DIRTY B_FREE, B_DONTNEED}. 470 * If len == 0, do from off to EOF. 471 */ 472 static int swap_nopage = 0; /* Don't do swap_putpage's if set */ 473 474 /* ARGSUSED */ 475 static int 476 swap_putpage( 477 struct vnode *vp, 478 offset_t off, 479 size_t len, 480 int flags, 481 struct cred *cr, 482 caller_context_t *ct) 483 { 484 page_t *pp; 485 u_offset_t io_off; 486 size_t io_len = 0; 487 int err = 0; 488 int nowait; 489 struct async_reqs *arg; 490 491 if (swap_nopage) 492 return (0); 493 494 ASSERT(vp->v_count != 0); 495 496 nowait = flags & B_PAGE_NOWAIT; 497 498 /* 499 * Clear force flag so that p_lckcnt pages are not invalidated. 500 */ 501 flags &= ~(B_FORCE | B_PAGE_NOWAIT); 502 503 SWAPFS_PRINT(SWAP_VOPS, 504 "swap_putpage: vp %p, off %llx len %lx, flags %x\n", 505 (void *)vp, off, len, flags, 0); 506 TRACE_3(TR_FAC_SWAPFS, TR_SWAPFS_PUTPAGE, 507 "swapfs putpage:vp %p off %llx len %ld", (void *)vp, off, len); 508 509 if (vp->v_flag & VNOMAP) 510 return (ENOSYS); 511 512 if (!vn_has_cached_data(vp)) 513 return (0); 514 515 if (len == 0) { 516 if (curproc == proc_pageout) 517 cmn_err(CE_PANIC, "swapfs: pageout can't block"); 518 519 /* Search the entire vp list for pages >= off. */ 520 err = pvn_vplist_dirty(vp, (u_offset_t)off, swap_putapage, 521 flags, cr); 522 } else { 523 u_offset_t eoff; 524 525 /* 526 * Loop over all offsets in the range [off...off + len] 527 * looking for pages to deal with. 528 */ 529 eoff = off + len; 530 for (io_off = (u_offset_t)off; io_off < eoff; 531 io_off += io_len) { 532 /* 533 * If we run out of the async req slot, put the page 534 * now instead of queuing. 535 */ 536 if (flags == (B_ASYNC | B_FREE) && 537 sw_pending_size < klustsize && 538 (arg = sw_getfree())) { 539 /* 540 * If we are clustering, we should allow 541 * pageout to feed us more pages because # of 542 * pushes is limited by # of I/Os, and one 543 * cluster is considered to be one I/O. 544 */ 545 if (pushes) 546 pushes--; 547 548 arg->a_vp = vp; 549 arg->a_off = io_off; 550 arg->a_len = PAGESIZE; 551 arg->a_flags = B_ASYNC | B_FREE; 552 arg->a_cred = kcred; 553 sw_putreq(arg); 554 io_len = PAGESIZE; 555 continue; 556 } 557 /* 558 * If we are not invalidating pages, use the 559 * routine page_lookup_nowait() to prevent 560 * reclaiming them from the free list. 561 */ 562 if (!nowait && ((flags & B_INVAL) || 563 (flags & (B_ASYNC | B_FREE)) == B_FREE)) 564 pp = page_lookup(vp, io_off, SE_EXCL); 565 else 566 pp = page_lookup_nowait(vp, io_off, 567 (flags & (B_FREE | B_INVAL)) ? 568 SE_EXCL : SE_SHARED); 569 570 if (pp == NULL || pvn_getdirty(pp, flags) == 0) 571 io_len = PAGESIZE; 572 else { 573 err = swap_putapage(vp, pp, &io_off, &io_len, 574 flags, cr); 575 if (err != 0) 576 break; 577 } 578 } 579 } 580 /* If invalidating, verify all pages on vnode list are gone. */ 581 if (err == 0 && off == 0 && len == 0 && 582 (flags & B_INVAL) && vn_has_cached_data(vp)) { 583 cmn_err(CE_WARN, 584 "swap_putpage: B_INVAL, pages not gone"); 585 } 586 return (err); 587 } 588 589 /* 590 * Write out a single page. 591 * For swapfs this means choose a physical swap slot and write the page 592 * out using VOP_PAGEIO. 593 * In the (B_ASYNC | B_FREE) case we try to find a bunch of other dirty 594 * swapfs pages, a bunch of contiguous swap slots and then write them 595 * all out in one clustered i/o. 596 */ 597 /*ARGSUSED*/ 598 static int 599 swap_putapage( 600 struct vnode *vp, 601 page_t *pp, 602 u_offset_t *offp, 603 size_t *lenp, 604 int flags, 605 struct cred *cr) 606 { 607 int err; 608 struct vnode *pvp; 609 u_offset_t poff, off; 610 u_offset_t doff; 611 size_t dlen; 612 size_t klsz = 0; 613 u_offset_t klstart = 0; 614 struct vnode *klvp = NULL; 615 page_t *pplist; 616 se_t se; 617 struct async_reqs *arg; 618 size_t swap_klustsize; 619 620 /* 621 * This check is added for callers who access swap_putpage with len = 0. 622 * swap_putpage calls swap_putapage page-by-page via pvn_vplist_dirty. 623 * And it's necessary to do the same queuing if users have the same 624 * B_ASYNC|B_FREE flags on. 625 */ 626 if (flags == (B_ASYNC | B_FREE) && 627 sw_pending_size < klustsize && (arg = sw_getfree())) { 628 629 hat_setmod(pp); 630 page_io_unlock(pp); 631 page_unlock(pp); 632 633 arg->a_vp = vp; 634 arg->a_off = pp->p_offset; 635 arg->a_len = PAGESIZE; 636 arg->a_flags = B_ASYNC | B_FREE; 637 arg->a_cred = kcred; 638 sw_putreq(arg); 639 640 return (0); 641 } 642 643 SWAPFS_PRINT(SWAP_PUTP, 644 "swap_putapage: pp %p, vp %p, off %llx, flags %x\n", 645 pp, vp, pp->p_offset, flags, 0); 646 647 ASSERT(PAGE_LOCKED(pp)); 648 649 off = pp->p_offset; 650 651 doff = off; 652 dlen = PAGESIZE; 653 654 if (err = swap_newphysname(vp, off, &doff, &dlen, &pvp, &poff)) { 655 err = (flags == (B_ASYNC | B_FREE) ? ENOMEM : 0); 656 hat_setmod(pp); 657 page_io_unlock(pp); 658 page_unlock(pp); 659 goto out; 660 } 661 662 klvp = pvp; 663 klstart = poff; 664 pplist = pp; 665 /* 666 * If this is ASYNC | FREE and we've accumulated a bunch of such 667 * pending requests, kluster. 668 */ 669 if (flags == (B_ASYNC | B_FREE)) 670 swap_klustsize = klustsize; 671 else 672 swap_klustsize = PAGESIZE; 673 se = (flags & B_FREE ? SE_EXCL : SE_SHARED); 674 klsz = PAGESIZE; 675 while (klsz < swap_klustsize) { 676 if ((arg = sw_getreq()) == NULL) { 677 swap_getiofail++; 678 swap_getiopages += btop(klsz); 679 break; 680 } 681 ASSERT(vn_matchops(arg->a_vp, swap_vnodeops)); 682 vp = arg->a_vp; 683 off = arg->a_off; 684 685 if ((pp = page_lookup_nowait(vp, off, se)) == NULL) { 686 swap_otherfail++; 687 swap_otherpages += btop(klsz); 688 sw_putfree(arg); 689 break; 690 } 691 if (pvn_getdirty(pp, flags | B_DELWRI) == 0) { 692 sw_putfree(arg); 693 continue; 694 } 695 /* Get new physical backing store for the page */ 696 doff = off; 697 dlen = PAGESIZE; 698 if (err = swap_newphysname(vp, off, &doff, &dlen, 699 &pvp, &poff)) { 700 swap_otherfail++; 701 swap_otherpages += btop(klsz); 702 hat_setmod(pp); 703 page_io_unlock(pp); 704 page_unlock(pp); 705 sw_putbackreq(arg); 706 break; 707 } 708 /* Try to cluster new physical name with previous ones */ 709 if (klvp == pvp && poff == klstart + klsz) { 710 klsz += PAGESIZE; 711 page_add(&pplist, pp); 712 pplist = pplist->p_next; 713 sw_putfree(arg); 714 } else if (klvp == pvp && poff == klstart - PAGESIZE) { 715 klsz += PAGESIZE; 716 klstart -= PAGESIZE; 717 page_add(&pplist, pp); 718 sw_putfree(arg); 719 } else { 720 swap_klustfail++; 721 swap_klustpages += btop(klsz); 722 hat_setmod(pp); 723 page_io_unlock(pp); 724 page_unlock(pp); 725 sw_putbackreq(arg); 726 break; 727 } 728 } 729 730 err = VOP_PAGEIO(klvp, pplist, klstart, klsz, 731 B_WRITE | flags, cr, NULL); 732 733 if ((flags & B_ASYNC) == 0) 734 pvn_write_done(pp, ((err) ? B_ERROR : 0) | B_WRITE | flags); 735 736 /* Statistics */ 737 if (!err) { 738 swap_putpagecnt++; 739 swap_pagespushed += btop(klsz); 740 } 741 out: 742 TRACE_4(TR_FAC_SWAPFS, TR_SWAPFS_PUTAPAGE, 743 "swapfs putapage:vp %p klvp %p, klstart %lx, klsz %lx", 744 vp, klvp, klstart, klsz); 745 if (err && err != ENOMEM) 746 cmn_err(CE_WARN, "swapfs_putapage: err %d\n", err); 747 if (lenp) 748 *lenp = PAGESIZE; 749 return (err); 750 } 751 752 static void 753 swap_dispose( 754 vnode_t *vp, 755 page_t *pp, 756 int fl, 757 int dn, 758 cred_t *cr, 759 caller_context_t *ct) 760 { 761 int err; 762 u_offset_t off = pp->p_offset; 763 vnode_t *pvp; 764 u_offset_t poff; 765 766 ASSERT(PAGE_EXCL(pp)); 767 768 /* 769 * The caller will free/invalidate large page in one shot instead of 770 * one small page at a time. 771 */ 772 if (pp->p_szc != 0) { 773 page_unlock(pp); 774 return; 775 } 776 777 err = swap_getphysname(vp, off, &pvp, &poff); 778 if (!err && pvp != NULL) 779 VOP_DISPOSE(pvp, pp, fl, dn, cr, ct); 780 else 781 fs_dispose(vp, pp, fl, dn, cr, ct); 782 } 783