EXT3分区表崩溃的解决方法

 

EXT3分区表崩溃的解决方法

 

分区表崩溃,主要是超级块或组块崩溃了。以下红色为修改的部分,主要在错误的时候进行修复分区表,可能还是想的不是周到,需要多次测试。这里只是分区崩溃后的处理方法,最好是可以找到造成分区崩溃的真正原因,以此来避免分区的崩溃。

 

struct super_block * ext3_read_super (struct super_block * sb, void * data,

                                  int silent)

{

       struct buffer_head * bh;

       struct ext3_super_block *es = 0;

       struct ext3_sb_info *sbi = EXT3_SB(sb);

       unsigned long sb_block = 1;

       unsigned long logic_sb_block = 1;

       unsigned long offset = 0;

       unsigned long journal_inum = 0;

       kdev_t dev = sb->s_dev;

       int blocksize;

       int hblock;

       int db_count;

       int i,j;

       int needs_recovery;

    struct buffer_head * bh2;

       struct buffer_head        *bh3; //add mwp

       struct buffer_head        *temp;

    int loop = 0;

#ifdef CONFIG_JBD_DEBUG

       ext3_ro_after = 0;

#endif

       /*

        * See what the current blocksize for the device is, and

        * use that as the blocksize.  Otherwise (or if the blocksize

        * is smaller than the default) use the default.

        * This is important for devices that have a hardware

        * sectorsize that is larger than the default.

        */

       blocksize = EXT3_MIN_BLOCK_SIZE;

       hblock = get_hardsect_size(dev);

       if (blocksize < hblock)

              blocksize = hblock;

        //printk("in ext3_read_super/n");

       sbi->s_mount_opt = 0;

       sbi->s_resuid = EXT3_DEF_RESUID;

       sbi->s_resgid = EXT3_DEF_RESGID;

       if (!parse_options ((char *) data, &sb_block, sbi, &journal_inum, 0)) {

              sb->s_dev = 0;

              goto out_fail;

       }

        //printk("after parse_options/n");

             

       sb->s_blocksize = blocksize;

       set_blocksize (dev, blocksize);

        //sb->s_flags |= MS_SYNCHRONOUS; //add mwp

       /*

        * The ext3 superblock will not be buffer aligned for other than 1kB

        * block sizes.  We need to calculate the offset from buffer start.

        */

       if (blocksize != EXT3_MIN_BLOCK_SIZE) {

              logic_sb_block = (sb_block * EXT3_MIN_BLOCK_SIZE) / blocksize;

              offset = (sb_block * EXT3_MIN_BLOCK_SIZE) % blocksize;

       }

        //printk("super logic block is %d/n,block size is %d,offset is %d",logic_sb_block,sb->s_blocksize,

       //            offset);

 

 

BEGIN:  

 

       if (!(bh = sb_bread(sb, logic_sb_block))) {

              printk (KERN_ERR "EXT3-fs: unable to read superblock/n");

              goto out_fail;

       }

             

       /*

        * Note: s_es must be initialized as soon as possible because

        *       some ext3 macro-instructions depend on its value

        */

             

       if(loop >=2)

              goto failed_mount; 

       loop ++;

      

       es = (struct ext3_super_block *) (((char *)bh->b_data) + offset);

       sbi->s_es = es;

       sb->s_magic = le16_to_cpu(es->s_magic);

       if (sb->s_magic != EXT3_SUPER_MAGIC) {

              if (!silent)

                     printk(KERN_ERR

                            "VFS: Can't find ext3 filesystem on dev %s.current sb->s_magic is %x/n",

                            bdevname(dev),sb->s_magic);

 

              //

              //if(sb->s_magic == 0)

              {

                printk("your filesystem have error/n");

                            if (!(bh2 = sb_bread(sb, 32768*4))) {

                                   printk (KERN_ERR "EXT3-fs: unable to read superblock/n");

                                   goto out_fail;

                            }

                           

                            es = (struct ext3_super_block *) (((char *)bh2->b_data) + offset);

                            sbi->s_es = es;

                            sb->s_magic = le16_to_cpu(es->s_magic);

                               if (sb->s_magic != EXT3_SUPER_MAGIC) {

                                        printk("find magic error/n");

 

                                      //  {

                                                            brelse(bh2);   

goto failed_mount;             

                                                               if (!(bh3 = sb_bread(sb, 32768 *4+1))) {

                                                                      printk (KERN_ERR "EXT3-fs: unable to read superblock/n");

                                                                      goto out_fail;

                                                               }

                                                               /*printk("in read block 32769/n");

                                                               for(i=0;i<blocksize/16;i++)

                                                               {

                                                                       for(j=0;j<16;j++)

                                                                       {

                                                                             printk("%x-",*(((char *)bh3->b_data) + offset+i*16+j));

                                                                       }

                                                                      printk("/n");

                                                               }*/

                                                               es = (struct ext3_super_block *) (((char *)bh3->b_data) + offset);

                                                               sbi->s_es = es;

                                                               sb->s_magic = le16_to_cpu(es->s_magic); 

                                                                if (sb->s_magic != EXT3_SUPER_MAGIC) {

                                                                                     printk("find maigic in 32769 block error/n");

                                                                           brelse(bh3);

                                                                          goto failed_mount;

                                                                 }

                                                                 else

                                                                 {

                                                                           printk("find magic in 32769 block correct/n");

                                                                }

                                                                

                                                                

 

                                      // }

                                                                     

                            }

                                else

                                {

                                       printk("find correct magic   in 32768*4/n");

                                   //备份新的超级块

                                    //brelse(bh);

                                    for(i=0;i<blocksize;i++)

                                    {

                                           *((char *)bh->b_data + offset +i)= *((char *)bh2->b_data + offset+i);

                                    }

 

                                   /*printk("after copy/n");

                                   for(i=0;i<blocksize/16;i++)

                                   {

                                           for(j=0;j<16;j++)

                                           {

                                                 printk("%x-",*(((char *)bh->b_data) + offset+i*16+j));

                                           }

                                          printk("/n");

                                   }*/

 

                                   //让其脏

                                     mark_buffer_dirty(bh);

                                   brelse(bh2);

                                   set_bit(BH_Sync, &bh->b_state);

                                   ll_rw_block(WRITE, 1, &bh);

                                   wait_on_buffer(bh);

                                   //fsync_dev(sb->s_dev); //add mwp

                                   if (buffer_uptodate(bh))

                                   {

                                          //return bh;

                                              brelse(bh);

                                         goto BEGIN;

                   

                                   }

                                   else

                                          goto failed_mount;

 

                                }

                                            

 

             

              }

              goto failed_mount;

       }

 

       if (le32_to_cpu(es->s_rev_level) == EXT3_GOOD_OLD_REV &&

           (EXT3_HAS_COMPAT_FEATURE(sb, ~0U) ||

            EXT3_HAS_RO_COMPAT_FEATURE(sb, ~0U) ||

            EXT3_HAS_INCOMPAT_FEATURE(sb, ~0U)))

              printk(KERN_WARNING

                     "EXT3-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 = EXT3_HAS_INCOMPAT_FEATURE(sb, ~EXT3_FEATURE_INCOMPAT_SUPP))) {

              printk(KERN_ERR "EXT3-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 = EXT3_HAS_RO_COMPAT_FEATURE(sb, ~EXT3_FEATURE_RO_COMPAT_SUPP))){

              printk(KERN_ERR "EXT3-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(es->s_log_block_size) + 10;

       sb->s_blocksize = 1 << sb->s_blocksize_bits;

 

        printk("after process sb->s_flags/n");

             

       if (sb->s_blocksize < EXT3_MIN_BLOCK_SIZE ||

           sb->s_blocksize > EXT3_MAX_BLOCK_SIZE) {

              printk(KERN_ERR

                     "EXT3-fs: Unsupported filesystem blocksize %d on %s./n",

                     blocksize, bdevname(dev));

              goto failed_mount;

       }

 

       sb->s_maxbytes = ext3_max_size(sb->s_blocksize_bits);

 

       // printk("after get sb->s_maxbytes/n");

             

       if (sb->s_blocksize != blocksize) {

              blocksize = sb->s_blocksize;

 

              /*

               * Make sure the blocksize for the filesystem is larger

               * than the hardware sectorsize for the machine.

               */

              if (sb->s_blocksize < hblock) {

                     printk(KERN_ERR "EXT3-fs: blocksize %d too small for "

                            "device blocksize %d./n", blocksize, hblock);

                     goto failed_mount;

              }

 

              brelse (bh);

              set_blocksize (dev, sb->s_blocksize);

              logic_sb_block = (sb_block * EXT3_MIN_BLOCK_SIZE) / blocksize;

              offset = (sb_block * EXT3_MIN_BLOCK_SIZE) % blocksize;

              bh = sb_bread(sb, logic_sb_block);

              if (!bh) {

                     printk(KERN_ERR

                            "EXT3-fs: Can't read superblock on 2nd try./n");

                     return NULL;

              }

              es = (struct ext3_super_block *)(((char *)bh->b_data) + offset);

              sbi->s_es = es;

             

              if (es->s_magic != le16_to_cpu(EXT3_SUPER_MAGIC)) {

                     printk (KERN_ERR

                            "EXT3-fs: Magic mismatch, very weird !/n");

                     goto failed_mount;

              }

       }

 

       if (le32_to_cpu(es->s_rev_level) == EXT3_GOOD_OLD_REV) {

              sbi->s_inode_size = EXT3_GOOD_OLD_INODE_SIZE;

              sbi->s_first_ino = EXT3_GOOD_OLD_FIRST_INO;

       } else {

              sbi->s_inode_size = le16_to_cpu(es->s_inode_size);

              sbi->s_first_ino = le32_to_cpu(es->s_first_ino);

              if (sbi->s_inode_size != EXT3_GOOD_OLD_INODE_SIZE) {

                     printk (KERN_ERR

                            "EXT3-fs: unsupported inode size: %d/n",

                            sbi->s_inode_size);

                     goto failed_mount;

              }

       }

       sbi->s_frag_size = EXT3_MIN_FRAG_SIZE <<

                               le32_to_cpu(es->s_log_frag_size);

       if (blocksize != sbi->s_frag_size) {

              printk(KERN_ERR

                     "EXT3-fs: fragsize %lu != blocksize %u (unsupported)/n",

                     sbi->s_frag_size, blocksize);

              goto failed_mount;

       }

       sbi->s_frags_per_block = 1;

       sbi->s_blocks_per_group = le32_to_cpu(es->s_blocks_per_group);

       sbi->s_frags_per_group = le32_to_cpu(es->s_frags_per_group);

       sbi->s_inodes_per_group = le32_to_cpu(es->s_inodes_per_group);

       sbi->s_inodes_per_block = blocksize / EXT3_INODE_SIZE(sb);

       sbi->s_itb_per_group = sbi->s_inodes_per_group /sbi->s_inodes_per_block;

       sbi->s_desc_per_block = blocksize / sizeof(struct ext3_group_desc);

       sbi->s_sbh = bh;

       if (sbi->s_resuid == EXT3_DEF_RESUID)

              sbi->s_resuid = le16_to_cpu(es->s_def_resuid);

       if (sbi->s_resgid == EXT3_DEF_RESGID)

              sbi->s_resgid = le16_to_cpu(es->s_def_resgid);

       sbi->s_mount_state = le16_to_cpu(es->s_state);

       sbi->s_addr_per_block_bits = log2(EXT3_ADDR_PER_BLOCK(sb));

       sbi->s_desc_per_block_bits = log2(EXT3_DESC_PER_BLOCK(sb));

 

       if (sbi->s_blocks_per_group > blocksize * 8) {

              printk (KERN_ERR

                     "EXT3-fs: #blocks per group too big: %lu/n",

                     sbi->s_blocks_per_group);

              goto failed_mount;

       }

       if (sbi->s_frags_per_group > blocksize * 8) {

              printk (KERN_ERR

                     "EXT3-fs: #fragments per group too big: %lu/n",

                     sbi->s_frags_per_group);

              goto failed_mount;

       }

       if (sbi->s_inodes_per_group > blocksize * 8) {

              printk (KERN_ERR

                     "EXT3-fs: #inodes per group too big: %lu/n",

                     sbi->s_inodes_per_group);

              goto failed_mount;

       }

 

       sbi->s_groups_count = (le32_to_cpu(es->s_blocks_count) -

                            le32_to_cpu(es->s_first_data_block) +

                            EXT3_BLOCKS_PER_GROUP(sb) - 1) /

                           EXT3_BLOCKS_PER_GROUP(sb);

       db_count = (sbi->s_groups_count + EXT3_DESC_PER_BLOCK(sb) - 1) /

                 EXT3_DESC_PER_BLOCK(sb);

       sbi->s_group_desc = kmalloc(db_count * sizeof (struct buffer_head *),

                                GFP_KERNEL);

       if (sbi->s_group_desc == NULL) {

              printk (KERN_ERR "EXT3-fs: not enough memory/n");

              goto failed_mount;

       }

 

       for (i = 0; i < db_count; i++) {

              sbi->s_group_desc[i] = sb_bread(sb, logic_sb_block + i + 1);

              if (!sbi->s_group_desc[i]) {

                     printk (KERN_ERR "EXT3-fs: "

                            "can't read group descriptor %d/n", i);

                     db_count = i;

                     goto failed_mount2;

              }

       }

       //检查组描述符

       if (!ext3_check_descriptors (sb)) {

              printk (KERN_ERR "EXT3-fs: group descriptors corrupted !/n");

 

         //释放内存

              for(i = 0 ;i< db_count; i++)

              {

                  

brelse (sbi->s_group_desc[i] );

              }

             

              for (i = 0; i < db_count; i++) {

                     sbi->s_group_desc[i] = sb_bread(sb, logic_sb_block + i + 1);

                     if (!sbi->s_group_desc[i]) {

                            printk (KERN_ERR "EXT3-fs: "

                                   "can't read group descriptor %d/n", i);

                            db_count = i;

                            goto failed_mount2;

                     }

                     temp = sb_bread(sb, 32768 + i + 1);

                    

                        //拷贝数据

                     for(j=0;j<sb->s_blocksize;j++)

                     {

                         

*((char *)(sbi->s_group_desc[i])->b_data  +j)= *((char *)temp->b_data +j);

                     }

                     mark_buffer_dirty(sbi->s_group_desc[i]);

                     brelse(temp);

                     set_bit(BH_Sync, &sbi->s_group_desc[i]->b_state);

                     ll_rw_block(WRITE, 1, &sbi->s_group_desc[i]);

                     wait_on_buffer(sbi->s_group_desc[i]);

                     if (buffer_uptodate(sbi->s_group_desc[i]))

                     {

                          printk("flush buffer sbi->s_group_desc[%d] error /n",i);

                     }

      

              }

 

              //继续进行判断

               if (!ext3_check_descriptors (sb)) {

                    goto failed_mount2;

               }

       }

 

      

       for (i = 0; i < EXT3_MAX_GROUP_LOADED; i++) {

              sbi->s_inode_bitmap_number[i] = 0;

              sbi->s_inode_bitmap[i] = NULL;

              sbi->s_block_bitmap_number[i] = 0;

              sbi->s_block_bitmap[i] = NULL;

       }

       sbi->s_loaded_inode_bitmaps = 0;

       sbi->s_loaded_block_bitmaps = 0;

       sbi->s_gdb_count = db_count;

       get_random_bytes(&sbi->s_next_generation, sizeof(u32));

       /*

        * set up enough so that it can read an inode

        */

       sb->s_op = &ext3_sops;

       sb->dq_op = &ext3_qops;

       INIT_LIST_HEAD(&sbi->s_orphan); /* unlinked but open files */

 

       sb->s_root = 0;

 

       needs_recovery = (es->s_last_orphan != 0 ||

                       EXT3_HAS_INCOMPAT_FEATURE(sb,

                                EXT3_FEATURE_INCOMPAT_RECOVER));

 

       /*

        * The first inode we look at is the journal inode.  Don't try

        * root first: it may be modified in the journal!

        */

       if (!test_opt(sb, NOLOAD) &&

           EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {

              if (ext3_load_journal(sb, es))

                     goto failed_mount2;

       } else if (journal_inum) {

              if (ext3_create_journal(sb, es, journal_inum))

                     goto failed_mount2;

       } else {

              if (!silent)

                     printk (KERN_ERR

                            "ext3: No journal on filesystem on %s/n",

                            bdevname(dev));

              goto failed_mount2;

       }

 

       /* We have now updated the journal if required, so we can

        * validate the data journaling mode. */

       switch (test_opt(sb, DATA_FLAGS)) {

       case 0:

              /* No mode set, assume a default based on the journal

                   capabilities: ORDERED_DATA if the journal can

                   cope, else JOURNAL_DATA */

              if (journal_check_available_features

                  (sbi->s_journal, 0, 0, JFS_FEATURE_INCOMPAT_REVOKE))

                     set_opt(sbi->s_mount_opt, ORDERED_DATA);

              else

                     set_opt(sbi->s_mount_opt, JOURNAL_DATA);

              break;

 

       case EXT3_MOUNT_ORDERED_DATA:

       case EXT3_MOUNT_WRITEBACK_DATA:

              if (!journal_check_available_features

                  (sbi->s_journal, 0, 0, JFS_FEATURE_INCOMPAT_REVOKE)) {

                     printk(KERN_ERR "EXT3-fs: Journal does not support "

                            "requested data journaling mode/n");

                     goto failed_mount3;

              }

       default:

              break;

       }

 

       /*

        * The journal_load will have done any necessary log recovery,

        * so we can safely mount the rest of the filesystem now.

        */

 

       sb->s_root = d_alloc_root(iget(sb, EXT3_ROOT_INO));

       if (!sb->s_root || !S_ISDIR(sb->s_root->d_inode->i_mode) ||

           !sb->s_root->d_inode->i_blocks || !sb->s_root->d_inode->i_size) {

              if (sb->s_root) {

                     dput(sb->s_root);

                     sb->s_root = NULL;

                     printk(KERN_ERR

                            "EXT3-fs: corrupt root inode, run e2fsck/n");

              } else

                     printk(KERN_ERR "EXT3-fs: get root inode failed/n");

              goto failed_mount3;

       }

 

       ext3_setup_super (sb, es, sb->s_flags & MS_RDONLY);

       /*

        * akpm: core read_super() calls in here with the superblock locked.

        * That deadlocks, because orphan cleanup needs to lock the superblock

        * in numerous places.  Here we just pop the lock - it's relatively

        * harmless, because we are now ready to accept write_super() requests,

        * and aviro says that's the only reason for hanging onto the

        * superblock lock.

        */

       EXT3_SB(sb)->s_mount_state |= EXT3_ORPHAN_FS;

       unlock_super(sb);  /* akpm: sigh */

       ext3_orphan_cleanup(sb, es);

       lock_super(sb);

       EXT3_SB(sb)->s_mount_state &= ~EXT3_ORPHAN_FS;

       if (needs_recovery)

              printk (KERN_INFO "EXT3-fs: recovery complete./n");

       ext3_mark_recovery_complete(sb, es);

       printk (KERN_INFO "EXT3-fs: mounted filesystem with %s data mode./n",

              test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_JOURNAL_DATA ? "journal":

              test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA ? "ordered":

              "writeback");

 

       return sb;

 

failed_mount3:

       journal_destroy(sbi->s_journal);

failed_mount2:

       for (i = 0; i < db_count; i++)

              brelse(sbi->s_group_desc[i]);

       kfree(sbi->s_group_desc);

failed_mount:

       ext3_blkdev_remove(sbi);

       brelse(bh);

out_fail:

       return NULL;

}

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值