~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to fs/romfs/super.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Block- or MTD-based romfs
 
2
 *
 
3
 * Copyright Ā© 2007 Red Hat, Inc. All Rights Reserved.
 
4
 * Written by David Howells (dhowells@redhat.com)
 
5
 *
 
6
 * Derived from: ROMFS file system, Linux implementation
 
7
 *
 
8
 * Copyright Ā© 1997-1999  Janos Farkas <chexum@shadow.banki.hu>
 
9
 *
 
10
 * Using parts of the minix filesystem
 
11
 * Copyright Ā© 1991, 1992  Linus Torvalds
 
12
 *
 
13
 * and parts of the affs filesystem additionally
 
14
 * Copyright Ā© 1993  Ray Burr
 
15
 * Copyright Ā© 1996  Hans-Joachim Widmaier
 
16
 *
 
17
 * Changes
 
18
 *                                      Changed for 2.1.19 modules
 
19
 *      Jan 1997                        Initial release
 
20
 *      Jun 1997                        2.1.43+ changes
 
21
 *                                      Proper page locking in readpage
 
22
 *                                      Changed to work with 2.1.45+ fs
 
23
 *      Jul 1997                        Fixed follow_link
 
24
 *                      2.1.47
 
25
 *                                      lookup shouldn't return -ENOENT
 
26
 *                                      from Horst von Brand:
 
27
 *                                        fail on wrong checksum
 
28
 *                                        double unlock_super was possible
 
29
 *                                        correct namelen for statfs
 
30
 *                                      spotted by Bill Hawes:
 
31
 *                                        readlink shouldn't iput()
 
32
 *      Jun 1998        2.1.106         from Avery Pennarun: glibc scandir()
 
33
 *                                        exposed a problem in readdir
 
34
 *                      2.1.107         code-freeze spellchecker run
 
35
 *      Aug 1998                        2.1.118+ VFS changes
 
36
 *      Sep 1998        2.1.122         another VFS change (follow_link)
 
37
 *      Apr 1999        2.2.7           no more EBADF checking in
 
38
 *                                        lookup/readdir, use ERR_PTR
 
39
 *      Jun 1999        2.3.6           d_alloc_root use changed
 
40
 *                      2.3.9           clean up usage of ENOENT/negative
 
41
 *                                        dentries in lookup
 
42
 *                                      clean up page flags setting
 
43
 *                                        (error, uptodate, locking) in
 
44
 *                                        in readpage
 
45
 *                                      use init_special_inode for
 
46
 *                                        fifos/sockets (and streamline) in
 
47
 *                                        read_inode, fix _ops table order
 
48
 *      Aug 1999        2.3.16          __initfunc() => __init change
 
49
 *      Oct 1999        2.3.24          page->owner hack obsoleted
 
50
 *      Nov 1999        2.3.27          2.3.25+ page->offset => index change
 
51
 *
 
52
 *
 
53
 * This program is free software; you can redistribute it and/or
 
54
 * modify it under the terms of the GNU General Public Licence
 
55
 * as published by the Free Software Foundation; either version
 
56
 * 2 of the Licence, or (at your option) any later version.
 
57
 */
 
58
 
 
59
#include <linux/module.h>
 
60
#include <linux/string.h>
 
61
#include <linux/fs.h>
 
62
#include <linux/time.h>
 
63
#include <linux/slab.h>
 
64
#include <linux/init.h>
 
65
#include <linux/blkdev.h>
 
66
#include <linux/parser.h>
 
67
#include <linux/mount.h>
 
68
#include <linux/namei.h>
 
69
#include <linux/statfs.h>
 
70
#include <linux/mtd/super.h>
 
71
#include <linux/ctype.h>
 
72
#include <linux/highmem.h>
 
73
#include <linux/pagemap.h>
 
74
#include <linux/uaccess.h>
 
75
#include "internal.h"
 
76
 
 
77
static struct kmem_cache *romfs_inode_cachep;
 
