* Copyright (c) 1980, 1989, 1993
* The Regents of the University of California. All rights reserved.
* %sccs.include.redist.c%
static char sccsid
[] = "@(#)mkfs.c 8.1 (Berkeley) %G%";
#include <sys/resource.h>
#include <ufs/ufs/dinode.h>
#include <sys/disklabel.h>
* make file system for cylinder-group style file systems
* The size of a cylinder group is calculated by CGSIZE. The maximum size
* is limited by the fact that cylinder groups are at most one block.
* Its size is derived from the size of the maps maintained in the
* cylinder group and the (struct cg) size.
/* base cg */ (sizeof(struct cg) + \
/* blktot size */ (fs)->fs_cpg * sizeof(long) + \
/* blks size */ (fs)->fs_cpg * (fs)->fs_nrpos * sizeof(short) + \
/* inode map */ howmany((fs)->fs_ipg, NBBY) + \
/* block map */ howmany((fs)->fs_cpg * (fs)->fs_spc / NSPF(fs), NBBY))
* We limit the size of the inode map to be no more than a
* third of the cylinder group space, since we must leave at
* least an equal amount of space for the block map.
* N.B.: MAXIPG must be a multiple of INOPB(fs).
#define MAXIPG(fs) roundup((fs)->fs_bsize * NBBY / 3, INOPB(fs))
#define MAXINOPB (MAXBSIZE / sizeof(struct dinode))
#define POWEROF2(num) (((num) & ((num) - 1)) == 0)
* variables set up by front end.
extern int mfs
; /* run as the memory based filesystem */
extern int Nflag
; /* run mkfs without writing file system */
extern int Oflag
; /* format as an 4.3BSD file system */
extern int fssize
; /* file system size */
extern int ntracks
; /* # tracks/cylinder */
extern int nsectors
; /* # sectors/track */
extern int nphyssectors
; /* # sectors/track including spares */
extern int secpercyl
; /* sectors per cylinder */
extern int sectorsize
; /* bytes/sector */
extern int rpm
; /* revolutions/minute of drive */
extern int interleave
; /* hardware sector interleave */
extern int trackskew
; /* sector 0 skew, per track */
extern int headswitch
; /* head switch time, usec */
extern int trackseek
; /* track-to-track seek, usec */
extern int fsize
; /* fragment size */
extern int bsize
; /* block size */
extern int cpg
; /* cylinders/cylinder group */
extern int cpgflg
; /* cylinders/cylinder group flag was given */
extern int minfree
; /* free space threshold */
extern int opt
; /* optimization preference (space or time) */
extern int density
; /* number of bytes per inode */
extern int maxcontig
; /* max contiguous blocks to allocate */
extern int rotdelay
; /* rotational delay between blocks */
extern int maxbpg
; /* maximum blocks per file in a cyl group */
extern int nrpos
; /* # of distinguished rotational positions */
extern int bbsize
; /* boot block size */
extern int sbsize
; /* superblock size */
extern u_long memleft
; /* virtual memory available */
extern caddr_t membase
; /* start address of memory based filesystem */
extern caddr_t
malloc(), calloc();
struct dinode zino
[MAXBSIZE
/ sizeof(struct dinode
)];
register long i
, mincpc
, mincpg
, inospercg
;
long cylno
, rpos
, blk
, j
, warn
= 0;
long used
, mincpgcnt
, bpcg
;
long mapcramped
, inodecramped
;
long postblsize
, rotblsize
, totalsbsize
;
(void) signal(SIGUSR1
, started
);
if (waitpid(i
, &status
, 0) != -1 && WIFEXITED(status
))
exit(WEXITSTATUS(status
));
if (fssize
* sectorsize
> memleft
)
fssize
= (memleft
- 16384) / sectorsize
;
if ((membase
= malloc(fssize
* sectorsize
)) == 0)
sblock
.fs_inodefmt
= FS_42INODEFMT
;
sblock
.fs_maxsymlinklen
= 0;
sblock
.fs_inodefmt
= FS_44INODEFMT
;
sblock
.fs_maxsymlinklen
= MAXSYMLINKLEN
;
* Validate the given file system size.
* Verify that its last block can actually be accessed.
printf("preposterous size %d\n", fssize
), exit(13);
wtfs(fssize
- 1, sectorsize
, (char *)&sblock
);
* collect and verify the sector and track info
sblock
.fs_nsect
= nsectors
;
sblock
.fs_ntrak
= ntracks
;
if (sblock
.fs_ntrak
<= 0)
printf("preposterous ntrak %d\n", sblock
.fs_ntrak
), exit(14);
if (sblock
.fs_nsect
<= 0)
printf("preposterous nsect %d\n", sblock
.fs_nsect
), exit(15);
* collect and verify the block and fragment sizes
if (!POWEROF2(sblock
.fs_bsize
)) {
printf("block size must be a power of 2, not %d\n",
if (!POWEROF2(sblock
.fs_fsize
)) {
printf("fragment size must be a power of 2, not %d\n",
if (sblock
.fs_fsize
< sectorsize
) {
printf("fragment size %d is too small, minimum is %d\n",
sblock
.fs_fsize
, sectorsize
);
if (sblock
.fs_bsize
< MINBSIZE
) {
printf("block size %d is too small, minimum is %d\n",
sblock
.fs_bsize
, MINBSIZE
);
if (sblock
.fs_bsize
< sblock
.fs_fsize
) {
printf("block size (%d) cannot be smaller than fragment size (%d)\n",
sblock
.fs_bsize
, sblock
.fs_fsize
);
sblock
.fs_bmask
= ~(sblock
.fs_bsize
- 1);
sblock
.fs_fmask
= ~(sblock
.fs_fsize
- 1);
sblock
.fs_qbmask
= ~sblock
.fs_bmask
;
sblock
.fs_qfmask
= ~sblock
.fs_fmask
;
for (sblock
.fs_bshift
= 0, i
= sblock
.fs_bsize
; i
> 1; i
>>= 1)
for (sblock
.fs_fshift
= 0, i
= sblock
.fs_fsize
; i
> 1; i
>>= 1)
sblock
.fs_frag
= numfrags(&sblock
, sblock
.fs_bsize
);
for (sblock
.fs_fragshift
= 0, i
= sblock
.fs_frag
; i
> 1; i
>>= 1)
if (sblock
.fs_frag
> MAXFRAG
) {
printf("fragment size %d is too small, minimum with block size %d is %d\n",
sblock
.fs_fsize
, sblock
.fs_bsize
,
sblock
.fs_bsize
/ MAXFRAG
);
sblock
.fs_nindir
= sblock
.fs_bsize
/ sizeof(daddr_t
);
sblock
.fs_inopb
= sblock
.fs_bsize
/ sizeof(struct dinode
);
sblock
.fs_nspf
= sblock
.fs_fsize
/ sectorsize
;
for (sblock
.fs_fsbtodb
= 0, i
= NSPF(&sblock
); i
> 1; i
>>= 1)
roundup(howmany(bbsize
+ sbsize
, sblock
.fs_fsize
), sblock
.fs_frag
);
sblock
.fs_cblkno
= (daddr_t
)(sblock
.fs_sblkno
+
roundup(howmany(sbsize
, sblock
.fs_fsize
), sblock
.fs_frag
));
sblock
.fs_iblkno
= sblock
.fs_cblkno
+ sblock
.fs_frag
;
sblock
.fs_cgoffset
= roundup(
howmany(sblock
.fs_nsect
, NSPF(&sblock
)), sblock
.fs_frag
);
for (sblock
.fs_cgmask
= 0xffffffff, i
= sblock
.fs_ntrak
; i
> 1; i
>>= 1)
if (!POWEROF2(sblock
.fs_ntrak
))
sblock
.fs_maxfilesize
= sblock
.fs_bsize
* NDADDR
- 1;
for (sizepb
= sblock
.fs_bsize
, i
= 0; i
< NIADDR
; i
++) {
sizepb
*= NINDIR(&sblock
);
sblock
.fs_maxfilesize
+= sizepb
;
* Validate specified/determined secpercyl
* and calculate minimum cylinders per group.
sblock
.fs_spc
= secpercyl
;
for (sblock
.fs_cpc
= NSPB(&sblock
), i
= sblock
.fs_spc
;
sblock
.fs_cpc
> 1 && (i
& 1) == 0;
sblock
.fs_cpc
>>= 1, i
>>= 1)
bpcg
= sblock
.fs_spc
* sectorsize
;
inospercg
= roundup(bpcg
/ sizeof(struct dinode
), INOPB(&sblock
));
if (inospercg
> MAXIPG(&sblock
))
inospercg
= MAXIPG(&sblock
);
used
= (sblock
.fs_iblkno
+ inospercg
/ INOPF(&sblock
)) * NSPF(&sblock
);
mincpgcnt
= howmany(sblock
.fs_cgoffset
* (~sblock
.fs_cgmask
) + used
,
mincpg
= roundup(mincpgcnt
, mincpc
);
* Insure that cylinder group with mincpg has enough space
sblock
.fs_ipg
= inospercg
;
while (CGSIZE(&sblock
) > sblock
.fs_bsize
) {
if (sblock
.fs_bsize
< MAXBSIZE
) {
mincpg
= roundup(mincpgcnt
, mincpc
);
sblock
.fs_fragshift
+= 1;
if (sblock
.fs_frag
<= MAXFRAG
)
if (sblock
.fs_fsize
== sblock
.fs_bsize
) {
printf("There is no block size that");
printf(" can support this disk\n");
sblock
.fs_fragshift
-= 1;
* Insure that cylinder group with mincpg has enough space for inodes
inospercg
= roundup((mincpg
* bpcg
- used
) / density
, INOPB(&sblock
));
sblock
.fs_ipg
= inospercg
;
while (inospercg
> MAXIPG(&sblock
)) {
if (mincpc
== 1 || sblock
.fs_frag
== 1 ||
sblock
.fs_bsize
== MINBSIZE
)
printf("With a block size of %d %s %d\n", sblock
.fs_bsize
,
"minimum bytes per inode is",
(mincpg
* bpcg
- used
) / MAXIPG(&sblock
) + 1);
sblock
.fs_fragshift
-= 1;
sblock
.fs_cpg
= roundup(mincpgcnt
, mincpc
);
if (CGSIZE(&sblock
) > sblock
.fs_bsize
) {
roundup((mincpg
* bpcg
- used
) / density
, INOPB(&sblock
));
sblock
.fs_ipg
= inospercg
;
if (inospercg
> MAXIPG(&sblock
)) {
printf("Minimum bytes per inode is %d\n",
(mincpg
* bpcg
- used
) / MAXIPG(&sblock
) + 1);
} else if (!mapcramped
) {
printf("With %d bytes per inode, ", density
);
printf("minimum cylinders per group is %d\n", mincpg
);
printf("With %d sectors per cylinder, ", sblock
.fs_spc
);
printf("minimum cylinders per group is %d\n", mincpg
);
if (inodecramped
|| mapcramped
) {
if (sblock
.fs_bsize
!= bsize
)
printf("%s to be changed from %d to %d\n",
"This requires the block size",
if (sblock
.fs_fsize
!= fsize
)
printf("\t%s to be changed from %d to %d\n",
* Calculate the number of cylinders per group
if (sblock
.fs_cpg
% mincpc
!= 0) {
printf("%s groups must have a multiple of %d cylinders\n",
cpgflg
? "Cylinder" : "Warning: cylinder", mincpc
);
sblock
.fs_cpg
= roundup(sblock
.fs_cpg
, mincpc
);
* Must insure there is enough space for inodes
sblock
.fs_ipg
= roundup((sblock
.fs_cpg
* bpcg
- used
) / density
,
while (sblock
.fs_ipg
> MAXIPG(&sblock
)) {
sblock
.fs_ipg
= roundup((sblock
.fs_cpg
* bpcg
- used
) / density
,
* Must insure there is enough space to hold block map
while (CGSIZE(&sblock
) > sblock
.fs_bsize
) {
sblock
.fs_ipg
= roundup((sblock
.fs_cpg
* bpcg
- used
) / density
,
sblock
.fs_fpg
= (sblock
.fs_cpg
* sblock
.fs_spc
) / NSPF(&sblock
);
if ((sblock
.fs_cpg
* sblock
.fs_spc
) % NSPB(&sblock
) != 0) {
printf("panic (fs_cpg * fs_spc) % NSPF != 0");
if (sblock
.fs_cpg
< mincpg
) {
printf("cylinder groups must have at least %d cylinders\n",
} else if (sblock
.fs_cpg
!= cpg
) {
else if (!mapcramped
&& !inodecramped
)
if (mapcramped
&& inodecramped
)
printf("Block size and bytes per inode restrict");
printf("Block size restricts");
printf("Bytes per inode restrict");
printf(" cylinders per group to %d.\n", sblock
.fs_cpg
);
sblock
.fs_cgsize
= fragroundup(&sblock
, CGSIZE(&sblock
));
* Now have size for file system and nsect and ntrak.
* Determine number of cylinders and blocks in the file system.
sblock
.fs_size
= fssize
= dbtofsb(&sblock
, fssize
);
sblock
.fs_ncyl
= fssize
* NSPF(&sblock
) / sblock
.fs_spc
;
if (fssize
* NSPF(&sblock
) > sblock
.fs_ncyl
* sblock
.fs_spc
) {
if (sblock
.fs_ncyl
< 1) {
printf("file systems must have at least one cylinder\n");
* Determine feasability/values of rotational layout tables.
* The size of the rotational layout tables is limited by the
* size of the superblock, SBSIZE. The amount of space available
* for tables is calculated as (SBSIZE - sizeof (struct fs)).
* The size of these tables is inversely proportional to the block
* size of the file system. The size increases if sectors per track
* are not powers of two, because more cylinders must be described
* by the tables before the rotational pattern repeats (fs_cpc).
sblock
.fs_interleave
= interleave
;
sblock
.fs_trackskew
= trackskew
;
sblock
.fs_npsect
= nphyssectors
;
sblock
.fs_postblformat
= FS_DYNAMICPOSTBLFMT
;
sblock
.fs_sbsize
= fragroundup(&sblock
, sizeof(struct fs
));
if (sblock
.fs_ntrak
== 1) {
postblsize
= sblock
.fs_nrpos
* sblock
.fs_cpc
* sizeof(short);
rotblsize
= sblock
.fs_cpc
* sblock
.fs_spc
/ NSPB(&sblock
);
totalsbsize
= sizeof(struct fs
) + rotblsize
;
if (sblock
.fs_nrpos
== 8 && sblock
.fs_cpc
<= 16) {
/* use old static table space */
sblock
.fs_postbloff
= (char *)(&sblock
.fs_opostbl
[0][0]) -
(char *)(&sblock
.fs_link
);
sblock
.fs_rotbloff
= &sblock
.fs_space
[0] -
(u_char
*)(&sblock
.fs_link
);
/* use dynamic table space */
sblock
.fs_postbloff
= &sblock
.fs_space
[0] -
(u_char
*)(&sblock
.fs_link
);
sblock
.fs_rotbloff
= sblock
.fs_postbloff
+ postblsize
;
totalsbsize
+= postblsize
;
if (totalsbsize
> SBSIZE
||
sblock
.fs_nsect
> (1 << NBBY
) * NSPB(&sblock
)) {
printf("%s %s %d %s %d.%s",
"Warning: insufficient space in super block for\n",
"rotational layout tables with nsect", sblock
.fs_nsect
,
"and ntrak", sblock
.fs_ntrak
,
"\nFile system performance may be impared.\n");
sblock
.fs_sbsize
= fragroundup(&sblock
, totalsbsize
);
* calculate the available blocks for each rotational position
for (cylno
= 0; cylno
< sblock
.fs_cpc
; cylno
++)
for (rpos
= 0; rpos
< sblock
.fs_nrpos
; rpos
++)
fs_postbl(&sblock
, cylno
)[rpos
] = -1;
for (i
= (rotblsize
- 1) * sblock
.fs_frag
;
i
>= 0; i
-= sblock
.fs_frag
) {
cylno
= cbtocylno(&sblock
, i
);
rpos
= cbtorpos(&sblock
, i
);
blk
= fragstoblks(&sblock
, i
);
if (fs_postbl(&sblock
, cylno
)[rpos
] == -1)
fs_rotbl(&sblock
)[blk
] = 0;
fs_postbl(&sblock
, cylno
)[rpos
] - blk
;
fs_postbl(&sblock
, cylno
)[rpos
] = blk
;
* Compute/validate number of cylinder groups.
sblock
.fs_ncg
= sblock
.fs_ncyl
/ sblock
.fs_cpg
;
if (sblock
.fs_ncyl
% sblock
.fs_cpg
)
sblock
.fs_dblkno
= sblock
.fs_iblkno
+ sblock
.fs_ipg
/ INOPF(&sblock
);
i
= MIN(~sblock
.fs_cgmask
, sblock
.fs_ncg
- 1);
if (cgdmin(&sblock
, i
) - cgbase(&sblock
, i
) >= sblock
.fs_fpg
) {
printf("inode blocks/cyl group (%d) >= data blocks (%d)\n",
cgdmin(&sblock
, i
) - cgbase(&sblock
, i
) / sblock
.fs_frag
,
sblock
.fs_fpg
/ sblock
.fs_frag
);
printf("number of cylinders per cylinder group (%d) %s.\n",
sblock
.fs_cpg
, "must be increased");
if ((i
= fssize
- j
* sblock
.fs_fpg
) < sblock
.fs_fpg
&&
cgdmin(&sblock
, j
) - cgbase(&sblock
, j
) > i
) {
printf("Filesystem must have at least %d sectors\n",
(cgdmin(&sblock
, 0) + 3 * sblock
.fs_frag
));
printf("Warning: inode blocks/cyl group (%d) >= data blocks (%d) in last\n",
(cgdmin(&sblock
, j
) - cgbase(&sblock
, j
)) / sblock
.fs_frag
,
printf(" cylinder group. This implies %d sector(s) cannot be allocated.\n",
sblock
.fs_ncyl
-= sblock
.fs_ncyl
% sblock
.fs_cpg
;
sblock
.fs_size
= fssize
= sblock
.fs_ncyl
* sblock
.fs_spc
/
printf("Warning: %d sector(s) in last cylinder unallocated\n",
(fssize
* NSPF(&sblock
) - (sblock
.fs_ncyl
- 1)
* fill in remaining fields of the super block
sblock
.fs_csaddr
= cgdmin(&sblock
, 0);
fragroundup(&sblock
, sblock
.fs_ncg
* sizeof(struct csum
));
i
= sblock
.fs_bsize
/ sizeof(struct csum
);
sblock
.fs_csmask
= ~(i
- 1);
for (sblock
.fs_csshift
= 0; i
> 1; i
>>= 1)
fscs
= (struct csum
*)calloc(1, sblock
.fs_cssize
);
sblock
.fs_magic
= FS_MAGIC
;
sblock
.fs_rotdelay
= rotdelay
;
sblock
.fs_minfree
= minfree
;
sblock
.fs_maxcontig
= maxcontig
;
sblock
.fs_headswitch
= headswitch
;
sblock
.fs_trkseek
= trackseek
;
sblock
.fs_maxbpg
= maxbpg
;
sblock
.fs_rps
= rpm
/ 60;
sblock
.fs_cstotal
.cs_ndir
= 0;
sblock
.fs_cstotal
.cs_nbfree
= 0;
sblock
.fs_cstotal
.cs_nifree
= 0;
sblock
.fs_cstotal
.cs_nffree
= 0;
* Dump out summary information about file system.
printf("%s:\t%d sectors in %d %s of %d tracks, %d sectors\n",
fsys
, sblock
.fs_size
* NSPF(&sblock
), sblock
.fs_ncyl
,
"cylinders", sblock
.fs_ntrak
, sblock
.fs_nsect
);
#define B2MBFACTOR (1 / (1024.0 * 1024.0))
printf("\t%.1fMB in %d cyl groups (%d c/g, %.2fMB/g, %d i/g)\n",
(float)sblock
.fs_size
* sblock
.fs_fsize
* B2MBFACTOR
,
sblock
.fs_ncg
, sblock
.fs_cpg
,
(float)sblock
.fs_fpg
* sblock
.fs_fsize
* B2MBFACTOR
,
* Now build the cylinders group blocks and
* then print out indices of cylinder groups.
printf("super-block backups (for fsck -b #) at:");
for (cylno
= 0; cylno
< sblock
.fs_ncg
; cylno
++) {
printf(" %d,", fsbtodb(&sblock
, cgsblock(&sblock
, cylno
)));
* Now construct the initial file system,
* then write out the super-block.
wtfs((int)SBOFF
/ sectorsize
, sbsize
, (char *)&sblock
);
for (i
= 0; i
< sblock
.fs_cssize
; i
+= sblock
.fs_bsize
)
wtfs(fsbtodb(&sblock
, sblock
.fs_csaddr
+ numfrags(&sblock
, i
)),
sblock
.fs_cssize
- i
< sblock
.fs_bsize
?
sblock
.fs_cssize
- i
: sblock
.fs_bsize
,
* Write out the duplicate super blocks
for (cylno
= 0; cylno
< sblock
.fs_ncg
; cylno
++)
wtfs(fsbtodb(&sblock
, cgsblock(&sblock
, cylno
)),
sbsize
, (char *)&sblock
);
* Update information about this partion in pack
* label, to that it may be updated on disk.
pp
->p_fstype
= FS_BSDFFS
;
pp
->p_fsize
= sblock
.fs_fsize
;
pp
->p_frag
= sblock
.fs_frag
;
pp
->p_cpg
= sblock
.fs_cpg
;
* Notify parent process of success.
* Dissociate from session and tty.
* Initialize a cylinder group.
daddr_t cbase
, d
, dlower
, dupper
, dmax
;
register struct csum
*cs
;
* Determine block bounds for cylinder group.
* Allow space for super block summary information in first
cbase
= cgbase(&sblock
, cylno
);
dmax
= cbase
+ sblock
.fs_fpg
;
if (dmax
> sblock
.fs_size
)
dlower
= cgsblock(&sblock
, cylno
) - cbase
;
dupper
= cgdmin(&sblock
, cylno
) - cbase
;
dupper
+= howmany(sblock
.fs_cssize
, sblock
.fs_fsize
);
if (cylno
== sblock
.fs_ncg
- 1)
acg
.cg_ncyl
= sblock
.fs_ncyl
% sblock
.fs_cpg
;
acg
.cg_ncyl
= sblock
.fs_cpg
;
acg
.cg_niblk
= sblock
.fs_ipg
;
acg
.cg_ndblk
= dmax
- cbase
;
acg
.cg_btotoff
= &acg
.cg_space
[0] - (u_char
*)(&acg
.cg_link
);
acg
.cg_boff
= acg
.cg_btotoff
+ sblock
.fs_cpg
* sizeof(long);
acg
.cg_iusedoff
= acg
.cg_boff
+
sblock
.fs_cpg
* sblock
.fs_nrpos
* sizeof(short);
acg
.cg_freeoff
= acg
.cg_iusedoff
+ howmany(sblock
.fs_ipg
, NBBY
);
acg
.cg_nextfreeoff
= acg
.cg_freeoff
+
howmany(sblock
.fs_cpg
* sblock
.fs_spc
/ NSPF(&sblock
), NBBY
);
for (i
= 0; i
< sblock
.fs_frag
; i
++) {
bzero((caddr_t
)cg_inosused(&acg
), acg
.cg_freeoff
- acg
.cg_iusedoff
);
acg
.cg_cs
.cs_nifree
+= sblock
.fs_ipg
;
for (i
= 0; i
< ROOTINO
; i
++) {
setbit(cg_inosused(&acg
), i
);
for (i
= 0; i
< sblock
.fs_ipg
/ INOPF(&sblock
); i
+= sblock
.fs_frag
)
wtfs(fsbtodb(&sblock
, cgimin(&sblock
, cylno
) + i
),
sblock
.fs_bsize
, (char *)zino
);
bzero((caddr_t
)cg_blktot(&acg
), acg
.cg_boff
- acg
.cg_btotoff
);
bzero((caddr_t
)cg_blks(&sblock
, &acg
, 0),
acg
.cg_iusedoff
- acg
.cg_boff
);
bzero((caddr_t
)cg_blksfree(&acg
), acg
.cg_nextfreeoff
- acg
.cg_freeoff
);
* In cylno 0, beginning space is reserved
* for boot and super blocks.
for (d
= 0; d
< dlower
; d
+= sblock
.fs_frag
) {
setblock(&sblock
, cg_blksfree(&acg
), d
/sblock
.fs_frag
);
cg_blktot(&acg
)[cbtocylno(&sblock
, d
)]++;
cg_blks(&sblock
, &acg
, cbtocylno(&sblock
, d
))
[cbtorpos(&sblock
, d
)]++;
sblock
.fs_dsize
+= dlower
;
sblock
.fs_dsize
+= acg
.cg_ndblk
- dupper
;
if (i
= dupper
% sblock
.fs_frag
) {
acg
.cg_frsum
[sblock
.fs_frag
- i
]++;
for (d
= dupper
+ sblock
.fs_frag
- i
; dupper
< d
; dupper
++) {
setbit(cg_blksfree(&acg
), dupper
);
for (d
= dupper
; d
+ sblock
.fs_frag
<= dmax
- cbase
; ) {
setblock(&sblock
, cg_blksfree(&acg
), d
/ sblock
.fs_frag
);
cg_blktot(&acg
)[cbtocylno(&sblock
, d
)]++;
cg_blks(&sblock
, &acg
, cbtocylno(&sblock
, d
))
[cbtorpos(&sblock
, d
)]++;
acg
.cg_frsum
[dmax
- cbase
- d
]++;
for (; d
< dmax
- cbase
; d
++) {
setbit(cg_blksfree(&acg
), d
);
sblock
.fs_cstotal
.cs_ndir
+= acg
.cg_cs
.cs_ndir
;
sblock
.fs_cstotal
.cs_nffree
+= acg
.cg_cs
.cs_nffree
;
sblock
.fs_cstotal
.cs_nbfree
+= acg
.cg_cs
.cs_nbfree
;
sblock
.fs_cstotal
.cs_nifree
+= acg
.cg_cs
.cs_nifree
;
wtfs(fsbtodb(&sblock
, cgtod(&sblock
, cylno
)),
sblock
.fs_bsize
, (char *)&acg
);
* initialize the file system
struct direct root_dir
[] = {
{ ROOTINO
, sizeof(struct direct
), DT_DIR
, 1, "." },
{ ROOTINO
, sizeof(struct direct
), DT_DIR
, 2, ".." },
{ LOSTFOUNDINO
, sizeof(struct direct
), DT_DIR
, 10, "lost+found" },
u_char d_name
[MAXNAMLEN
+ 1];
{ ROOTINO
, sizeof(struct direct
), 1, "." },
{ ROOTINO
, sizeof(struct direct
), 2, ".." },
{ LOSTFOUNDINO
, sizeof(struct direct
), 10, "lost+found" },
struct direct lost_found_dir
[] = {
{ LOSTFOUNDINO
, sizeof(struct direct
), DT_DIR
, 1, "." },
{ ROOTINO
, sizeof(struct direct
), DT_DIR
, 2, ".." },
{ 0, DIRBLKSIZ
, 0, 0, 0 },
struct odirect olost_found_dir
[] = {
{ LOSTFOUNDINO
, sizeof(struct direct
), 1, "." },
{ ROOTINO
, sizeof(struct direct
), 2, ".." },
node
.di_atime
.ts_sec
= utime
;
node
.di_mtime
.ts_sec
= utime
;
node
.di_ctime
.ts_sec
= utime
;
* create the lost+found directory
(void)makedir((struct direct
*)olost_found_dir
, 2);
for (i
= DIRBLKSIZ
; i
< sblock
.fs_bsize
; i
+= DIRBLKSIZ
)
bcopy(&olost_found_dir
[2], &buf
[i
],
DIRSIZ(0, &olost_found_dir
[2]));
(void)makedir(lost_found_dir
, 2);
for (i
= DIRBLKSIZ
; i
< sblock
.fs_bsize
; i
+= DIRBLKSIZ
)
bcopy(&lost_found_dir
[2], &buf
[i
],
DIRSIZ(0, &lost_found_dir
[2]));
node
.di_mode
= IFDIR
| UMASK
;
node
.di_size
= sblock
.fs_bsize
;
node
.di_db
[0] = alloc(node
.di_size
, node
.di_mode
);
node
.di_blocks
= btodb(fragroundup(&sblock
, node
.di_size
));
wtfs(fsbtodb(&sblock
, node
.di_db
[0]), node
.di_size
, buf
);
iput(&node
, LOSTFOUNDINO
);
* create the root directory
node
.di_mode
= IFDIR
| 01777;
node
.di_mode
= IFDIR
| UMASK
;
node
.di_nlink
= PREDEFDIR
;
node
.di_size
= makedir((struct direct
*)oroot_dir
, PREDEFDIR
);
node
.di_size
= makedir(root_dir
, PREDEFDIR
);
node
.di_db
[0] = alloc(sblock
.fs_fsize
, node
.di_mode
);
node
.di_blocks
= btodb(fragroundup(&sblock
, node
.di_size
));
wtfs(fsbtodb(&sblock
, node
.di_db
[0]), sblock
.fs_fsize
, buf
);
* construct a set of directory entries in "buf".
* return size of directory.
makedir(protodir
, entries
)
register struct direct
*protodir
;
for (cp
= buf
, i
= 0; i
< entries
- 1; i
++) {
protodir
[i
].d_reclen
= DIRSIZ(0, &protodir
[i
]);
bcopy(&protodir
[i
], cp
, protodir
[i
].d_reclen
);
cp
+= protodir
[i
].d_reclen
;
spcleft
-= protodir
[i
].d_reclen
;
protodir
[i
].d_reclen
= spcleft
;
bcopy(&protodir
[i
], cp
, DIRSIZ(0, &protodir
[i
]));
* allocate a block or frag
rdfs(fsbtodb(&sblock
, cgtod(&sblock
, 0)), sblock
.fs_cgsize
,
if (acg
.cg_magic
!= CG_MAGIC
) {
printf("cg 0: bad magic number\n");
if (acg
.cg_cs
.cs_nbfree
== 0) {
printf("first cylinder group ran out of space\n");
for (d
= 0; d
< acg
.cg_ndblk
; d
+= sblock
.fs_frag
)
if (isblock(&sblock
, cg_blksfree(&acg
), d
/ sblock
.fs_frag
))
printf("internal error: can't find block in cyl 0\n");
clrblock(&sblock
, cg_blksfree(&acg
), d
/ sblock
.fs_frag
);
sblock
.fs_cstotal
.cs_nbfree
--;
sblock
.fs_cstotal
.cs_ndir
++;
cg_blktot(&acg
)[cbtocylno(&sblock
, d
)]--;
cg_blks(&sblock
, &acg
, cbtocylno(&sblock
, d
))[cbtorpos(&sblock
, d
)]--;
if (size
!= sblock
.fs_bsize
) {
frag
= howmany(size
, sblock
.fs_fsize
);
fscs
[0].cs_nffree
+= sblock
.fs_frag
- frag
;
sblock
.fs_cstotal
.cs_nffree
+= sblock
.fs_frag
- frag
;
acg
.cg_cs
.cs_nffree
+= sblock
.fs_frag
- frag
;
acg
.cg_frsum
[sblock
.fs_frag
- frag
]++;
for (i
= frag
; i
< sblock
.fs_frag
; i
++)
setbit(cg_blksfree(&acg
), d
+ i
);
wtfs(fsbtodb(&sblock
, cgtod(&sblock
, 0)), sblock
.fs_cgsize
,
* Allocate an inode on the disk
register struct dinode
*ip
;
struct dinode buf
[MAXINOPB
];
rdfs(fsbtodb(&sblock
, cgtod(&sblock
, 0)), sblock
.fs_cgsize
,
if (acg
.cg_magic
!= CG_MAGIC
) {
printf("cg 0: bad magic number\n");
setbit(cg_inosused(&acg
), ino
);
wtfs(fsbtodb(&sblock
, cgtod(&sblock
, 0)), sblock
.fs_cgsize
,
sblock
.fs_cstotal
.cs_nifree
--;
if (ino
>= sblock
.fs_ipg
* sblock
.fs_ncg
) {
printf("fsinit: inode value out of range (%d).\n", ino
);
d
= fsbtodb(&sblock
, itod(&sblock
, ino
));
rdfs(d
, sblock
.fs_bsize
, buf
);
buf
[itoo(&sblock
, ino
)] = *ip
;
wtfs(d
, sblock
.fs_bsize
, buf
);
* Notify parent process that the filesystem has created itself successfully.
* Replace libc function with one suited to our needs.
pgsz
= getpagesize() - 1;
i
= (char *)((u_long
)(base
+ pgsz
) &~ pgsz
);
if (getrlimit(RLIMIT_DATA
, &rlp
) < 0)
rlp
.rlim_cur
= rlp
.rlim_max
;
if (setrlimit(RLIMIT_DATA
, &rlp
) < 0)
memleft
= rlp
.rlim_max
- (u_long
)base
;
size
= (size
+ pgsz
) &~ pgsz
;
return ((caddr_t
)sbrk(size
));
* Replace libc function with one suited to our needs.
if ((p
= malloc(size
)) == NULL
)
* Replace libc function with one suited to our needs.
* Replace libc function with one suited to our needs.
/* do not worry about it for now */
* read a block from the file system
bcopy(membase
+ bno
* sectorsize
, bf
, size
);
if (lseek(fsi
, (off_t
)bno
* sectorsize
, 0) < 0) {
printf("seek error: %ld\n", bno
);
printf("read error: %ld\n", bno
);
* write a block to the file system
bcopy(bf
, membase
+ bno
* sectorsize
, size
);
if (lseek(fso
, (off_t
)bno
* sectorsize
, SEEK_SET
) < 0) {
printf("seek error: %ld\n", bno
);
n
= write(fso
, bf
, size
);
printf("write error: %ld\n", bno
);
* check if a block is available
mask
= 0x0f << ((h
& 0x1) << 2);
return ((cp
[h
>> 1] & mask
) == mask
);
mask
= 0x03 << ((h
& 0x3) << 1);
return ((cp
[h
>> 2] & mask
) == mask
);
mask
= 0x01 << (h
& 0x7);
return ((cp
[h
>> 3] & mask
) == mask
);
printf("isblock bad fs_frag %d\n", fs
->fs_frag
);
fprintf(stderr
, "isblock bad fs_frag %d\n", fs
->fs_frag
);
* take a block out of the map
cp
[h
>> 1] &= ~(0x0f << ((h
& 0x1) << 2));
cp
[h
>> 2] &= ~(0x03 << ((h
& 0x3) << 1));
cp
[h
>> 3] &= ~(0x01 << (h
& 0x7));
printf("clrblock bad fs_frag %d\n", fs
->fs_frag
);
fprintf(stderr
, "clrblock bad fs_frag %d\n", fs
->fs_frag
);
* put a block into the map
cp
[h
>> 1] |= (0x0f << ((h
& 0x1) << 2));
cp
[h
>> 2] |= (0x03 << ((h
& 0x3) << 1));
cp
[h
>> 3] |= (0x01 << (h
& 0x7));
printf("setblock bad fs_frag %d\n", fs
->fs_frag
);
fprintf(stderr
, "setblock bad fs_frag %d\n", fs
->fs_frag
);