Ejemplo n.º 1
0
/*
 * Lookup and fill in the inode data..
 */
static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry)
{
	unsigned int offset = 0;

	while (offset < dir->i_size) {
		struct cramfs_inode *de;
		char *name;
		int namelen;

		de = cramfs_read(dir->i_sb, OFFSET(dir) + offset, sizeof(*de)+256);
		name = (char *)(de+1);
		namelen = de->namelen << 2;
		offset += sizeof(*de) + namelen;

		/* Quick check that the name is roughly the right length */
		if (((dentry->d_name.len + 3) & ~3) != namelen)
			continue;

		for (;;) {
			if (!namelen)
				return ERR_PTR(-EIO);
			if (name[namelen-1])
				break;
			namelen--;
		}
		if (namelen != dentry->d_name.len)
			continue;
		if (memcmp(dentry->d_name.name, name, namelen))
			continue;
		d_add(dentry, get_cramfs_inode(dir->i_sb, de));
		return NULL;
	}
	d_add(dentry, NULL);
	return NULL;
}
Ejemplo n.º 2
0
/*
 * Lookup and fill in the inode data..
 */
static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
{
	unsigned int offset = 0;
	struct inode *inode = NULL;
	int sorted;

	mutex_lock(&read_mutex);
	sorted = CRAMFS_SB(dir->i_sb)->flags & CRAMFS_FLAG_SORTED_DIRS;
	while (offset < dir->i_size) {
		struct cramfs_inode *de;
		char *name;
		int namelen, retval;
		int dir_off = OFFSET(dir) + offset;

		de = cramfs_read(dir->i_sb, dir_off, sizeof(*de)+CRAMFS_MAXPATHLEN);
		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;

		/* Quick check that the name is roughly the right length */
		if (((dentry->d_name.len + 3) & ~3) != namelen)
			continue;

		for (;;) {
			if (!namelen) {
				inode = ERR_PTR(-EIO);
				goto out;
			}
			if (name[namelen-1])
				break;
			namelen--;
		}
		if (namelen != dentry->d_name.len)
			continue;
		retval = memcmp(dentry->d_name.name, name, namelen);
		if (retval > 0)
			continue;
		if (!retval) {
			inode = get_cramfs_inode(dir->i_sb, de, dir_off);
			break;
		}
		/* else (retval < 0) */
		if (sorted)
			break;
	}
out:
	mutex_unlock(&read_mutex);
	if (IS_ERR(inode))
		return ERR_CAST(inode);
	d_add(dentry, inode);
	return NULL;
}
Ejemplo n.º 3
0
/*
 * Lookup and fill in the inode data..
 */
static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
{
	unsigned int offset = 0;
	int sorted;

	down(&read_mutex);
	sorted = CRAMFS_SB(dir->i_sb)->flags & CRAMFS_FLAG_SORTED_DIRS;
	while (offset < dir->i_size) {
		struct cramfs_inode *de;
		char *name;
		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;

		/* Quick check that the name is roughly the right length */
		if (((dentry->d_name.len + 3) & ~3) != namelen)
			continue;

		for (;;) {
			if (!namelen) {
				up(&read_mutex);
				return ERR_PTR(-EIO);
			}
			if (name[namelen-1])
				break;
			namelen--;
		}
		if (namelen != dentry->d_name.len)
			continue;
		retval = memcmp(dentry->d_name.name, name, namelen);
		if (retval > 0)
			continue;
		if (!retval) {
			struct cramfs_inode entry = *de;
			up(&read_mutex);
			d_add(dentry, get_cramfs_inode(dir->i_sb, &entry));
			return NULL;
		}
		/* else (retval < 0) */
		if (sorted)
			break;
	}
	up(&read_mutex);
	d_add(dentry, NULL);
	return NULL;
}
Ejemplo n.º 4
0
static struct super_block * cramfs_read_super(struct super_block *sb, void *data, int silent)
{
	int i;
	struct cramfs_super super;
	unsigned long root_offset;
	struct super_block * retval = NULL;

