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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [fs/] [intermezzo/] [super.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) 1998 Peter J. Braam <braam@clusterfs.com>
5
 *  Copyright (C) 2000 Stelias Computing, Inc.
6
 *  Copyright (C) 2000 Red Hat, Inc.
7
 *
8
 *   This file is part of InterMezzo, http://www.inter-mezzo.org.
9
 *
10
 *   InterMezzo is free software; you can redistribute it and/or
11
 *   modify it under the terms of version 2 of the GNU General Public
12
 *   License as published by the Free Software Foundation.
13
 *
14
 *   InterMezzo is distributed in the hope that it will be useful,
15
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 *   GNU General Public License for more details.
18
 *
19
 *   You should have received a copy of the GNU General Public License
20
 *   along with InterMezzo; if not, write to the Free Software
21
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22
 *
23
 *  presto's super.c
24
 */
25
 
26
static char rcsid[] __attribute ((unused)) = "$Id: super.c,v 1.1.1.1 2004-04-15 01:09:15 phoenix Exp $";
27
#define INTERMEZZO_VERSION "$Revision: 1.1.1.1 $"
28
 
29
#include <stdarg.h>
30
 
31
#include <asm/bitops.h>
32
#include <asm/uaccess.h>
33
#include <asm/system.h>
34
 
35
#include <linux/errno.h>
36
#include <linux/fs.h>
37
#include <linux/ext2_fs.h>
38
#include <linux/slab.h>
39
#include <linux/vmalloc.h>
40
#include <linux/sched.h>
41
#include <linux/stat.h>
42
#include <linux/string.h>
43
#include <linux/locks.h>
44
#include <linux/blkdev.h>
45
#include <linux/init.h>
46
#include <linux/devfs_fs_kernel.h>
47
#define __NO_VERSION__
48
#include <linux/module.h>
49
 
50
#include <linux/intermezzo_fs.h>
51
#include <linux/intermezzo_psdev.h>
52
 
53
#ifdef PRESTO_DEBUG
54
long presto_vmemory = 0;
55
long presto_kmemory = 0;
56
#endif
57
 
58
/* returns an allocated string, copied out from data if opt is found */
59
static char *opt_read(const char *opt, char *data)
60
{
61
        char *value;
62
        char *retval;
63
 
64
        CDEBUG(D_SUPER, "option: %s, data %s\n", opt, data);
65
        if ( strncmp(opt, data, strlen(opt)) )
66
                return NULL;
67
 
68
        if ( (value = strchr(data, '=')) == NULL )
69
                return NULL;
70
 
71
        value++;
72
        PRESTO_ALLOC(retval, strlen(value) + 1);
73
        if ( !retval ) {
74
                CERROR("InterMezzo: Out of memory!\n");
75
                return NULL;
76
        }
77
 
78
        strcpy(retval, value);
79
        CDEBUG(D_SUPER, "Assigned option: %s, value %s\n", opt, retval);
80
        return retval;
81
}
82
 
83
static void opt_store(char **dst, char *opt)
84
{
85
        if (!dst)
86
                CERROR("intermezzo: store_opt, error dst == NULL\n");
87
 
88
        if (*dst)
89
                PRESTO_FREE(*dst, strlen(*dst) + 1);
90
        *dst = opt;
91
}
92
 
93
static void opt_set_default(char **dst, char *defval)
94
{
95
        if (!dst)
96
                CERROR("intermezzo: store_opt, error dst == NULL\n");
97
 
98
        if (*dst)
99
                PRESTO_FREE(*dst, strlen(*dst) + 1);
100
        if (defval) {
101
                char *def_alloced;
102
                PRESTO_ALLOC(def_alloced, strlen(defval)+1);
103
                if (!def_alloced) {
104
                        CERROR("InterMezzo: Out of memory!\n");
105
                        return ;
106
                }
107
                strcpy(def_alloced, defval);
108
                *dst = def_alloced;
109
        }
110
}
111
 
112
 
113
/* Find the options for InterMezzo in "options", saving them into the
114
 * passed pointers.  If the pointer is null, the option is discarded.
115
 * Copy out all non-InterMezzo options into cache_data (to be passed
116
 * to the read_super operation of the cache).  The return value will
117
 * be a pointer to the end of the cache_data.
118
 */
119
static char *presto_options(struct super_block *sb,
120
                            char *options, char *cache_data,
121
                            char **cache_type, char **fileset,
122
                            char **channel)
