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