]> Zhao Yanbai Git Server - minix.git/commitdiff
Support for larger disks.
authorDavid van Moolenbroek <david@minix3.org>
Mon, 21 Dec 2009 11:20:30 +0000 (11:20 +0000)
committerDavid van Moolenbroek <david@minix3.org>
Mon, 21 Dec 2009 11:20:30 +0000 (11:20 +0000)
- MFS, df(1), fsck(1), badblocks(8), de(1x) now compute the
  superblock's s_firstdatazone value if the on-disk value is zero
- mkfs(1) sets s_firstdatazone in the superblock to zero if the
  on-disk field is too small to store the actual value
- more agressive mkfs(1) inode number heuristic, copied from r5261

commands/de/de_diskio.c
commands/simple/badblocks.c
commands/simple/df.c
commands/simple/fsck.c
commands/simple/mkfs.c
servers/mfs/inode.c
servers/mfs/super.c
servers/mfs/super.h

index e14383bd9378a646e09995b86cb19944c4634851..2151c359f1f47f4e25d694cffeacca966b2b59a6 100644 (file)
@@ -188,13 +188,14 @@ void Read_Super_Block( s )
 
   s->inode_blocks = (s->inodes + inodes_per_block - 1) / inodes_per_block;
   s->first_data   = 2 + s->inode_maps + s->zone_maps + s->inode_blocks;
-  if ( s->first_data != super->s_firstdatazone )
+  if ( super->s_firstdatazone_old != 0 &&
+       s->first_data != super->s_firstdatazone_old )
   {
-    if ( s->first_data > super->s_firstdatazone )
+    if ( s->first_data > super->s_firstdatazone_old )
       Error( "Corrupted first data zone offset or inode count in super block" );
     else
       Warning( "First data zone in super block suspiciously high" );
-    s->first_data = super->s_firstdatazone;
+    s->first_data = super->s_firstdatazone_old;
   }  
 
   s->inodes_in_map = s->inodes + 1;
@@ -209,7 +210,7 @@ void Read_Super_Block( s )
 
   if ( super->s_log_zone_size != 0 )
     Error( "Can not handle multiple blocks per zone" );
-  }
+}
 
 
 
index 5acbdbc27bae591dab09f10655cc885c6385df34..cfa1c23c0c7d135640f1b6706b6dd37e7ed41ce8 100644 (file)
@@ -170,7 +170,7 @@ int rw_mode;
 
   i_num = stat_ptr->st_ino;
 
-  blk = (block_t) (2 + sp->s_imap_blocks + sp->s_zmap_blocks);
+  blk = (block_t) (START_BLOCK + sp->s_imap_blocks + sp->s_zmap_blocks);
   blk += (block_t) ((i_num - 1) / inodes_per_block);
   blk *= (block_t) (BLOCK_SIZE);/* this block */
 
@@ -334,6 +334,14 @@ char *argv[];
        inode_size = V2_INODE_SIZE;
   }
 
