Support for larger disks.
- 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
This commit is contained in:
parent
6aa43dc9e4
commit
d5dee93bee
8 changed files with 97 additions and 46 deletions
|
@ -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" );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in a new issue