78
 
 
79
static const umode_t romfs_modemap[8] = {
 
80
        0,                      /* hard link */
 
81
        S_IFDIR  | 0644,        /* directory */
 
82
        S_IFREG  | 0644,        /* regular file */
 
83
        S_IFLNK  | 0777,        /* symlink */
 
84
        S_IFBLK  | 0600,        /* blockdev */
 
85
        S_IFCHR  | 0600,        /* chardev */
 
86
        S_IFSOCK | 0644,        /* socket */
 
87
        S_IFIFO  | 0644         /* FIFO */
 
88
};
 
89
 
 
90
static const unsigned char romfs_dtype_table[] = {
 
91
        DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_SOCK, DT_FIFO
 
92
};
 
93
 
 
94
static struct inode *romfs_iget(struct super_block *sb, unsigned long pos);
 
95
 
 
96
/*
 
97
 * read a page worth of data from the image
 
98
 */
 
99
static int romfs_readpage(struct file *file, struct page *page)
 
100
{
 
101
        struct inode *inode = page->mapping->host;
 
102
        loff_t offset, size;
 
103
        unsigned long fillsize, pos;
 
104
        void *buf;
 
105
        int ret;
 
106
 
 
107
        buf = kmap(page);
 
108
        if (!buf)
 
109
                return -ENOMEM;
 
110
 
 
111
        /* 32 bit warning -- but not for us :) */
 
112
        offset = page_offset(page);
 
113
        size = i_size_read(inode);
 
114
        fillsize = 0;
 
115
        ret = 0;
 
116
        if (offset < size) {
 
117
                size -= offset;
 
118
                fillsize = size > PAGE_SIZE ? PAGE_SIZE : size;
 
119
 
 
120
                pos = ROMFS_I(inode)->i_dataoffset + offset;
 
121
 
 
122
                ret = romfs_dev_read(inode->i_sb, pos, buf, fillsize);
 
123
                if (ret < 0) {
 
124
                        SetPageError(page);
 
125
                        fillsize = 0;
 
126
                        ret = -EIO;
 
127
                }
 
128
        }
 
129
 
 
130
        if (fillsize < PAGE_SIZE)
 
131
                memset(buf + fillsize, 0, PAGE_SIZE - fillsize);
 
132
        if (ret == 0)
 
133
                SetPageUptodate(page);
 
134
 
 
135
        flush_dcache_page(page);
 
136
        kunmap(page);
 
137
        unlock_page(page);
 
138
        return ret;
 
139
}
 
140
 
 
141
static const struct address_space_operations romfs_aops = {
 
142
        .readpage       = romfs_readpage
 
143
};
 
144
 
 
145
/*
 
146
 * read the entries from a directory
 
147
 */
 
148
static int romfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
 
149
{
 
150
        struct inode *i = filp->f_dentry->d_inode;
 
151
        struct romfs_inode ri;
 
152
        unsigned long offset, maxoff;
 
153
        int j, ino, nextfh;
 
154
        int stored = 0;
 
155
        char fsname[ROMFS_MAXFN];       /* XXX dynamic? */
 
156
        int ret;
 
157
 
 
158
        maxoff = romfs_maxsize(i->i_sb);
 
159
 
 
160
        offset = filp->f_pos;
 
161
        if (!offset) {
 
162
                offset = i->i_ino & ROMFH_MASK;
 
163
                ret = romfs_dev_read(i->i_sb, offset, &ri, ROMFH_SIZE);
 
164
                if (ret < 0)
 
165
                        goto out;
 
166
                offset = be32_to_cpu(ri.spec) & ROMFH_MASK;
 
167
        }
 
168
 
 
169
        /* Not really failsafe, but we are read-only... */
 
170
        for (;;) {
 
171
                if (!offset || offset >= maxoff) {
 
172
                        offset = maxoff;
 
173
                        filp->f_pos = offset;
 
174
                        goto out;
 
175
                }
 
176
                filp->f_pos = offset;
 
177
 
 
178
                /* Fetch inode info */
 
179
                ret = romfs_dev_read(i->i_sb, offset, &ri, ROMFH_SIZE);
 
180
                if (ret < 0)
 
181
                        goto out;
 
182
 
 
183
                j = romfs_dev_strnlen(i->i_sb, offset + ROMFH_SIZE,
 
184
                                      sizeof(fsname) - 1);
 
185
                if (j < 0)
 
186
                        goto out;
 
187
 
 
188
                ret = romfs_dev_read(i->i_sb, offset + ROMFH_SIZE, fsname, j);
 
189
                if (ret < 0)
 
190
                        goto out;
 
191
                fsname[j] = '\0';
 
192
 
 
193
                ino = offset;
 
194
                nextfh = be32_to_cpu(ri.next);
 
195
                if ((nextfh & ROMFH_TYPE) == ROMFH_HRD)
 
196
                        ino = be32_to_cpu(ri.spec);
 
197
                if (filldir(dirent, fsname, j, offset, ino,
 
198
                            romfs_dtype_table[nextfh & ROMFH_TYPE]) < 0)
 
199
                        goto out;
 
200
 
 
201
                stored++;
 
202
                offset = nextfh & ROMFH_MASK;
 
203
        }
 
204
 
 
205
out:
 
206
        return stored;
 
207
}
 
