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;
if ( super->s_log_zone_size != 0 )
Error( "Can not handle multiple blocks per zone" );
- }
+}
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 */
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;) {
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 */
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);
{
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;
}
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",
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 */
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);
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);
}
}
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)
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
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;
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) {
}
/* 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;
/* 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;
int magic;
int version, native, r;
static char *sbbuf;
+ block_t offset;
STATICINIT(sbbuf, _MIN_BLOCK_SIZE);
/* 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
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);
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 */
/*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 */