static char *sccsid
= "@(#)mkfs.c 1.10 (Berkeley) %G%";
* make file system for cylinder-group style file systems
* or: mkfs size [ bsize frag nsect ntrak cpg ]
#define NDIRECT(fs) ((fs)->fs_bsize/sizeof(struct direct))
struct dinode zino
[MAXIPG
];
printf("usage: mkfs sblock proto/size [ bsize frag nsect ntrak cpg ]\n");
printf("file sys size: ");
} while (fso
< 0 || fsi
< 0);
printf("%s: cannot create\n", fsys
);
printf("%s: cannot open\n", fsys
);
printf("%s: cannot open init\n", string
);
read(f
, (char *)&head
, sizeof head
);
c
= head
.a_text
+ head
.a_data
;
printf("%s: too big\n", string
);
wtfs(BBLOCK
, MAXBSIZE
, buf
);
sblock
.fs_bsize
= MAXBSIZE
;
sblock
.fs_frag
= MAXFRAG
;
sblock
.fs_fsize
= MAXBSIZE
/ MAXFRAG
;
sblock
.fs_rotdelay
= ROTDELAY
;
sblock
.fs_minfree
= MINFREE
;
sblock
.fs_ntrak
= getnum();
sblock
.fs_nsect
= getnum();
sblock
.fs_cpg
= getnum();
for (f
=0; c
=proto
[f
]; f
++) {
printf("%s: cannot open\n", proto
);
sblock
.fs_bsize
= atoi(argv
[2]);
sblock
.fs_bsize
= MAXBSIZE
;
sblock
.fs_fsize
= atoi(argv
[3]);
sblock
.fs_fsize
= MAXBSIZE
/ MAXFRAG
;
sblock
.fs_nsect
= atoi(argv
[4]);
sblock
.fs_ntrak
= atoi(argv
[5]);
sblock
.fs_frag
= sblock
.fs_bsize
/ sblock
.fs_fsize
;
sblock
.fs_rotdelay
= ROTDELAY
;
sblock
.fs_minfree
= MINFREE
;
* Now have size for file system and nsect and ntrak.
* (And, if coming from prototype, cpg).
* Determine number of cylinders occupied by file system.
if (sblock
.fs_fsize
< DEV_BSIZE
) {
printf("fragment size %d is too small, minimum is %d\n",
sblock
.fs_fsize
, DEV_BSIZE
);
if (sblock
.fs_bsize
< MINBSIZE
) {
printf("block size %d is too small, minimum is %d\n",
sblock
.fs_bsize
, MINBSIZE
);
sblock
.fs_size
= n
= dbtofsb(&sblock
, n
);
if (sblock
.fs_ntrak
<= 0)
printf("preposterous ntrak %d\n", sblock
.fs_ntrak
), exit(1);
if (sblock
.fs_nsect
<= 0)
printf("preposterous nsect %d\n", sblock
.fs_nsect
), exit(1);
printf("preposterous size %d\n", sblock
.fs_size
), exit(1);
if (sblock
.fs_ntrak
* sblock
.fs_nsect
> MAXBPG(&sblock
) * NSPB(&sblock
)) {
printf("cylinder too large (%d sectors)\n",
sblock
.fs_ntrak
* sblock
.fs_nsect
);
printf("maximum cylinder size: %d sectors\n",
MAXBPG(&sblock
) * NSPB(&sblock
));
sblock
.fs_ncyl
= n
* NSPF(&sblock
) / (sblock
.fs_nsect
* sblock
.fs_ntrak
);
if (n
* NSPF(&sblock
) > sblock
.fs_ncyl
* sblock
.fs_nsect
* sblock
.fs_ntrak
) {
printf("%d sector(s) in last cylinder unused\n",
n
* NSPF(&sblock
) - sblock
.fs_ncyl
* sblock
.fs_nsect
* sblock
.fs_ntrak
);
sblock
.fs_magic
= FS_MAGIC
;
* Validate specified/determined cpg.
((fs).fs_nsect * (fs).fs_ntrak * (fs).fs_cpg/NSPB(&sblock) > MAXBPG(&sblock))
sblock
.fs_cpg
= atoi(argv
[6]);
printf("cylinder group too large (%d blocks); ",
sblock
.fs_cpg
* sblock
.fs_nsect
* sblock
.fs_ntrak
/ NSPB(&sblock
));
printf("max: %d blocks\n", MAXBPG(&sblock
));
if (sblock
.fs_cpg
> MAXCPG
) {
printf("cylinder groups are limited to %d cylinders\n",
* Compute/validate number of cylinder groups.
sblock
.fs_ncg
= sblock
.fs_ncyl
/ sblock
.fs_cpg
;
if (sblock
.fs_ncyl
% sblock
.fs_cpg
)
if ((sblock
.fs_nsect
*sblock
.fs_ntrak
*sblock
.fs_cpg
) % NSPF(&sblock
)) {
printf("mkfs: nsect %d, ntrak %d, cpg %d is not tolerable\n",
sblock
.fs_nsect
, sblock
.fs_ntrak
, sblock
.fs_cpg
);
printf("as this would would have cyl groups whose size\n");
printf("is not a multiple of %d; choke!\n", sblock
.fs_fsize
);
calloc(1, roundup(sblock
.fs_ncg
* sizeof (struct csum
),
* Compute number of inode blocks per cylinder group.
* Start with one inode per NBPI bytes; adjust as necessary.
n
= ((n
* sblock
.fs_fsize
) / NBPI
) / INOPB(&sblock
);
sblock
.fs_ipg
= ((n
/ sblock
.fs_ncg
) + 1) * INOPB(&sblock
);
if (sblock
.fs_ipg
< INOPB(&sblock
))
sblock
.fs_ipg
= INOPB(&sblock
);
if (sblock
.fs_ipg
> MAXIPG
)
sblock
.fs_spc
= sblock
.fs_ntrak
* sblock
.fs_nsect
;
sblock
.fs_fpg
= (sblock
.fs_cpg
* sblock
.fs_spc
) /
(sblock
.fs_fsize
/ SECTSIZE
);
if (cgdmin(0,&sblock
) >= sblock
.fs_fpg
) {
printf("inode blocks/cyl group (%d) >= data blocks (%d)\n",
cgdmin(0,&sblock
) / sblock
.fs_frag
,
sblock
.fs_fpg
/ sblock
.fs_frag
);
sblock
.fs_cstotal
.cs_nifree
= sblock
.fs_ipg
* sblock
.fs_ncg
;
sblock
.fs_cgsize
= cgsize(&sblock
);
sblock
.fs_csaddr
= cgdmin(0, &sblock
);
sblock
.fs_cssize
= sblock
.fs_ncg
* sizeof(struct csum
);
sblock
.fs_sblkno
= SBLOCK
;
* Dump out information about file system.
printf("%s:\t%d sectors in %d cylinders of %d tracks, %d sectors\n",
fsys
, sblock
.fs_size
*NSPF(&sblock
), sblock
.fs_ncyl
,
sblock
.fs_ntrak
, sblock
.fs_nsect
);
printf("\t%.1fMb in %d cyl groups (%d c/g, %.2fMb/g, %d i/g)\n",
(float)sblock
.fs_size
* sblock
.fs_fsize
* 1e-6, sblock
.fs_ncg
,
sblock
.fs_cpg
, (float)sblock
.fs_fpg
* sblock
.fs_fsize
* 1e-6,
printf("%7d size (%d blocks)\n",
sblock.fs_size, sblock.fs_size / sblock.fs_frag);
printf("%7d cylinder groups\n", sblock.fs_ncg);
printf("%7d cylinder group block size\n", sblock.fs_cgsize);
printf("%7d tracks\n", sblock.fs_ntrak);
printf("%7d sectors\n", sblock.fs_nsect);
printf("%7d sectors per cylinder\n", sblock.fs_spc);
printf("%7d cylinders\n", sblock.fs_ncyl);
printf("%7d cylinders per group\n", sblock.fs_cpg);
printf("%7d blocks per group\n", sblock.fs_fpg/sblock.fs_frag);
printf("%7d inodes per group\n", sblock.fs_ipg);
if (sblock.fs_ncyl % sblock.fs_cpg) {
printf("%7d cylinders in last group\n",
i = sblock.fs_ncyl % sblock.fs_cpg);
printf("%7d blocks in last group\n",
i * sblock.fs_spc / NSPB(&sblock));
* Now build the cylinders group blocks and
* then print out indices of cylinder groups forwarded
* past bad blocks or other obstructions.
sblock
.fs_cstotal
.cs_ndir
= 0;
sblock
.fs_cstotal
.cs_nbfree
= 0;
sblock
.fs_cstotal
.cs_nifree
= 0;
sblock
.fs_cstotal
.cs_nffree
= 0;
for (i
= 0; i
< NRPOS
; i
++)
sblock
.fs_postbl
[i
] = -1;
for (i
= 0; i
< sblock
.fs_spc
; i
+= (NSPF(&sblock
) * sblock
.fs_frag
))
for (i
-= (NSPF(&sblock
) * sblock
.fs_frag
);
i
-= (NSPF(&sblock
) * sblock
.fs_frag
)) {
c
= i
% sblock
.fs_nsect
* NRPOS
/ sblock
.fs_nsect
;
sblock
.fs_rotbl
[i
/ (NSPF(&sblock
) * sblock
.fs_frag
)] =
sblock
.fs_postbl
[c
] = i
/ (NSPF(&sblock
) * sblock
.fs_frag
);
for (c
= 0; c
< sblock
.fs_ncg
; c
++)
printf("Warning, no super-block backups with only one cylinder group\n");
printf("\tsuper-block backups (for fsck -b#) at %d+k*%d (%d .. %d)\n",
SBLOCK
, fsbtodb(&sblock
, sblock
.fs_fpg
),
SBLOCK
+ fsbtodb(&sblock
, sblock
.fs_fpg
),
SBLOCK
+ fsbtodb(&sblock
, (sblock
.fs_ncg
- 1) *
* Now construct the initial file system, and
* then write out the super-block.
cfile((struct inode
*)0);
wtfs(SBLOCK
, MAXBSIZE
, (char *)&sblock
);
for (i
= 0; i
< sblock
.fs_cssize
; i
+= sblock
.fs_bsize
)
wtfs(fsbtodb(&sblock
, sblock
.fs_csaddr
+ i
/ sblock
.fs_fsize
),
sblock
.fs_bsize
, ((char *)fscs
) + i
);
for (c
= 0; c
< sblock
.fs_ncg
; c
++)
wtfs(fsbtodb(&sblock
, cgsblock(c
, &sblock
)),
MAXBSIZE
, (char *)&sblock
);
* Initialize a cylinder group.
daddr_t cbase
, d
, dmin
, dmax
;
register struct csum
*cs
;
* Determine block bounds for cylinder group.
* Allow space for super block summary information in first
cbase
= cgbase(c
,&sblock
);
dmax
= cbase
+ sblock
.fs_fpg
;
if (dmax
> sblock
.fs_size
)
dmin
= cgdmin(c
,&sblock
) - cbase
;
acg
.cg_ncyl
= sblock
.fs_cpg
;
acg
.cg_niblk
= sblock
.fs_ipg
;
acg
.cg_ndblk
= dmax
- cbase
;
for (i
= 0; i
< sblock
.fs_frag
; i
++) {
for (i
= 0; i
< sblock
.fs_ipg
; ) {
for (j
= INOPB(&sblock
); j
> 0; j
--) {
acg
.cg_cs
.cs_nifree
+= INOPB(&sblock
);
lseek(fso
, fsbtodb(&sblock
, cgimin(c
,&sblock
)) * DEV_BSIZE
, 0);
if (write(fso
, (char *)zino
, sblock
.fs_ipg
* sizeof (struct dinode
)) !=
sblock
.fs_ipg
* sizeof (struct dinode
))
printf("write error %D\n", tell(fso
) / sblock
.fs_bsize
);
for (i
= 0; i
< MAXCPG
; i
++)
for (j
= 0; j
< NRPOS
; j
++)
dmin
+= howmany(sblock
.fs_cssize
, sblock
.fs_bsize
) *
for (d
= 0; d
< dmin
; d
+= sblock
.fs_frag
)
clrblock(&sblock
, acg
.cg_free
, d
/sblock
.fs_frag
);
while ((d
+sblock
.fs_frag
) <= dmax
- cbase
) {
setblock(&sblock
, acg
.cg_free
, d
/sblock
.fs_frag
);
acg
.cg_b
[s
/ sblock
.fs_spc
]
[s
% sblock
.fs_nsect
* NRPOS
/ sblock
.fs_nsect
]++;
for (; d
< dmax
- cbase
; d
++) {
for (; d
< MAXBPG(&sblock
); d
++)
sblock
.fs_dsize
+= acg
.cg_ndblk
- dmin
;
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(c
, &sblock
)),
sblock
.fs_bsize
, (char *)&acg
);
daddr_t ib
[MAXBSIZE
/ sizeof(daddr_t
)];
in
.i_mode
= gmode(string
[0], "-bcd", IFREG
, IFBLK
, IFCHR
, IFDIR
);
in
.i_mode
|= gmode(string
[1], "-u", 0, ISUID
, 0, 0);
in
.i_mode
|= gmode(string
[2], "-g", 0, ISGID
, 0, 0);
printf("%c/%s: bad octal mode digit\n", c
, string
);
in
.i_mode
|= (c
-'0')<<(15-3*i
);
* general initialization prior to
for(i
=0; i
<sblock
.fs_bsize
; i
++)
for(i
=0; i
<NINDIR(&sblock
); i
++)
if(par
== (struct inode
*)0) {
* contents is a file name
printf("%s: cannot open\n", string
);
while((i
= read(f
, db
, sblock
.fs_bsize
)) > 0) {
newblk(&dbc
, db
, &ibc
, ib
,
ibc
< NDADDR
? i
: sblock
.fs_bsize
, 0);
* content is maj/min types
in
.i_rdev
= makedev(i
, f
);
entry(in
.i_number
, ".", &dbc
, db
, &ibc
, ib
);
entry(par
->i_number
, "..", &dbc
, db
, &ibc
, ib
);
in
.i_size
= 2*sizeof(struct direct
);
if(string
[0]=='$' && string
[1]=='\0')
if (in
.i_size
>= sblock
.fs_bsize
* NDADDR
) {
printf("can't handle direct of > %d entries\n",
NDIRECT(&sblock
) * NDADDR
);
entry(ino
+1, string
, &dbc
, db
, &ibc
, ib
);
in
.i_size
+= sizeof(struct direct
);
newblk(&dbc
, db
, &ibc
, ib
, roundup(dbc
, sblock
.fs_fsize
),
gmode(c
, s
, m0
, m1
, m2
, m3
)
printf("%c/%s: bad mode\n", c
, string
);
for(i
=0; c
=string
[i
]; i
++) {
printf("%s: bad number\n", string
);
} while(c
!=' '&&c
!='\t'&&c
!='\n'&&c
!='\0');
lseek(fsi
, bno
* DEV_BSIZE
, 0);
printf("read error: %ld\n", bno
);
lseek(fso
, bno
* DEV_BSIZE
, 0);
n
= write(fso
, bf
, size
);
printf("write error: %D\n", bno
);
rdfs(fsbtodb(&sblock
, cgtod(0,&sblock
)),
sblock
.fs_cgsize
, (char *)&acg
);
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
, acg
.cg_free
, d
/ sblock
.fs_frag
))
printf("internal error: can't find block in cyl 0\n");
clrblock(&sblock
, acg
.cg_free
, d
/ sblock
.fs_frag
);
sblock
.fs_cstotal
.cs_nbfree
--;
sblock
.fs_cstotal
.cs_ndir
++;
acg
.cg_b
[s
/ sblock
.fs_spc
]
[s
% sblock
.fs_nsect
* NRPOS
/ sblock
.fs_nsect
]--;
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(acg
.cg_free
, d
+i
);
wtfs(fsbtodb(&sblock
, cgtod(0,&sblock
)),
roundup(sblock
.fs_cgsize
, DEV_BSIZE
), (char *)&acg
);
entry(inum
, str
, adbc
, db
, aibc
, ib
)
if (*adbc
== NDIRECT(&sblock
))
newblk(adbc
, db
, aibc
, ib
, sblock
.fs_bsize
, 0);
dp
= (struct direct
*)db
;
for(i
=0; i
< DIRSIZ
; i
++)
for(i
=0; i
< DIRSIZ
; i
++)
if((dp
->d_name
[i
] = str
[i
]) == 0)
newblk(adbc
, db
, aibc
, ib
, size
, mode
)
wtfs(fsbtodb(&sblock
, bno
), size
, db
);
for(i
= 0; i
< size
; i
++)
if(*aibc
>= NINDIR(&sblock
)) {
printf("indirect block full\n");
int i
, c
= ip
->i_number
/ sblock
.fs_ipg
;
rdfs(fsbtodb(&sblock
, cgtod(c
,&sblock
)),
sblock
.fs_cgsize
, (char *)&acg
);
setbit(acg
.cg_iused
, ip
->i_number
);
wtfs(fsbtodb(&sblock
, cgtod(c
,&sblock
)),
roundup(sblock
.fs_cgsize
, DEV_BSIZE
), (char *)&acg
);
sblock
.fs_cstotal
.cs_nifree
--;
if(ip
->i_number
>= sblock
.fs_ipg
) {
printf("mkfs: cant handle more than one cg of inodes (yet)\n");
if(ip
->i_number
>= sblock
.fs_ipg
* sblock
.fs_ncg
) {
printf("ilist too small\n");
d
= itod(ip
->i_number
,&sblock
);
rdfs(fsbtodb(&sblock
, d
), sblock
.fs_bsize
, buf
);
for(i
= 0; i
< *aibc
; i
++) {
ip
->i_ib
[0] = alloc(sblock
.fs_bsize
, 0);
for(i
=0; i
<NINDIR(&sblock
)-NDADDR
; i
++) {
ib
[i
+NDADDR
] = (daddr_t
)0;
wtfs(fsbtodb(&sblock
, ip
->i_ib
[0]), sblock
.fs_bsize
,
((struct dinode
*)buf
+ itoo(ip
->i_number
, &sblock
))->di_ic
= ip
->i_ic
;
wtfs(fsbtodb(&sblock
, d
), sblock
.fs_bsize
, buf
);
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
);
fprintf(stderr
, "isblock bad fs_frag %d\n", fs
->fs_frag
);
cp
[h
>> 1] &= ~(0x0f << ((h
& 0x1) << 2));
cp
[h
>> 2] &= ~(0x03 << ((h
& 0x3) << 1));
cp
[h
>> 3] &= ~(0x01 << (h
& 0x7));
fprintf(stderr
, "clrblock bad fs_frag %d\n", fs
->fs_frag
);
cp
[h
>> 1] |= (0x0f << ((h
& 0x1) << 2));
cp
[h
>> 2] |= (0x03 << ((h
& 0x3) << 1));
cp
[h
>> 3] |= (0x01 << (h
& 0x7));
fprintf(stderr
, "setblock bad fs_frag %d\n", fs
->fs_frag
);