home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.0 / LINUX-1.0 / LINUX-1 / linux / fs / ext2 / super.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-03-10  |  18.9 KB  |  678 lines

  1. /*
  2.  *  linux/fs/ext2/super.c
  3.  *
  4.  *  Copyright (C) 1992, 1993, 1994  Remy Card (card@masi.ibp.fr)
  5.  *                                  Laboratoire MASI - Institut Blaise Pascal
  6.  *                                  Universite Pierre et Marie Curie (Paris VI)
  7.  *
  8.  *  from
  9.  *
  10.  *  linux/fs/minix/inode.c
  11.  *
  12.  *  Copyright (C) 1991, 1992  Linus Torvalds
  13.  */
  14.  
  15. #include <stdarg.h>
  16.  
  17. #include <asm/segment.h>
  18. #include <asm/system.h>
  19.  
  20. #include <linux/errno.h>
  21. #include <linux/fs.h>
  22. #include <linux/ext2_fs.h>
  23. #include <linux/sched.h>
  24. #include <linux/stat.h>
  25. #include <linux/string.h>
  26. #include <linux/locks.h>
  27.  
  28. extern int vsprintf (char *, const char *, va_list);
  29.  
  30. void ext2_error (struct super_block * sb, const char * function,
  31.          const char * fmt, ...)
  32. {
  33.     char buf[1024];
  34.     va_list args;
  35.  
  36.     if (!(sb->s_flags & MS_RDONLY)) {
  37.         sb->u.ext2_sb.s_mount_state |= EXT2_ERROR_FS;
  38.         sb->u.ext2_sb.s_es->s_state |= EXT2_ERROR_FS;
  39.         sb->u.ext2_sb.s_sbh->b_dirt = 1;
  40.         sb->s_dirt = 1;
  41.     }
  42.     va_start (args, fmt);
  43.     vsprintf (buf, fmt, args);
  44.     va_end (args);
  45.     if (test_opt (sb, ERRORS_PANIC) ||
  46.         (sb->u.ext2_sb.s_es->s_errors == EXT2_ERRORS_PANIC &&
  47.          !test_opt (sb, ERRORS_CONT) && !test_opt (sb, ERRORS_RO)))
  48.         panic ("EXT2-fs panic (device %d/%d): %s: %s\n",
  49.                MAJOR(sb->s_dev), MINOR(sb->s_dev), function, buf);
  50.     printk (KERN_CRIT "EXT2-fs error (device %d/%d): %s: %s\n",
  51.         MAJOR(sb->s_dev), MINOR(sb->s_dev), function, buf);
  52.     if (test_opt (sb, ERRORS_RO) ||
  53.         (sb->u.ext2_sb.s_es->s_errors == EXT2_ERRORS_RO &&
  54.          !test_opt (sb, ERRORS_CONT) && !test_opt (sb, ERRORS_PANIC))) {
  55.         printk ("Remounting filesystem read-only\n");
  56.         sb->s_flags |= MS_RDONLY;
  57.     }
  58. }
  59.  
  60. NORET_TYPE void ext2_panic (struct super_block * sb, const char * function,
  61.                 const char * fmt, ...)
  62. {
  63.     char buf[1024];
  64.     va_list args;
  65.  
  66.     if (!(sb->s_flags & MS_RDONLY)) {
  67.         sb->u.ext2_sb.s_mount_state |= EXT2_ERROR_FS;
  68.         sb->u.ext2_sb.s_es->s_state |= EXT2_ERROR_FS;
  69.         sb->u.ext2_sb.s_sbh->b_dirt = 1;
  70.         sb->s_dirt = 1;
  71.     }
  72.     va_start (args, fmt);
  73.     vsprintf (buf, fmt, args);
  74.     va_end (args);
  75.     panic ("EXT2-fs panic (device %d/%d): %s: %s\n",
  76.            MAJOR(sb->s_dev), MINOR(sb->s_dev), function, buf);
  77. }
  78.  
  79. void ext2_warning (struct super_block * sb, const char * function,
  80.            const char * fmt, ...)
  81. {
  82.     char buf[1024];
  83.     va_list args;
  84.  
  85.     va_start (args, fmt);
  86.     vsprintf (buf, fmt, args);
  87.     va_end (args);
  88.     printk (KERN_WARNING "EXT2-fs warning (device %d/%d): %s: %s\n",
  89.         MAJOR(sb->s_dev), MINOR(sb->s_dev), function, buf);
  90. }
  91.  
  92. void ext2_put_super (struct super_block * sb)
  93. {
  94.     int i;
  95.  
  96.     lock_super (sb);
  97.     if (!(sb->s_flags & MS_RDONLY)) {
  98.         sb->u.ext2_sb.s_es->s_state = sb->u.ext2_sb.s_mount_state;
  99.         sb->u.ext2_sb.s_sbh->b_dirt = 1;
  100.     }
  101. #ifndef DONT_USE_DCACHE
  102.     ext2_dcache_invalidate (sb->s_dev);
  103. #endif
  104.     sb->s_dev = 0;
  105.     for (i = 0; i < EXT2_MAX_GROUP_DESC; i++)
  106.         if (sb->u.ext2_sb.s_group_desc[i])
  107.             brelse (sb->u.ext2_sb.s_group_desc[i]);
  108.     for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++)
  109.         if (sb->u.ext2_sb.s_inode_bitmap[i])
  110.             brelse (sb->u.ext2_sb.s_inode_bitmap[i]);
  111.     for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++)
  112.         if (sb->u.ext2_sb.s_block_bitmap[i])
  113.             brelse (sb->u.ext2_sb.s_block_bitmap[i]);
  114.     brelse (sb->u.ext2_sb.s_sbh);
  115.     unlock_super (sb);
  116.     return;
  117. }
  118.  
  119. static struct super_operations ext2_sops = { 
  120.     ext2_read_inode,
  121.     NULL,
  122.     ext2_write_inode,
  123.     ext2_put_inode,
  124.     ext2_put_super,
  125.     ext2_write_super,
  126.     ext2_statfs,
  127.     ext2_remount
  128. };
  129.  
  130. #ifdef EXT2FS_PRE_02B_COMPAT
  131.  
  132. static int convert_pre_02b_fs (struct super_block * sb,
  133.                    struct buffer_head * bh)
  134. {
  135.     struct ext2_super_block * es;
  136.     struct ext2_old_group_desc old_group_desc [BLOCK_SIZE / sizeof (struct ext2_old_group_desc)];
  137.     struct ext2_group_desc * gdp;
  138.     struct buffer_head * bh2;
  139.     int groups_count;
  140.     int i;
  141.  
  142.     es = (struct ext2_super_block *) bh->b_data;
  143.     bh2 = bread (sb->s_dev, 2, BLOCK_SIZE);
  144.     if (!bh2) {
  145.         printk ("Cannot read descriptor blocks while converting !\n");
  146.         return 0;
  147.     }
  148.     memcpy (old_group_desc, bh2->b_data, BLOCK_SIZE);
  149.     groups_count = (sb->u.ext2_sb.s_blocks_count - 
  150.             sb->u.ext2_sb.s_first_data_block +
  151.             (EXT2_BLOCK_SIZE(sb) * 8) - 1) /
  152.                 (EXT2_BLOCK_SIZE(sb) * 8);
  153.     memset (bh2->b_data, 0, BLOCK_SIZE);
  154.     gdp = (struct ext2_group_desc *) bh2->b_data;
  155.     for (i = 0; i < groups_count; i++) {
  156.         gdp[i].bg_block_bitmap = old_group_desc[i].bg_block_bitmap;
  157.         gdp[i].bg_inode_bitmap = old_group_desc[i].bg_inode_bitmap;
  158.         gdp[i].bg_inode_table = old_group_desc[i].bg_inode_table;
  159.         gdp[i].bg_free_blocks_count = old_group_desc[i].bg_free_blocks_count;
  160.         gdp[i].bg_free_inodes_count = old_group_desc[i].bg_free_inodes_count;
  161.     }
  162.     bh2->b_dirt = 1;
  163.     brelse (bh2);
  164.     es->s_magic = EXT2_SUPER_MAGIC;
  165.     bh->b_dirt = 1;
  166.     sb->s_magic = EXT2_SUPER_MAGIC;
  167.     return 1;
  168. }
  169.  
  170. #endif
  171.  
  172. /*
  173.  * This function has been shamelessly adapted from the msdos fs
  174.  */
  175. static int parse_options (char * options, unsigned long * sb_block,
  176.               unsigned long * mount_options)
  177. {
  178.     char * this_char;
  179.     char * value;
  180.  
  181.     if (!options)
  182.         return 1;
  183.     for (this_char = strtok (options, ",");
  184.          this_char != NULL;
  185.          this_char = strtok (NULL, ",")) {
  186.         if ((value = strchr (this_char, '=')) != NULL)
  187.             *value++ = 0;
  188.         if (!strcmp (this_char, "check")) {
  189.             if (!value || !*value)
  190.                 set_opt (*mount_options, CHECK_NORMAL);
  191.             else if (!strcmp (value, "none")) {
  192.                 clear_opt (*mount_options, CHECK_NORMAL);
  193.                 clear_opt (*mount_options, CHECK_STRICT);
  194.             }
  195.             else if (strcmp (value, "normal"))
  196.                 set_opt (*mount_options, CHECK_NORMAL);
  197.             else if (strcmp (value, "strict")) {
  198.                 set_opt (*mount_options, CHECK_NORMAL);
  199.                 set_opt (*mount_options, CHECK_STRICT);
  200.             }
  201.             else {
  202.                 printk ("EXT2-fs: Invalid check option: %s\n",
  203.                     value);
  204.                 return 0;
  205.             }
  206.         }
  207.         else if (!strcmp (this_char, "debug"))
  208.             set_opt (*mount_options, DEBUG);
  209.         else if (!strcmp (this_char, "errors")) {
  210.             if (!value || !*value) {
  211.                 printk ("EXT2-fs: the errors option requires "
  212.                     "an argument");
  213.                 return 0;
  214.             }
  215.             if (!strcmp (value, "continue")) {
  216.                 clear_opt (*mount_options, ERRORS_RO);
  217.                 clear_opt (*mount_options, ERRORS_PANIC);
  218.                 set_opt (*mount_options, ERRORS_CONT);
  219.             }
  220.             else if (!strcmp (value, "remount-ro")) {
  221.                 clear_opt (*mount_options, ERRORS_CONT);
  222.                 clear_opt (*mount_options, ERRORS_PANIC);
  223.                 set_opt (*mount_options, ERRORS_RO);
  224.             }
  225.             else if (!strcmp (value, "panic")) {
  226.                 clear_opt (*mount_options, ERRORS_CONT);
  227.                 clear_opt (*mount_options, ERRORS_RO);
  228.                 set_opt (*mount_options, ERRORS_PANIC);
  229.             }
  230.             else {
  231.                 printk ("EXT2-fs: Invalid errors option: %s\n",
  232.                     value);
  233.                 return 0;
  234.             }
  235.         }
  236.         else if (!strcmp (this_char, "grpid") ||
  237.              !strcmp (this_char, "bsdgroups"))
  238.             set_opt (*mount_options, GRPID);
  239.         else if (!strcmp (this_char, "nocheck")) {
  240.             clear_opt (*mount_options, CHECK_NORMAL);
  241.             clear_opt (*mount_options, CHECK_STRICT);
  242.         }
  243.         else if (!strcmp (this_char, "nogrpid") ||
  244.              !strcmp (this_char, "sysvgroups"))
  245.             clear_opt (*mount_options, GRPID);
  246.         else if (!strcmp (this_char, "sb")) {
  247.             if (!value || !*value) {
  248.                 printk ("EXT2-fs: the sb option requires "
  249.                     "an argument");
  250.                 return 0;
  251.             }
  252.             *sb_block = simple_strtoul (value, &value, 0);
  253.             if (*value) {
  254.                 printk ("EXT2-fs: Invalid sb option: %s\n",
  255.                     value);
  256.                 return 0;
  257.             }
  258.         }
  259.         else {
  260.             printk ("EXT2-fs: Unrecognized mount option %s\n", this_char);
  261.             return 0;
  262.         }
  263.     }
  264.     return 1;
  265. }
  266.  
  267. static void ext2_setup_super (struct super_block * sb,
  268.                   struct ext2_super_block * es)
  269. {
  270.     if (!(sb->s_flags & MS_RDONLY)) {
  271.         if (!(sb->u.ext2_sb.s_mount_state & EXT2_VALID_FS))
  272.             printk ("EXT2-fs warning: mounting unchecked fs, "
  273.                 "running e2fsck is recommended\n");
  274.         else if ((sb->u.ext2_sb.s_mount_state & EXT2_ERROR_FS))
  275.             printk ("EXT2-fs warning: mounting fs with errors, "
  276.                 "running e2fsck is recommended\n");
  277.         else if (es->s_max_mnt_count >= 0 &&
  278.                  es->s_mnt_count >= (unsigned short) es->s_max_mnt_count)
  279.             printk ("EXT2-fs warning: maximal mount count reached, "
  280.                 "running e2fsck is recommended\n");
  281.         else if (es->s_checkinterval &&
  282.             (es->s_lastcheck + es->s_checkinterval <= CURRENT_TIME))
  283.             printk ("EXT2-fs warning: checktime reached, "
  284.                 "running e2fsck is recommended\n");
  285.         es->s_state &= ~EXT2_VALID_FS;
  286.         if (!es->s_max_mnt_count)
  287.             es->s_max_mnt_count = EXT2_DFL_MAX_MNT_COUNT;
  288.         es->s_mnt_count++;
  289.         es->s_mtime = CURRENT_TIME;
  290.         sb->u.ext2_sb.s_sbh->b_dirt = 1;
  291.         sb->s_dirt = 1;
  292.         if (test_opt (sb, DEBUG))
  293.             printk ("[EXT II FS %s, %s, bs=%lu, fs=%lu, gc=%lu, "
  294.                 "bpg=%lu, ipg=%lu, mo=%04lx]\n",
  295.                 EXT2FS_VERSION, EXT2FS_DATE, sb->s_blocksize,
  296.                 sb->u.ext2_sb.s_frag_size,
  297.                 sb->u.ext2_sb.s_groups_count,
  298.                 EXT2_BLOCKS_PER_GROUP(sb),
  299.                 EXT2_INODES_PER_GROUP(sb),
  300.                 sb->u.ext2_sb.s_mount_opt);
  301.         if (test_opt (sb, CHECK)) {
  302.             ext2_check_blocks_bitmap (sb);
  303.             ext2_check_inodes_bitmap (sb);
  304.         }
  305.     }
  306. }
  307.  
  308. static int ext2_check_descriptors (struct super_block * sb)
  309. {
  310.     int i;
  311.     int desc_block = 0;
  312.     unsigned long block = sb->u.ext2_sb.s_es->s_first_data_block;
  313.     struct ext2_group_desc * gdp = NULL;
  314.  
  315.     ext2_debug ("Checking group descriptors");
  316.  
  317.     for (i = 0; i < sb->u.ext2_sb.s_groups_count; i++)
  318.     {
  319.         if ((i % EXT2_DESC_PER_BLOCK(sb)) == 0)
  320.             gdp = (struct ext2_group_desc *) sb->u.ext2_sb.s_group_desc[desc_block++]->b_data;
  321.         if (gdp->bg_block_bitmap < block ||
  322.             gdp->bg_block_bitmap >= block + EXT2_BLOCKS_PER_GROUP(sb))
  323.         {
  324.             ext2_error (sb, "ext2_check_desciptors",
  325.                     "Block bitmap for group %d"
  326.                     " not in group (block %lu)!",
  327.                     i, gdp->bg_block_bitmap);
  328.             return 0;
  329.         }
  330.         if (gdp->bg_inode_bitmap < block ||
  331.             gdp->bg_inode_bitmap >= block + EXT2_BLOCKS_PER_GROUP(sb))
  332.         {
  333.             ext2_error (sb, "ext2_check_desciptors",
  334.                     "Inode bitmap for group %d"
  335.                     " not in group (block %lu)!",
  336.                     i, gdp->bg_inode_bitmap);
  337.             return 0;
  338.         }
  339.         if (gdp->bg_inode_table < block ||
  340.             gdp->bg_inode_table + sb->u.ext2_sb.s_itb_per_group >=
  341.             block + EXT2_BLOCKS_PER_GROUP(sb))
  342.         {
  343.             ext2_error (sb, "ext2_check_desciptors",
  344.                     "Inode table for group %d"
  345.                     " not in group (block %lu)!",
  346.                     i, gdp->bg_inode_table);
  347.             return 0;
  348.         }
  349.         block += EXT2_BLOCKS_PER_GROUP(sb);
  350.         gdp++;
  351.     }
  352.     return 1;
  353. }
  354.  
  355. struct super_block * ext2_read_super (struct super_block * sb, void * data,
  356.                       int silent)
  357. {
  358.     struct buffer_head * bh;
  359.     struct ext2_super_block * es;
  360.     unsigned long sb_block = 1;
  361.     unsigned long logic_sb_block = 1;
  362.     int dev = sb->s_dev;
  363.     int bh_count;
  364.     int i, j;
  365. #ifdef EXT2FS_PRE_02B_COMPAT
  366.     int fs_converted = 0;
  367. #endif
  368.  
  369.     set_opt (sb->u.ext2_sb.s_mount_opt, CHECK_NORMAL);
  370.     if (!parse_options ((char *) data, &sb_block,
  371.         &sb->u.ext2_sb.s_mount_opt)) {
  372.         sb->s_dev = 0;
  373.         return NULL;
  374.     }
  375.  
  376.     lock_super (sb);
  377.     set_blocksize (dev, BLOCK_SIZE);
  378.     if (!(bh = bread (dev, sb_block, BLOCK_SIZE))) {
  379.         sb->s_dev = 0;
  380.         unlock_super (sb);
  381.         printk ("EXT2-fs: unable to read superblock\n");
  382.         return NULL;
  383.     }
  384.     /*
  385.      * Note: s_es must be initialized s_es as soon as possible because
  386.      * some ext2 macro-instructions depend on its value
  387.      */
  388.     es = (struct ext2_super_block *) bh->b_data;
  389.     sb->u.ext2_sb.s_es = es;
  390.     sb->s_magic = es->s_magic;
  391.     if (sb->s_magic != EXT2_SUPER_MAGIC
  392. #ifdef EXT2FS_PRE_02B_COMPAT
  393.        && sb->s_magic != EXT2_PRE_02B_MAGIC
  394. #endif
  395.        ) {
  396.         sb->s_dev = 0;
  397.         unlock_super (sb);
  398.         brelse (bh);
  399.         if (!silent)
  400.             printk ("VFS: Can't find an ext2 filesystem on dev %d/%d.\n",
  401.                 MAJOR(dev), MINOR(dev));
  402.         return NULL;
  403.     }
  404.     sb->s_blocksize = EXT2_MIN_BLOCK_SIZE << es->s_log_block_size;
  405.     sb->s_blocksize_bits = EXT2_BLOCK_SIZE_BITS(sb);
  406.     if (sb->s_blocksize != BLOCK_SIZE && 
  407.         (sb->s_blocksize == 1024 || sb->s_blocksize == 2048 ||  
  408.          sb->s_blocksize == 4096)) {
  409.         unsigned long offset;
  410.  
  411.         brelse (bh);
  412.         set_blocksize (dev, sb->s_blocksize);
  413.         logic_sb_block = sb_block / sb->s_blocksize;
  414.         offset = sb_block % sb->s_blocksize;
  415.         bh = bread (dev, logic_sb_block, sb->s_blocksize);
  416.         if(!bh)
  417.             return NULL;
  418.         es = (struct ext2_super_block *) (((char *)bh->b_data) + offset);
  419.         sb->u.ext2_sb.s_es = es;
  420.         if (es->s_magic != EXT2_SUPER_MAGIC) {
  421.             sb->s_dev = 0;
  422.             unlock_super (sb);
  423.             brelse (bh);
  424.             printk ("EXT2-fs: Magic mismatch, very weird !\n");
  425.             return NULL;
  426.         }
  427.     }
  428.     sb->u.ext2_sb.s_frag_size = EXT2_MIN_FRAG_SIZE <<
  429.                    es->s_log_frag_size;
  430.     if (sb->u.ext2_sb.s_frag_size)
  431.         sb->u.ext2_sb.s_frags_per_block = sb->s_blocksize /
  432.                           sb->u.ext2_sb.s_frag_size;
  433.     else
  434.         sb->s_magic = 0;
  435.     sb->u.ext2_sb.s_blocks_per_group = es->s_blocks_per_group;
  436.     sb->u.ext2_sb.s_frags_per_group = es->s_frags_per_group;
  437.     sb->u.ext2_sb.s_inodes_per_group = es->s_inodes_per_group;
  438.     sb->u.ext2_sb.s_inodes_per_block = sb->s_blocksize /
  439.                        sizeof (struct ext2_inode);
  440.     sb->u.ext2_sb.s_itb_per_group = sb->u.ext2_sb.s_inodes_per_group /
  441.                         sb->u.ext2_sb.s_inodes_per_block;
  442.     sb->u.ext2_sb.s_desc_per_block = sb->s_blocksize /
  443.                      sizeof (struct ext2_group_desc);
  444.     sb->u.ext2_sb.s_sbh = bh;
  445.     sb->u.ext2_sb.s_es = es;
  446.     sb->u.ext2_sb.s_mount_state = es->s_state;
  447.     sb->u.ext2_sb.s_rename_lock = 0;
  448.     sb->u.ext2_sb.s_rename_wait = NULL;
  449. #ifdef EXT2FS_PRE_02B_COMPAT
  450.     if (sb->s_magic == EXT2_PRE_02B_MAGIC) {
  451.         if (es->s_blocks_count > 262144) {
  452.             /*
  453.              * fs > 256 MB can't be converted
  454.              */ 
  455.             sb->s_dev = 0;
  456.             unlock_super (sb);
  457.             brelse (bh);
  458.             printk ("EXT2-fs: trying to mount a pre-0.2b file"
  459.                 "system which cannot be converted\n");
  460.             return NULL;
  461.         }
  462.         printk ("EXT2-fs: mounting a pre 0.2b file system, "
  463.             "will try to convert the structure\n");
  464.         if (!(sb->s_flags & MS_RDONLY)) {
  465.             sb->s_dev = 0;
  466.             unlock_super (sb);
  467.             brelse (bh);
  468.             printk ("EXT2-fs: cannot convert a read-only fs\n");
  469.             return NULL;
  470.         }
  471.         if (!convert_pre_02b_fs (sb, bh)) {
  472.             sb->s_dev = 0;
  473.             unlock_super (sb);
  474.             brelse (bh);
  475.             printk ("EXT2-fs: conversion failed !!!\n");
  476.             return NULL;
  477.         }
  478.         printk ("EXT2-fs: conversion succeeded !!!\n");
  479.         fs_converted = 1;
  480.     }
  481. #endif
  482.     if (sb->s_magic != EXT2_SUPER_MAGIC) {
  483.         sb->s_dev = 0;
  484.         unlock_super (sb);
  485.         brelse (bh);
  486.         if (!silent)
  487.             printk ("VFS: Can't find an ext2 filesystem on dev %d/%d.\n",
  488.                 MAJOR(dev), MINOR(dev));
  489.         return NULL;
  490.     }
  491.     if (sb->s_blocksize != bh->b_size) {
  492.         sb->s_dev = 0;
  493.         unlock_super (sb);
  494.         brelse (bh);
  495.         if (!silent)
  496.             printk ("VFS: Unsupported blocksize on dev 0x%04x.\n",
  497.                 dev);
  498.         return NULL;
  499.     }
  500.  
  501.     if (sb->s_blocksize != sb->u.ext2_sb.s_frag_size) {
  502.         sb->s_dev = 0;
  503.         unlock_super (sb);
  504.         brelse (bh);
  505.         printk ("EXT2-fs: fragsize %lu != blocksize %lu (not supported yet)\n",
  506.             sb->u.ext2_sb.s_frag_size, sb->s_blocksize);
  507.         return NULL;
  508.     }
  509.  
  510.     sb->u.ext2_sb.s_groups_count = (es->s_blocks_count -
  511.                         es->s_first_data_block +
  512.                        EXT2_BLOCKS_PER_GROUP(sb) - 1) /
  513.                        EXT2_BLOCKS_PER_GROUP(sb);
  514.     for (i = 0; i < EXT2_MAX_GROUP_DESC; i++)
  515.         sb->u.ext2_sb.s_group_desc[i] = NULL;
  516.     bh_count = (sb->u.ext2_sb.s_groups_count + EXT2_DESC_PER_BLOCK(sb) - 1) /
  517.            EXT2_DESC_PER_BLOCK(sb);
  518.     if (bh_count > EXT2_MAX_GROUP_DESC) {
  519.         sb->s_dev = 0;
  520.         unlock_super (sb);
  521.         brelse (bh);
  522.         printk ("EXT2-fs: file system is too big\n");
  523.         return NULL;
  524.     }
  525.     for (i = 0; i < bh_count; i++) {
  526.         sb->u.ext2_sb.s_group_desc[i] = bread (dev, logic_sb_block + i + 1,
  527.                                sb->s_blocksize);
  528.         if (!sb->u.ext2_sb.s_group_desc[i]) {
  529.             sb->s_dev = 0;
  530.             unlock_super (sb);
  531.             for (j = 0; j < i; j++)
  532.                 brelse (sb->u.ext2_sb.s_group_desc[j]);
  533.             brelse (bh);
  534.             printk ("EXT2-fs: unable to read group descriptors\n");
  535.             return NULL;
  536.         }
  537.     }
  538.     if (!ext2_check_descriptors (sb)) {
  539.         sb->s_dev = 0;
  540.         unlock_super (sb);
  541.         for (j = 0; j < i; j++)
  542.             brelse (sb->u.ext2_sb.s_group_desc[j]);
  543.         brelse (bh);
  544.         printk ("EXT2-fs: group descriptors corrupted !\n");
  545.         return NULL;
  546.     }
  547.     for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++) {
  548.         sb->u.ext2_sb.s_inode_bitmap_number[i] = 0;
  549.         sb->u.ext2_sb.s_inode_bitmap[i] = NULL;
  550.         sb->u.ext2_sb.s_block_bitmap_number[i] = 0;
  551.         sb->u.ext2_sb.s_block_bitmap[i] = NULL;
  552.     }
  553.     sb->u.ext2_sb.s_loaded_inode_bitmaps = 0;
  554.     sb->u.ext2_sb.s_loaded_block_bitmaps = 0;
  555.     unlock_super (sb);
  556.     /*
  557.      * set up enough so that it can read an inode
  558.      */
  559.     sb->s_dev = dev;
  560.     sb->s_op = &ext2_sops;
  561.     if (!(sb->s_mounted = iget (sb, EXT2_ROOT_INO))) {
  562.         sb->s_dev = 0;
  563.         for (i = 0; i < EXT2_MAX_GROUP_DESC; i++)
  564.             if (sb->u.ext2_sb.s_group_desc[i])
  565.                 brelse (sb->u.ext2_sb.s_group_desc[i]);
  566.         brelse (bh);
  567.         printk ("EXT2-fs: get root inode failed\n");
  568.         return NULL;
  569.     }
  570. #ifdef EXT2FS_PRE_02B_COMPAT
  571.     if (fs_converted) {
  572.         for (i = 0; i < bh_count; i++)
  573.             sb->u.ext2_sb.s_group_desc[i]->b_dirt = 1;
  574.         sb->s_dirt = 1;
  575.     }
  576. #endif
  577.     ext2_setup_super (sb, es);
  578.     return sb;
  579. }
  580.  
  581. static void ext2_commit_super (struct super_block * sb,
  582.                    struct ext2_super_block * es)
  583. {
  584.     es->s_wtime = CURRENT_TIME;
  585.     sb->u.ext2_sb.s_sbh->b_dirt = 1;
  586.     sb->s_dirt = 0;
  587. }
  588.  
  589. /*
  590.  * In the second extended file system, it is not necessary to
  591.  * write the super block since we use a mapping of the
  592.  * disk super block in a buffer.
  593.  *
  594.  * However, this function is still used to set the fs valid
  595.  * flags to 0.  We need to set this flag to 0 since the fs
  596.  * may have been checked while mounted and e2fsck may have
  597.  * set s_state to EXT2_VALID_FS after some corrections.
  598.  */
  599.  
  600. void ext2_write_super (struct super_block * sb)
  601. {
  602.     struct ext2_super_block * es;
  603.  
  604.     if (!(sb->s_flags & MS_RDONLY)) {
  605.         es = sb->u.ext2_sb.s_es;
  606.  
  607.         ext2_debug ("setting valid to 0\n");
  608.  
  609.         if (es->s_state & EXT2_VALID_FS) {
  610.             es->s_state &= ~EXT2_VALID_FS;
  611.             es->s_mtime = CURRENT_TIME;
  612.         }
  613.         ext2_commit_super (sb, es);
  614.     }
  615.     sb->s_dirt = 0;
  616. }
  617.  
  618. int ext2_remount (struct super_block * sb, int * flags, char * data)
  619. {
  620.     struct ext2_super_block * es;
  621.     unsigned long tmp;
  622.  
  623.     /*
  624.      * Allow the "check" option to be passed as a remount option.
  625.      */
  626.     set_opt (sb->u.ext2_sb.s_mount_opt, CHECK_NORMAL);
  627.     parse_options (data, &tmp, &sb->u.ext2_sb.s_mount_opt);
  628.  
  629.     es = sb->u.ext2_sb.s_es;
  630.     if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
  631.         return 0;
  632.     if (*flags & MS_RDONLY) {
  633.         if (es->s_state & EXT2_VALID_FS ||
  634.             !(sb->u.ext2_sb.s_mount_state & EXT2_VALID_FS))
  635.             return 0;
  636.         /*
  637.          * OK, we are remounting a valid rw partition rdonly, so set
  638.          * the rdonly flag and then mark the partition as valid again.
  639.          */
  640.         es->s_state = sb->u.ext2_sb.s_mount_state;
  641.         es->s_mtime = CURRENT_TIME;
  642.         sb->u.ext2_sb.s_sbh->b_dirt = 1;
  643.         sb->s_dirt = 1;
  644.         ext2_commit_super (sb, es);
  645.     }
  646.     else {
  647.         /*
  648.          * Mounting a RDONLY partition read-write, so reread and
  649.          * store the current valid flag.  (It may have been changed 
  650.          * by e2fsck since we originally mounted the partition.)
  651.          */
  652.         sb->u.ext2_sb.s_mount_state = es->s_state;
  653.         sb->s_flags &= ~MS_RDONLY;
  654.         ext2_setup_super (sb, es);
  655.     }
  656.     return 0;
  657. }
  658.  
  659. void ext2_statfs (struct super_block * sb, struct statfs * buf)
  660. {
  661.     long tmp;
  662.  
  663.     put_fs_long (EXT2_SUPER_MAGIC, &buf->f_type);
  664.     put_fs_long (sb->s_blocksize, &buf->f_bsize);
  665.     put_fs_long (sb->u.ext2_sb.s_es->s_blocks_count, &buf->f_blocks);
  666.     tmp = ext2_count_free_blocks (sb);
  667.     put_fs_long (tmp, &buf->f_bfree);
  668.     if (tmp >= sb->u.ext2_sb.s_es->s_r_blocks_count)
  669.         put_fs_long (tmp - sb->u.ext2_sb.s_es->s_r_blocks_count,
  670.                  &buf->f_bavail);
  671.     else
  672.         put_fs_long (0, &buf->f_bavail);
  673.     put_fs_long (sb->u.ext2_sb.s_es->s_inodes_count, &buf->f_files);
  674.     put_fs_long (ext2_count_free_inodes (sb), &buf->f_ffree);
  675.     put_fs_long (EXT2_NAME_LEN, &buf->f_namelen);
  676.     /* Don't know what value to put in buf->f_fsid */
  677. }
  678.