patch-2.4.15 linux/fs/intermezzo/cache.c

Next file: linux/fs/intermezzo/dcache.c
Previous file: linux/fs/intermezzo/Makefile
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.14/linux/fs/intermezzo/cache.c linux/fs/intermezzo/cache.c
@@ -0,0 +1,256 @@
+/*
+ *
+ *
+ *  Copyright (C) 2000 Stelias Computing, Inc.
+ *  Copyright (C) 2000 Red Hat, Inc.
+ *
+ *
+ */
+
+#define __NO_VERSION__
+#include <linux/module.h>
+#include <stdarg.h>
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/ext2_fs.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/sched.h>
+#include <linux/stat.h>
+#include <linux/string.h>
+#include <linux/locks.h>
+#include <linux/blkdev.h>
+#include <linux/init.h>
+
+#include <linux/intermezzo_fs.h>
+#include <linux/intermezzo_upcall.h>
+#include <linux/intermezzo_psdev.h>
+
+/*
+   This file contains the routines associated with managing a
+   cache of files for InterMezzo.  These caches have two reqs:
+   - need to be found fast so they are hashed by the device, 
+     with an attempt to have collision chains of length 1.
+   The methods for the cache are set up in methods.
+*/
+
+/* the intent of this hash is to have collision chains of length 1 */
+#define CACHES_BITS 8
+#define CACHES_SIZE (1 << CACHES_BITS)
+#define CACHES_MASK CACHES_SIZE - 1
+static struct list_head presto_caches[CACHES_SIZE];
+
+static inline int presto_cache_hash(kdev_t dev)
+{
+        return (CACHES_MASK) & ((0x000F & (dev)) + ((0x0F00 & (dev)) >>8));
+}
+
+inline void presto_cache_add(struct presto_cache *cache, kdev_t dev)
+{
+        list_add(&cache->cache_chain,
+                 &presto_caches[presto_cache_hash(dev)]);
+        cache->cache_dev = dev;
+}
+
+inline void presto_init_cache_hash(void)
+{
+        int i;
+        for ( i = 0; i < CACHES_SIZE; i++ ) {
+                INIT_LIST_HEAD(&presto_caches[i]);
+        }
+}
+
+/* map a device to a cache */
+struct presto_cache *presto_find_cache(kdev_t dev)
+{
+        struct presto_cache *cache;
+        struct list_head *lh, *tmp;
+
+        lh = tmp = &(presto_caches[presto_cache_hash(dev)]);
+        while ( (tmp = lh->next) != lh ) {
+                cache = list_entry(tmp, struct presto_cache, cache_chain);
+                if ( cache->cache_dev == dev ) {
+                        return cache;
+                }
+        }
+        return NULL;
+}
+
+
+/* map an inode to a cache */
+struct presto_cache *presto_get_cache(struct inode *inode)
+{
+        struct presto_cache *cache;
+
+        /* find the correct presto_cache here, based on the device */
+        cache = presto_find_cache(inode->i_dev);
+        if ( !cache ) {
+                printk("WARNING: no presto cache for dev %x, ino %ld\n",
+                       inode->i_dev, inode->i_ino);
+                EXIT;
+                return NULL;
+        }
+        return cache;
+}
+
+
+/* list cache mount points for ioctl's or /proc/fs/intermezzo/mounts */
+int presto_sprint_mounts(char *buf, int buflen, int minor)
+{
+        int len = 0;
+        int i;
+        struct list_head *head, *tmp;
+        struct presto_cache *cache;
+
+        buf[0] = '\0';
+        for (i=0 ; i<CACHES_SIZE ; i++) {
+                head = tmp = &presto_caches[i];
+                while ( (tmp = tmp->next) != head ) {
+                        cache = list_entry(tmp, struct presto_cache,
+                                            cache_chain);
+                        if ( !cache->cache_root_fileset || !cache->cache_mtpt)
+                                continue;
+                        if ((minor != -1) &&
+                            (cache->cache_psdev->uc_minor != minor))
+                                continue;
+                        if ( strlen(cache->cache_root_fileset) +
+                             strlen(cache->cache_mtpt) + 
+                             strlen(cache->cache_psdev->uc_devname) +
+                             4 > buflen - len)
+                                break;
+                        len += sprintf(buf + len, "%s %s %s\n",
+                                       cache->cache_root_fileset,
+                                       cache->cache_mtpt,
+                                       cache->cache_psdev->uc_devname);
+                }
+        }
+
+        buf[buflen-1] = '\0';
+        CDEBUG(D_SUPER, "%s\n", buf);
+        return len;
+}
+
+#ifdef CONFIG_KREINT
+/* get mount point by volname
+       Arthur Ma, 2000.12.25
+ */
+int presto_get_mount (char *buf, int buflen, char *volname)
+{
+        int i;
+        struct list_head *head, *tmp;
+        struct presto_cache *cache = NULL;
+        char *path = "";
+
+        buf[0] = '\0';
+        for (i=0 ; i<CACHES_SIZE ; i++) {
+                head = tmp = &presto_caches[i];
+                while ( (tmp = tmp->next) != head ) {
+                        cache = list_entry(tmp, struct presto_cache,
+                                            cache_chain);
+                        if ( !cache->cache_root_fileset || !cache->cache_mtpt)
+                                continue;
+                        if ( strcmp(cache->cache_root_fileset, volname) == 0)
+                                break;
+                }
+        }
+        if (cache != NULL)
+                path = cache->cache_mtpt;
+        strncpy (buf, path, buflen);
+        return strlen (buf);
+}
+#endif
+
+/* another debugging routine: check fs is InterMezzo fs */
+int presto_ispresto(struct inode *inode)
+{
+        struct presto_cache *cache;
+
+        if ( !inode )
+                return 0;
+        cache = presto_get_cache(inode);
+        if ( !cache )
+                return 0;
+        return (inode->i_dev == cache->cache_dev);
+}
+
+/* setup a cache structure when we need one */
+struct presto_cache *presto_init_cache(void)
+{
+        struct presto_cache *cache;
+
+        /* make a presto_cache structure for the hash */
+        PRESTO_ALLOC(cache, struct presto_cache *, sizeof(struct presto_cache));
+        if ( cache ) {
+                memset(cache, 0, sizeof(struct presto_cache));
+                INIT_LIST_HEAD(&cache->cache_chain);
+                INIT_LIST_HEAD(&cache->cache_fset_list);
+        }
+	cache->cache_lock = SPIN_LOCK_UNLOCKED;
+	cache->cache_reserved = 0; 
+        return cache;
+}
+
+
+/* free a cache structure and all of the memory it is pointing to */
+inline void presto_free_cache(struct presto_cache *cache)
+{
+        if (!cache)
+                return;
+
+        list_del(&cache->cache_chain);
+        if (cache->cache_mtpt)
+                PRESTO_FREE(cache->cache_mtpt, strlen(cache->cache_mtpt) + 1);
+        if (cache->cache_type)
+                PRESTO_FREE(cache->cache_type, strlen(cache->cache_type) + 1);
+        if (cache->cache_root_fileset)
+                PRESTO_FREE(cache->cache_root_fileset, strlen(cache->cache_root_fileset) + 1);
+
+        PRESTO_FREE(cache, sizeof(struct presto_cache));
+}
+
+int presto_reserve_space(struct presto_cache *cache, loff_t req)
+{
+        struct filter_fs *filter; 
+        loff_t avail; 
+	struct super_block *sb = cache->cache_sb;
+        filter = cache->cache_filter;
+	if (!filter ) {
+		EXIT;
+		return 0; 
+	}
+	if (!filter->o_trops ) {
+		EXIT;
+		return 0; 
+	}
+	if (!filter->o_trops->tr_avail ) {
+		EXIT;
+		return 0; 
+	}
+        avail = filter->o_trops->tr_avail(cache, sb); 
+        CDEBUG(D_SUPER, "ESC::%ld +++> %ld \n", (long) cache->cache_reserved,
+	         (long) (cache->cache_reserved + req)); 
+        CDEBUG(D_SUPER, "ESC::Avail::%ld \n", (long) avail);
+	spin_lock(&cache->cache_lock);
+        if (req + cache->cache_reserved > avail) {
+		spin_unlock(&cache->cache_lock);
+                EXIT;
+                return -ENOSPC;
+        }
+	cache->cache_reserved += req; 
+	spin_unlock(&cache->cache_lock);
+
+        return 0;
+}
+
+void presto_release_space(struct presto_cache *cache, loff_t req)
+{
+        CDEBUG(D_SUPER, "ESC::%ld ---> %ld \n", (long) cache->cache_reserved,
+	         (long) (cache->cache_reserved - req)); 
+	spin_lock(&cache->cache_lock);
+	cache->cache_reserved -= req; 
+	spin_unlock(&cache->cache_lock);
+}

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)