+  /* If the s_firstdatazone_old field is zero, we have to compute the value. */
+  if (sp->s_firstdatazone_old == 0)
+       sp->s_firstdatazone =
+               START_BLOCK + sp->s_imap_blocks + sp->s_zmap_blocks +
+               (sp->s_ninodes + inodes_per_block - 1) / inodes_per_block;
+  else
+       sp->s_firstdatazone = sp->s_firstdatazone_old;
+
   get_inode(&stat_buf);
 
   for (finished = 0; !finished;) {
@@ -481,7 +489,7 @@ block_t num;
   offset = z_num - (blk << BIT_MAP_SHIFT);     /* offset */
   words = z_num / INT_BITS;    /* which word */
 
-  blk_offset = (block_t) (2 + sp->s_imap_blocks);      /* zone map */
+  blk_offset = (block_t) (START_BLOCK + sp->s_imap_blocks);    /* zone map */
   blk_offset *= (block_t) BLOCK_SIZE;  /* of course in block */
   blk_offset += (block_t) (words * SIZE_OF_INT);       /* offset */
 
@@ -520,7 +528,7 @@ zone_t num;
   offset = z_num - (blk << BIT_MAP_SHIFT);     /* offset in block */
   words = z_num / INT_BITS;    /* which word */
 
-  blk_offset = (long) (2 + sp->s_imap_blocks);
+  blk_offset = (long) (START_BLOCK + sp->s_imap_blocks);
   blk_offset *= (long) BLOCK_SIZE;
   blk_offset += (long) (words * SIZE_OF_INT);
 
index 5379e94e16eeaf144dbafc141370d330f3956ed5..8231279606dbd5a99c9a3de30379baac2ef8cf9f 100644 (file)
@@ -271,7 +271,7 @@ int df(const struct mtab *mt)
 {
   int fd;
   bit_t i_count, z_count;
-  block_t totblocks, busyblocks;
+  block_t totblocks, busyblocks, offset;
   int n, block_size;
   struct v12_super_block super, *sp;
 
@@ -300,7 +300,7 @@ int df(const struct mtab *mt)
   }
 
   if(sp->s_magic != SUPER_V3) block_size = _STATIC_BLOCK_SIZE;
-  else block_size = super.s_block_size;
+  else block_size = sp->s_block_size;
 
   if(block_size < _MIN_BLOCK_SIZE) {
        fprintf(stderr, "df: %s: funny block size (%d)\n",
@@ -309,7 +309,24 @@ int df(const struct mtab *mt)
        return(1);
   }
 
-  if (sp->s_magic == SUPER_V1) sp->s_zones= sp->s_nzones;
+  if (sp->s_magic == SUPER_V1) {
+       sp->s_zones = sp->s_nzones;
+       sp->s_inodes_per_block = V1_INODES_PER_BLOCK;
+  } else {
+       sp->s_inodes_per_block = V2_INODES_PER_BLOCK(block_size);
+  }
+
+  /* If the s_firstdatazone_old field is zero, we have to compute the value. */
+  if (sp->s_firstdatazone_old == 0) {
+       offset = START_BLOCK + sp->s_imap_blocks + sp->s_zmap_blocks;
+       offset += (sp->s_ninodes + sp->s_inodes_per_block - 1) /
+               sp->s_inodes_per_block;
+
+       sp->s_firstdatazone = (offset + (1 << sp->s_log_zone_size) - 1) >>
+               sp->s_log_zone_size;
+  } else {
+       sp->s_firstdatazone = sp->s_firstdatazone_old;
+  }
 
   lseek(fd, (off_t) block_size * 2L, SEEK_SET);        /* skip rest of super block */
 
index 7e63abf04a7f9823b40a25d32b885b1d545b419f..371c012af641362a0f15a3a289a7ceef245f7c50 100644 (file)
@@ -528,8 +528,8 @@ void lsuper()
        if (input(buf, 80)) sb.s_imap_blocks = atol(buf);
        printf("zmap_blocks   = %u", sb.s_zmap_blocks);
        if (input(buf, 80)) sb.s_zmap_blocks = atol(buf);
-       printf("firstdatazone = %u", sb.s_firstdatazone);
-       if (input(buf, 80)) sb.s_firstdatazone = atol(buf);
+       printf("firstdatazone = %u", sb.s_firstdatazone_old);
+       if (input(buf, 80)) sb.s_firstdatazone_old = atol(buf);
        printf("log_zone_size = %u", sb.s_log_zone_size);
        if (input(buf, 80)) sb.s_log_zone_size = atol(buf);
        printf("maxsize       = %ld", sb.s_max_size);
@@ -569,12 +569,12 @@ void getsuper()
   if (sb.s_zones <= 0) fatal("no zones");
   if (sb.s_imap_blocks <= 0) fatal("no imap");
   if (sb.s_zmap_blocks <= 0) fatal("no zmap");
-  if (sb.s_firstdatazone <= 4) fatal("first data zone too small");
+  if (sb.s_firstdatazone != 0 && sb.s_firstdatazone <= 4)
+       fatal("first data zone too small");
   if (sb.s_log_zone_size < 0) fatal("zone size < block size");
   if (sb.s_max_size <= 0) {
-       printf("max file size %ld ", sb.s_max_size);
+       printf("warning: invalid max file size %ld\n", sb.s_max_size);
        sb.s_max_size = LONG_MAX;
-       printf("set to %ld\n", sb.s_max_size);
   }
 }
 
@@ -602,17 +602,22 @@ void chksuper()
        pr("warning: expected %d zmap_block%s", n, "", "s");
        printf(" instead of %d\n", sb.s_zmap_blocks);
   }
-  if (sb.s_firstdatazone >= sb.s_zones)
-       fatal("first data zone too large");
   if (sb.s_log_zone_size >= 8 * sizeof(block_nr))
        fatal("log_zone_size too large");
   if (sb.s_log_zone_size > 8) printf("warning: large log_zone_size (%d)\n",
               sb.s_log_zone_size);
