swap_vnops.c revision 23d9e5ac1800241d2b06a5418bd3fdc6ec3b48b5
2N/A * The contents of this file are subject to the terms of the 2N/A * Common Development and Distribution License (the "License"). 2N/A * You may not use this file except in compliance with the License. 2N/A * See the License for the specific language governing permissions 2N/A * and limitations under the License. 2N/A * When distributing Covered Code, include this CDDL HEADER in each 2N/A * If applicable, add the following below this CDDL HEADER, with the 2N/A * fields enclosed by brackets "[]" replaced with your own identifying 2N/A * information: Portions Copyright [yyyy] [name of copyright owner] 2N/A * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved. 2N/A * Define the routines within this file. * Return all the pages from [off..off+len] in given file "swapfs getpage:vp %p off %llx len %ld",
* Called from pvn_getpages or swap_getpage to get a particular page. * Until there is a call-back mechanism to cause SEGKP * pages to be unlocked, make them non-relocatable. * In very rare instances, a segkp page may have been * relocated outside of the kernel by the kernel cage * due to the window between page_unlock() and * VOP_PUTPAGE() in segkp_unlock(). Due to the * rareness of these occurances, the solution is to * relocate the page to a P_NORELOC page. "page_relocate_cage failed");
* Someone raced in and created the page after we did the * lookup but before we did the create, so go back and * try to look it up again. * If it's a fault ahead, release page_io_lock * and SE_EXCL we grabbed in page_create_va * If we are here, we haven't called VOP_PAGEIO * and thus calling pvn_read_done(pp, B_READ) * below may mislead that we tried i/o. Besides, * in case of async, pvn_read_done() should * not be called by *getpage() * swap_getphysname can return error * only when we are getting called from * swapslot_free which passes non-NULL "swapfs getapage:pp %p vp %p off %llx",
pp,
vp,
off);
* Called from large page anon routines only! This is an ugly hack where * the anon layer directly calls into swapfs with a preallocated large page. * Another method would have been to change to VOP and add an extra arg for * the preallocated large page. This all could be cleaned up later when we * solve the anonymous naming problem and no longer need to loop across of * the VOP in PAGESIZE increments to fill in or initialize a large page as * is done today. I think the latter is better since it avoid a change to * the VOP interface that could later be avoided. * If we are not using a preallocated page then we know one already * exists. So just let the old code handle it. * If existing page is found we may need to relocate. * If necessary do the page io. * Since we are only called now on behalf of an * address space operation it's impossible for * us to fail unlike swap_getapge() which * also gets called from swapslot_free(). "swap_getconpage: swap_getphysname failed!");
panic(
"swap_getconpage: null anon");
panic(
"swap_getconpage: bad anon");
* Normally we would let pvn_read_done() destroy * the page on IO error. But since this is a preallocated * page we'll let the anon layer handle it. "swapfs getconpage:pp %p vp %p off %llx",
pp,
vp,
off);
/* Async putpage klustering stuff */ * Flags are composed of {B_INVAL, B_DIRTY B_FREE, B_DONTNEED}. * If len == 0, do from off to EOF. static int swap_nopage = 0;
/* Don't do swap_putpage's if set */ * Clear force flag so that p_lckcnt pages are not invalidated. "swap_putpage: vp %p, off %llx len %lx, flags %x\n",
"swapfs putpage:vp %p off %llx len %ld", (
void *)
vp,
off,
len);
/* Search the entire vp list for pages >= off. */ * Loop over all offsets in the range [off...off + len] * looking for pages to deal with. * If we run out of the async req slot, put the page * now instead of queuing. * If we are clustering, we should allow * pageout to feed us more pages because # of * pushes is limited by # of I/Os, and one * cluster is considered to be one I/O. * If we are not invalidating pages, use the * routine page_lookup_nowait() to prevent * reclaiming them from the free list. /* If invalidating, verify all pages on vnode list are gone. */ "swap_putpage: B_INVAL, pages not gone");
* Write out a single page. * For swapfs this means choose a physical swap slot and write the page * In the (B_ASYNC | B_FREE) case we try to find a bunch of other dirty * swapfs pages, a bunch of contiguous swap slots and then write them * all out in one clustered i/o. * This check is added for callers who access swap_putpage with len = 0. * swap_putpage calls swap_putapage page-by-page via pvn_vplist_dirty. * And it's necessary to do the same queuing if users have the same * B_ASYNC|B_FREE flags on. "swap_putapage: pp %p, vp %p, off %llx, flags %x\n",
* If this is ASYNC | FREE and we've accumulated a bunch of such * pending requests, kluster. /* Get new physical backing store for the page */ /* Try to cluster new physical name with previous ones */ "swapfs putapage:vp %p klvp %p, klstart %lx, klsz %lx",
* one small page at a time.