xmem_subr.c revision 4fceebdf03eeac0d7c58a4f70cc19b00a8c40a73
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/sysmacros.h>
#include <vm/seg_kmem.h>
#define MODESHIFT 3
int
{
int shift = 0;
/*
* Check access based on owner, group and
* public permissions in xmemnode.
*/
}
if (mode == 0)
return (0);
}
/*
* Decide whether it is okay to remove within a sticky directory.
* Two conditions need to be met: write access to the directory
* is needed. In sticky directories, write access is not sufficient;
* you can remove entries from a directory only if you own the directory,
* if you are privileged, if you own the entry or if they entry is
* a plain file and you have write access to that file.
* Function returns 0 if remove access is granted.
*/
int
{
return (secpolicy_vnode_remove(cr));
return (0);
}
/*
* Allocate zeroed memory if xmemfs_maxkmem has not been exceeded
* or the 'musthave' flag is set. 'musthave' allocations should
* always be subordinate to normal allocations so that xmemfs_maxkmem
* can't be exceeded by more than a few KB. Example: when creating
* a new directory, the xmemnode is a normal allocation; if that
* succeeds, the dirents for "." and ".." are 'musthave' allocations.
*/
void *
{
if (musthave) {
/*
* kmemcnt may have increased since above check so a little
* more than xmemfs_maxkmem may be allocated.
*/
if (ptr)
}
return (ptr);
}
void
{
extern size_t xmemfs_kmemcnt;
}
/* add to the number of pages we have created */
int
{
/* allocate the last available block */
return (1);
}
return (0);
}
/* sub to the number of pages we have created */
static void
{
}
/*
* xmem_acquire_pages: returns an array of size btop(xm_bsize) page pointers
* or xm_bsize bytes.
*
* If large page, the array will contain 1024 entries (4MB) or 512 entries.
*
* If not large page, there is no array as a page_t * is returned.
*/
static page_t **
{
return (NULL);
/* ppa is a direct page pointer */
panic("xmem_acquire_pages: hashin failed"
}
} else {
pindex = 0;
}
panic("xmem_acquire_pages: hashin failed"
}
}
return (ppa);
}
xm->xm_mntpath);
return (NULL);
}
}
return (NULL);
}
}
PP_CLRFREE(pp);
PP_CLRAGED(pp);
else
panic("xmem_acquire_pages: hashin failed"
}
}
return (ppa);
}
static void
{
/*
* if ppb == 1 and to lessen the load on kmem memory in
* having to allocate a million 4 byte pointers for a
* 4 GB file system, ppa is actually a page_t *
*/
} else
pindex = 0;
}
} else {
} else {
}
}
}
/*
* Initialize a xmemnode and add it to file list under mount point.
*/
void
{
xp->xn_nblocks = 0;
gethrestime(&now);
/*
* Increment the pseudo generation number for this xmemnode.
* Since xmemnodes are allocated and freed, there really is no
* particular generation number for a new xmemnode. Just fake it
* by using a counter in each file system.
*/
/*
* Add new xmemnode to end of linked list of xmemnodes for this xmemfs
* Root directory is handled specially in xmem_mount.
*/
}
}
/*
*
*/
int
{
int error = 0;
return (EINVAL);
/* Create missing pages if any */
return (ENOSPC);
if (zerofill) {
else
}
xp->xn_nblocks++;
}
blockno++;
}
return (error);
}
/*
* xmemnode_trunc - set length of xmemnode and deal with resources
*/
int
{
int error = 0;
/* Required by POSIX */
goto stamp_out;
}
case VREG:
/*
* xn_ppasz is the size of the ppa array which may not
* be fully populated if pages cannot be allocated.
*/
/* Growing the file */
}
}
}
/* Free pages if shrinking file over block boundary. */
if (next) {
KM_SLEEP);
}
continue;
xp->xn_nblocks--;
}
}
/*
* Update the file size now to reflect the pages we just
* blew away as we're about to drop the
* contents lock to zero the partial page (which could
* re-enter xmemfs via getpage and try to reacquire the lock)
* Once we drop the lock, faulters can fill in holes in
* the file and if we haven't updated the size they
* may fill in holes that are beyond EOF, which will then
* never get cleared.
*/
if (newsize) {
/* Zero new size of file to page boundary. */
}
break;
case VLNK:
/*
* Don't do anything here
* xmem_inactive frees the memory
*/
if (newsize != 0)
goto out;
case VDIR:
/*
* Remove all the directory entries under this directory.
*/
if (newsize != 0) {
goto out;
}
break;
default:
goto out;
}
gethrestime(&now);
out:
/*
* xmemnode_trunc() cannot fail when newsize == 0.
*/
return (error);
}