-  n = (BLK_ILIST + N_ILIST + SCALE - 1) >> sb.s_log_zone_size;
-  if (sb.s_firstdatazone < n) fatal("first data zone too small");
-  if (sb.s_firstdatazone != n) {
-       printf("warning: expected first data zone to be %d ", n);
-       printf("instead of %u\n", sb.s_firstdatazone);
+  sb.s_firstdatazone = (BLK_ILIST + N_ILIST + SCALE - 1) >> sb.s_log_zone_size;
+  if (sb.s_firstdatazone_old != 0) {
+       if (sb.s_firstdatazone_old >= sb.s_zones)
+               fatal("first data zone too large");
+       if (sb.s_firstdatazone_old < sb.s_firstdatazone)
+               fatal("first data zone too small");
+       if (sb.s_firstdatazone_old != sb.s_firstdatazone) {
+               printf("warning: expected first data zone to be %u ",
+                       sb.s_firstdatazone);
+               printf("instead of %u\n", sb.s_firstdatazone_old);
+               sb.s_firstdatazone = sb.s_firstdatazone_old;
+       }
   }
   maxsize = MAX_FILE_POS;
   if (((maxsize - 1) >> sb.s_log_zone_size) / block_size >= MAX_ZONES)
@@ -627,12 +632,12 @@ void chksuper()
 
 int inoblock(int inn)
 {
-       return div64u(mul64u(inn - 1, INODE_SIZE), block_size) + BLK_ILIST;
+  return div64u(mul64u(inn - 1, INODE_SIZE), block_size) + BLK_ILIST;
 }
 
 int inooff(int inn)
 {
-       return rem64u(mul64u(inn - 1, INODE_SIZE), block_size);
+  return rem64u(mul64u(inn - 1, INODE_SIZE), block_size);
 }
 
 /* Make a listing of the inodes given by `clist'.  If `repair' is set, ask
index 236293af852407aece06d840f132ad7df90b66e6..dcac038a6a4382e02abd74c402654bf72283a78b 100644 (file)
@@ -270,12 +270,9 @@ char *argv[];
                if (blocks == 0) pexit("Can't open prototype file");
        }
        if (i == 0) {
-               i = blocks / 2;
-               if (blocks >= 20000) i = blocks / 3;
-               if (blocks >= 40000) i = blocks / 4;
-               if (blocks >= 60000) i = blocks / 5;
-               if (blocks >= 80000) i = blocks / 6;
-               if (blocks >= 100000) i = blocks / 7;
+               u32_t kb = div64u(mul64u(blocks, block_size), 1024);
+               i = kb / 2;
+               if (kb >= 100000) i = kb / 4;
 
                /* round up to fill inode block */
                i += inodes_per_block - 1;
@@ -462,15 +459,21 @@ ino_t inodes;
        fprintf(stderr, "mkfs: too many block bitmap blocks.\n" BIGGERBLOCKS);
        exit(1);
   }
-  inode_offset = sup->s_imap_blocks + sup->s_zmap_blocks + 2;
+  inode_offset = START_BLOCK + sup->s_imap_blocks + sup->s_zmap_blocks;
   inodeblks = (inodes + inodes_per_block - 1) / inodes_per_block;
   initblks = inode_offset + inodeblks;
-  sup->s_firstdatazone = nb = (initblks + (1 << zone_shift) - 1) >> zone_shift;
+  sup->s_firstdatazone_old = nb =
+       (initblks + (1 << zone_shift) - 1) >> zone_shift;
   if(nb >= zones) pexit("bit maps too large");
