summaryrefslogtreecommitdiffstats
path: root/sys/gnu/fs/xfs/xfs_refcache.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/gnu/fs/xfs/xfs_refcache.c')
-rw-r--r--sys/gnu/fs/xfs/xfs_refcache.c431
1 files changed, 0 insertions, 431 deletions
diff --git a/sys/gnu/fs/xfs/xfs_refcache.c b/sys/gnu/fs/xfs/xfs_refcache.c
deleted file mode 100644
index 09918b5..0000000
--- a/sys/gnu/fs/xfs/xfs_refcache.c
+++ /dev/null
@@ -1,431 +0,0 @@
-/*
- * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-#include "xfs.h"
-#include "xfs_fs.h"
-#include "xfs_types.h"
-#include "xfs_bit.h"
-#include "xfs_log.h"
-#include "xfs_inum.h"
-#include "xfs_trans.h"
-#include "xfs_sb.h"
-#include "xfs_ag.h"
-#include "xfs_dir.h"
-#include "xfs_dir2.h"
-#include "xfs_dmapi.h"
-#include "xfs_mount.h"
-#include "xfs_bmap_btree.h"
-#include "xfs_alloc_btree.h"
-#include "xfs_ialloc_btree.h"
-#include "xfs_dir_sf.h"
-#include "xfs_dir2_sf.h"
-#include "xfs_attr_sf.h"
-#include "xfs_dinode.h"
-#include "xfs_inode.h"
-#include "xfs_inode_item.h"
-#include "xfs_itable.h"
-#include "xfs_btree.h"
-#include "xfs_alloc.h"
-#include "xfs_ialloc.h"
-#include "xfs_bmap.h"
-#include "xfs_attr.h"
-#include "xfs_error.h"
-#include "xfs_buf_item.h"
-#include "xfs_refcache.h"
-
-STATIC lock_t xfs_refcache_lock;
-STATIC xfs_inode_t **xfs_refcache;
-STATIC int xfs_refcache_index;
-STATIC int xfs_refcache_busy;
-STATIC int xfs_refcache_count;
-
-void
-xfs_refcache_init(void)
-{
- spinlock_init(&xfs_refcache_lock, "xfs_refcache");
-}
-/*
- * Insert the given inode into the reference cache.
- */
-void
-xfs_refcache_insert(
- xfs_inode_t *ip)
-{
- vnode_t *vp;
- xfs_inode_t *release_ip;
- xfs_inode_t **refcache;
-
- ASSERT(ismrlocked(&(ip->i_iolock), MR_UPDATE));
-
- /*
- * If an unmount is busy blowing entries out of the cache,
- * then don't bother.
- */
- if (xfs_refcache_busy) {
- return;
- }
-
- /*
- * If we tuned the refcache down to zero, don't do anything.
- */
- if (!xfs_refcache_size) {
- return;
- }
-
- /*
- * The inode is already in the refcache, so don't bother
- * with it.
- */
- if (ip->i_refcache != NULL) {
- return;
- }
-
- vp = XFS_ITOV(ip);
- /* ASSERT(vp->v_count > 0); */
- VN_HOLD(vp);
-
- /*
- * We allocate the reference cache on use so that we don't
- * waste the memory on systems not being used as NFS servers.
- */
- if (xfs_refcache == NULL) {
- refcache = (xfs_inode_t **)kmem_zalloc(XFS_REFCACHE_SIZE_MAX *
- sizeof(xfs_inode_t *),
- KM_SLEEP);
- } else {
- refcache = NULL;
- }
-
- spin_lock(&xfs_refcache_lock);
-
- /*
- * If we allocated memory for the refcache above and it still
- * needs it, then use the memory we allocated. Otherwise we'll
- * free the memory below.
- */
- if (refcache != NULL) {
- if (xfs_refcache == NULL) {
- xfs_refcache = refcache;
- refcache = NULL;
- }
- }
-
- /*
- * If an unmount is busy clearing out the cache, don't add new
- * entries to it.
- */
- if (xfs_refcache_busy) {
- spin_unlock(&xfs_refcache_lock);
- VN_RELE(vp);
- /*
- * If we allocated memory for the refcache above but someone
- * else beat us to using it, then free the memory now.
- */
- if (refcache != NULL) {
- kmem_free(refcache,
- XFS_REFCACHE_SIZE_MAX * sizeof(xfs_inode_t *));
- }
- return;
- }
- release_ip = xfs_refcache[xfs_refcache_index];
- if (release_ip != NULL) {
- release_ip->i_refcache = NULL;
- xfs_refcache_count--;
- ASSERT(xfs_refcache_count >= 0);
- }
- xfs_refcache[xfs_refcache_index] = ip;
- ASSERT(ip->i_refcache == NULL);
- ip->i_refcache = &(xfs_refcache[xfs_refcache_index]);
- xfs_refcache_count++;
- ASSERT(xfs_refcache_count <= xfs_refcache_size);
- xfs_refcache_index++;
- if (xfs_refcache_index == xfs_refcache_size) {
- xfs_refcache_index = 0;
- }
- spin_unlock(&xfs_refcache_lock);
-
- /*
- * Save the pointer to the inode to be released so that we can
- * VN_RELE it once we've dropped our inode locks in xfs_rwunlock().
- * The pointer may be NULL, but that's OK.
- */
- ip->i_release = release_ip;
-
- /*
- * If we allocated memory for the refcache above but someone
- * else beat us to using it, then free the memory now.
- */
- if (refcache != NULL) {
- kmem_free(refcache,
- XFS_REFCACHE_SIZE_MAX * sizeof(xfs_inode_t *));
- }
-}
-
-
-/*
- * If the given inode is in the reference cache, purge its entry and
- * release the reference on the vnode.
- */
-void
-xfs_refcache_purge_ip(
- xfs_inode_t *ip)
-{
- vnode_t *vp;
- int error;
-
- /*
- * If we're not pointing to our entry in the cache, then
- * we must not be in the cache.
- */
- if (ip->i_refcache == NULL) {
- return;
- }
-
- spin_lock(&xfs_refcache_lock);
- if (ip->i_refcache == NULL) {
- spin_unlock(&xfs_refcache_lock);
- return;
- }
-
- /*
- * Clear both our pointer to the cache entry and its pointer
- * back to us.
- */
- ASSERT(*(ip->i_refcache) == ip);
- *(ip->i_refcache) = NULL;
- ip->i_refcache = NULL;
- xfs_refcache_count--;
- ASSERT(xfs_refcache_count >= 0);
- spin_unlock(&xfs_refcache_lock);
-
- vp = XFS_ITOV(ip);
- /* ASSERT(vp->v_count > 1); */
- VOP_RELEASE(vp, error);
- VN_RELE(vp);
-}
-
-
-/*
- * This is called from the XFS unmount code to purge all entries for the
- * given mount from the cache. It uses the refcache busy counter to
- * make sure that new entries are not added to the cache as we purge them.
- */
-void
-xfs_refcache_purge_mp(
- xfs_mount_t *mp)
-{
- vnode_t *vp;
- int error, i;
- xfs_inode_t *ip;
-
- if (xfs_refcache == NULL) {
- return;
- }
-
- spin_lock(&xfs_refcache_lock);
- /*
- * Bumping the busy counter keeps new entries from being added
- * to the cache. We use a counter since multiple unmounts could
- * be in here simultaneously.
- */
- xfs_refcache_busy++;
-
- for (i = 0; i < xfs_refcache_size; i++) {
- ip = xfs_refcache[i];
- if ((ip != NULL) && (ip->i_mount == mp)) {
- xfs_refcache[i] = NULL;
- ip->i_refcache = NULL;
- xfs_refcache_count--;
- ASSERT(xfs_refcache_count >= 0);
- spin_unlock(&xfs_refcache_lock);
- vp = XFS_ITOV(ip);
- VOP_RELEASE(vp, error);
- VN_RELE(vp);
- spin_lock(&xfs_refcache_lock);
- }
- }
-
- xfs_refcache_busy--;
- ASSERT(xfs_refcache_busy >= 0);
- spin_unlock(&xfs_refcache_lock);
-}
-
-
-/*
- * This is called from the XFS sync code to ensure that the refcache
- * is emptied out over time. We purge a small number of entries with
- * each call.
- */
-void
-xfs_refcache_purge_some(xfs_mount_t *mp)
-{
- int error, i;
- xfs_inode_t *ip;
- int iplist_index;
- xfs_inode_t **iplist;
-
- if ((xfs_refcache == NULL) || (xfs_refcache_count == 0)) {
- return;
- }
-
- iplist_index = 0;
- iplist = (xfs_inode_t **)kmem_zalloc(xfs_refcache_purge_count *
- sizeof(xfs_inode_t *), KM_SLEEP);
-
- spin_lock(&xfs_refcache_lock);
-
- /*
- * Store any inodes we find in the next several entries
- * into the iplist array to be released after dropping
- * the spinlock. We always start looking from the currently
- * oldest place in the cache. We move the refcache index
- * forward as we go so that we are sure to eventually clear
- * out the entire cache when the system goes idle.
- */
- for (i = 0; i < xfs_refcache_purge_count; i++) {
- ip = xfs_refcache[xfs_refcache_index];
- if (ip != NULL) {
- xfs_refcache[xfs_refcache_index] = NULL;
- ip->i_refcache = NULL;
- xfs_refcache_count--;
- ASSERT(xfs_refcache_count >= 0);
- iplist[iplist_index] = ip;
- iplist_index++;
- }
- xfs_refcache_index++;
- if (xfs_refcache_index == xfs_refcache_size) {
- xfs_refcache_index = 0;
- }
- }
-
- spin_unlock(&xfs_refcache_lock);
-
- /*
- * Now drop the inodes we collected.
- */
- for (i = 0; i < iplist_index; i++) {
- VOP_RELEASE(XFS_ITOV(iplist[i]), error);
- VN_RELE(XFS_ITOV(iplist[i]));
- }
-
- kmem_free(iplist, xfs_refcache_purge_count *
- sizeof(xfs_inode_t *));
-}
-
-/*
- * This is called when the refcache is dynamically resized
- * via a sysctl.
- *
- * If the new size is smaller than the old size, purge all
- * entries in slots greater than the new size, and move
- * the index if necessary.
- *
- * If the refcache hasn't even been allocated yet, or the
- * new size is larger than the old size, just set the value
- * of xfs_refcache_size.
- */
-
-void
-xfs_refcache_resize(int xfs_refcache_new_size)
-{
- int i;
- xfs_inode_t *ip;
- int iplist_index = 0;
- xfs_inode_t **iplist;
- int error;
-
- /*
- * If the new size is smaller than the current size,
- * purge entries to create smaller cache, and
- * reposition index if necessary.
- * Don't bother if no refcache yet.
- */
- if (xfs_refcache && (xfs_refcache_new_size < xfs_refcache_size)) {
-
- iplist = (xfs_inode_t **)kmem_zalloc(XFS_REFCACHE_SIZE_MAX *
- sizeof(xfs_inode_t *), KM_SLEEP);
-
- spin_lock(&xfs_refcache_lock);
-
- for (i = xfs_refcache_new_size; i < xfs_refcache_size; i++) {
- ip = xfs_refcache[i];
- if (ip != NULL) {
- xfs_refcache[i] = NULL;
- ip->i_refcache = NULL;
- xfs_refcache_count--;
- ASSERT(xfs_refcache_count >= 0);
- iplist[iplist_index] = ip;
- iplist_index++;
- }
- }
-
- xfs_refcache_size = xfs_refcache_new_size;
-
- /*
- * Move index to beginning of cache if it's now past the end
- */
- if (xfs_refcache_index >= xfs_refcache_new_size)
- xfs_refcache_index = 0;
-
- spin_unlock(&xfs_refcache_lock);
-
- /*
- * Now drop the inodes we collected.
- */
- for (i = 0; i < iplist_index; i++) {
- VOP_RELEASE(XFS_ITOV(iplist[i]), error);
- VN_RELE(XFS_ITOV(iplist[i]));
- }
-
- kmem_free(iplist, XFS_REFCACHE_SIZE_MAX *
- sizeof(xfs_inode_t *));
- } else {
- spin_lock(&xfs_refcache_lock);
- xfs_refcache_size = xfs_refcache_new_size;
- spin_unlock(&xfs_refcache_lock);
- }
-}
-
-void
-xfs_refcache_iunlock(
- xfs_inode_t *ip,
- uint lock_flags)
-{
- xfs_inode_t *release_ip;
- int error;
-
- release_ip = ip->i_release;
- ip->i_release = NULL;
-
- xfs_iunlock(ip, lock_flags);
-
- if (release_ip != NULL) {
- VOP_RELEASE(XFS_ITOV(release_ip), error);
- VN_RELE(XFS_ITOV(release_ip));
- }
-}
-
-void
-xfs_refcache_destroy(void)
-{
- if (xfs_refcache) {
- kmem_free(xfs_refcache,
- XFS_REFCACHE_SIZE_MAX * sizeof(xfs_inode_t *));
- xfs_refcache = NULL;
- }
- spinlock_destroy(&xfs_refcache_lock);
-}
OpenPOWER on IntegriCloud