patch-2.4.7 linux/fs/cramfs/inode.c
Next file: linux/fs/dcache.c
Previous file: linux/fs/cramfs/cramfs.h
Back to the patch index
Back to the overall index
- Lines: 194
- Date:
Thu Jul 19 16:14:53 2001
- Orig file:
v2.4.6/linux/fs/cramfs/inode.c
- Orig date:
Tue Apr 17 23:16:38 2001
diff -u --recursive --new-file v2.4.6/linux/fs/cramfs/inode.c linux/fs/cramfs/inode.c
@@ -17,10 +17,16 @@
#include <linux/init.h>
#include <linux/string.h>
#include <linux/locks.h>
+#include <linux/blkdev.h>
+#include <linux/cramfs_fs.h>
#include <asm/uaccess.h>
-#include "cramfs.h"
+#define CRAMFS_SB_MAGIC u.cramfs_sb.magic
+#define CRAMFS_SB_SIZE u.cramfs_sb.size
+#define CRAMFS_SB_BLOCKS u.cramfs_sb.blocks
+#define CRAMFS_SB_FILES u.cramfs_sb.files
+#define CRAMFS_SB_FLAGS u.cramfs_sb.flags
static struct super_operations cramfs_ops;
static struct inode_operations cramfs_dir_inode_operations;
@@ -40,6 +46,8 @@
inode->i_mode = cramfs_inode->mode;
inode->i_uid = cramfs_inode->uid;
inode->i_size = cramfs_inode->size;
+ inode->i_blocks = (cramfs_inode->size - 1) / 512 + 1;
+ inode->i_blksize = PAGE_CACHE_SIZE;
inode->i_gid = cramfs_inode->gid;
inode->i_ino = CRAMINO(cramfs_inode);
/* inode->i_nlink is left 1 - arguably wrong for directories,
@@ -100,7 +108,11 @@
static void *cramfs_read(struct super_block *sb, unsigned int offset, unsigned int len)
{
struct buffer_head * bh_array[BLKS_PER_BUF];
- unsigned i, blocknr, buffer;
+ struct buffer_head * read_array[BLKS_PER_BUF];
+ unsigned i, blocknr, buffer, unread;
+ unsigned long devsize;
+ int major, minor;
+
char *data;
if (!len)
@@ -123,9 +135,34 @@
return read_buffers[i] + blk_offset;
}
+ devsize = ~0UL;
+ major = MAJOR(sb->s_dev);
+ minor = MINOR(sb->s_dev);
+
+ if (blk_size[major])
+ devsize = blk_size[major][minor] >> 2;
+
/* Ok, read in BLKS_PER_BUF pages completely first. */
- for (i = 0; i < BLKS_PER_BUF; i++)
- bh_array[i] = bread(sb->s_dev, blocknr + i, PAGE_CACHE_SIZE);
+ unread = 0;
+ for (i = 0; i < BLKS_PER_BUF; i++) {
+ struct buffer_head *bh;
+
+ bh = NULL;
+ if (blocknr + i < devsize) {
+ bh = getblk(sb->s_dev, blocknr + i, PAGE_CACHE_SIZE);
+ if (!buffer_uptodate(bh))
+ read_array[unread++] = bh;
+ }
+ bh_array[i] = bh;
+ }
+
+ if (unread) {
+ ll_rw_block(READ, unread, read_array);
+ do {
+ unread--;
+ wait_on_buffer(read_array[unread]);
+ } while (unread);
+ }
/* Ok, copy them to the staging area without sleeping. */
buffer = next_buffer;
@@ -167,34 +204,50 @@
/* Do sanity checks on the superblock */
if (super.magic != CRAMFS_MAGIC) {
- printk("wrong magic\n");
- goto out;
- }
- if (memcmp(super.signature, CRAMFS_SIGNATURE, sizeof(super.signature))) {
- printk("wrong signature\n");
- goto out;
+ /* check at 512 byte offset */
+ memcpy(&super, cramfs_read(sb, 512, sizeof(super)), sizeof(super));
+ if (super.magic != CRAMFS_MAGIC) {
+ printk(KERN_ERR "cramfs: wrong magic\n");
+ goto out;
+ }
}
+
+ /* get feature flags first */
if (super.flags & ~CRAMFS_SUPPORTED_FLAGS) {
- printk("unsupported filesystem features\n");
+ printk(KERN_ERR "cramfs: unsupported filesystem features\n");
goto out;
}
/* Check that the root inode is in a sane state */
if (!S_ISDIR(super.root.mode)) {
- printk("root is not a directory\n");
+ printk(KERN_ERR "cramfs: root is not a directory\n");
goto out;
}
root_offset = super.root.offset << 2;
+ if (super.flags & CRAMFS_FLAG_FSID_VERSION_2) {
+ sb->CRAMFS_SB_SIZE=super.size;
+ sb->CRAMFS_SB_BLOCKS=super.fsid.blocks;
+ sb->CRAMFS_SB_FILES=super.fsid.files;
+ } else {
+ sb->CRAMFS_SB_SIZE=1<<28;
+ sb->CRAMFS_SB_BLOCKS=0;
+ sb->CRAMFS_SB_FILES=0;
+ }
+ sb->CRAMFS_SB_MAGIC=super.magic;
+ sb->CRAMFS_SB_FLAGS=super.flags;
if (root_offset == 0)
- printk(KERN_INFO "cramfs: note: empty filesystem");
- else if (root_offset != sizeof(struct cramfs_super)) {
- printk("bad root offset %lu\n", root_offset);
+ printk(KERN_INFO "cramfs: empty filesystem");
+ else if (!(super.flags & CRAMFS_FLAG_SHIFTED_ROOT_OFFSET) &&
+ ((root_offset != sizeof(struct cramfs_super)) &&
+ (root_offset != 512 + sizeof(struct cramfs_super))))
+ {
+ printk(KERN_ERR "cramfs: bad root offset %lu\n", root_offset);
goto out;
}
/* Set it all up.. */
- sb->s_op = &cramfs_ops;
- sb->s_root = d_alloc_root(get_cramfs_inode(sb, &super.root));
+ sb->s_op = &cramfs_ops;
+ sb->s_root = d_alloc_root(get_cramfs_inode(sb, &super.root));
retval = sb;
out:
return retval;
@@ -204,8 +257,10 @@
{
buf->f_type = CRAMFS_MAGIC;
buf->f_bsize = PAGE_CACHE_SIZE;
+ buf->f_blocks = sb->CRAMFS_SB_BLOCKS;
buf->f_bfree = 0;
buf->f_bavail = 0;
+ buf->f_files = sb->CRAMFS_SB_FILES;
buf->f_ffree = 0;
buf->f_namelen = 255;
return 0;
@@ -270,14 +325,20 @@
static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry)
{
unsigned int offset = 0;
+ int sorted = dir->i_sb->CRAMFS_SB_FLAGS & CRAMFS_FLAG_SORTED_DIRS;
while (offset < dir->i_size) {
struct cramfs_inode *de;
char *name;
- int namelen;
+ int namelen, retval;
de = cramfs_read(dir->i_sb, OFFSET(dir) + offset, sizeof(*de)+256);
name = (char *)(de+1);
+
+ /* Try to take advantage of sorted directories */
+ if (sorted && (dentry->d_name.name[0] < name[0]))
+ break;
+
namelen = de->namelen << 2;
offset += sizeof(*de) + namelen;
@@ -294,10 +355,16 @@
}
if (namelen != dentry->d_name.len)
continue;
- if (memcmp(dentry->d_name.name, name, namelen))
+ retval = memcmp(dentry->d_name.name, name, namelen);
+ if (retval > 0)
continue;
- d_add(dentry, get_cramfs_inode(dir->i_sb, de));
- return NULL;
+ if (!retval) {
+ d_add(dentry, get_cramfs_inode(dir->i_sb, de));
+ return NULL;
+ }
+ /* else (retval < 0) */
+ if (sorted)
+ break;
}
d_add(dentry, NULL);
return NULL;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)