-  if(nb != sup->s_firstdatazone) {
-       fprintf(stderr, "mkfs: too much bitmap and inode data.\n" BIGGERBLOCKS);
-       exit(1);
+  if(nb != sup->s_firstdatazone_old) {
+       /* The field is too small to store the value. Fortunately, the value
+        * can be computed from other fields. We set the on-disk field to zero
+        * to indicate that it must not be used. Eventually, we can always set
+        * the on-disk field to zero, and stop using it.
+        */
+       sup->s_firstdatazone_old = 0;
   }
+  sup->s_firstdatazone = nb;
   zoff = sup->s_firstdatazone - 1;
   sup->s_log_zone_size = zone_shift;
   if (fs_version == 1) {
@@ -508,7 +511,7 @@ ino_t inodes;
   }
 
   /* Clear maps and inodes. */
-  for (i = 2; i < initblks; i++) put_block((block_t) i, zero);
+  for (i = START_BLOCK; i < initblks; i++) put_block((block_t) i, zero);
 
   next_zone = sup->s_firstdatazone;
   next_inode = 1;
index 4f044dcd208f10392ed5e566fd0065b2b044fdb3..214d8b057025dfdb5d06f7ea763c1a68a85341b6 100644 (file)
@@ -385,7 +385,7 @@ int rw_flag;                        /* READING or WRITING */
   /* Get the block where the inode resides. */
   sp = get_super(rip->i_dev);  /* get pointer to super block */
   rip->i_sp = sp;              /* inode must contain super block pointer */
-  offset = sp->s_imap_blocks + sp->s_zmap_blocks + 2;
+  offset = START_BLOCK + sp->s_imap_blocks + sp->s_zmap_blocks;
   b = (block_t) (rip->i_num - 1)/sp->s_inodes_per_block + offset;
   bp = get_block(rip->i_dev, b, NORMAL);
   dip  = bp->b_v1_ino + (rip->i_num - 1) % V1_INODES_PER_BLOCK;
index 45090a2500f1c8608e4d4c09f6e42fcd24e6aaf6..52ea86a961a0caf2e3a496ca791ff509e4ac6804 100644 (file)
@@ -183,6 +183,7 @@ register struct super_block *sp; /* pointer to a superblock */
   int magic;
   int version, native, r;
   static char *sbbuf;
+  block_t offset;
 
   STATICINIT(sbbuf, _MIN_BLOCK_SIZE);
 
@@ -215,14 +216,14 @@ register struct super_block *sp; /* pointer to a superblock */
 
   /* If the super block has the wrong byte order, swap the fields; the magic
    * number doesn't need conversion. */
-  sp->s_ninodes =       conv4(native, sp->s_ninodes);
-  sp->s_nzones =        conv2(native, (int) sp->s_nzones);
-  sp->s_imap_blocks =   conv2(native, (int) sp->s_imap_blocks);
-  sp->s_zmap_blocks =   conv2(native, (int) sp->s_zmap_blocks);
-  sp->s_firstdatazone = conv2(native, (int) sp->s_firstdatazone);
-  sp->s_log_zone_size = conv2(native, (int) sp->s_log_zone_size);
-  sp->s_max_size =      conv4(native, sp->s_max_size);
-  sp->s_zones =         conv4(native, sp->s_zones);
+  sp->s_ninodes =           conv4(native, sp->s_ninodes);
+  sp->s_nzones =            conv2(native, (int) sp->s_nzones);
+  sp->s_imap_blocks =       conv2(native, (int) sp->s_imap_blocks);
+  sp->s_zmap_blocks =       conv2(native, (int) sp->s_zmap_blocks);
+  sp->s_firstdatazone_old = conv2(native, (int) sp->s_firstdatazone_old);
+  sp->s_log_zone_size =     conv2(native, (int) sp->s_log_zone_size);
+  sp->s_max_size =          conv4(native, sp->s_max_size);
+  sp->s_zones =             conv4(native, sp->s_zones);
 
   /* In V1, the device size was kept in a short, s_nzones, which limited
    * devices to 32K zones.  For V2, it was decided to keep the size as a
@@ -252,6 +253,21 @@ register struct super_block *sp; /* pointer to a superblock */
        sp->s_nindirs = V2_INDIRECTS(sp->s_block_size);
   }
 
+  /* For even larger disks, a similar problem occurs with s_firstdatazone.
+   * If the on-disk field contains zero, we assume that the value was too
+   * large to fit, and compute it on the fly.
+   */
+  if (sp->s_firstdatazone_old == 0) {
+       offset = START_BLOCK + sp->s_imap_blocks + sp->s_zmap_blocks;
+       offset += (sp->s_ninodes + sp->s_inodes_per_block - 1) /
+               sp->s_inodes_per_block;
+
+       sp->s_firstdatazone = (offset + (1 << sp->s_log_zone_size) - 1) >>
+               sp->s_log_zone_size;
+  } else {
+       sp->s_firstdatazone = sp->s_firstdatazone_old;
+  }
+
   if (sp->s_block_size < _MIN_BLOCK_SIZE) 
        return(EINVAL);
   
index 42bea7cb864e6a28f6a6da7db103008f4e8df259..4336bfd90d27b5a50ad46029ef40c27a4d0466c4 100644 (file)
@@ -23,7 +23,7 @@ EXTERN struct super_block {
   zone1_t  s_nzones;           /* total device size, including bit maps etc */
   short s_imap_blocks;         /* # of blocks used by inode bit map */
   short s_zmap_blocks;         /* # of blocks used by zone bit map */
-  zone1_t s_firstdatazone;     /* number of first data zone */
+  zone1_t s_firstdatazone_old; /* number of first data zone (small) */
   short s_log_zone_size;       /* log2 of blocks/zone */
   short s_pad;                 /* try to avoid compiler-dependent padding */
   off_t s_max_size;            /* maximum file size on this device */
@@ -45,6 +45,7 @@ EXTERN struct super_block {
   /*struct inode *s_isup;*/    /* inode for root dir of mounted file sys */
   /*struct inode *s_imount;*/   /* inode mounted on */
   unsigned s_inodes_per_block; /* precalculated from magic number */
+  zone_t s_firstdatazone;      /* number of first data zone (big) */
   dev_t s_dev;                 /* whose super block is this? */
   int s_rd_only;               /* set to 1 iff file sys mounted read only */
   int s_native;                        /* set to 1 iff not byte swapped file system */