OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [fs/] [intermezzo/] [cache.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2
 * vim:expandtab:shiftwidth=8:tabstop=8:
3
 *
4
 *  Copyright (C) 2000 Stelias Computing, Inc.
5
 *  Copyright (C) 2000 Red Hat, Inc.
6
 *
7
 *   This file is part of InterMezzo, http://www.inter-mezzo.org.
8
 *
9
 *   InterMezzo is free software; you can redistribute it and/or
10
 *   modify it under the terms of version 2 of the GNU General Public
11
 *   License as published by the Free Software Foundation.
12
 *
13
 *   InterMezzo is distributed in the hope that it will be useful,
14
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 *   GNU General Public License for more details.
17
 *
18
 *   You should have received a copy of the GNU General Public License
19
 *   along with InterMezzo; if not, write to the Free Software
20
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
 */
22
 
23
#define __NO_VERSION__
24
#include <linux/module.h>
25
#include <stdarg.h>
26
#include <asm/bitops.h>
27
#include <asm/uaccess.h>
28
#include <asm/system.h>
29
 
30
#include <linux/errno.h>
31
#include <linux/fs.h>
32
#include <linux/ext2_fs.h>
33
#include <linux/slab.h>
34
#include <linux/vmalloc.h>
35
#include <linux/sched.h>
36
#include <linux/stat.h>
37
#include <linux/string.h>
38
#include <linux/locks.h>
39
#include <linux/blkdev.h>
40
#include <linux/init.h>
41
 
42
#include <linux/intermezzo_fs.h>
43
#include <linux/intermezzo_psdev.h>
44
 
45
/*
46
   This file contains the routines associated with managing a
47
   cache of files for InterMezzo.  These caches have two reqs:
48
   - need to be found fast so they are hashed by the device,
49
     with an attempt to have collision chains of length 1.
50
   The methods for the cache are set up in methods.
51
*/
52
 
53
extern kmem_cache_t * presto_dentry_slab;
54
 
55
/* the intent of this hash is to have collision chains of length 1 */
56
#define CACHES_BITS 8
57
#define CACHES_SIZE (1 << CACHES_BITS)
58
#define CACHES_MASK CACHES_SIZE - 1
59
static struct list_head presto_caches[CACHES_SIZE];
60
 
61
static inline int presto_cache_hash(kdev_t dev)
62
{
63
        return (CACHES_MASK) & ((0x000F & (dev)) + ((0x0F00 & (dev)) >>8));
64
}
65
 
66
inline void presto_cache_add(struct presto_cache *cache, kdev_t dev)
67
{
68
        list_add(&cache->cache_chain,
69
                 &presto_caches[presto_cache_hash(dev)]);
70
        cache->cache_dev = dev;
71
}
72
 
73
inline void presto_cache_init_hash(void)
74
{
75
        int i;
76
        for ( i = 0; i < CACHES_SIZE; i++ ) {
77
                INIT_LIST_HEAD(&presto_caches[i]);
78
        }
79
}
80
 
81
/* map a device to a cache */
82
struct presto_cache *presto_cache_find(kdev_t dev)
83
{
84
        struct presto_cache *cache;
85
        struct list_head *lh, *tmp;
86
 
87
        lh = tmp = &(presto_caches[presto_cache_hash(dev)]);
88
        while ( (tmp = lh->next) != lh ) {
89
                cache = list_entry(tmp, struct presto_cache, cache_chain);
90
                if ( cache->cache_dev == dev ) {
91
                        return cache;
92
                }
93
        }
94
        return NULL;
95
}
96
 
97
 
98
/* map an inode to a cache */
99
struct presto_cache *presto_get_cache(struct inode *inode)
100
{
101
        struct presto_cache *cache;
102
        ENTRY;
103
        /* find the correct presto_cache here, based on the device */
104
        cache = presto_cache_find(inode->i_dev);
105
        if ( !cache ) {
106
                CERROR("WARNING: no presto cache for dev %x, ino %ld\n",
107
                       inode->i_dev, inode->i_ino);
108
                EXIT;
109
                return NULL;
110
        }
111
        EXIT;
112
        return cache;
113
}
114
 
115
/* another debugging routine: check fs is InterMezzo fs */
116
int presto_ispresto(struct inode *inode)
117
{
118
        struct presto_cache *cache;
119
 
120
        if ( !inode )
121
                return 0;
122
        cache = presto_get_cache(inode);
123
        if ( !cache )
124
                return 0;
125
        return (inode->i_dev == cache->cache_dev);
126
}
127
 
128
/* setup a cache structure when we need one */
129
struct presto_cache *presto_cache_init(void)
130
{
131
        struct presto_cache *cache;
132
 
133
        PRESTO_ALLOC(cache, sizeof(struct presto_cache));
134
        if ( cache ) {
135
                memset(cache, 0, sizeof(struct presto_cache));
136
                INIT_LIST_HEAD(&cache->cache_chain);
137
                INIT_LIST_HEAD(&cache->cache_fset_list);
138
                cache->cache_lock = SPIN_LOCK_UNLOCKED;
139
                cache->cache_reserved = 0;
140
        }
141
        return cache;
142
}
143
 
144
/* free a cache structure and all of the memory it is pointing to */
145
inline void presto_free_cache(struct presto_cache *cache)
146
{
147
        if (!cache)
148
                return;
149
 
150
        list_del(&cache->cache_chain);
151
        if (cache->cache_sb && cache->cache_sb->s_root &&
152
                        presto_d2d(cache->cache_sb->s_root)) {
153
                kmem_cache_free(presto_dentry_slab,
154
                                presto_d2d(cache->cache_sb->s_root));
155
                cache->cache_sb->s_root->d_fsdata = NULL;
156
        }
157
 
158
        PRESTO_FREE(cache, sizeof(struct presto_cache));
159
}
160
 
161
int presto_reserve_space(struct presto_cache *cache, loff_t req)
162
{
163
        struct filter_fs *filter;
164
        loff_t avail;
165
        struct super_block *sb = cache->cache_sb;
166
        filter = cache->cache_filter;
167
        if (!filter ) {
168
                EXIT;
169
                return 0;
170
        }
171
        if (!filter->o_trops ) {
172
                EXIT;
173
                return 0;
174
        }
175
        if (!filter->o_trops->tr_avail ) {
176
                EXIT;
177
                return 0;
178
        }
179
 
180
        spin_lock(&cache->cache_lock);
181
        avail = filter->o_trops->tr_avail(cache, sb);
182
        CDEBUG(D_SUPER, "ESC::%ld +++> %ld \n", (long) cache->cache_reserved,
183
                 (long) (cache->cache_reserved + req));
184
        CDEBUG(D_SUPER, "ESC::Avail::%ld \n", (long) avail);
185
        if (req + cache->cache_reserved > avail) {
186
                spin_unlock(&cache->cache_lock);
187
                EXIT;
188
                return -ENOSPC;
189
        }
190
        cache->cache_reserved += req;
191
        spin_unlock(&cache->cache_lock);
192
 
193
        EXIT;
194
        return 0;
195
}
196
 
197
void presto_release_space(struct presto_cache *cache, loff_t req)
198
{
199
        CDEBUG(D_SUPER, "ESC::%ld ---> %ld \n", (long) cache->cache_reserved,
200
                 (long) (cache->cache_reserved - req));
201
        spin_lock(&cache->cache_lock);
202
        cache->cache_reserved -= req;
203
        spin_unlock(&cache->cache_lock);
204
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.