📄 super.c
字号:
gdp->bg_inode_table + sb->u.ext2_sb.s_itb_per_group >=
block + EXT2_BLOCKS_PER_GROUP(sb))
{
ext2_error (sb, "ext2_check_desciptors",
"Inode table for group %d"
" not in group (block %lu)!",
i, gdp->bg_inode_table);
return 0;
}
block += EXT2_BLOCKS_PER_GROUP(sb);
gdp++;
}
return 1;
}
struct super_block * ext2_read_super (struct super_block * sb, void * data,
int silent)
{
struct buffer_head * bh;
struct ext2_super_block * es;
unsigned long sb_block = 1;
unsigned long logic_sb_block = 1;
int dev = sb->s_dev;
int bh_count;
int i, j;
#ifdef EXT2FS_PRE_02B_COMPAT
int fs_converted = 0;
#endif
set_opt (sb->u.ext2_sb.s_mount_opt, CHECK_NORMAL);
if (!parse_options ((char *) data, &sb_block,
&sb->u.ext2_sb.s_mount_opt)) {
sb->s_dev = 0;
return NULL;
}
lock_super (sb);
set_blocksize (dev, BLOCK_SIZE);
if (!(bh = bread (dev, sb_block, BLOCK_SIZE))) {
sb->s_dev = 0;
unlock_super (sb);
printk ("EXT2-fs: unable to read superblock\n");
return NULL;
}
/*
* Note: s_es must be initialized s_es as soon as possible because
* some ext2 macro-instructions depend on its value
*/
es = (struct ext2_super_block *) bh->b_data;
sb->u.ext2_sb.s_es = es;
sb->s_magic = es->s_magic;
if (sb->s_magic != EXT2_SUPER_MAGIC
#ifdef EXT2FS_PRE_02B_COMPAT
&& sb->s_magic != EXT2_PRE_02B_MAGIC
#endif
) {
sb->s_dev = 0;
unlock_super (sb);
brelse (bh);
if (!silent)
printk ("VFS: Can't find an ext2 filesystem on dev %d/%d.\n",
MAJOR(dev), MINOR(dev));
return NULL;
}
sb->s_blocksize = EXT2_MIN_BLOCK_SIZE << es->s_log_block_size;
sb->s_blocksize_bits = EXT2_BLOCK_SIZE_BITS(sb);
if (sb->s_blocksize != BLOCK_SIZE &&
(sb->s_blocksize == 1024 || sb->s_blocksize == 2048 ||
sb->s_blocksize == 4096)) {
unsigned long offset;
brelse (bh);
set_blocksize (dev, sb->s_blocksize);
logic_sb_block = sb_block / sb->s_blocksize;
offset = sb_block % sb->s_blocksize;
bh = bread (dev, logic_sb_block, sb->s_blocksize);
if(!bh)
return NULL;
es = (struct ext2_super_block *) (((char *)bh->b_data) + offset);
sb->u.ext2_sb.s_es = es;
if (es->s_magic != EXT2_SUPER_MAGIC) {
sb->s_dev = 0;
unlock_super (sb);
brelse (bh);
printk ("EXT2-fs: Magic mismatch, very weird !\n");
return NULL;
}
}
sb->u.ext2_sb.s_frag_size = EXT2_MIN_FRAG_SIZE <<
es->s_log_frag_size;
if (sb->u.ext2_sb.s_frag_size)
sb->u.ext2_sb.s_frags_per_block = sb->s_blocksize /
sb->u.ext2_sb.s_frag_size;
else
sb->s_magic = 0;
sb->u.ext2_sb.s_blocks_per_group = es->s_blocks_per_group;
sb->u.ext2_sb.s_frags_per_group = es->s_frags_per_group;
sb->u.ext2_sb.s_inodes_per_group = es->s_inodes_per_group;
sb->u.ext2_sb.s_inodes_per_block = sb->s_blocksize /
sizeof (struct ext2_inode);
sb->u.ext2_sb.s_itb_per_group = sb->u.ext2_sb.s_inodes_per_group /
sb->u.ext2_sb.s_inodes_per_block;
sb->u.ext2_sb.s_desc_per_block = sb->s_blocksize /
sizeof (struct ext2_group_desc);
sb->u.ext2_sb.s_sbh = bh;
sb->u.ext2_sb.s_es = es;
sb->u.ext2_sb.s_mount_state = es->s_state;
sb->u.ext2_sb.s_rename_lock = 0;
sb->u.ext2_sb.s_rename_wait = NULL;
#ifdef EXT2FS_PRE_02B_COMPAT
if (sb->s_magic == EXT2_PRE_02B_MAGIC) {
if (es->s_blocks_count > 262144) {
/*
* fs > 256 MB can't be converted
*/
sb->s_dev = 0;
unlock_super (sb);
brelse (bh);
printk ("EXT2-fs: trying to mount a pre-0.2b file"
"system which cannot be converted\n");
return NULL;
}
printk ("EXT2-fs: mounting a pre 0.2b file system, "
"will try to convert the structure\n");
if (!(sb->s_flags & MS_RDONLY)) {
sb->s_dev = 0;
unlock_super (sb);
brelse (bh);
printk ("EXT2-fs: cannot convert a read-only fs\n");
return NULL;
}
if (!convert_pre_02b_fs (sb, bh)) {
sb->s_dev = 0;
unlock_super (sb);
brelse (bh);
printk ("EXT2-fs: conversion failed !!!\n");
return NULL;
}
printk ("EXT2-fs: conversion succeeded !!!\n");
fs_converted = 1;
}
#endif
if (sb->s_magic != EXT2_SUPER_MAGIC) {
sb->s_dev = 0;
unlock_super (sb);
brelse (bh);
if (!silent)
printk ("VFS: Can't find an ext2 filesystem on dev %d/%d.\n",
MAJOR(dev), MINOR(dev));
return NULL;
}
if (sb->s_blocksize != bh->b_size) {
sb->s_dev = 0;
unlock_super (sb);
brelse (bh);
if (!silent)
printk ("VFS: Unsupported blocksize on dev 0x%04x.\n",
dev);
return NULL;
}
if (sb->s_blocksize != sb->u.ext2_sb.s_frag_size) {
sb->s_dev = 0;
unlock_super (sb);
brelse (bh);
printk ("EXT2-fs: fragsize %lu != blocksize %lu (not supported yet)\n",
sb->u.ext2_sb.s_frag_size, sb->s_blocksize);
return NULL;
}
sb->u.ext2_sb.s_groups_count = (es->s_blocks_count -
es->s_first_data_block +
EXT2_BLOCKS_PER_GROUP(sb) - 1) /
EXT2_BLOCKS_PER_GROUP(sb);
for (i = 0; i < EXT2_MAX_GROUP_DESC; i++)
sb->u.ext2_sb.s_group_desc[i] = NULL;
bh_count = (sb->u.ext2_sb.s_groups_count + EXT2_DESC_PER_BLOCK(sb) - 1) /
EXT2_DESC_PER_BLOCK(sb);
if (bh_count > EXT2_MAX_GROUP_DESC) {
sb->s_dev = 0;
unlock_super (sb);
brelse (bh);
printk ("EXT2-fs: file system is too big\n");
return NULL;
}
for (i = 0; i < bh_count; i++) {
sb->u.ext2_sb.s_group_desc[i] = bread (dev, logic_sb_block + i + 1,
sb->s_blocksize);
if (!sb->u.ext2_sb.s_group_desc[i]) {
sb->s_dev = 0;
unlock_super (sb);
for (j = 0; j < i; j++)
brelse (sb->u.ext2_sb.s_group_desc[j]);
brelse (bh);
printk ("EXT2-fs: unable to read group descriptors\n");
return NULL;
}
}
if (!ext2_check_descriptors (sb)) {
sb->s_dev = 0;
unlock_super (sb);
for (j = 0; j < i; j++)
brelse (sb->u.ext2_sb.s_group_desc[j]);
brelse (bh);
printk ("EXT2-fs: group descriptors corrupted !\n");
return NULL;
}
for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++) {
sb->u.ext2_sb.s_inode_bitmap_number[i] = 0;
sb->u.ext2_sb.s_inode_bitmap[i] = NULL;
sb->u.ext2_sb.s_block_bitmap_number[i] = 0;
sb->u.ext2_sb.s_block_bitmap[i] = NULL;
}
sb->u.ext2_sb.s_loaded_inode_bitmaps = 0;
sb->u.ext2_sb.s_loaded_block_bitmaps = 0;
unlock_super (sb);
/*
* set up enough so that it can read an inode
*/
sb->s_dev = dev;
sb->s_op = &ext2_sops;
if (!(sb->s_mounted = iget (sb, EXT2_ROOT_INO))) {
sb->s_dev = 0;
for (i = 0; i < EXT2_MAX_GROUP_DESC; i++)
if (sb->u.ext2_sb.s_group_desc[i])
brelse (sb->u.ext2_sb.s_group_desc[i]);
brelse (bh);
printk ("EXT2-fs: get root inode failed\n");
return NULL;
}
#ifdef EXT2FS_PRE_02B_COMPAT
if (fs_converted) {
for (i = 0; i < bh_count; i++)
sb->u.ext2_sb.s_group_desc[i]->b_dirt = 1;
sb->s_dirt = 1;
}
#endif
ext2_setup_super (sb, es);
return sb;
}
static void ext2_commit_super (struct super_block * sb,
struct ext2_super_block * es)
{
es->s_wtime = CURRENT_TIME;
sb->u.ext2_sb.s_sbh->b_dirt = 1;
sb->s_dirt = 0;
}
/*
* In the second extended file system, it is not necessary to
* write the super block since we use a mapping of the
* disk super block in a buffer.
*
* However, this function is still used to set the fs valid
* flags to 0. We need to set this flag to 0 since the fs
* may have been checked while mounted and e2fsck may have
* set s_state to EXT2_VALID_FS after some corrections.
*/
void ext2_write_super (struct super_block * sb)
{
struct ext2_super_block * es;
if (!(sb->s_flags & MS_RDONLY)) {
es = sb->u.ext2_sb.s_es;
ext2_debug ("setting valid to 0\n");
if (es->s_state & EXT2_VALID_FS) {
es->s_state &= ~EXT2_VALID_FS;
es->s_mtime = CURRENT_TIME;
}
ext2_commit_super (sb, es);
}
sb->s_dirt = 0;
}
int ext2_remount (struct super_block * sb, int * flags, char * data)
{
struct ext2_super_block * es;
unsigned long tmp;
/*
* Allow the "check" option to be passed as a remount option.
*/
set_opt (sb->u.ext2_sb.s_mount_opt, CHECK_NORMAL);
parse_options (data, &tmp, &sb->u.ext2_sb.s_mount_opt);
es = sb->u.ext2_sb.s_es;
if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
return 0;
if (*flags & MS_RDONLY) {
if (es->s_state & EXT2_VALID_FS ||
!(sb->u.ext2_sb.s_mount_state & EXT2_VALID_FS))
return 0;
/*
* OK, we are remounting a valid rw partition rdonly, so set
* the rdonly flag and then mark the partition as valid again.
*/
es->s_state = sb->u.ext2_sb.s_mount_state;
es->s_mtime = CURRENT_TIME;
sb->u.ext2_sb.s_sbh->b_dirt = 1;
sb->s_dirt = 1;
ext2_commit_super (sb, es);
}
else {
/*
* Mounting a RDONLY partition read-write, so reread and
* store the current valid flag. (It may have been changed
* by e2fsck since we originally mounted the partition.)
*/
sb->u.ext2_sb.s_mount_state = es->s_state;
sb->s_flags &= ~MS_RDONLY;
ext2_setup_super (sb, es);
}
return 0;
}
void ext2_statfs (struct super_block * sb, struct statfs * buf)
{
long tmp;
put_fs_long (EXT2_SUPER_MAGIC, &buf->f_type);
put_fs_long (sb->s_blocksize, &buf->f_bsize);
put_fs_long (sb->u.ext2_sb.s_es->s_blocks_count, &buf->f_blocks);
tmp = ext2_count_free_blocks (sb);
put_fs_long (tmp, &buf->f_bfree);
if (tmp >= sb->u.ext2_sb.s_es->s_r_blocks_count)
put_fs_long (tmp - sb->u.ext2_sb.s_es->s_r_blocks_count,
&buf->f_bavail);
else
put_fs_long (0, &buf->f_bavail);
put_fs_long (sb->u.ext2_sb.s_es->s_inodes_count, &buf->f_files);
put_fs_long (ext2_count_free_inodes (sb), &buf->f_ffree);
put_fs_long (EXT2_NAME_LEN, &buf->f_namelen);
/* Don't know what value to put in buf->f_fsid */
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -