Back to home page

OSCL-LXR

 
 

    


0001 /* Block- or MTD-based romfs
0002  *
0003  * Copyright © 2007 Red Hat, Inc. All Rights Reserved.
0004  * Written by David Howells (dhowells@redhat.com)
0005  *
0006  * Derived from: ROMFS file system, Linux implementation
0007  *
0008  * Copyright © 1997-1999  Janos Farkas <chexum@shadow.banki.hu>
0009  *
0010  * Using parts of the minix filesystem
0011  * Copyright © 1991, 1992  Linus Torvalds
0012  *
0013  * and parts of the affs filesystem additionally
0014  * Copyright © 1993  Ray Burr
0015  * Copyright © 1996  Hans-Joachim Widmaier
0016  *
0017  * Changes
0018  *                  Changed for 2.1.19 modules
0019  *  Jan 1997            Initial release
0020  *  Jun 1997            2.1.43+ changes
0021  *                  Proper page locking in read_folio
0022  *                  Changed to work with 2.1.45+ fs
0023  *  Jul 1997            Fixed follow_link
0024  *          2.1.47
0025  *                  lookup shouldn't return -ENOENT
0026  *                  from Horst von Brand:
0027  *                    fail on wrong checksum
0028  *                    double unlock_super was possible
0029  *                    correct namelen for statfs
0030  *                  spotted by Bill Hawes:
0031  *                    readlink shouldn't iput()
0032  *  Jun 1998    2.1.106     from Avery Pennarun: glibc scandir()
0033  *                    exposed a problem in readdir
0034  *          2.1.107     code-freeze spellchecker run
0035  *  Aug 1998            2.1.118+ VFS changes
0036  *  Sep 1998    2.1.122     another VFS change (follow_link)
0037  *  Apr 1999    2.2.7       no more EBADF checking in
0038  *                    lookup/readdir, use ERR_PTR
0039  *  Jun 1999    2.3.6       d_alloc_root use changed
0040  *          2.3.9       clean up usage of ENOENT/negative
0041  *                    dentries in lookup
0042  *                  clean up page flags setting
0043  *                    (error, uptodate, locking) in
0044  *                    in read_folio
0045  *                  use init_special_inode for
0046  *                    fifos/sockets (and streamline) in
0047  *                    read_inode, fix _ops table order
0048  *  Aug 1999    2.3.16      __initfunc() => __init change
0049  *  Oct 1999    2.3.24      page->owner hack obsoleted
0050  *  Nov 1999    2.3.27      2.3.25+ page->offset => index change
0051  *
0052  *
0053  * This program is free software; you can redistribute it and/or
0054  * modify it under the terms of the GNU General Public Licence
0055  * as published by the Free Software Foundation; either version
0056  * 2 of the Licence, or (at your option) any later version.
0057  */
0058 
0059 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0060 
0061 #include <linux/module.h>
0062 #include <linux/string.h>
0063 #include <linux/fs.h>
0064 #include <linux/time.h>
0065 #include <linux/slab.h>
0066 #include <linux/init.h>
0067 #include <linux/blkdev.h>
0068 #include <linux/fs_context.h>
0069 #include <linux/mount.h>
0070 #include <linux/namei.h>
0071 #include <linux/statfs.h>
0072 #include <linux/mtd/super.h>
0073 #include <linux/ctype.h>
0074 #include <linux/highmem.h>
0075 #include <linux/pagemap.h>
0076 #include <linux/uaccess.h>
0077 #include <linux/major.h>
0078 #include "internal.h"
0079 
0080 static struct kmem_cache *romfs_inode_cachep;
0081 
0082 static const umode_t romfs_modemap[8] = {
0083     0,          /* hard link */
0084     S_IFDIR  | 0644,    /* directory */
0085     S_IFREG  | 0644,    /* regular file */
0086     S_IFLNK  | 0777,    /* symlink */
0087     S_IFBLK  | 0600,    /* blockdev */
0088     S_IFCHR  | 0600,    /* chardev */
0089     S_IFSOCK | 0644,    /* socket */
0090     S_IFIFO  | 0644     /* FIFO */
0091 };
0092 
0093 static const unsigned char romfs_dtype_table[] = {
0094     DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_SOCK, DT_FIFO
0095 };
0096 
0097 static struct inode *romfs_iget(struct super_block *sb, unsigned long pos);
0098 
0099 /*
0100  * read a page worth of data from the image
0101  */
0102 static int romfs_read_folio(struct file *file, struct folio *folio)
0103 {
0104     struct page *page = &folio->page;
0105     struct inode *inode = page->mapping->host;
0106     loff_t offset, size;
0107     unsigned long fillsize, pos;
0108     void *buf;
0109     int ret;
0110 
0111     buf = kmap(page);
0112     if (!buf)
0113         return -ENOMEM;
0114 
0115     /* 32 bit warning -- but not for us :) */
0116     offset = page_offset(page);
0117     size = i_size_read(inode);
0118     fillsize = 0;
0119     ret = 0;
0120     if (offset < size) {
0121         size -= offset;
0122         fillsize = size > PAGE_SIZE ? PAGE_SIZE : size;
0123 
0124         pos = ROMFS_I(inode)->i_dataoffset + offset;
0125 
0126         ret = romfs_dev_read(inode->i_sb, pos, buf, fillsize);
0127         if (ret < 0) {
0128             SetPageError(page);
0129             fillsize = 0;
0130             ret = -EIO;
0131         }
0132     }
0133 
0134     if (fillsize < PAGE_SIZE)
0135         memset(buf + fillsize, 0, PAGE_SIZE - fillsize);
0136     if (ret == 0)
0137         SetPageUptodate(page);
0138 
0139     flush_dcache_page(page);
0140     kunmap(page);
0141     unlock_page(page);
0142     return ret;
0143 }
0144 
0145 static const struct address_space_operations romfs_aops = {
0146     .read_folio = romfs_read_folio
0147 };
0148 
0149 /*
0150  * read the entries from a directory
0151  */
0152 static int romfs_readdir(struct file *file, struct dir_context *ctx)
0153 {
0154     struct inode *i = file_inode(file);
0155     struct romfs_inode ri;
0156     unsigned long offset, maxoff;
0157     int j, ino, nextfh;
0158     char fsname[ROMFS_MAXFN];   /* XXX dynamic? */
0159     int ret;
0160 
0161     maxoff = romfs_maxsize(i->i_sb);
0162 
0163     offset = ctx->pos;
0164     if (!offset) {
0165         offset = i->i_ino & ROMFH_MASK;
0166         ret = romfs_dev_read(i->i_sb, offset, &ri, ROMFH_SIZE);
0167         if (ret < 0)
0168             goto out;
0169         offset = be32_to_cpu(ri.spec) & ROMFH_MASK;
0170     }
0171 
0172     /* Not really failsafe, but we are read-only... */
0173     for (;;) {
0174         if (!offset || offset >= maxoff) {
0175             offset = maxoff;
0176             ctx->pos = offset;
0177             goto out;
0178         }
0179         ctx->pos = offset;
0180 
0181         /* Fetch inode info */
0182         ret = romfs_dev_read(i->i_sb, offset, &ri, ROMFH_SIZE);
0183         if (ret < 0)
0184             goto out;
0185 
0186         j = romfs_dev_strnlen(i->i_sb, offset + ROMFH_SIZE,
0187                       sizeof(fsname) - 1);
0188         if (j < 0)
0189             goto out;
0190 
0191         ret = romfs_dev_read(i->i_sb, offset + ROMFH_SIZE, fsname, j);
0192         if (ret < 0)
0193             goto out;
0194         fsname[j] = '\0';
0195 
0196         ino = offset;
0197         nextfh = be32_to_cpu(ri.next);
0198         if ((nextfh & ROMFH_TYPE) == ROMFH_HRD)
0199             ino = be32_to_cpu(ri.spec);
0200         if (!dir_emit(ctx, fsname, j, ino,
0201                 romfs_dtype_table[nextfh & ROMFH_TYPE]))
0202             goto out;
0203 
0204         offset = nextfh & ROMFH_MASK;
0205     }
0206 out:
0207     return 0;
0208 }
0209 
0210 /*
0211  * look up an entry in a directory
0212  */
0213 static struct dentry *romfs_lookup(struct inode *dir, struct dentry *dentry,
0214                    unsigned int flags)
0215 {
0216     unsigned long offset, maxoff;
0217     struct inode *inode = NULL;
0218     struct romfs_inode ri;
0219     const char *name;       /* got from dentry */
0220     int len, ret;
0221 
0222     offset = dir->i_ino & ROMFH_MASK;
0223     ret = romfs_dev_read(dir->i_sb, offset, &ri, ROMFH_SIZE);
0224     if (ret < 0)
0225         goto error;
0226 
0227     /* search all the file entries in the list starting from the one
0228      * pointed to by the directory's special data */
0229     maxoff = romfs_maxsize(dir->i_sb);
0230     offset = be32_to_cpu(ri.spec) & ROMFH_MASK;
0231 
0232     name = dentry->d_name.name;
0233     len = dentry->d_name.len;
0234 
0235     for (;;) {
0236         if (!offset || offset >= maxoff)
0237             break;
0238 
0239         ret = romfs_dev_read(dir->i_sb, offset, &ri, sizeof(ri));
0240         if (ret < 0)
0241             goto error;
0242 
0243         /* try to match the first 16 bytes of name */
0244         ret = romfs_dev_strcmp(dir->i_sb, offset + ROMFH_SIZE, name,
0245                        len);
0246         if (ret < 0)
0247             goto error;
0248         if (ret == 1) {
0249             /* Hard link handling */
0250             if ((be32_to_cpu(ri.next) & ROMFH_TYPE) == ROMFH_HRD)
0251                 offset = be32_to_cpu(ri.spec) & ROMFH_MASK;
0252             inode = romfs_iget(dir->i_sb, offset);
0253             break;
0254         }
0255 
0256         /* next entry */
0257         offset = be32_to_cpu(ri.next) & ROMFH_MASK;
0258     }
0259 
0260     return d_splice_alias(inode, dentry);
0261 error:
0262     return ERR_PTR(ret);
0263 }
0264 
0265 static const struct file_operations romfs_dir_operations = {
0266     .read       = generic_read_dir,
0267     .iterate_shared = romfs_readdir,
0268     .llseek     = generic_file_llseek,
0269 };
0270 
0271 static const struct inode_operations romfs_dir_inode_operations = {
0272     .lookup     = romfs_lookup,
0273 };
0274 
0275 /*
0276  * get a romfs inode based on its position in the image (which doubles as the
0277  * inode number)
0278  */
0279 static struct inode *romfs_iget(struct super_block *sb, unsigned long pos)
0280 {
0281     struct romfs_inode_info *inode;
0282     struct romfs_inode ri;
0283     struct inode *i;
0284     unsigned long nlen;
0285     unsigned nextfh;
0286     int ret;
0287     umode_t mode;
0288 
0289     /* we might have to traverse a chain of "hard link" file entries to get
0290      * to the actual file */
0291     for (;;) {
0292         ret = romfs_dev_read(sb, pos, &ri, sizeof(ri));
0293         if (ret < 0)
0294             goto error;
0295 
0296         /* XXX: do romfs_checksum here too (with name) */
0297 
0298         nextfh = be32_to_cpu(ri.next);
0299         if ((nextfh & ROMFH_TYPE) != ROMFH_HRD)
0300             break;
0301 
0302         pos = be32_to_cpu(ri.spec) & ROMFH_MASK;
0303     }
0304 
0305     /* determine the length of the filename */
0306     nlen = romfs_dev_strnlen(sb, pos + ROMFH_SIZE, ROMFS_MAXFN);
0307     if (IS_ERR_VALUE(nlen))
0308         goto eio;
0309 
0310     /* get an inode for this image position */
0311     i = iget_locked(sb, pos);
0312     if (!i)
0313         return ERR_PTR(-ENOMEM);
0314 
0315     if (!(i->i_state & I_NEW))
0316         return i;
0317 
0318     /* precalculate the data offset */
0319     inode = ROMFS_I(i);
0320     inode->i_metasize = (ROMFH_SIZE + nlen + 1 + ROMFH_PAD) & ROMFH_MASK;
0321     inode->i_dataoffset = pos + inode->i_metasize;
0322 
0323     set_nlink(i, 1);        /* Hard to decide.. */
0324     i->i_size = be32_to_cpu(ri.size);
0325     i->i_mtime.tv_sec = i->i_atime.tv_sec = i->i_ctime.tv_sec = 0;
0326     i->i_mtime.tv_nsec = i->i_atime.tv_nsec = i->i_ctime.tv_nsec = 0;
0327 
0328     /* set up mode and ops */
0329     mode = romfs_modemap[nextfh & ROMFH_TYPE];
0330 
0331     switch (nextfh & ROMFH_TYPE) {
0332     case ROMFH_DIR:
0333         i->i_size = ROMFS_I(i)->i_metasize;
0334         i->i_op = &romfs_dir_inode_operations;
0335         i->i_fop = &romfs_dir_operations;
0336         if (nextfh & ROMFH_EXEC)
0337             mode |= S_IXUGO;
0338         break;
0339     case ROMFH_REG:
0340         i->i_fop = &romfs_ro_fops;
0341         i->i_data.a_ops = &romfs_aops;
0342         if (nextfh & ROMFH_EXEC)
0343             mode |= S_IXUGO;
0344         break;
0345     case ROMFH_SYM:
0346         i->i_op = &page_symlink_inode_operations;
0347         inode_nohighmem(i);
0348         i->i_data.a_ops = &romfs_aops;
0349         mode |= S_IRWXUGO;
0350         break;
0351     default:
0352         /* depending on MBZ for sock/fifos */
0353         nextfh = be32_to_cpu(ri.spec);
0354         init_special_inode(i, mode, MKDEV(nextfh >> 16,
0355                           nextfh & 0xffff));
0356         break;
0357     }
0358 
0359     i->i_mode = mode;
0360     i->i_blocks = (i->i_size + 511) >> 9;
0361 
0362     unlock_new_inode(i);
0363     return i;
0364 
0365 eio:
0366     ret = -EIO;
0367 error:
0368     pr_err("read error for inode 0x%lx\n", pos);
0369     return ERR_PTR(ret);
0370 }
0371 
0372 /*
0373  * allocate a new inode
0374  */
0375 static struct inode *romfs_alloc_inode(struct super_block *sb)
0376 {
0377     struct romfs_inode_info *inode;
0378 
0379     inode = alloc_inode_sb(sb, romfs_inode_cachep, GFP_KERNEL);
0380     return inode ? &inode->vfs_inode : NULL;
0381 }
0382 
0383 /*
0384  * return a spent inode to the slab cache
0385  */
0386 static void romfs_free_inode(struct inode *inode)
0387 {
0388     kmem_cache_free(romfs_inode_cachep, ROMFS_I(inode));
0389 }
0390 
0391 /*
0392  * get filesystem statistics
0393  */
0394 static int romfs_statfs(struct dentry *dentry, struct kstatfs *buf)
0395 {
0396     struct super_block *sb = dentry->d_sb;
0397     u64 id = 0;
0398 
0399     /* When calling huge_encode_dev(),
0400      * use sb->s_bdev->bd_dev when,
0401      *   - CONFIG_ROMFS_ON_BLOCK defined
0402      * use sb->s_dev when,
0403      *   - CONFIG_ROMFS_ON_BLOCK undefined and
0404      *   - CONFIG_ROMFS_ON_MTD defined
0405      * leave id as 0 when,
0406      *   - CONFIG_ROMFS_ON_BLOCK undefined and
0407      *   - CONFIG_ROMFS_ON_MTD undefined
0408      */
0409     if (sb->s_bdev)
0410         id = huge_encode_dev(sb->s_bdev->bd_dev);
0411     else if (sb->s_dev)
0412         id = huge_encode_dev(sb->s_dev);
0413 
0414     buf->f_type = ROMFS_MAGIC;
0415     buf->f_namelen = ROMFS_MAXFN;
0416     buf->f_bsize = ROMBSIZE;
0417     buf->f_bfree = buf->f_bavail = buf->f_ffree;
0418     buf->f_blocks =
0419         (romfs_maxsize(dentry->d_sb) + ROMBSIZE - 1) >> ROMBSBITS;
0420     buf->f_fsid = u64_to_fsid(id);
0421     return 0;
0422 }
0423 
0424 /*
0425  * remounting must involve read-only
0426  */
0427 static int romfs_reconfigure(struct fs_context *fc)
0428 {
0429     sync_filesystem(fc->root->d_sb);
0430     fc->sb_flags |= SB_RDONLY;
0431     return 0;
0432 }
0433 
0434 static const struct super_operations romfs_super_ops = {
0435     .alloc_inode    = romfs_alloc_inode,
0436     .free_inode = romfs_free_inode,
0437     .statfs     = romfs_statfs,
0438 };
0439 
0440 /*
0441  * checksum check on part of a romfs filesystem
0442  */
0443 static __u32 romfs_checksum(const void *data, int size)
0444 {
0445     const __be32 *ptr = data;
0446     __u32 sum;
0447 
0448     sum = 0;
0449     size >>= 2;
0450     while (size > 0) {
0451         sum += be32_to_cpu(*ptr++);
0452         size--;
0453     }
0454     return sum;
0455 }
0456 
0457 /*
0458  * fill in the superblock
0459  */
0460 static int romfs_fill_super(struct super_block *sb, struct fs_context *fc)
0461 {
0462     struct romfs_super_block *rsb;
0463     struct inode *root;
0464     unsigned long pos, img_size;
0465     const char *storage;
0466     size_t len;
0467     int ret;
0468 
0469 #ifdef CONFIG_BLOCK
0470     if (!sb->s_mtd) {
0471         sb_set_blocksize(sb, ROMBSIZE);
0472     } else {
0473         sb->s_blocksize = ROMBSIZE;
0474         sb->s_blocksize_bits = blksize_bits(ROMBSIZE);
0475     }
0476 #endif
0477 
0478     sb->s_maxbytes = 0xFFFFFFFF;
0479     sb->s_magic = ROMFS_MAGIC;
0480     sb->s_flags |= SB_RDONLY | SB_NOATIME;
0481     sb->s_time_min = 0;
0482     sb->s_time_max = 0;
0483     sb->s_op = &romfs_super_ops;
0484 
0485 #ifdef CONFIG_ROMFS_ON_MTD
0486     /* Use same dev ID from the underlying mtdblock device */
0487     if (sb->s_mtd)
0488         sb->s_dev = MKDEV(MTD_BLOCK_MAJOR, sb->s_mtd->index);
0489 #endif
0490     /* read the image superblock and check it */
0491     rsb = kmalloc(512, GFP_KERNEL);
0492     if (!rsb)
0493         return -ENOMEM;
0494 
0495     sb->s_fs_info = (void *) 512;
0496     ret = romfs_dev_read(sb, 0, rsb, 512);
0497     if (ret < 0)
0498         goto error_rsb;
0499 
0500     img_size = be32_to_cpu(rsb->size);
0501 
0502     if (sb->s_mtd && img_size > sb->s_mtd->size)
0503         goto error_rsb_inval;
0504 
0505     sb->s_fs_info = (void *) img_size;
0506 
0507     if (rsb->word0 != ROMSB_WORD0 || rsb->word1 != ROMSB_WORD1 ||
0508         img_size < ROMFH_SIZE) {
0509         if (!(fc->sb_flags & SB_SILENT))
0510             errorf(fc, "VFS: Can't find a romfs filesystem on dev %s.\n",
0511                    sb->s_id);
0512         goto error_rsb_inval;
0513     }
0514 
0515     if (romfs_checksum(rsb, min_t(size_t, img_size, 512))) {
0516         pr_err("bad initial checksum on dev %s.\n", sb->s_id);
0517         goto error_rsb_inval;
0518     }
0519 
0520     storage = sb->s_mtd ? "MTD" : "the block layer";
0521 
0522     len = strnlen(rsb->name, ROMFS_MAXFN);
0523     if (!(fc->sb_flags & SB_SILENT))
0524         pr_notice("Mounting image '%*.*s' through %s\n",
0525               (unsigned) len, (unsigned) len, rsb->name, storage);
0526 
0527     kfree(rsb);
0528     rsb = NULL;
0529 
0530     /* find the root directory */
0531     pos = (ROMFH_SIZE + len + 1 + ROMFH_PAD) & ROMFH_MASK;
0532 
0533     root = romfs_iget(sb, pos);
0534     if (IS_ERR(root))
0535         return PTR_ERR(root);
0536 
0537     sb->s_root = d_make_root(root);
0538     if (!sb->s_root)
0539         return -ENOMEM;
0540 
0541     return 0;
0542 
0543 error_rsb_inval:
0544     ret = -EINVAL;
0545 error_rsb:
0546     kfree(rsb);
0547     return ret;
0548 }
0549 
0550 /*
0551  * get a superblock for mounting
0552  */
0553 static int romfs_get_tree(struct fs_context *fc)
0554 {
0555     int ret = -EINVAL;
0556 
0557 #ifdef CONFIG_ROMFS_ON_MTD
0558     ret = get_tree_mtd(fc, romfs_fill_super);
0559 #endif
0560 #ifdef CONFIG_ROMFS_ON_BLOCK
0561     if (ret == -EINVAL)
0562         ret = get_tree_bdev(fc, romfs_fill_super);
0563 #endif
0564     return ret;
0565 }
0566 
0567 static const struct fs_context_operations romfs_context_ops = {
0568     .get_tree   = romfs_get_tree,
0569     .reconfigure    = romfs_reconfigure,
0570 };
0571 
0572 /*
0573  * Set up the filesystem mount context.
0574  */
0575 static int romfs_init_fs_context(struct fs_context *fc)
0576 {
0577     fc->ops = &romfs_context_ops;
0578     return 0;
0579 }
0580 
0581 /*
0582  * destroy a romfs superblock in the appropriate manner
0583  */
0584 static void romfs_kill_sb(struct super_block *sb)
0585 {
0586 #ifdef CONFIG_ROMFS_ON_MTD
0587     if (sb->s_mtd) {
0588         kill_mtd_super(sb);
0589         return;
0590     }
0591 #endif
0592 #ifdef CONFIG_ROMFS_ON_BLOCK
0593     if (sb->s_bdev) {
0594         kill_block_super(sb);
0595         return;
0596     }
0597 #endif
0598 }
0599 
0600 static struct file_system_type romfs_fs_type = {
0601     .owner      = THIS_MODULE,
0602     .name       = "romfs",
0603     .init_fs_context = romfs_init_fs_context,
0604     .kill_sb    = romfs_kill_sb,
0605     .fs_flags   = FS_REQUIRES_DEV,
0606 };
0607 MODULE_ALIAS_FS("romfs");
0608 
0609 /*
0610  * inode storage initialiser
0611  */
0612 static void romfs_i_init_once(void *_inode)
0613 {
0614     struct romfs_inode_info *inode = _inode;
0615 
0616     inode_init_once(&inode->vfs_inode);
0617 }
0618 
0619 /*
0620  * romfs module initialisation
0621  */
0622 static int __init init_romfs_fs(void)
0623 {
0624     int ret;
0625 
0626     pr_info("ROMFS MTD (C) 2007 Red Hat, Inc.\n");
0627 
0628     romfs_inode_cachep =
0629         kmem_cache_create("romfs_i",
0630                   sizeof(struct romfs_inode_info), 0,
0631                   SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD |
0632                   SLAB_ACCOUNT, romfs_i_init_once);
0633 
0634     if (!romfs_inode_cachep) {
0635         pr_err("Failed to initialise inode cache\n");
0636         return -ENOMEM;
0637     }
0638     ret = register_filesystem(&romfs_fs_type);
0639     if (ret) {
0640         pr_err("Failed to register filesystem\n");
0641         goto error_register;
0642     }
0643     return 0;
0644 
0645 error_register:
0646     kmem_cache_destroy(romfs_inode_cachep);
0647     return ret;
0648 }
0649 
0650 /*
0651  * romfs module removal
0652  */
0653 static void __exit exit_romfs_fs(void)
0654 {
0655     unregister_filesystem(&romfs_fs_type);
0656     /*
0657      * Make sure all delayed rcu free inodes are flushed before we
0658      * destroy cache.
0659      */
0660     rcu_barrier();
0661     kmem_cache_destroy(romfs_inode_cachep);
0662 }
0663 
0664 module_init(init_romfs_fs);
0665 module_exit(exit_romfs_fs);
0666 
0667 MODULE_DESCRIPTION("Direct-MTD Capable RomFS");
0668 MODULE_AUTHOR("Red Hat, Inc.");
0669 MODULE_LICENSE("GPL"); /* Actually dual-licensed, but it doesn't matter for */