208
 
 
209
/*
 
210
 * look up an entry in a directory
 
211
 */
 
212
static struct dentry *romfs_lookup(struct inode *dir, struct dentry *dentry,
 
213
                                   struct nameidata *nd)
 
214
{
 
215
        unsigned long offset, maxoff;
 
216
        struct inode *inode;
 
217
        struct romfs_inode ri;
 
218
        const char *name;               /* got from dentry */
 
219
        int len, ret;
 
220
 
 
221
        offset = dir->i_ino & ROMFH_MASK;
 
222
        ret = romfs_dev_read(dir->i_sb, offset, &ri, ROMFH_SIZE);
 
223
        if (ret < 0)
 
224
                goto error;
 
225
 
 
226
        /* search all the file entries in the list starting from the one
 
227
         * pointed to by the directory's special data */
 
228
        maxoff = romfs_maxsize(dir->i_sb);
 
229
        offset = be32_to_cpu(ri.spec) & ROMFH_MASK;
 
230
 
 
231
        name = dentry->d_name.name;
 
232
        len = dentry->d_name.len;
 
233
 
 
234
        for (;;) {
 
235
                if (!offset || offset >= maxoff)
 
236
                        goto out0;
 
237
 
 
238
                ret = romfs_dev_read(dir->i_sb, offset, &ri, sizeof(ri));
 
239
                if (ret < 0)
 
240
                        goto error;
 
241
 
 
242
                /* try to match the first 16 bytes of name */
 
243
                ret = romfs_dev_strcmp(dir->i_sb, offset + ROMFH_SIZE, name,
 
244
                                       len);
 
245
                if (ret < 0)
 
246
                        goto error;
 
247
                if (ret == 1)
 
248
                        break;
 
249
 
 
250
                /* next entry */
 
251
                offset = be32_to_cpu(ri.next) & ROMFH_MASK;
 
252
        }
 
253
 
 
254
        /* Hard link handling */
 
255
        if ((be32_to_cpu(ri.next) & ROMFH_TYPE) == ROMFH_HRD)
 
256
                offset = be32_to_cpu(ri.spec) & ROMFH_MASK;
 
257
 
 
258
        inode = romfs_iget(dir->i_sb, offset);
 
259
        if (IS_ERR(inode)) {
 
260
                ret = PTR_ERR(inode);
 
261
                goto error;
 
262
        }
 
263
        goto outi;
 
264
 
 
265
        /*
 
266
         * it's a bit funky, _lookup needs to return an error code
 
267
         * (negative) or a NULL, both as a dentry.  ENOENT should not
 
268
         * be returned, instead we need to create a negative dentry by
 
269
         * d_add(dentry, NULL); and return 0 as no error.
 
270
         * (Although as I see, it only matters on writable file
 
271
         * systems).
 
272
         */
 
273
out0:
 
274
        inode = NULL;
 
275
outi:
 
276
        d_add(dentry, inode);
 
277
        ret = 0;
 
278
error:
 
279
        return ERR_PTR(ret);
 
280
}
 
