summaryrefslogtreecommitdiff
path: root/usr/src/uts/intel/fs/xmemfs/xmem_subr.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/intel/fs/xmemfs/xmem_subr.c')
-rw-r--r--usr/src/uts/intel/fs/xmemfs/xmem_subr.c566
1 files changed, 0 insertions, 566 deletions
diff --git a/usr/src/uts/intel/fs/xmemfs/xmem_subr.c b/usr/src/uts/intel/fs/xmemfs/xmem_subr.c
deleted file mode 100644
index fd8f80e82f..0000000000
--- a/usr/src/uts/intel/fs/xmemfs/xmem_subr.c
+++ /dev/null
@@ -1,566 +0,0 @@
-/*
- * 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
- * or http://www.opensolaris.org/os/licensing.
- * 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/types.h>
-#include <sys/errno.h>
-#include <sys/param.h>
-#include <sys/t_lock.h>
-#include <sys/systm.h>
-#include <sys/sysmacros.h>
-#include <sys/debug.h>
-#include <sys/time.h>
-#include <sys/cmn_err.h>
-#include <sys/vnode.h>
-#include <sys/vfs.h>
-#include <sys/cred.h>
-#include <sys/kmem.h>
-#include <sys/stat.h>
-#include <sys/mode.h>
-#include <vm/hat.h>
-#include <vm/seg_map.h>
-#include <vm/seg_kmem.h>
-#include <vm/pvn.h>
-#include <vm/page.h>
-#include <sys/atomic.h>
-#include <sys/policy.h>
-#include <sys/fs/xmem.h>
-
-
-extern void *xpgget(struct xmount *);
-extern void xpgput(struct xmount *, void *);
-
-#define MODESHIFT 3
-
-size_t xmemfs_maxkmem = 32768;
-size_t xmemfs_kmemcnt;
-
-int
-xmem_xaccess(void *vxp, int mode, struct cred *cred)
-{
- struct xmemnode *xp = vxp;
- int shift = 0;
- /*
- * Check access based on owner, group and
- * public permissions in xmemnode.
- */
- if (crgetuid(cred) != xp->xn_uid) {
- shift += MODESHIFT;
- if (groupmember(xp->xn_gid, cred) == 0)
- shift += MODESHIFT;
- }
-
- mode &= ~(xp->xn_mode << shift);
-
- if (mode == 0)
- return (0);
-
- return (secpolicy_vnode_access(cred, XNTOV(xp), xp->xn_uid, mode));
-}
-
-/*
- * 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
-xmem_sticky_remove_access(struct xmemnode *dir, struct xmemnode *entry,
- struct cred *cr)
-{
- uid_t uid;
-
- if ((dir->xn_mode & S_ISVTX) &&
- (uid = crgetuid(cr)) != dir->xn_uid &&
- uid != entry->xn_uid &&
- (entry->xn_type != VREG ||
- xmem_xaccess(entry, VWRITE, cr) != 0))
- 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 *
-xmem_memalloc(size_t size, int musthave)
-{
- void *ptr = NULL;
-
- if (musthave) {
- atomic_add_long(&xmemfs_kmemcnt, size);
- ptr = kmem_zalloc(size, KM_SLEEP);
- } else if (xmemfs_kmemcnt + size < xmemfs_maxkmem) {
- /*
- * kmemcnt may have increased since above check so a little
- * more than xmemfs_maxkmem may be allocated.
- */
- ptr = kmem_zalloc(size, KM_NOSLEEP);
- if (ptr)
- atomic_add_long(&xmemfs_kmemcnt, size);
- }
- return (ptr);
-}
-
-void
-xmem_memfree(void *cp, size_t size)
-{
- extern size_t xmemfs_kmemcnt;
-
- kmem_free(cp, size);
- atomic_add_long(&xmemfs_kmemcnt, -size);
-}
-
-/* add to the number of pages we have created */
-
-int
-xmem_mem_add(struct xmount *xm, size_t size)
-{
- mutex_enter(&xm->xm_contents);
-
- /* allocate the last available block */
- if ((xm->xm_mem + size) > xm->xm_max) {
- mutex_exit(&xm->xm_contents);
- return (1);
- }
- xm->xm_mem += size;
- mutex_exit(&xm->xm_contents);
- return (0);
-}
-
-/* sub to the number of pages we have created */
-
-static void
-xmem_mem_sub(struct xmount *xm, size_t size)
-{
- mutex_enter(&xm->xm_contents);
- xm->xm_mem -= size;
- mutex_exit(&xm->xm_contents);
-}
-
-/*
- * 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 **
-xmem_acquire_pages(struct xmount *xm, struct vnode *vp, offset_t off)
-{
- page_t **ppa, *pp, *pplist;
- uint_t pindex;
- size_t bsize;
- struct seg tmpseg;
-
- bsize = xm->xm_bsize;
-
- if (xmem_mem_add(xm, 1))
- return (NULL);
-
- if (xm->xm_flags & XARGS_RESERVEMEM) {
-
- mutex_enter(&xm->xm_contents);
- ppa = xpgget(xm);
- mutex_exit(&xm->xm_contents);
-
- if (xm->xm_ppb == 1) {
- /* ppa is a direct page pointer */
-
- if (!page_hashin((page_t *)ppa, vp, off, NULL)) {
- panic("xmem_acquire_pages: hashin failed"
- " %p %llx", (void *)vp, off);
- }
- pindex = xm->xm_ppb; /* bypass for loop */
- } else {
- pindex = 0;
- }
-
- for (; pindex < xm->xm_ppb; pindex++, off += PAGESIZE) {
- pp = ppa[pindex];
- if (!page_hashin(pp, vp, off, NULL)) {
- panic("xmem_acquire_pages: hashin failed"
- " %p %p %llx", (void *)pp, (void *)vp, off);
- }
- }
- return (ppa);
- }
- bzero(&tmpseg, sizeof (struct seg));
- tmpseg.s_as = &kas;
-
- if ((freemem - xm->xm_ppb) < xmemfs_minfree ||
- page_resv(xm->xm_ppb, KM_NOSLEEP) == 0) {
-
- cmn_err(CE_WARN, "%s: File system full, no memory",
- xm->xm_mntpath);
- return (NULL);
- }
-
- (void) page_create_wait(xm->xm_ppb, PG_WAIT);
-
- pplist = page_get_freelist(vp, off, &tmpseg,
- (caddr_t)(uintptr_t)off, bsize, 0, NULL);
- if (pplist == NULL && xm->xm_ppb == 1) {
- pplist = page_get_cachelist(vp, off, &tmpseg,
- (caddr_t)(uintptr_t)off, 0, NULL);
- }
- if (pplist == NULL) {
- page_create_putback(xm->xm_ppb);
- page_unresv(xm->xm_ppb);
- return (NULL);
- }
- if (PP_ISAGED(pplist) == 0) {
- ASSERT(xm->xm_ppb == 1);
- page_hashout(pplist, NULL);
- }
-
- if (xm->xm_ppb > 1)
- ppa = kmem_alloc(sizeof (*ppa) * xm->xm_ppb, KM_SLEEP);
-
- for (pindex = 0; pindex < xm->xm_ppb; pindex++, off += PAGESIZE) {
- pp = pplist;
- page_sub(&pplist, pp);
- ASSERT(PAGE_EXCL(pp));
- ASSERT(pp->p_vnode == NULL);
- ASSERT(!hat_page_is_mapped(pp));
- PP_CLRFREE(pp);
- PP_CLRAGED(pp);
-
- if (xm->xm_ppb == 1)
- ppa = (page_t **)pp;
- else
- ppa[pindex] = pp;
-
- if (!page_hashin(pp, vp, off, NULL)) {
- panic("xmem_acquire_pages: hashin failed"
- " %p %p %llx", (void *)pp, (void *)vp, off);
- }
- page_downgrade(pp); /* XXX */
- }
- return (ppa);
-}
-
-static void
-xmem_release_pages(struct xmount *xm, page_t **ppa)
-{
- uint_t pindex;
- page_t *pp;
-
- xmem_mem_sub(xm, 1);
-
- if (xm->xm_flags & XARGS_RESERVEMEM) {
-
- /*
- * 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 *
- */
-
- if (xm->xm_ppb == 1) {
- page_hashout((page_t *)ppa, NULL);
- pindex = xm->xm_ppb; /* bypass for loop */
- } else
- pindex = 0;
-
- for (; pindex < xm->xm_ppb; pindex++) {
- pp = ppa[pindex];
- page_hashout(pp, NULL);
- }
- mutex_enter(&xm->xm_contents);
- xpgput(xm, ppa);
- mutex_exit(&xm->xm_contents);
-
- } else {
- int flag = B_INVAL;
-
- if (xm->xm_ppb == 1) {
- VN_DISPOSE((page_t *)ppa, flag, 0, kcred);
- } else {
-
- for (pindex = 0; pindex < xm->xm_ppb; pindex++)
- VN_DISPOSE(ppa[pindex], flag, 0, kcred);
-
- kmem_free(ppa, sizeof (*ppa) * xm->xm_ppb);
- }
- page_unresv(xm->xm_ppb);
- }
-}
-
-/*
- * Initialize a xmemnode and add it to file list under mount point.
- */
-void
-xmemnode_init(struct xmount *xm, struct xmemnode *xp,
- vattr_t *vap, cred_t *cred)
-{
- struct vnode *vp;
- timestruc_t now;
-
- ASSERT(vap != NULL);
- ASSERT(cred != NULL);
-
- rw_init(&xp->xn_rwlock, NULL, RW_DEFAULT, NULL);
- mutex_init(&xp->xn_tlock, NULL, MUTEX_DEFAULT, NULL);
- xp->xn_mode = MAKEIMODE(vap->va_type, vap->va_mode);
-
- if (S_ISREG(xp->xn_mode))
- xp->xn_mode &= ~(S_IXUSR | S_IXGRP | S_IXOTH);
-
- xp->xn_mask = 0;
- xp->xn_type = vap->va_type;
- xp->xn_nodeid = (ino64_t)(uint32_t)((uintptr_t)xp >> 3);
- xp->xn_nlink = 1;
- xp->xn_size = 0;
- xp->xn_uid = crgetuid(cred);
- xp->xn_gid = crgetgid(cred);
-
- xp->xn_fsid = xm->xm_dev;
- xp->xn_rdev = vap->va_rdev;
- xp->xn_blksize = PAGESIZE;
- xp->xn_nblocks = 0;
- gethrestime(&now);
- xp->xn_atime = now;
- xp->xn_mtime = now;
- xp->xn_ctime = now;
- xp->xn_seq = 0;
- xp->xn_dir = NULL;
-
- vp = XNTOV(xp);
- vn_reinit(vp);
- vn_setops(vp, xmem_vnodeops);
- vp->v_vfsp = xm->xm_vfsp;
- vp->v_type = vap->va_type;
- vp->v_rdev = vap->va_rdev;
- vp->v_data = (caddr_t)xp;
-
- mutex_enter(&xm->xm_contents);
- /*
- * 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.
- */
- xp->xn_gen = xm->xm_gen++;
-
- /*
- * Add new xmemnode to end of linked list of xmemnodes for this xmemfs
- * Root directory is handled specially in xmem_mount.
- */
- if (xm->xm_rootnode != (struct xmemnode *)NULL) {
- xp->xn_forw = NULL;
- xp->xn_back = xm->xm_rootnode->xn_back;
- xp->xn_back->xn_forw = xm->xm_rootnode->xn_back = xp;
- }
- mutex_exit(&xm->xm_contents);
-}
-
-/*
- *
- */
-int
-xmem_fillpages(struct xmemnode *xp, struct vnode *vp, offset_t off,
- offset_t len, int zerofill)
-{
- uint_t blockno, endblock;
- caddr_t base;
- int error = 0;
- struct xmount *xm = (struct xmount *)VTOXM(vp);
- offset_t poff;
- size_t bsize = xm->xm_bsize;
-
- blockno = off >> xm->xm_bshift;
- poff = (offset_t)blockno << xm->xm_bshift;
- endblock = howmany(off + len, (offset_t)bsize);
-
- if (endblock > xp->xn_ppasz)
- return (EINVAL);
-
- /* Create missing pages if any */
- for (; blockno < endblock; ) {
- if (!xp->xn_ppa[blockno]) {
- xp->xn_ppa[blockno] = xmem_acquire_pages(xm, vp, poff);
- if (!xp->xn_ppa[blockno])
- return (ENOSPC);
- if (zerofill) {
- page_t **ppp;
- if (xm->xm_ppb == 1)
- ppp = (page_t **)&xp->xn_ppa[blockno];
- else
- ppp = xp->xn_ppa[blockno];
-
- base = segxmem_getmap(xm->xm_map, vp, poff,
- bsize, ppp, S_WRITE);
- (void) kzero(base, bsize);
- segxmem_release(xm->xm_map, base, bsize);
- }
- xp->xn_nblocks++;
- }
- blockno++;
- poff += bsize;
- }
- return (error);
-}
-
-/*
- * xmemnode_trunc - set length of xmemnode and deal with resources
- */
-int
-xmemnode_trunc(struct xmount *xm, struct xmemnode *xp, u_offset_t newsize)
-{
- u_offset_t oldsize = xp->xn_size;
- timestruc_t now;
- int error = 0;
- size_t zlen;
- ulong_t newblocks, oldblocks;
-
- ASSERT(RW_WRITE_HELD(&xp->xn_rwlock));
- ASSERT(RW_WRITE_HELD(&xp->xn_contents));
-
- if (newsize == oldsize) {
- /* Required by POSIX */
- goto stamp_out;
- }
-
- switch (xp->xn_type) {
- case VREG:
-
- oldblocks = howmany(oldsize, xm->xm_bsize);
- newblocks = howmany(newsize, xm->xm_bsize);
-
- XMEMPRINTF(4, ("xmemnode_trunc: xp %p old %lx new %lx\n",
- xp, oldblocks, newblocks));
- /*
- * xn_ppasz is the size of the ppa array which may not
- * be fully populated if pages cannot be allocated.
- */
- ASSERT(xp->xn_ppasz >= oldblocks);
-
- /* Growing the file */
- if (newblocks > oldblocks) {
- if (xp->xn_ppasz < newblocks) {
- page_t ***ppa;
- ppa = kmem_zalloc(newblocks * sizeof (*ppa), KM_SLEEP);
- if (xp->xn_ppasz) {
- bcopy(xp->xn_ppa, ppa,
- newblocks * sizeof (*ppa));
-
- kmem_free(xp->xn_ppa,
- xp->xn_ppasz * sizeof (*ppa));
- }
- xp->xn_ppa = ppa;
- xp->xn_ppasz = newblocks;
- }
- }
-
- /* Free pages if shrinking file over block boundary. */
- if (newblocks < oldblocks) {
- uint_t next;
- page_t ***ppa = NULL;
- next = newblocks;
- if (next) {
- ppa = kmem_zalloc(next * sizeof (*ppa),
- KM_SLEEP);
- bcopy(xp->xn_ppa, ppa, next * sizeof (*ppa));
- }
- for (; next < oldblocks; next++) {
- if (!xp->xn_ppa[next])
- continue;
- xmem_release_pages(xm, xp->xn_ppa[next]);
- xp->xn_nblocks--;
- }
- kmem_free(xp->xn_ppa, xp->xn_ppasz * sizeof (*ppa));
- xp->xn_ppa = ppa;
- xp->xn_ppasz = newblocks;
- }
-
- /*
- * 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.
- */
- xp->xn_size = newsize;
-
-
- if (newsize) {
- /* Zero new size of file to page boundary. */
- zlen = PAGESIZE - ((ulong_t)newsize & PAGEOFFSET);
- rw_exit(&xp->xn_contents);
- pvn_vpzero(XNTOV(xp), (u_offset_t)newsize, zlen);
- rw_enter(&xp->xn_contents, RW_WRITER);
- }
-
- break;
-
- case VLNK:
- /*
- * Don't do anything here
- * xmem_inactive frees the memory
- */
- if (newsize != 0)
- error = EINVAL;
- goto out;
- case VDIR:
- /*
- * Remove all the directory entries under this directory.
- */
- if (newsize != 0) {
- error = EINVAL;
- goto out;
- }
- xdirtrunc(xp);
- ASSERT(xp->xn_nlink == 0);
- break;
- default:
- goto out;
- }
-
-stamp_out:
- gethrestime(&now);
- xp->xn_mtime = now;
- xp->xn_ctime = now;
-out:
- /*
- * xmemnode_trunc() cannot fail when newsize == 0.
- */
- ASSERT(error == 0 || newsize != 0);
- return (error);
-}