123
{
124
        char *this_char;
125
        char *cache_data_end = cache_data;
126
 
127
        /* set the defaults */
128
        if (strcmp(sb->s_type->name, "intermezzo") == 0)
129
            opt_set_default(cache_type, "ext3");
130
        else
131
            opt_set_default(cache_type, "tmpfs");
132
 
133
        if (!options || !cache_data)
134
                return cache_data_end;
135
 
136
 
137
        CDEBUG(D_SUPER, "parsing options\n");
138
        for (this_char = strtok (options, ",");
139
             this_char != NULL;
140
             this_char = strtok (NULL, ",")) {
141
                char *opt;
142
                CDEBUG(D_SUPER, "this_char %s\n", this_char);
143
 
144
                if ( (opt = opt_read("fileset", this_char)) ) {
145
                        opt_store(fileset, opt);
146
                        continue;
147
                }
148
                if ( (opt = opt_read("cache_type", this_char)) ) {
149
                        opt_store(cache_type, opt);
150
                        continue;
151
                }
152
                if ( (opt = opt_read("channel", this_char)) ) {
153
                        opt_store(channel, opt);
154
                        continue;
155
                }
156
 
157
                cache_data_end +=
158
                        sprintf(cache_data_end, "%s%s",
159
                                cache_data_end != cache_data ? ",":"",
160
                                this_char);
161
        }
162
 
163
        return cache_data_end;
164
}
165
 
166
static int presto_set_channel(struct presto_cache *cache, char *channel)
167
{
168
        int minor;
169
 
170
        ENTRY;
171
        if (!channel) {
172
                minor = izo_psdev_get_free_channel();
173
        } else {
174
                minor = simple_strtoul(channel, NULL, 0);
175
        }
176
        if (minor < 0 || minor >= MAX_CHANNEL) {
177
                CERROR("all channels in use or channel too large %d\n",
178
                       minor);
179
                return -EINVAL;
180
        }
181
 
182
        cache->cache_psdev = &(izo_channels[minor]);
183
        list_add(&cache->cache_channel_list,
184
                 &cache->cache_psdev->uc_cache_list);
185
 
186
        EXIT;
187
        return minor;
188
}
189
 
190
/* We always need to remove the presto options before passing
191
   mount options to cache FS */
192
struct super_block * presto_read_super(struct super_block * sb,
193
                                       void * data, int silent)
194
{
195
        struct file_system_type *fstype;
196
        struct presto_cache *cache = NULL;
197
        char *cache_data = NULL;
198
        char *cache_data_end;
199
        char *cache_type = NULL;
200
        char *fileset = NULL;
201
        char *channel = NULL;
202
        int err;
203
        unsigned int minor;
204
 
205
        ENTRY;
206
 
207
        /* reserve space for the cache's data */
208
        PRESTO_ALLOC(cache_data, PAGE_SIZE);
209
        if ( !cache_data ) {
210
                CERROR("presto_read_super: Cannot allocate data page.\n");
211
                EXIT;
212
                goto out_err;
213
        }
214
 
215
        /* read and validate options */
216
        cache_data_end = presto_options(sb, data, cache_data, &cache_type,
217
                                        &fileset, &channel);
218
 
219
        /* was there anything for the cache filesystem in the data? */
220
        if (cache_data_end == cache_data) {
221
                PRESTO_FREE(cache_data, PAGE_SIZE);
222
                cache_data = NULL;
223
        } else {
224
                CDEBUG(D_SUPER, "cache_data at %p is: %s\n", cache_data,
225
                       cache_data);
226
        }
227
 
228
        /* set up the cache */
229
        cache = presto_cache_init();
230
        if ( !cache ) {
231
                CERROR("presto_read_super: failure allocating cache.\n");
232
                EXIT;
233
                goto out_err;
234
        }
235
        cache->cache_type = cache_type;
236
 
237
        /* link cache to channel */
238
        minor = presto_set_channel(cache, channel);
239
        if (minor < 0) {
240
                EXIT;
241
                goto out_err;
242
        }
243
 
244
        CDEBUG(D_SUPER, "Presto: type=%s, fset=%s, dev= %d, flags %x\n",
245
               cache_type, fileset?fileset:"NULL", minor, cache->cache_flags);
246
 
247
        MOD_INC_USE_COUNT;
248
 
249
        /* get the filter for the cache */
250
        fstype = get_fs_type(cache_type);
251
        cache->cache_filter = filter_get_filter_fs((const char *)cache_type);
252
        if ( !fstype || !cache->cache_filter) {
253
                CERROR("Presto: unrecognized fs type or cache type\n");
254
                MOD_DEC_USE_COUNT;
255
                EXIT;
256
                goto out_err;
257
        }
258
 
259
        /* can we in fact mount the cache */
260
        if ((fstype->fs_flags & FS_REQUIRES_DEV) && !sb->s_bdev) {
261
                CERROR("filesystem \"%s\" requires a valid block device\n",
262
                                cache_type);
263
                MOD_DEC_USE_COUNT;
264
                EXIT;
265
                goto out_err;
266
        }
267
 
268
        sb = fstype->read_super(sb, cache_data, silent);
269
 
270
        /* this might have been freed above */
271
        if (cache_data) {
272
                PRESTO_FREE(cache_data, PAGE_SIZE);
273
                cache_data = NULL;
274
        }
275
 
276
        if ( !sb ) {
277
                CERROR("InterMezzo: cache mount failure.\n");
278
                MOD_DEC_USE_COUNT;
279
                EXIT;
280
                goto out_err;
281
        }
282
 
283
        cache->cache_sb = sb;
284
        cache->cache_root = dget(sb->s_root);
285
 
286
        /* we now know the dev of the cache: hash the cache */
287
        presto_cache_add(cache, sb->s_dev);
288
        err = izo_prepare_fileset(sb->s_root, fileset);
289
 
290
        filter_setup_journal_ops(cache->cache_filter, cache->cache_type);
291
 
292
        /* make sure we have our own super operations: sb
293
           still contains the cache operations */
294
        filter_setup_super_ops(cache->cache_filter, sb->s_op,
295
                               &presto_super_ops);
296
        sb->s_op = filter_c2usops(cache->cache_filter);
297
 
298
        /* get izo directory operations: sb->s_root->d_inode exists now */
299
        filter_setup_dir_ops(cache->cache_filter, sb->s_root->d_inode,
300
                             &presto_dir_iops, &presto_dir_fops);
301
        filter_setup_dentry_ops(cache->cache_filter, sb->s_root->d_op,
302
                                &presto_dentry_ops);
303
        sb->s_root->d_inode->i_op = filter_c2udiops(cache->cache_filter);
304
        sb->s_root->d_inode->i_fop = filter_c2udfops(cache->cache_filter);
305
        sb->s_root->d_op = filter_c2udops(cache->cache_filter);
306
 
307
        EXIT;
308
        return sb;
309
 
310
 out_err:
311
        CDEBUG(D_SUPER, "out_err called\n");
312
        if (cache)
313
                PRESTO_FREE(cache, sizeof(struct presto_cache));
314
        if (cache_data)
315
                PRESTO_FREE(cache_data, PAGE_SIZE);
316
        if (fileset)
317
                PRESTO_FREE(fileset, strlen(fileset) + 1);
318
        if (channel)
319
                PRESTO_FREE(channel, strlen(channel) + 1);
320
        if (cache_type)
321
                PRESTO_FREE(cache_type, strlen(cache_type) + 1);
322
 
323
        CDEBUG(D_MALLOC, "mount error exit: kmem %ld, vmem %ld\n",
324
               presto_kmemory, presto_vmemory);
325
        return NULL;
326
}
327
 
