4 * Copyright (C) 1999 Linus Torvalds
5 * Copyright (C) 2000-2002 Transmeta Corporation
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License (Version 2) as
9 * published by the Free Software Foundation.
11 * Compressed ROM filesystem for Linux.
15 * These are the VFS interfaces to the compressed ROM filesystem.
16 * The actual compression is based on zlib, see the other files.
19 #include <linux/module.h>
21 #include <linux/pagemap.h>
22 #include <linux/init.h>
23 #include <linux/string.h>
24 #include <linux/locks.h>
25 #include <linux/blkdev.h>
26 #include <linux/cramfs_fs.h>
27 #include <asm/semaphore.h>
29 #include <asm/uaccess.h>
31 #define CRAMFS_SB_MAGIC u.cramfs_sb.magic
32 #define CRAMFS_SB_SIZE u.cramfs_sb.size
33 #define CRAMFS_SB_BLOCKS u.cramfs_sb.blocks
34 #define CRAMFS_SB_FILES u.cramfs_sb.files
35 #define CRAMFS_SB_FLAGS u.cramfs_sb.flags
37 static struct super_operations cramfs_ops;
38 static struct inode_operations cramfs_dir_inode_operations;
39 static struct file_operations cramfs_directory_operations;
40 static struct address_space_operations cramfs_aops;
42 static DECLARE_MUTEX(read_mutex);
45 /* These two macros may change in future, to provide better st_ino
47 #define CRAMINO(x) (CRAMFS_GET_OFFSET(x) ? CRAMFS_GET_OFFSET(x)<<2 : 1)
48 #define OFFSET(x) ((x)->i_ino)
50 static struct inode *get_cramfs_inode(struct super_block *sb, struct cramfs_inode * cramfs_inode)
52 struct inode * inode = new_inode(sb);
55 inode->i_mode = CRAMFS_16(cramfs_inode->mode);
56 inode->i_uid = CRAMFS_16(cramfs_inode->uid);
57 inode->i_size = CRAMFS_24(cramfs_inode->size);
58 inode->i_blocks = (CRAMFS_24(cramfs_inode->size) - 1)/512 + 1;
59 inode->i_blksize = PAGE_CACHE_SIZE;
60 inode->i_gid = cramfs_inode->gid;
61 inode->i_ino = CRAMINO(cramfs_inode);
62 /* inode->i_nlink is left 1 - arguably wrong for directories,
63 but it's the best we can do without reading the directory
64 contents. 1 yields the right result in GNU find, even
65 without -noleaf option. */
66 insert_inode_hash(inode);
67 if (S_ISREG(inode->i_mode)) {
68 inode->i_fop = &generic_ro_fops;
69 inode->i_data.a_ops = &cramfs_aops;
70 } else if (S_ISDIR(inode->i_mode)) {
71 inode->i_op = &cramfs_dir_inode_operations;
72 inode->i_fop = &cramfs_directory_operations;
73 } else if (S_ISLNK(inode->i_mode)) {
74 inode->i_op = &page_symlink_inode_operations;
75 inode->i_data.a_ops = &cramfs_aops;
78 init_special_inode(inode, inode->i_mode, CRAMFS_24(cramfs_inode->size));
85 * We have our own block cache: don't fill up the buffer cache
86 * with the ROM image, because the way the filesystem is set
87 * up the accesses should be fairly regular and cached in the
88 * page cache and dentry tree anyway..
90 * This also acts as a way to guarantee contiguous areas of up to
91 * BLKS_PER_BUF*PAGE_CACHE_SIZE, so that the caller doesn't need to
92 * worry about end-of-buffer issues even when decompressing a full
95 #define READ_BUFFERS (2)
96 /* NEXT_BUFFER(): Loop over [0..(READ_BUFFERS-1)]. */
97 #define NEXT_BUFFER(_ix) ((_ix) ^ 1)
100 * BLKS_PER_BUF_SHIFT should be at least 2 to allow for "compressed"
101 * data that takes up more space than the original and with unlucky
104 #define BLKS_PER_BUF_SHIFT (2)
105 #define BLKS_PER_BUF (1 << BLKS_PER_BUF_SHIFT)
106 #define BUFFER_SIZE (BLKS_PER_BUF*PAGE_CACHE_SIZE)
108 static unsigned char read_buffers[READ_BUFFERS][BUFFER_SIZE];
109 static unsigned buffer_blocknr[READ_BUFFERS];
110 static struct super_block * buffer_dev[READ_BUFFERS];
111 static int next_buffer;
114 * Returns a pointer to a buffer containing at least LEN bytes of
115 * filesystem starting at byte offset OFFSET into the filesystem.
117 static void *cramfs_read(struct super_block *sb, unsigned int offset, unsigned int len)
119 struct buffer_head * bh_array[BLKS_PER_BUF];
120 struct buffer_head * read_array[BLKS_PER_BUF];
121 unsigned i, blocknr, buffer, unread;
122 unsigned long devsize;
129 blocknr = offset >> PAGE_CACHE_SHIFT;
130 offset &= PAGE_CACHE_SIZE - 1;
132 /* Check if an existing buffer already has the data.. */
133 for (i = 0; i < READ_BUFFERS; i++) {
134 unsigned int blk_offset;
136 if (buffer_dev[i] != sb)
138 if (blocknr < buffer_blocknr[i])
140 blk_offset = (blocknr - buffer_blocknr[i]) << PAGE_CACHE_SHIFT;
141 blk_offset += offset;
142 if (blk_offset + len > BUFFER_SIZE)
144 return read_buffers[i] + blk_offset;
148 major = MAJOR(sb->s_dev);
149 minor = MINOR(sb->s_dev);
152 devsize = blk_size[major][minor] >> 2;
154 /* Ok, read in BLKS_PER_BUF pages completely first. */
156 for (i = 0; i < BLKS_PER_BUF; i++) {
157 struct buffer_head *bh;
160 if (blocknr + i < devsize) {
161 bh = sb_getblk(sb, blocknr + i);
162 if (!buffer_uptodate(bh))
163 read_array[unread++] = bh;
169 ll_rw_block(READ, unread, read_array);
172 wait_on_buffer(read_array[unread]);
176 /* Ok, copy them to the staging area without sleeping. */
177 buffer = next_buffer;
178 next_buffer = NEXT_BUFFER(buffer);
179 buffer_blocknr[buffer] = blocknr;
180 buffer_dev[buffer] = sb;
182 data = read_buffers[buffer];
183 for (i = 0; i < BLKS_PER_BUF; i++) {
184 struct buffer_head * bh = bh_array[i];
186 memcpy(data, bh->b_data, PAGE_CACHE_SIZE);
189 memset(data, 0, PAGE_CACHE_SIZE);
190 data += PAGE_CACHE_SIZE;
192 return read_buffers[buffer] + offset;
196 static struct super_block * cramfs_read_super(struct super_block *sb, void *data, int silent)
199 struct cramfs_super super;
200 unsigned long root_offset;
201 struct super_block * retval = NULL;
203 set_blocksize(sb->s_dev, PAGE_CACHE_SIZE);
204 sb->s_blocksize = PAGE_CACHE_SIZE;
205 sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
207 /* Invalidate the read buffers on mount: think disk change.. */
208 for (i = 0; i < READ_BUFFERS; i++)
209 buffer_blocknr[i] = -1;
212 /* Read the first block and get the superblock from it */
213 memcpy(&super, cramfs_read(sb, 0, sizeof(super)), sizeof(super));
216 /* Do sanity checks on the superblock */
217 if (super.magic != CRAMFS_32(CRAMFS_MAGIC)) {
218 /* check at 512 byte offset */
219 memcpy(&super, cramfs_read(sb, 512, sizeof(super)), sizeof(super));
220 if (super.magic != CRAMFS_32(CRAMFS_MAGIC)) {
221 printk(KERN_ERR "cramfs: wrong magic\n");
226 /* flags is reused several times, so swab it once */
227 super.flags = CRAMFS_32(super.flags);
229 /* get feature flags first */
230 if (super.flags & ~CRAMFS_SUPPORTED_FLAGS) {
231 printk(KERN_ERR "cramfs: unsupported filesystem features\n");
235 /* Check that the root inode is in a sane state */
236 if (!S_ISDIR(CRAMFS_16(super.root.mode))) {
237 printk(KERN_ERR "cramfs: root is not a directory\n");
240 root_offset = CRAMFS_GET_OFFSET(&(super.root)) << 2;
241 if (super.flags & CRAMFS_FLAG_FSID_VERSION_2) {
242 sb->CRAMFS_SB_SIZE = CRAMFS_32(super.size);
243 sb->CRAMFS_SB_BLOCKS = CRAMFS_32(super.fsid.blocks);
244 sb->CRAMFS_SB_FILES = CRAMFS_32(super.fsid.files);
246 sb->CRAMFS_SB_SIZE = 1 << 28;
247 sb->CRAMFS_SB_BLOCKS = 0;
248 sb->CRAMFS_SB_FILES = 0;
250 sb->CRAMFS_SB_MAGIC = CRAMFS_MAGIC;
251 sb->CRAMFS_SB_FLAGS = super.flags;
252 if (root_offset == 0)
253 printk(KERN_INFO "cramfs: empty filesystem");
254 else if (!(super.flags & CRAMFS_FLAG_SHIFTED_ROOT_OFFSET) &&
255 ((root_offset != sizeof(struct cramfs_super)) &&
256 (root_offset != 512 + sizeof(struct cramfs_super))))
258 printk(KERN_ERR "cramfs: bad root offset %lu\n", root_offset);
262 /* Set it all up.. */
263 sb->s_op = &cramfs_ops;
264 sb->s_root = d_alloc_root(get_cramfs_inode(sb, &super.root));
270 static int cramfs_statfs(struct super_block *sb, struct statfs *buf)
272 buf->f_type = CRAMFS_MAGIC;
273 buf->f_bsize = PAGE_CACHE_SIZE;
274 buf->f_blocks = sb->CRAMFS_SB_BLOCKS;
277 buf->f_files = sb->CRAMFS_SB_FILES;
279 buf->f_namelen = CRAMFS_MAXPATHLEN;
284 * Read a cramfs directory entry.
286 static int cramfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
288 struct inode *inode = filp->f_dentry->d_inode;
289 struct super_block *sb = inode->i_sb;
293 /* Offset within the thing. */
294 offset = filp->f_pos;
295 if (offset >= inode->i_size)
297 /* Directory entries are always 4-byte aligned */
302 while (offset < inode->i_size) {
303 struct cramfs_inode *de;
304 unsigned long nextoffset;
309 de = cramfs_read(sb, OFFSET(inode) + offset, sizeof(*de)+256);
311 name = (char *)(de+1);
314 * Namelengths on disk are shifted by two
315 * and the name padded out to 4-byte boundaries
318 namelen = CRAMFS_GET_NAMELEN(de) << 2;
319 nextoffset = offset + sizeof(*de) + namelen;
327 error = filldir(dirent, name, namelen, offset, CRAMINO(de), CRAMFS_16(de->mode) >> 12);
332 filp->f_pos = offset;
339 * Lookup and fill in the inode data..
341 static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry)
343 unsigned int offset = 0;
344 int sorted = dir->i_sb->CRAMFS_SB_FLAGS & CRAMFS_FLAG_SORTED_DIRS;
346 while (offset < dir->i_size) {
347 struct cramfs_inode *de;
352 de = cramfs_read(dir->i_sb, OFFSET(dir) + offset, sizeof(*de)+256);
354 name = (char *)(de+1);
356 /* Try to take advantage of sorted directories */
357 if (sorted && (dentry->d_name.name[0] < name[0]))
360 namelen = CRAMFS_GET_NAMELEN(de) << 2;
361 offset += sizeof(*de) + namelen;
363 /* Quick check that the name is roughly the right length */
364 if (((dentry->d_name.len + 3) & ~3) != namelen)
369 return ERR_PTR(-EIO);
374 if (namelen != dentry->d_name.len)
376 retval = memcmp(dentry->d_name.name, name, namelen);
380 d_add(dentry, get_cramfs_inode(dir->i_sb, de));
383 /* else (retval < 0) */
391 static int cramfs_readpage(struct file *file, struct page * page)
393 struct inode *inode = page->mapping->host;
394 u32 maxblock, bytes_filled;
397 maxblock = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
399 if (page->index < maxblock) {
400 struct super_block *sb = inode->i_sb;
401 u32 blkptr_offset = OFFSET(inode) + page->index*4;
402 u32 start_offset, compr_len;
404 start_offset = OFFSET(inode) + maxblock*4;
407 start_offset = CRAMFS_32(*(u32 *) cramfs_read(sb, blkptr_offset-4, 4));
408 compr_len = CRAMFS_32(*(u32 *) cramfs_read(sb, blkptr_offset, 4)) - start_offset;
415 bytes_filled = cramfs_uncompress_block(pgdata,
417 cramfs_read(sb, start_offset, compr_len),
423 memset(pgdata + bytes_filled, 0, PAGE_CACHE_SIZE - bytes_filled);
425 flush_dcache_page(page);
426 SetPageUptodate(page);
431 static struct address_space_operations cramfs_aops = {
432 readpage: cramfs_readpage
440 * A directory can only readdir
442 static struct file_operations cramfs_directory_operations = {
443 read: generic_read_dir,
444 readdir: cramfs_readdir,
447 static struct inode_operations cramfs_dir_inode_operations = {
448 lookup: cramfs_lookup,
451 static struct super_operations cramfs_ops = {
452 statfs: cramfs_statfs,
455 static DECLARE_FSTYPE_DEV(cramfs_fs_type, "cramfs", cramfs_read_super);
457 static int __init init_cramfs_fs(void)
459 cramfs_uncompress_init();
460 return register_filesystem(&cramfs_fs_type);
463 static void __exit exit_cramfs_fs(void)
465 cramfs_uncompress_exit();
466 unregister_filesystem(&cramfs_fs_type);
469 module_init(init_cramfs_fs)
470 module_exit(exit_cramfs_fs)
471 MODULE_LICENSE("GPL");