static int bfs_fill_super(struct super_block *s, void *data, int silent) { struct buffer_head *bh, *sbh; struct bfs_super_block *bfs_sb; struct inode *inode; unsigned i, imap_len; struct bfs_sb_info *info; int ret = -EINVAL; unsigned long i_sblock, i_eblock, i_eoff, s_size; info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; mutex_init(&info->bfs_lock); s->s_fs_info = info; sb_set_blocksize(s, BFS_BSIZE); sbh = sb_bread(s, 0); if (!sbh) goto out; bfs_sb = (struct bfs_super_block *)sbh->b_data; if (le32_to_cpu(bfs_sb->s_magic) != BFS_MAGIC) { if (!silent) printf("No BFS filesystem on %s (magic=%08x)\n", s->s_id, le32_to_cpu(bfs_sb->s_magic)); goto out1; } if (BFS_UNCLEAN(bfs_sb, s) && !silent) printf("%s is unclean, continuing\n", s->s_id); s->s_magic = BFS_MAGIC; if (le32_to_cpu(bfs_sb->s_start) > le32_to_cpu(bfs_sb->s_end)) { printf("Superblock is corrupted\n"); goto out1; } info->si_lasti = (le32_to_cpu(bfs_sb->s_start) - BFS_BSIZE) / sizeof(struct bfs_inode) + BFS_ROOT_INO - 1; imap_len = (info->si_lasti / 8) + 1; info->si_imap = kzalloc(imap_len, GFP_KERNEL); if (!info->si_imap) goto out1; for (i = 0; i < BFS_ROOT_INO; i++) set_bit(i, info->si_imap); s->s_op = &bfs_sops; inode = bfs_iget(s, BFS_ROOT_INO); if (IS_ERR(inode)) { ret = PTR_ERR(inode); goto out2; } s->s_root = d_alloc_root(inode); if (!s->s_root) { iput(inode); ret = -ENOMEM; goto out2; } info->si_blocks = (le32_to_cpu(bfs_sb->s_end) + 1) >> BFS_BSIZE_BITS; info->si_freeb = (le32_to_cpu(bfs_sb->s_end) + 1 - le32_to_cpu(bfs_sb->s_start)) >> BFS_BSIZE_BITS; info->si_freei = 0; info->si_lf_eblk = 0; /* can we read the last block? */ bh = sb_bread(s, info->si_blocks - 1); if (!bh) { printf("Last block not available: %lu\n", info->si_blocks - 1); ret = -EIO; goto out3; } brelse(bh); bh = NULL; for (i = BFS_ROOT_INO; i <= info->si_lasti; i++) { struct bfs_inode *di; int block = (i - BFS_ROOT_INO) / BFS_INODES_PER_BLOCK + 1; int off = (i - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK; unsigned long eblock; if (!off) { brelse(bh); bh = sb_bread(s, block); } if (!bh) continue; di = (struct bfs_inode *)bh->b_data + off; /* test if filesystem is not corrupted */ i_eoff = le32_to_cpu(di->i_eoffset); i_sblock = le32_to_cpu(di->i_sblock); i_eblock = le32_to_cpu(di->i_eblock); s_size = le32_to_cpu(bfs_sb->s_end); if (i_sblock > info->si_blocks || i_eblock > info->si_blocks || i_sblock > i_eblock || i_eoff > s_size || i_sblock * BFS_BSIZE > i_eoff) { printf("Inode 0x%08x corrupted\n", i); brelse(bh); ret = -EIO; goto out3; } if (!di->i_ino) { info->si_freei++; continue; } set_bit(i, info->si_imap); info->si_freeb -= BFS_FILEBLOCKS(di); eblock = le32_to_cpu(di->i_eblock); if (eblock > info->si_lf_eblk) info->si_lf_eblk = eblock; } brelse(bh); brelse(sbh); dump_imap("read_super", s); return 0; out3: dput(s->s_root); s->s_root = NULL; out2: kfree(info->si_imap); out1: brelse(sbh); out: mutex_destroy(&info->bfs_lock); kfree(info); s->s_fs_info = NULL; return ret; }
static struct super_block * bfs_read_super(struct super_block * s, void * data, int silent) { kdev_t dev; struct buffer_head * bh; struct bfs_super_block * bfs_sb; struct inode * inode; int i, imap_len; dev = s->s_dev; set_blocksize(dev, BFS_BSIZE); s->s_blocksize = BFS_BSIZE; s->s_blocksize_bits = BFS_BSIZE_BITS; bh = sb_bread(s, 0); if(!bh) goto out; bfs_sb = (struct bfs_super_block *)bh->b_data; if (bfs_sb->s_magic != BFS_MAGIC) { if (!silent) printf("No BFS filesystem on %s (magic=%08x)\n", bdevname(dev), bfs_sb->s_magic); goto out; } if (BFS_UNCLEAN(bfs_sb, s) && !silent) printf("%s is unclean, continuing\n", bdevname(dev)); s->s_magic = BFS_MAGIC; s->su_bfs_sb = bfs_sb; s->su_sbh = bh; s->su_lasti = (bfs_sb->s_start - BFS_BSIZE)/sizeof(struct bfs_inode) + BFS_ROOT_INO - 1; imap_len = s->su_lasti/8 + 1; s->su_imap = kmalloc(imap_len, GFP_KERNEL); if (!s->su_imap) goto out; memset(s->su_imap, 0, imap_len); for (i=0; i<BFS_ROOT_INO; i++) set_bit(i, s->su_imap); s->s_op = &bfs_sops; inode = iget(s, BFS_ROOT_INO); if (!inode) { kfree(s->su_imap); goto out; } s->s_root = d_alloc_root(inode); if (!s->s_root) { iput(inode); kfree(s->su_imap); goto out; } s->su_blocks = (bfs_sb->s_end + 1)>>BFS_BSIZE_BITS; /* for statfs(2) */ s->su_freeb = (bfs_sb->s_end + 1 - bfs_sb->s_start)>>BFS_BSIZE_BITS; s->su_freei = 0; s->su_lf_eblk = 0; s->su_lf_sblk = 0; s->su_lf_ioff = 0; for (i=BFS_ROOT_INO; i<=s->su_lasti; i++) { inode = iget(s,i); if (inode->iu_dsk_ino == 0) s->su_freei++; else { set_bit(i, s->su_imap); s->su_freeb -= inode->i_blocks; if (inode->iu_eblock > s->su_lf_eblk) { s->su_lf_eblk = inode->iu_eblock; s->su_lf_sblk = inode->iu_sblock; s->su_lf_ioff = BFS_INO2OFF(i); } } iput(inode); } if (!(s->s_flags & MS_RDONLY)) { mark_buffer_dirty(bh); s->s_dirt = 1; } dump_imap("read_super", s); return s; out: brelse(bh); return NULL; }
static int bfs_fill_super(struct super_block *s, void *data, int silent) { struct buffer_head * bh; struct bfs_super_block * bfs_sb; struct inode * inode; int i, imap_len; struct bfs_sb_info * info; info = kmalloc(sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; s->s_fs_info = info; memset(info, 0, sizeof(*info)); sb_set_blocksize(s, BFS_BSIZE); bh = sb_bread(s, 0); if(!bh) goto out; bfs_sb = (struct bfs_super_block *)bh->b_data; if (bfs_sb->s_magic != BFS_MAGIC) { if (!silent) printf("No BFS filesystem on %s (magic=%08x)\n", s->s_id, bfs_sb->s_magic); goto out; } if (BFS_UNCLEAN(bfs_sb, s) && !silent) printf("%s is unclean, continuing\n", s->s_id); s->s_magic = BFS_MAGIC; info->si_bfs_sb = bfs_sb; info->si_sbh = bh; info->si_lasti = (bfs_sb->s_start - BFS_BSIZE)/sizeof(struct bfs_inode) + BFS_ROOT_INO - 1; imap_len = info->si_lasti/8 + 1; info->si_imap = kmalloc(imap_len, GFP_KERNEL); if (!info->si_imap) goto out; memset(info->si_imap, 0, imap_len); for (i=0; i<BFS_ROOT_INO; i++) set_bit(i, info->si_imap); s->s_op = &bfs_sops; inode = iget(s, BFS_ROOT_INO); if (!inode) { kfree(info->si_imap); goto out; } s->s_root = d_alloc_root(inode); if (!s->s_root) { iput(inode); kfree(info->si_imap); goto out; } info->si_blocks = (bfs_sb->s_end + 1)>>BFS_BSIZE_BITS; /* for statfs(2) */ info->si_freeb = (bfs_sb->s_end + 1 - bfs_sb->s_start)>>BFS_BSIZE_BITS; info->si_freei = 0; info->si_lf_eblk = 0; info->si_lf_sblk = 0; info->si_lf_ioff = 0; for (i=BFS_ROOT_INO; i<=info->si_lasti; i++) { inode = iget(s,i); if (BFS_I(inode)->i_dsk_ino == 0) info->si_freei++; else { set_bit(i, info->si_imap); info->si_freeb -= inode->i_blocks; if (BFS_I(inode)->i_eblock > info->si_lf_eblk) { info->si_lf_eblk = BFS_I(inode)->i_eblock; info->si_lf_sblk = BFS_I(inode)->i_sblock; info->si_lf_ioff = BFS_INO2OFF(i); } } iput(inode); } if (!(s->s_flags & MS_RDONLY)) { mark_buffer_dirty(bh); s->s_dirt = 1; } dump_imap("read_super", s); return 0; out: brelse(bh); kfree(info); s->s_fs_info = NULL; return -EINVAL; }
static int bfs_fill_super(struct super_block *s, void *data, int silent) { struct buffer_head *bh; struct bfs_super_block *bfs_sb; struct inode *inode; unsigned i, imap_len; struct bfs_sb_info *info; long ret = -EINVAL; info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; s->s_fs_info = info; sb_set_blocksize(s, BFS_BSIZE); bh = sb_bread(s, 0); if(!bh) goto out; bfs_sb = (struct bfs_super_block *)bh->b_data; if (le32_to_cpu(bfs_sb->s_magic) != BFS_MAGIC) { if (!silent) printf("No BFS filesystem on %s (magic=%08x)\n", s->s_id, le32_to_cpu(bfs_sb->s_magic)); goto out; } if (BFS_UNCLEAN(bfs_sb, s) && !silent) printf("%s is unclean, continuing\n", s->s_id); s->s_magic = BFS_MAGIC; info->si_sbh = bh; info->si_lasti = (le32_to_cpu(bfs_sb->s_start) - BFS_BSIZE) / sizeof(struct bfs_inode) + BFS_ROOT_INO - 1; imap_len = (info->si_lasti / 8) + 1; info->si_imap = kzalloc(imap_len, GFP_KERNEL); if (!info->si_imap) goto out; for (i = 0; i < BFS_ROOT_INO; i++) set_bit(i, info->si_imap); s->s_op = &bfs_sops; inode = bfs_iget(s, BFS_ROOT_INO); if (IS_ERR(inode)) { ret = PTR_ERR(inode); kfree(info->si_imap); goto out; } s->s_root = d_alloc_root(inode); if (!s->s_root) { iput(inode); ret = -ENOMEM; kfree(info->si_imap); goto out; } info->si_blocks = (le32_to_cpu(bfs_sb->s_end) + 1) >> BFS_BSIZE_BITS; info->si_freeb = (le32_to_cpu(bfs_sb->s_end) + 1 - le32_to_cpu(bfs_sb->s_start)) >> BFS_BSIZE_BITS; info->si_freei = 0; info->si_lf_eblk = 0; bh = NULL; for (i = BFS_ROOT_INO; i <= info->si_lasti; i++) { struct bfs_inode *di; int block = (i - BFS_ROOT_INO) / BFS_INODES_PER_BLOCK + 1; int off = (i - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK; unsigned long sblock, eblock; if (!off) { brelse(bh); bh = sb_bread(s, block); } if (!bh) continue; di = (struct bfs_inode *)bh->b_data + off; if (!di->i_ino) { info->si_freei++; continue; } set_bit(i, info->si_imap); info->si_freeb -= BFS_FILEBLOCKS(di); sblock = le32_to_cpu(di->i_sblock); eblock = le32_to_cpu(di->i_eblock); if (eblock > info->si_lf_eblk) info->si_lf_eblk = eblock; } brelse(bh); if (!(s->s_flags & MS_RDONLY)) { mark_buffer_dirty(info->si_sbh); s->s_dirt = 1; } dump_imap("read_super", s); return 0; out: brelse(bh); kfree(info); s->s_fs_info = NULL; return ret; }