328
 
329
 
330
#ifdef PRESTO_DEVEL
331
static DECLARE_FSTYPE(presto_fs_type, "izo", presto_read_super, FS_REQUIRES_DEV);
332
static DECLARE_FSTYPE(vpresto_fs_type, "vintermezzo", presto_read_super, FS_LITTER);
333
#else 
334
static DECLARE_FSTYPE(vpresto_fs_type, "vintermezzo", presto_read_super, FS_LITTER);
335
static DECLARE_FSTYPE(presto_fs_type, "intermezzo", presto_read_super, FS_REQUIRES_DEV);
336
#endif
337
 
338
 
339
 
340
int __init init_intermezzo_fs(void)
341
{
342
        int status;
343
 
344
        printk(KERN_INFO "InterMezzo Kernel/Intersync communications " INTERMEZZO_VERSION
345
               " info@clusterfs.com\n");
346
 
347
        status = presto_psdev_init();
348
        if ( status ) {
349
                CERROR("Problem (%d) in init_intermezzo_psdev\n", status);
350
                return status;
351
        }
352
 
353
        status = init_intermezzo_sysctl();
354
        if (status) {
355
                CERROR("presto: failed in init_intermezzo_sysctl!\n");
356
        }
357
 
358
        presto_cache_init_hash();
359
 
360
        if (!presto_init_ddata_cache()) {
361
                CERROR("presto out of memory!\n");
362
                return -ENOMEM;
363
        }
364
 
365
        status = register_filesystem(&presto_fs_type);
366
        if (status) {
367
                CERROR("presto: failed in register_filesystem!\n");
368
        }
369
        status = register_filesystem(&vpresto_fs_type);
370
        if (status) {
371
                CERROR("vpresto: failed in register_filesystem!\n");
372
        }
373
        return status;
374
}
375
 
376
void __exit exit_intermezzo_fs(void)
377
{
378
        int err;
379
 
380
        ENTRY;
381
 
382
        if ( (err = unregister_filesystem(&presto_fs_type)) != 0 ) {
383
                CERROR("presto: failed to unregister filesystem\n");
384
        }
385
        if ( (err = unregister_filesystem(&vpresto_fs_type)) != 0 ) {
386
                CERROR("vpresto: failed to unregister filesystem\n");
387
        }
388
 
389
        presto_psdev_cleanup();
390
        cleanup_intermezzo_sysctl();
391
        presto_cleanup_ddata_cache();
392
        CERROR("after cleanup: kmem %ld, vmem %ld\n",
393
               presto_kmemory, presto_vmemory);
394
}
395
 
396
 
397
MODULE_AUTHOR("Cluster Filesystems Inc. <info@clusterfs.com>");
398
MODULE_DESCRIPTION("InterMezzo Kernel/Intersync communications " INTERMEZZO_VERSION);
399
MODULE_LICENSE("GPL");
400
 
401
module_init(init_intermezzo_fs)
402
module_exit(exit_intermezzo_fs)

powered by: WebSVN 2.1.0

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