281
 
 
282
static const struct file_operations romfs_dir_operations = {
 
283
        .read           = generic_read_dir,
 
284
        .readdir        = romfs_readdir,
 
285
        .llseek         = default_llseek,
 
286
};
 
287
 
 
288
static const struct inode_operations romfs_dir_inode_operations = {
 
289
        .lookup         = romfs_lookup,
 
290
};
 
291
 
 
292
/*
 
293
 * get a romfs inode based on its position in the image (which doubles as the
 
294
 * inode number)
 
295
 */
 
296
static struct inode *romfs_iget(struct super_block *sb, unsigned long pos)
 
297
{
 
298
        struct romfs_inode_info *inode;
 
299
        struct romfs_inode ri;
 
300
        struct inode *i;
 
301
        unsigned long nlen;
 
302
        unsigned nextfh;
 
303
        int ret;
 
304
        umode_t mode;
 
305
 
 
306
        /* we might have to traverse a chain of "hard link" file entries to get
 
307
         * to the actual file */
 
308
        for (;;) {
 
309
                ret = romfs_dev_read(sb, pos, &ri, sizeof(ri));
 
310
                if (ret < 0)
 
311
                        goto error;
 
312
 
 
313
                /* XXX: do romfs_checksum here too (with name) */
 
314
 
 
315
                nextfh = be32_to_cpu(ri.next);
 
316
                if ((nextfh & ROMFH_TYPE) != ROMFH_HRD)
 
317
                        break;
 
318
 
 
319
                pos = be32_to_cpu(ri.spec) & ROMFH_MASK;
 
320
        }
 
321
 
 
322
        /* determine the length of the filename */
 
323
        nlen = romfs_dev_strnlen(sb, pos + ROMFH_SIZE, ROMFS_MAXFN);
 
324
        if (IS_ERR_VALUE(nlen))
 
325
                goto eio;
 
326
 
 
327
        /* get an inode for this image position */
 
328
        i = iget_locked(sb, pos);
 
329
        if (!i)
 
330
                return ERR_PTR(-ENOMEM);
 
331
 
 
332
        if (!(i->i_state & I_NEW))
 
333
                return i;
 
334
 
 
335
        /* precalculate the data offset */
 
336
        inode = ROMFS_I(i);
 
337
        inode->i_metasize = (ROMFH_SIZE + nlen + 1 + ROMFH_PAD) & ROMFH_MASK;
 
338
        inode->i_dataoffset = pos + inode->i_metasize;
 
339
 
 
340
        set_nlink(i, 1);                /* Hard to decide.. */
 
341
        i->i_size = be32_to_cpu(ri.size);
 
342
        i->i_mtime.tv_sec = i->i_atime.tv_sec = i->i_ctime.tv_sec = 0;
 
343
        i->i_mtime.tv_nsec = i->i_atime.tv_nsec = i->i_ctime.tv_nsec = 0;
 
344
 
 
345
        /* set up mode and ops */
 
346
        mode = romfs_modemap[nextfh & ROMFH_TYPE];
 
347
 
 
348
        switch (nextfh & ROMFH_TYPE) {
 
349
        case ROMFH_DIR:
 
350
                i->i_size = ROMFS_I(i)->i_metasize;
 
351
                i->i_op = &romfs_dir_inode_operations;
 
352
                i->i_fop = &romfs_dir_operations;
 
353
                if (nextfh & ROMFH_EXEC)
 
354
                        mode |= S_IXUGO;
 
355
                break;
 
356
        case ROMFH_REG:
 
357
                i->i_fop = &romfs_ro_fops;
 
358
                i->i_data.a_ops = &romfs_aops;
 
359
                if (i->i_sb->s_mtd)
 
360
                        i->i_data.backing_dev_info =
 
361
                                i->i_sb->s_mtd->backing_dev_info;
 
362
                if (nextfh & ROMFH_EXEC)
 
363
                        mode |= S_IXUGO;
 
364
                break;
 
365
        case ROMFH_SYM:
 
366
                i->i_op = &page_symlink_inode_operations;
 
367
                i->i_data.a_ops = &romfs_aops;
 
368
                mode |= S_IRWXUGO;
 
369
                break;
 
370
        default:
 
371
                /* depending on MBZ for sock/fifos */
 
372
                nextfh = be32_to_cpu(ri.spec);
 
373
                init_special_inode(i, mode, MKDEV(nextfh >> 16,
 
374
                                                  nextfh & 0xffff));
 
375
                break;
 
376
        }
 
377
 
 
378
        i->i_mode = mode;
 
379
 
 
380
        unlock_new_inode(i);
 
381
        return i;
 
382
 
 
383
eio:
 
384
        ret = -EIO;
 
385
error:
 
386
        printk(KERN_ERR "ROMFS: read error for inode 0x%lx\n", pos);
 
387
        return ERR_PTR(ret);
 
388
}
 
