/* * 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; }
/* * 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; }
/* * 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; }
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; }
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; }
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; }
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; }
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; }