---------- Forwarded message ----------
Date: Fri, 15 Oct 1999 14:47:54 -0400
From: [EMAIL PROTECTED]
To: [EMAIL PROTECTED]
Subject: Re: possible solution?

   Date: Thu, 14 Oct 1999 22:46:35 -0400 (EDT)
   From: Tom Oehser <[EMAIL PROTECTED]>

   I do have tune2fs included.  Is it safe to do:

           tune2fs -s 0

   on an existing filesystem?  It seems to work.  It requests running e2fsck.
   Is this absolutely necessary?  Can rescue-diskette users just do this,
   then set it back to 1 after working with the drive?

Yes, you absoluetely have to run e2fsck afterwards, and in order for it
to work, there needs to be enough free space on the filesystem to
allocate new copies of the superblock.  It's best to make sure the
filesystem is clean before trying to make this conversion, since
otherwise the possibility for data loss is much greater.  

If you're doing this for a rescue disk, telling users that they need to
do tune2fs -s 0 is probably a realy bad idea.

Here are some patches against Linux 2..0.35 to support sparse
filesystems.  I haven't had a chance to test it (but it does compile),
but it should give you an idea of what needs to be done.

                                       - Ted

Patch generated: on Fri Oct 15 11:58:14 EDT 1999 by [EMAIL PROTECTED]
against Linux version 2.0.35
 
===================================================================
RCS file: fs/ext2/RCS/super.c,v
retrieving revision 1.1
diff -u -r1.1 fs/ext2/super.c
--- fs/ext2/super.c     1999/10/15 12:06:21     1.1
+++ fs/ext2/super.c     1999/10/15 15:25:40
@@ -463,6 +463,9 @@
                        goto failed_mount;
                }
        }
+       sb->u.ext2_sb.s_feature_compat = es->s_feature_compat;
+       sb->u.ext2_sb.s_feature_incompat = es->s_feature_incompat;
+       sb->u.ext2_sb.s_feature_ro_compat = es->s_feature_ro_compat;
        sb->u.ext2_sb.s_frag_size = EXT2_MIN_FRAG_SIZE <<
                                   es->s_log_frag_size;
        if (sb->u.ext2_sb.s_frag_size)
@@ -710,6 +713,7 @@
        unsigned long overhead;
        unsigned long overhead_per_group;
        struct statfs tmp;
+       int     ngroups, i;
 
        if (test_opt (sb, MINIX_DF))
                overhead = 0;
@@ -717,13 +721,35 @@
                /*
                 * Compute the overhead (FS structures)
                 */
-               overhead_per_group = 1 /* super block */ +
-                                    sb->u.ext2_sb.s_db_per_group /* descriptors */ +
-                                    1 /* block bitmap */ +
-                                    1 /* inode bitmap */ +
-                                    sb->u.ext2_sb.s_itb_per_group /* inode table */;
-               overhead = sb->u.ext2_sb.s_es->s_first_data_block +
-                          sb->u.ext2_sb.s_groups_count * overhead_per_group;
+
+               /*
+                * All of the blocks before first_data_block are
+                * overhead
+                */
+               overhead = sb->u.ext2_sb.s_es->s_first_data_block;
+
+               /*
+                * 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.
+                */
+               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);
+
+               /*
+                * Every block group has an inode bitmap, a block
+                * bitmap, and an inode table.
+                */
+               overhead += (sb->u.ext2_sb.s_groups_count *
+                            (2 + sb->u.ext2_sb.s_itb_per_group));
        }
 
        tmp.f_type = EXT2_SUPER_MAGIC;
===================================================================
RCS file: fs/ext2/RCS/balloc.c,v
retrieving revision 1.1
diff -u -r1.1 fs/ext2/balloc.c
--- fs/ext2/balloc.c    1999/10/15 12:13:01     1.1
+++ fs/ext2/balloc.c    1999/10/15 12:15:57
@@ -645,6 +645,25 @@
                         EXT2_BLOCKS_PER_GROUP(sb), map);
 }
 
+static int test_root(int a, int b)
+{
+       if (a == 0)
+               return 1;
+       while (1) {
+               if (a == 1)
+                       return 1;
+               if (a % b)
+                       return 0;
+               a = a / b;
+       }
+}
+
+int ext2_group_sparse(int group)
+{
+       return (test_root(group, 3) || test_root(group, 5) ||
+               test_root(group, 7));
+}
+
 void ext2_check_blocks_bitmap (struct super_block * sb)
 {
        struct buffer_head * bh;
@@ -671,16 +690,22 @@
 
                bh = sb->u.ext2_sb.s_block_bitmap[bitmap_nr];
 
-               if (!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 (!test_bit (j + 1, bh->b_data))
+               if (!(sb->u.ext2_sb.s_feature_ro_compat &
+                    EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER) ||
+                   ext2_group_sparse(i)) {
+                       if (!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 (!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);
-
+               }
+               
                if (!block_in_use (gdp->bg_block_bitmap, sb, bh->b_data))
                        ext2_error (sb, "ext2_check_blocks_bitmap",
                                    "Block bitmap for group %d is marked free",
===================================================================
RCS file: include/linux/RCS/ext2_fs.h,v
retrieving revision 1.1
diff -u -r1.1 include/linux/ext2_fs.h
--- include/linux/ext2_fs.h     1999/10/15 12:06:06     1.1
+++ include/linux/ext2_fs.h     1999/10/15 15:26:35
@@ -417,11 +417,21 @@
                                         ~EXT2_DIR_ROUND)
 
 /*
- * Feature set definitions --- none are defined as of now
+ * Feature set definitions
  */
+
+#define EXT2_HAS_COMPAT_FEATURE(sb,mask)                       \
+       ( EXT2_SB(sb)->s_feature_compat & (mask) )
+#define EXT2_HAS_RO_COMPAT_FEATURE(sb,mask)                    \
+       ( EXT2_SB(sb)->s_feature_ro_compat & (mask) )
+#define EXT2_HAS_INCOMPAT_FEATURE(sb,mask)                     \
+       ( EXT2_SB(sb)->s_feature_incompat & (mask) )
+
+#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER    0x0001
+
 #define EXT2_FEATURE_COMPAT_SUPP       0
 #define EXT2_FEATURE_INCOMPAT_SUPP     0
-#define EXT2_FEATURE_RO_COMPAT_SUPP    0
+#define EXT2_FEATURE_RO_COMPAT_SUPP    EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER
 
 #ifdef __KERNEL__
 /*
@@ -440,6 +450,7 @@
 extern int ext2_permission (struct inode *, int);
 
 /* balloc.c */
+extern int ext2_group_sparse(int group);
 extern int ext2_new_block (const struct inode *, unsigned long,
                           __u32 *, __u32 *, int *);
 extern void ext2_free_blocks (const struct inode *, unsigned long,
===================================================================
RCS file: include/linux/RCS/ext2_fs_sb.h,v
retrieving revision 1.1
diff -u -r1.1 include/linux/ext2_fs_sb.h
--- include/linux/ext2_fs_sb.h  1999/10/15 14:12:51     1.1
+++ include/linux/ext2_fs_sb.h  1999/10/15 15:26:40
@@ -60,6 +60,9 @@
        int s_desc_per_block_bits;
        int s_inode_size;
        int s_first_ino;
+       int s_feature_compat;
+       int s_feature_incompat;
+       int s_feature_ro_compat;
 };
 
 #endif /* _LINUX_EXT2_FS_SB */

Reply via email to