389
 
 
390
/*
 
391
 * allocate a new inode
 
392
 */
 
393
static struct inode *romfs_alloc_inode(struct super_block *sb)
 
394
{
 
395
        struct romfs_inode_info *inode;
 
396
        inode = kmem_cache_alloc(romfs_inode_cachep, GFP_KERNEL);
 
397
        return inode ? &inode->vfs_inode : NULL;
 
398
}
 
399
 
 
400
/*
 
401
 * return a spent inode to the slab cache
 
402
 */
 
403
static void romfs_i_callback(struct rcu_head *head)
 
404
{
 
405
        struct inode *inode = container_of(head, struct inode, i_rcu);
 
406
        INIT_LIST_HEAD(&inode->i_dentry);
 
407
        kmem_cache_free(romfs_inode_cachep, ROMFS_I(inode));
 
408
}
 
409
 
 
410
static void romfs_destroy_inode(struct inode *inode)
 
411
{
 
412
        call_rcu(&inode->i_rcu, romfs_i_callback);
 
413
}
 
414
 
 
415
/*
 
416
 * get filesystem statistics
 
417
 */
 
418
static int romfs_statfs(struct dentry *dentry, struct kstatfs *buf)
 
419
{
 
420
        struct super_block *sb = dentry->d_sb;
 
421
        u64 id = huge_encode_dev(sb->s_bdev->bd_dev);
 
422
 
 
423
        buf->f_type = ROMFS_MAGIC;
 
424
        buf->f_namelen = ROMFS_MAXFN;
 
425
        buf->f_bsize = ROMBSIZE;
 
426
        buf->f_bfree = buf->f_bavail = buf->f_ffree;
 
427
        buf->f_blocks =
 
428
                (romfs_maxsize(dentry->d_sb) + ROMBSIZE - 1) >> ROMBSBITS;
 
429
        buf->f_fsid.val[0] = (u32)id;
 
430
        buf->f_fsid.val[1] = (u32)(id >> 32);
 
431
        return 0;
 
432
}
 
433
 
 
434
/*
 
435
 * remounting must involve read-only
 
436
 */
 
437
static int romfs_remount(struct super_block *sb, int *flags, char *data)
 
438
{
 
439
        *flags |= MS_RDONLY;
 
440
        return 0;
 
441
}
 
442
 
 
443
static const struct super_operations romfs_super_ops = {
 
444
        .alloc_inode    = romfs_alloc_inode,
 
445
        .destroy_inode  = romfs_destroy_inode,
 
446
        .statfs         = romfs_statfs,
 
447
        .remount_fs     = romfs_remount,
 
448
};
 
449
 
 
450
/*
 
451
 * checksum check on part of a romfs filesystem
 
452
 */
 
453
static __u32 romfs_checksum(const void *data, int size)
 
454
{
 
455
        const __be32 *ptr = data;
 
456
        __u32 sum;
 
457
 
 
458
        sum = 0;
 
459
        size >>= 2;
 
460
        while (size > 0) {
 
461
                sum += be32_to_cpu(*ptr++);
 
462
                size--;
 
463
        }
 
464
        return sum;
 
465
}
 