	set_blocksize(sb->s_dev, PAGE_CACHE_SIZE);
	sb->s_blocksize = PAGE_CACHE_SIZE;
	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;

	/* Invalidate the read buffers on mount: think disk change.. */
	for (i = 0; i < READ_BUFFERS; i++)
		buffer_blocknr[i] = -1;

	/* Read the first block and get the superblock from it */
	memcpy(&super, cramfs_read(sb, 0, sizeof(super)), sizeof(super));

	/* 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;
	}
	if (super.flags & ~CRAMFS_SUPPORTED_FLAGS) {
		printk("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");
		goto out;
	}
	root_offset = super.root.offset << 2;
	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);
		goto out;
	}

	/* Set it all up.. */
	sb->s_op	= &cramfs_ops;
	sb->s_root = d_alloc_root(get_cramfs_inode(sb, &super.root));
	retval = sb;

out:
	return retval;
}
Ejemplo n.º 5
0
static struct super_block * cramfs_read_super(struct super_block *sb, void *data, int silent)
{
#ifndef CONFIG_CRAMFS_LINEAR
	int i;
#else
	char *p;
#endif
	struct cramfs_super super;
	unsigned long root_offset;
	struct super_block * retval = NULL;

	sb->s_blocksize = PAGE_CACHE_SIZE;
	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;

#ifndef CONFIG_CRAMFS_LINEAR

	set_blocksize(sb->s_dev, PAGE_CACHE_SIZE);

	/* Invalidate the read buffers on mount: think disk change.. */
	for (i = 0; i < READ_BUFFERS; i++)
		buffer_blocknr[i] = -1;

#else

	/*
	 * The physical location of the cramfs image is specified as
	 * a mount parameter.  This parameter is mandatory for obvious
	 * reasons.  Some validation is made on the phys address but this
	 * is not exhaustive and we count on the fact that someone using
	 * this feature is supposed to know what he/she's doing.
	 */
	if (!data || !(p = strstr((char *)data, "physaddr="))) {
		printk(KERN_ERR "cramfs: unknown physical address for linear cramfs image\n");
		goto out;
	}
	sb->CRAMFS_SB_LINEAR_PHYS_ADDR = simple_strtoul(p + 9, NULL, 0);
	if (sb->CRAMFS_SB_LINEAR_PHYS_ADDR & (PAGE_SIZE-1)) {
		printk(KERN_ERR "cramfs: physical address 0x%lx for linear cramfs isn't aligned to a page boundary\n",
		       sb->CRAMFS_SB_LINEAR_PHYS_ADDR);
		goto out;
	}
	if (sb->CRAMFS_SB_LINEAR_PHYS_ADDR == 0) {
		printk(KERN_ERR "cramfs: physical address for linear cramfs image can't be 0\n");
		goto out;
	}
	printk(KERN_INFO "cramfs: checking physical address 0x%lx for linear cramfs image\n",
	       sb->CRAMFS_SB_LINEAR_PHYS_ADDR);

	/* Map only one page for now.  Will remap it when fs size is known. */
	sb->CRAMFS_SB_LINEAR_VIRT_ADDR =
		ioremap(sb->CRAMFS_SB_LINEAR_PHYS_ADDR, PAGE_SIZE);
	if (!sb->CRAMFS_SB_LINEAR_VIRT_ADDR) {
		printk(KERN_ERR "cramfs: ioremap of the linear cramfs image failed\n");
		goto out;
	}
#endif

	down(&read_mutex);
	/* Read the first block and get the superblock from it */
	memcpy(&super, cramfs_read(sb, 0, sizeof(super)), sizeof(super));
	up(&read_mutex);

