summaryrefslogtreecommitdiffstats
path: root/fs/ext2
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2001-01-10 17:17:53 +0000
committerRalf Baechle <ralf@linux-mips.org>2001-01-10 17:17:53 +0000
commitb2ad5f821b1381492d792ca10b1eb7a107b48f14 (patch)
tree954a648692e7da983db1d2470953705f6a729264 /fs/ext2
parentc9c06167e7933d93a6e396174c68abf242294abb (diff)
Merge with Linux 2.4.0-prerelease. Big Makefile rewrite, test your
Makefiles.
Diffstat (limited to 'fs/ext2')
-rw-r--r--fs/ext2/Makefile5
-rw-r--r--fs/ext2/balloc.c70
-rw-r--r--fs/ext2/inode.c10
-rw-r--r--fs/ext2/super.c105
4 files changed, 127 insertions, 63 deletions
diff --git a/fs/ext2/Makefile b/fs/ext2/Makefile
index 7321f45c8..aa8560f07 100644
--- a/fs/ext2/Makefile
+++ b/fs/ext2/Makefile
@@ -8,8 +8,9 @@
# Note 2! The CFLAGS definitions are now in the main makefile...
O_TARGET := ext2.o
-O_OBJS := acl.o balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
+
+obj-y := acl.o balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
ioctl.o namei.o super.o symlink.o
-M_OBJS := $(O_TARGET)
+obj-m := $(O_TARGET)
include $(TOPDIR)/Rules.make
diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c
index 81448e71b..e592850db 100644
--- a/fs/ext2/balloc.c
+++ b/fs/ext2/balloc.c
@@ -663,7 +663,7 @@ static inline int block_in_use (unsigned long block,
EXT2_BLOCKS_PER_GROUP(sb), map);
}
-static int test_root(int a, int b)
+static inline int test_root(int a, int b)
{
if (a == 0)
return 1;
@@ -682,24 +682,55 @@ int ext2_group_sparse(int group)
test_root(group, 7));
}
+/**
+ * ext2_bg_has_super - number of blocks used by the superblock in group
+ * @sb: superblock for filesystem
+ * @group: group number to check
+ *
+ * Return the number of blocks used by the superblock (primary or backup)
+ * in this group. Currently this will be only 0 or 1.
+ */
+int ext2_bg_has_super(struct super_block *sb, int group)
+{
+ if (EXT2_HAS_RO_COMPAT_FEATURE(sb,EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)&&
+ !ext2_group_sparse(group))
+ return 0;
+ return 1;
+}
+
+/**
+ * ext2_bg_num_gdb - number of blocks used by the group table in group
+ * @sb: superblock for filesystem
+ * @group: group number to check
+ *
+ * Return the number of blocks used by the group descriptor table
+ * (primary or backup) in this group. In the future there may be a
+ * different number of descriptor blocks in each group.
+ */
+unsigned long ext2_bg_num_gdb(struct super_block *sb, int group)
+{
+ if (EXT2_HAS_RO_COMPAT_FEATURE(sb,EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)&&
+ !ext2_group_sparse(group))
+ return 0;
+ return EXT2_SB(sb)->s_gdb_count;
+}
+
#ifdef CONFIG_EXT2_CHECK
/* Called at mount-time, super-block is locked */
void ext2_check_blocks_bitmap (struct super_block * sb)
{
struct buffer_head * bh;
struct ext2_super_block * es;
- unsigned long desc_count, bitmap_count, x;
+ unsigned long desc_count, bitmap_count, x, j;
unsigned long desc_blocks;
int bitmap_nr;
struct ext2_group_desc * gdp;
- int i, j;
+ int i;
es = sb->u.ext2_sb.s_es;
desc_count = 0;
bitmap_count = 0;
gdp = NULL;
- desc_blocks = (sb->u.ext2_sb.s_groups_count + EXT2_DESC_PER_BLOCK(sb) - 1) /
- EXT2_DESC_PER_BLOCK(sb);
for (i = 0; i < sb->u.ext2_sb.s_groups_count; i++) {
gdp = ext2_get_group_desc (sb, i, NULL);
if (!gdp)
@@ -708,24 +739,19 @@ void ext2_check_blocks_bitmap (struct super_block * sb)
bitmap_nr = load_block_bitmap (sb, i);
if (bitmap_nr < 0)
continue;
-
- bh = sb->u.ext2_sb.s_block_bitmap[bitmap_nr];
- if (!(sb->u.ext2_sb.s_feature_ro_compat &
- EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER) ||
- ext2_group_sparse(i)) {
- if (!ext2_test_bit (0, bh->b_data))
- ext2_error (sb, "ext2_check_blocks_bitmap",
- "Superblock in group %d "
- "is marked free", i);
-
- for (j = 0; j < desc_blocks; j++)
- if (!ext2_test_bit (j + 1, bh->b_data))
- ext2_error (sb,
- "ext2_check_blocks_bitmap",
- "Descriptor block #%d in group "
- "%d is marked free", j, i);
- }
+ bh = EXT2_SB(sb)->s_block_bitmap[bitmap_nr];
+
+ if (ext2_bg_has_super(sb, i) && !ext2_test_bit(0, bh->b_data))
+ ext2_error(sb, __FUNCTION__,
+ "Superblock in group %d is marked free", i);
+
+ desc_blocks = ext2_bg_num_gdb(sb, i);
+ for (j = 0; j < desc_blocks; j++)
+ if (!ext2_test_bit(j + 1, bh->b_data))
+ ext2_error(sb, __FUNCTION__,
+ "Descriptor block #%ld in group "
+ "%d is marked free", j, i);
if (!block_in_use (le32_to_cpu(gdp->bg_block_bitmap), sb, bh->b_data))
ext2_error (sb, "ext2_check_blocks_bitmap",
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index 658a06416..fd54c3040 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -1190,13 +1190,17 @@ static int ext2_update_inode(struct inode * inode, int do_sync)
raw_inode->i_size_high = cpu_to_le32(inode->i_size >> 32);
if (raw_inode->i_size_high) {
struct super_block *sb = inode->i_sb;
- struct ext2_super_block *es = sb->u.ext2_sb.s_es;
- if (!(es->s_feature_ro_compat & cpu_to_le32(EXT2_FEATURE_RO_COMPAT_LARGE_FILE))) {
+ if (!EXT2_HAS_RO_COMPAT_FEATURE(sb,
+ EXT2_FEATURE_RO_COMPAT_LARGE_FILE) ||
+ EXT2_SB(sb)->s_es->s_rev_level ==
+ cpu_to_le32(EXT2_GOOD_OLD_REV)) {
/* If this is the first large file
* created, add a flag to the superblock.
*/
lock_kernel();
- es->s_feature_ro_compat |= cpu_to_le32(EXT2_FEATURE_RO_COMPAT_LARGE_FILE);
+ ext2_update_dynamic_rev(sb);
+ EXT2_SET_RO_COMPAT_FEATURE(sb,
+ EXT2_FEATURE_RO_COMPAT_LARGE_FILE);
unlock_kernel();
ext2_write_super(sb);
}
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index 4d2dfedbf..7b88355f8 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -95,6 +95,31 @@ void ext2_warning (struct super_block * sb, const char * function,
bdevname(sb->s_dev), function, error_buf);
}
+void ext2_update_dynamic_rev(struct super_block *sb)
+{
+ struct ext2_super_block *es = EXT2_SB(sb)->s_es;
+
+ if (le32_to_cpu(es->s_rev_level) > EXT2_GOOD_OLD_REV)
+ return;
+
+ ext2_warning(sb, __FUNCTION__,
+ "updating to rev %d because of new feature flag, "
+ "running e2fsck is recommended",
+ EXT2_DYNAMIC_REV);
+
+ es->s_first_ino = cpu_to_le32(EXT2_GOOD_OLD_FIRST_INO);
+ es->s_inode_size = cpu_to_le16(EXT2_GOOD_OLD_INODE_SIZE);
+ es->s_rev_level = cpu_to_le32(EXT2_DYNAMIC_REV);
+ /* leave es->s_feature_*compat flags alone */
+ /* es->s_uuid will be set by e2fsck if empty */
+
+ /*
+ * The rest of the superblock fields should be zero, and if not it
+ * means they are likely already in use, so leave them alone. We
+ * can leave it up to e2fsck to clean up any inconsistencies there.
+ */
+}
+
void ext2_put_super (struct super_block * sb)
{
int db_count;
@@ -104,7 +129,7 @@ void ext2_put_super (struct super_block * sb)
sb->u.ext2_sb.s_es->s_state = le16_to_cpu(sb->u.ext2_sb.s_mount_state);
mark_buffer_dirty(sb->u.ext2_sb.s_sbh);
}
- db_count = sb->u.ext2_sb.s_db_per_group;
+ db_count = EXT2_SB(sb)->s_gdb_count;
for (i = 0; i < db_count; i++)
if (sb->u.ext2_sb.s_group_desc[i])
brelse (sb->u.ext2_sb.s_group_desc[i]);
@@ -261,9 +286,9 @@ static int ext2_setup_super (struct super_block * sb,
{
int res = 0;
if (le32_to_cpu(es->s_rev_level) > EXT2_MAX_SUPP_REV) {
- printk ("EXT2-fs warning: revision level too high, "
- "forcing read/only mode\n");
- res = MS_RDONLY;
+ printk ("EXT2-fs warning: revision level too high, "
+ "forcing read-only mode\n");
+ res = MS_RDONLY;
}
if (read_only)
return res;
@@ -423,22 +448,32 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
brelse(bh);
return NULL;
}
- if (le32_to_cpu(es->s_rev_level) > EXT2_GOOD_OLD_REV) {
- if (le32_to_cpu(es->s_feature_incompat) & ~EXT2_FEATURE_INCOMPAT_SUPP) {
- printk("EXT2-fs: %s: couldn't mount because of "
- "unsupported optional features.\n",
- bdevname(dev));
- goto failed_mount;
- }
- if (!(sb->s_flags & MS_RDONLY) &&
- (le32_to_cpu(es->s_feature_ro_compat) & ~EXT2_FEATURE_RO_COMPAT_SUPP)) {
- printk("EXT2-fs: %s: couldn't mount RDWR because of "
- "unsupported optional features.\n",
- bdevname(dev));
- goto failed_mount;
- }
+ if (le32_to_cpu(es->s_rev_level) == EXT2_GOOD_OLD_REV &&
+ (EXT2_HAS_COMPAT_FEATURE(sb, ~0U) ||
+ EXT2_HAS_RO_COMPAT_FEATURE(sb, ~0U) ||
+ EXT2_HAS_INCOMPAT_FEATURE(sb, ~0U)))
+ printk("EXT2-fs warning: feature flags set on rev 0 fs, "
+ "running e2fsck is recommended\n");
+ /*
+ * Check feature flags regardless of the revision level, since we
+ * previously didn't change the revision level when setting the flags,
+ * so there is a chance incompat flags are set on a rev 0 filesystem.
+ */
+ if ((i = EXT2_HAS_INCOMPAT_FEATURE(sb, ~EXT2_FEATURE_INCOMPAT_SUPP))) {
+ printk("EXT2-fs: %s: couldn't mount because of "
+ "unsupported optional features (%x).\n",
+ bdevname(dev), i);
+ goto failed_mount;
+ }
+ if (!(sb->s_flags & MS_RDONLY) &&
+ (i = EXT2_HAS_RO_COMPAT_FEATURE(sb, ~EXT2_FEATURE_RO_COMPAT_SUPP))){
+ printk("EXT2-fs: %s: couldn't mount RDWR because of "
+ "unsupported optional features (%x).\n",
+ bdevname(dev), i);
+ goto failed_mount;
}
- sb->s_blocksize_bits = le32_to_cpu(sb->u.ext2_sb.s_es->s_log_block_size) + 10;
+ sb->s_blocksize_bits =
+ le32_to_cpu(EXT2_SB(sb)->s_es->s_log_block_size) + 10;
sb->s_blocksize = 1 << sb->s_blocksize_bits;
if (sb->s_blocksize != BLOCK_SIZE &&
(sb->s_blocksize == 1024 || sb->s_blocksize == 2048 ||
@@ -484,9 +519,6 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
goto failed_mount;
}
}
- sb->u.ext2_sb.s_feature_compat = le32_to_cpu(es->s_feature_compat);
- sb->u.ext2_sb.s_feature_incompat = le32_to_cpu(es->s_feature_incompat);
- sb->u.ext2_sb.s_feature_ro_compat = le32_to_cpu(es->s_feature_ro_compat);
sb->u.ext2_sb.s_frag_size = EXT2_MIN_FRAG_SIZE <<
le32_to_cpu(es->s_log_frag_size);
if (sb->u.ext2_sb.s_frag_size)
@@ -590,7 +622,7 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
}
sb->u.ext2_sb.s_loaded_inode_bitmaps = 0;
sb->u.ext2_sb.s_loaded_block_bitmaps = 0;
- sb->u.ext2_sb.s_db_per_group = db_count;
+ sb->u.ext2_sb.s_gdb_count = db_count;
/*
* set up enough so that it can read an inode
*/
@@ -683,6 +715,14 @@ int ext2_remount (struct super_block * sb, int * flags, char * data)
ext2_commit_super (sb, es);
}
else {
+ int ret;
+ if ((ret = EXT2_HAS_RO_COMPAT_FEATURE(sb,
+ ~EXT2_FEATURE_RO_COMPAT_SUPP))) {
+ printk("EXT2-fs: %s: couldn't remount RDWR because of "
+ "unsupported optional features (%x).\n",
+ bdevname(sb->s_dev), ret);
+ return -EROFS;
+ }
/*
* Mounting a RDONLY partition read-write, so reread and
* store the current valid flag. (It may have been changed
@@ -698,7 +738,7 @@ int ext2_remount (struct super_block * sb, int * flags, char * data)
int ext2_statfs (struct super_block * sb, struct statfs * buf)
{
unsigned long overhead;
- int ngroups, i;
+ int i;
if (test_opt (sb, MINIX_DF))
overhead = 0;
@@ -715,19 +755,12 @@ int ext2_statfs (struct super_block * sb, struct statfs * buf)
/*
* Add the overhead attributed to the superblock and
- * block group descriptors. If this is sparse
- * superblocks is turned on, then not all groups have
- * this.
+ * block group descriptors. If the sparse superblocks
+ * feature is turned on, then not all groups have this.
*/
- if (sb->u.ext2_sb.s_feature_ro_compat &
- EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER) {
- ngroups = 0;
- for (i=0 ; i < sb->u.ext2_sb.s_groups_count; i++)
- if (ext2_group_sparse(i))
- ngroups++;
- } else
- ngroups = sb->u.ext2_sb.s_groups_count;
- overhead += ngroups * (1 + sb->u.ext2_sb.s_db_per_group);
+ for (i = 0; i < EXT2_SB(sb)->s_groups_count; i++)
+ overhead += ext2_bg_has_super(sb, i) +
+ ext2_bg_num_gdb(sb, i);
/*
* Every block group has an inode bitmap, a block