466
 
 
467
/*
 
468
 * fill in the superblock
 
469
 */
 
470
static int romfs_fill_super(struct super_block *sb, void *data, int silent)
 
471
{
 
472
        struct romfs_super_block *rsb;
 
473
        struct inode *root;
 
474
        unsigned long pos, img_size;
 
475
        const char *storage;
 
476
        size_t len;
 
477
        int ret;
 
478
 
 
479
#ifdef CONFIG_BLOCK
 
480
        if (!sb->s_mtd) {
 
481
                sb_set_blocksize(sb, ROMBSIZE);
 
482
        } else {
 
483
                sb->s_blocksize = ROMBSIZE;
 
484
                sb->s_blocksize_bits = blksize_bits(ROMBSIZE);
 
485
        }
 
486
#endif
 
487
 
 
488
        sb->s_maxbytes = 0xFFFFFFFF;
 
489
        sb->s_magic = ROMFS_MAGIC;
 
490
        sb->s_flags |= MS_RDONLY | MS_NOATIME;
 
491
        sb->s_op = &romfs_super_ops;
 
492
 
 
493
        /* read the image superblock and check it */
 
494
        rsb = kmalloc(512, GFP_KERNEL);
 
495
        if (!rsb)
 
496
                return -ENOMEM;
 
497
 
 
498
        sb->s_fs_info = (void *) 512;
 
499
        ret = romfs_dev_read(sb, 0, rsb, 512);
 
500
        if (ret < 0)
 
501
                goto error_rsb;
 
502
 
 
503
        img_size = be32_to_cpu(rsb->size);
 
504
 
 
505
        if (sb->s_mtd && img_size > sb->s_mtd->size)
 
506
                goto error_rsb_inval;
 
507
 
 
508
        sb->s_fs_info = (void *) img_size;
 
509
 
 
510
        if (rsb->word0 != ROMSB_WORD0 || rsb->word1 != ROMSB_WORD1 ||
 
511
            img_size < ROMFH_SIZE) {
 
512
                if (!silent)
 
513
                        printk(KERN_WARNING "VFS:"
 
514
                               " Can't find a romfs filesystem on dev %s.\n",
 
515
                               sb->s_id);
 
516
                goto error_rsb_inval;
 
517
        }
 
518
 
 
519
        if (romfs_checksum(rsb, min_t(size_t, img_size, 512))) {
 
520
                printk(KERN_ERR "ROMFS: bad initial checksum on dev %s.\n",
 
521
                       sb->s_id);
 
522
                goto error_rsb_inval;
 
523
        }
 
524
 
 
525
        storage = sb->s_mtd ? "MTD" : "the block layer";
 
526
 
 
527
        len = strnlen(rsb->name, ROMFS_MAXFN);
 
528
        if (!silent)
 
529
                printk(KERN_NOTICE "ROMFS: Mounting image '%*.*s' through %s\n",
 
530
                       (unsigned) len, (unsigned) len, rsb->name, storage);
 
531
 
 
532
        kfree(rsb);
 
533
        rsb = NULL;
 
534
 
 
535
        /* find the root directory */
 
536
        pos = (ROMFH_SIZE + len + 1 + ROMFH_PAD) & ROMFH_MASK;
 
537
 
 
538
        root = romfs_iget(sb, pos);
 
539
        if (IS_ERR(root))
 
540
                goto error;
 
541
 
 
542
        sb->s_root = d_alloc_root(root);
 
543
        if (!sb->s_root)
 
544
                goto error_i;
 
545
 
 
546
        return 0;
 
547
 
 
548
error_i:
 
549
        iput(root);
 
550
error:
 
551
        return -EINVAL;
 
552
error_rsb_inval:
 
553
        ret = -EINVAL;
 
554
error_rsb:
 
555
        kfree(rsb);
 
556
        return ret;
 
557
}
 
558
 
 
559
/*
 
560
 * get a superblock for mounting
 
561
 */
 
562
static struct dentry *romfs_mount(struct file_system_type *fs_type,
 
563
                        int flags, const char *dev_name,
 
564
                        void *data)
 
565
{
 
566
        struct dentry *ret = ERR_PTR(-EINVAL);
 
567
 
 
568
#ifdef CONFIG_ROMFS_ON_MTD
 
569
        ret = mount_mtd(fs_type, flags, dev_name, data, romfs_fill_super);
 
570
#endif
 
571
#ifdef CONFIG_ROMFS_ON_BLOCK
 
572
        if (ret == ERR_PTR(-EINVAL))
 
573
                ret = mount_bdev(fs_type, flags, dev_name, data,
 
574
                                  romfs_fill_super);
 
575
#endif
 
576
        return ret;
 
577
}
 
578
 
 
579
/*
 
580
 * destroy a romfs superblock in the appropriate manner
 
581
 */
 
582
static void romfs_kill_sb(struct super_block *sb)
 
583
{
 
584
#ifdef CONFIG_ROMFS_ON_MTD
 
585
        if (sb->s_mtd) {
 
586
                kill_mtd_super(sb);
 
587
                return;
 
588
        }
 
589
#endif
 
590
#ifdef CONFIG_ROMFS_ON_BLOCK
 
591
        if (sb->s_bdev) {
 
592
                kill_block_super(sb);
 
593
                return;
 
594
        }
 
595
#endif
 
596
}
 
597
 
 
598
static struct file_system_type romfs_fs_type = {
 
599
        .owner          = THIS_MODULE,
 
600
        .name           = "romfs",
 
601
        .mount          = romfs_mount,
 
602
        .kill_sb        = romfs_kill_sb,
 
603
        .fs_flags       = FS_REQUIRES_DEV,
 
604
};
 
605
 
 
606
/*
 
607
 * inode storage initialiser
 
608
 */
 
609
static void romfs_i_init_once(void *_inode)
 
610
{
 
611
        struct romfs_inode_info *inode = _inode;
 
612
 
 
613
        inode_init_once(&inode->vfs_inode);
 
614
}
 
615
 
 
616
/*
 
617
 * romfs module initialisation
 
618
 */
 
619
static int __init init_romfs_fs(void)
 
620
{
 
621
        int ret;
 
622
 
 
623
        printk(KERN_INFO "ROMFS MTD (C) 2007 Red Hat, Inc.\n");
 
624
 
 
625
        romfs_inode_cachep =
 
626
                kmem_cache_create("romfs_i",
 
627
                                  sizeof(struct romfs_inode_info), 0,
 
628
                                  SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD,
 
629
                                  romfs_i_init_once);
 
630
 
 
631
        if (!romfs_inode_cachep) {
 
632
                printk(KERN_ERR
 
633
                       "ROMFS error: Failed to initialise inode cache\n");
 
634
                return -ENOMEM;
 
635
        }
 
636
        ret = register_filesystem(&romfs_fs_type);
 
637
        if (ret) {
 
638
                printk(KERN_ERR "ROMFS error: Failed to register filesystem\n");
 
639
                goto error_register;
 
640
        }
 
641
        return 0;
 
642
 
 
643
error_register:
 
644
        kmem_cache_destroy(romfs_inode_cachep);
 
645
        return ret;
 
646
}
 
647
 
 
648
/*
 
649
 * romfs module removal
 
650
 */
 
651
static void __exit exit_romfs_fs(void)
 
652
{
 
653
        unregister_filesystem(&romfs_fs_type);
 
654
        kmem_cache_destroy(romfs_inode_cachep);
 
655
}
 
656
 
 
657
module_init(init_romfs_fs);
 
658
module_exit(exit_romfs_fs);
 
659
 
 
660
MODULE_DESCRIPTION("Direct-MTD Capable RomFS");
 
661
MODULE_AUTHOR("Red Hat, Inc.");
 
662
MODULE_LICENSE("GPL"); /* Actually dual-licensed, but it doesn't matter for */