	/* Do sanity checks on the superblock */
	if (super.magic != CRAMFS_MAGIC) {
		/* 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(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(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: 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));

#ifdef CONFIG_CRAMFS_LINEAR
	/* Remap the whole filesystem now */
	iounmap(sb->CRAMFS_SB_LINEAR_VIRT_ADDR);
	printk(KERN_INFO "cramfs: linear cramfs image appears to be %lu KB in size\n",
	       sb->CRAMFS_SB_SIZE/1024);
	sb->CRAMFS_SB_LINEAR_VIRT_ADDR =
		ioremap(sb->CRAMFS_SB_LINEAR_PHYS_ADDR, sb->CRAMFS_SB_SIZE);
	if (!sb->CRAMFS_SB_LINEAR_VIRT_ADDR) {
		printk(KERN_ERR "cramfs: ioremap of the linear cramfs image failed\n");
		goto out;
	}
#endif

	retval = sb;
out:
#ifdef CONFIG_CRAMFS_LINEAR
	if (!retval && sb->CRAMFS_SB_LINEAR_VIRT_ADDR)
		iounmap(sb->CRAMFS_SB_LINEAR_VIRT_ADDR);
#endif
	return retval;
}
Ejemplo n.º 6
0
static int cramfs_fill_super(struct super_block *sb, void *data, int silent)
{
	int i;
	struct cramfs_super super;
	unsigned long root_offset;
	struct cramfs_sb_info *sbi;
	struct inode *root;

	sb->s_flags |= MS_RDONLY;

	sbi = kzalloc(sizeof(struct cramfs_sb_info), GFP_KERNEL);
	if (!sbi)
		return -ENOMEM;
	sb->s_fs_info = sbi;
	cramfs_read = cramfs_read_comm;

	if (MAJOR(sb->s_dev) == MTD_BLOCK_MAJOR) {
		struct mtd_info *mtd;
		int blocks, *block_map;

		mtd = get_mtd_device(NULL, MINOR(sb->s_dev));
		if (!mtd)
			goto not_mtdblock;

		if (mtd->type != MTD_NANDFLASH)
			goto not_mtdblock;

		cramfs_read = cramfs_read_nand;
		sbi->mtd = mtd;

		blocks = mtd->size / mtd->erasesize;
		block_map = kmalloc(blocks * sizeof(int), GFP_KERNEL);

		for (i = 0; i < blocks; i++) {
			block_map[i] = -1;
		}

		sbi->block_map = block_map;
		sbi->nblock = blocks;
	}
not_mtdblock:
	/* Invalidate the read buffers on mount: think disk change.. */
	mutex_lock(&read_mutex);
	for (i = 0; i < READ_BUFFERS; i++)
		buffer_blocknr[i] = -1;

	/* Read the first block and get the superblock from it */
	memcpy(&super, cramfs_read(sb, 0, sizeof(super)), sizeof(super));
	mutex_unlock(&read_mutex);

	/* Do sanity checks on the superblock */
	if (super.magic != CRAMFS_MAGIC) {
		/* check for wrong endianess */
		if (super.magic == CRAMFS_MAGIC_WEND) {
			if (!silent)
				printk(KERN_ERR "cramfs: wrong endianess\n");
			goto out;
		}

		/* check at 512 byte offset */
		mutex_lock(&read_mutex);
		memcpy(&super, cramfs_read(sb, 512, sizeof(super)), sizeof(super));
		mutex_unlock(&read_mutex);
		if (super.magic != CRAMFS_MAGIC) {
			if (super.magic == CRAMFS_MAGIC_WEND && !silent)
				printk(KERN_ERR "cramfs: wrong endianess\n");
			else if (!silent)
				printk(KERN_ERR "cramfs: wrong magic\n");
			goto out;
		}
	}

	/* get feature flags first */
	if (super.flags & ~CRAMFS_SUPPORTED_FLAGS) {
		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(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) {
		sbi->size=super.size;
		sbi->blocks=super.fsid.blocks;
		sbi->files=super.fsid.files;
	} else {
		sbi->size=1<<28;
		sbi->blocks=0;
		sbi->files=0;
	}
	sbi->magic=super.magic;
	sbi->flags=super.flags;
	if (root_offset == 0)
		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;
	root = get_cramfs_inode(sb, &super.root);
	if (!root)
		goto out;
	sb->s_root = d_alloc_root(root);
	if (!sb->s_root) {
		iput(root);
		goto out;
	}
	return 0;
out:
	kfree(sbi);
	sb->s_fs_info = NULL;
	return -EINVAL;
}
Ejemplo n.º 7
0
static int cramfs_fill_super(struct super_block *sb, void *data, int silent)
{
	int i;
	struct cramfs_super super;
	unsigned long root_offset;
	struct cramfs_sb_info *sbi;
	struct inode *root;

	sb->s_flags |= MS_RDONLY;

	sbi = kzalloc(sizeof(struct cramfs_sb_info), GFP_KERNEL);
	if (!sbi)
		return -ENOMEM;
	sb->s_fs_info = sbi;

	/* Invalidate the read buffers on mount: think disk change.. */
	mutex_lock(&read_mutex);
	for (i = 0; i < READ_BUFFERS; i++)
		buffer_blocknr[i] = -1;

	/* Read the first block and get the superblock from it */
	memcpy(&super, cramfs_read(sb, 0, sizeof(super)), sizeof(super));
	mutex_unlock(&read_mutex);

	/* Do sanity checks on the superblock */
	if (super.magic != CRAMFS_MAGIC) {
		/* check for wrong endianess */
		if (super.magic == CRAMFS_MAGIC_WEND) {
			if (!silent)
				printk(KERN_ERR "cramfs: wrong endianess\n");
			goto out;
		}

		/* check at 512 byte offset */
		mutex_lock(&read_mutex);
		memcpy(&super, cramfs_read(sb, 512, sizeof(super)), sizeof(super));
		mutex_unlock(&read_mutex);
		if (super.magic != CRAMFS_MAGIC) {
			if (super.magic == CRAMFS_MAGIC_WEND && !silent)
				printk(KERN_ERR "cramfs: wrong endianess\n");
			else if (!silent)
				printk(KERN_ERR "cramfs: wrong magic\n");
			goto out;
		}
	}

	/* get feature flags first */
	if (super.flags & ~CRAMFS_SUPPORTED_FLAGS) {
		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(KERN_ERR "cramfs: root is not a directory\n");
		goto out;
	}
	/* correct strange, hard-coded permissions of mkcramfs */
	super.root.mode |= (S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);

	root_offset = super.root.offset << 2;
	if (super.flags & CRAMFS_FLAG_FSID_VERSION_2) {
		sbi->size=super.size;
		sbi->blocks=super.fsid.blocks;
		sbi->files=super.fsid.files;
	} else {
		sbi->size=1<<28;
		sbi->blocks=0;
		sbi->files=0;
	}
	sbi->magic=super.magic;
	sbi->flags=super.flags;
	if (root_offset == 0)
		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;
	root = get_cramfs_inode(sb, &super.root, 0);
	if (IS_ERR(root))
		goto out;
	sb->s_root = d_alloc_root(root);
	if (!sb->s_root) {
		iput(root);
		goto out;
	}
	return 0;
out:
	kfree(sbi);
	sb->s_fs_info = NULL;
	return -EINVAL;
}
Ejemplo n.º 8
0
static struct super_block * cramfs_read_super(struct super_block *sb, void *data, int silent)
{
	int i;
	struct cramfs_super super;
	unsigned long root_offset;
	struct super_block * retval = NULL;

	/* Invalidate the read buffers on mount: think disk change.. */
	for (i = 0; i < READ_BUFFERS; i++)
		buffer_blocknr[i] = -1;

	down(&read_mutex);
	/* Read the first block and get the superblock from it */
	memcpy(&super, cramfs_read(sb, 0, sizeof(super)), sizeof(super));
	up(&read_mutex);

	/* Do sanity checks on the superblock */
	if (super.magic != CRAMFS_MAGIC) {
		/* 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(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(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: 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));
	retval = sb;
out:
	return retval;
}