static char *sccsid
= "@(#)mkfs.c 1.1 (Berkeley) %G%";
* make file system for cylinder-group style file systems
* or: mkfs size [ nsect ntrak cpg ]
#define NDIRECT (BSIZE/sizeof(struct direct))
#define setbit(a,i) ((a)[(i)/NBBY] |= 1<<((i)%NBBY))
#define clrbit(a,i) ((a)[(i)/NBBY] &= ~(1<<((i)%NBBY)))
#define isset(a,i) ((a)[(i)/NBBY] & (1<<((i)%NBBY)))
#define howmany(x, y) (((x)+((y)-1))/(y))
#define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
struct dinode zino
[MAXIPG
];
printf("usage: mkfs sblock proto/size [ 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
, BSIZE
, buf
);
n
= sblock
.fs_size
= getnum();
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_nsect
= atoi(argv
[2]);
sblock
.fs_ntrak
= atoi(argv
[3]);
* 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_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
* NSPB
) {
printf("cylinder too large (%d sectors)\n",
sblock
.fs_ntrak
* sblock
.fs_nsect
);
printf("maximum cylinder size: %d sectors\n",
sblock
.fs_ncyl
= n
* NSPF
/ (sblock
.fs_nsect
* sblock
.fs_ntrak
);
if (n
* NSPF
> sblock
.fs_ncyl
* sblock
.fs_nsect
* sblock
.fs_ntrak
) {
printf("%d sector(s) in last cylinder unused\n",
n
* NSPF
- sblock
.fs_ncyl
* sblock
.fs_nsect
* sblock
.fs_ntrak
);
sblock
.fs_magic
= FS_MAGIC
;
* Validate specified/determined cpg.
#define CGTOOBIG(fs) ((fs).fs_nsect*(fs).fs_ntrak*(fs).fs_cpg/NSPB > MAXBPG)
sblock
.fs_cpg
= atoi(argv
[4]);
printf("cylinder group too large (%d blocks); ",
sblock
.fs_cpg
* sblock
.fs_nsect
* sblock
.fs_ntrak
/ NSPB
);
printf("max: %d blocks\n", MAXBPG
);
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
) {
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", FSIZE
);
calloc(1, roundup(sblock
.fs_ncg
* sizeof (struct csum
), BSIZE
));
* Compute number of inode blocks per cylinder group.
* Start with one inode per NBPI bytes; adjust as necessary.
n
= ((n
* BSIZE
) / NBPI
) / INOPB
;
sblock
.fs_ipg
= ((n
/ sblock
.fs_ncg
) + 1) * INOPB
;
if (sblock
.fs_ipg
< INOPB
)
if (sblock
.fs_ipg
> MAXIPG
)
while (sblock
.fs_ipg
* sblock
.fs_ncyl
> 65500)
sblock
.fs_spc
= sblock
.fs_ntrak
* sblock
.fs_nsect
;
sblock
.fs_fpg
= (sblock
.fs_cpg
* sblock
.fs_spc
) / (FSIZE
/ 512);
if (cgdmin(0,&sblock
) >= sblock
.fs_fpg
)
printf("inode blocks/cyl group (%d) >= data blocks (%d)\n",
cgdmin(0,&sblock
)/FRAG
, sblock
.fs_fpg
/FRAG
), exit(1);
sblock
.fs_nifree
= sblock
.fs_ipg
* sblock
.fs_ncg
;
sblock
.fs_cgsize
= cgsize(&sblock
);
sblock
.fs_cssize
= cssize(&sblock
);
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
.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
*FSIZE
*1e-6, sblock
.fs_ncg
, sblock
.fs_cpg
,
(float)sblock
.fs_fpg
*FSIZE
*1e-6, sblock
.fs_ipg
);
printf("%7d size (%d blocks)\n", sblock.fs_size, sblock.fs_size/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/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);
* Now build the cylinders group blocks and
* then print out indices of cylinder groups forwarded
* past bad blocks or other obstructions.
for (c
= 0; c
< sblock
.fs_ncg
; c
++)
printf("\tsuper-block backups (for fsck -b#) at %d+k*%d (%d .. %d)\n",
SBLOCK
, sblock
.fs_fpg
, SBLOCK
+sblock
.fs_fpg
,
SBLOCK
+(sblock
.fs_ncg
-1)*sblock
.fs_fpg
);
* Now construct the initial file system, and
* then write out the super-block.
cfile((struct inode
*)0);
wtfs(SBLOCK
, BSIZE
, (char *)&sblock
);
for (i
= 0; i
< cssize(&sblock
); i
+= BSIZE
)
wtfs(csaddr(&sblock
) + i
/BSIZE
, BSIZE
, ((char *)fscs
)+i
);
for (c
= 0; c
< sblock
.fs_ncg
; c
++)
wtfs(cgsblock(c
, &sblock
), BSIZE
, (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
)
for (i
= cgdmin(c
,&sblock
) - FRAG
; i
>= 0; i
-= FRAG
)
if (d
+ sblock
.fs_ipg
/INOPB
>= dmax
) {
printf("bad blocks: cyl grp %d unusable\n", c
);
acg
.cg_ncyl
= sblock
.fs_cpg
;
acg
.cg_niblk
= sblock
.fs_ipg
;
acg
.cg_ndblk
= dmax
- cbase
;
while (i
< sblock
.fs_ipg
) {
for (j
= INOPB
; j
> 0; j
--) {
lseek(fso
, cgimin(c
,&sblock
)*FSIZE
, 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
) / BSIZE
);
for (i
= 0; i
< MAXCPG
; i
++)
for (j
= 0; j
< NRPOS
; j
++)
dmin
= cgdmin(c
,&sblock
) - cbase
;
dmin
+= howmany(cssize(&sblock
), BSIZE
) * FRAG
;
for (d
= 0; d
< dmin
; d
+= FRAG
)
clrblock(acg
.cg_free
, d
/FRAG
);
while ((d
+FRAG
) <= dmax
- cbase
) {
clrblock(acg
.cg_free
, d
/FRAG
);
setblock(acg
.cg_free
, d
/FRAG
);
acg
.cg_b
[s
/sblock
.fs_spc
]
[s
%sblock
.fs_nsect
*NRPOS
/sblock
.fs_nsect
]++;
for (; d
< dmax
- cbase
; d
++)
for (; d
< dmax
- cbase
; d
++) {
sblock
.fs_nffree
+= acg
.cg_nffree
;
sblock
.fs_nbfree
+= acg
.cg_nbfree
;
cs
->cs_nifree
= acg
.cg_nifree
;
cs
->cs_nbfree
= acg
.cg_nbfree
;
wtfs(cgtod(c
, &sblock
), BSIZE
, (char *)&acg
);
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
in
.i_un
.i_f
.i_db
[i
] = (daddr_t
)0;
in
.i_un
.i_f
.i_ib
[i
] = (daddr_t
)0;
if(par
== (struct inode
*)0) {
* contents is a file name
printf("%s: cannot open\n", string
);
while((i
=read(f
, db
, BSIZE
)) > 0) {
newblk(&dbc
, db
, &ibc
, ib
, i
);
* content is maj/min types
in
.i_un
.i_d
.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
>= FSIZE
) {
printf("can't handle direct of > %d entries\n",
entry(ino
+1, string
, &dbc
, db
, &ibc
, ib
);
in
.i_size
+= sizeof(struct direct
);
newblk(&dbc
, db
, &ibc
, ib
, roundup(dbc
,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
*FSIZE
, 0);
printf("read error: %ld\n", bno
);
lseek(fso
, bno
*FSIZE
, 0);
n
= write(fso
, bf
, size
);
printf("write error: %D\n", bno
);
rdfs(cgtod(0,&sblock
), sblock
.fs_cgsize
, (char *)&acg
);
if (acg
.cg_nbfree
== 0) {
printf("first cylinder group ran out of space\n");
for (d
= 0; d
< acg
.cg_ndblk
; d
+= FRAG
)
if (isblock(acg
.cg_free
, d
/FRAG
))
printf("internal error: can't find block in cyl 0\n");
clrblock(acg
.cg_free
, d
/FRAG
);
acg
.cg_b
[s
/sblock
.fs_spc
][s
%sblock
.fs_nsect
*NRPOS
/sblock
.fs_nsect
]--;
frag
= howmany(size
, FSIZE
);
acg
.cg_nffree
+= FRAG
- frag
;
sblock
.fs_nffree
+= FRAG
- frag
;
for (i
= frag
; i
< FRAG
; i
++)
setbit(acg
.cg_free
, d
+i
);
wtfs(cgtod(0,&sblock
), sblock
.fs_cgsize
, (char *)&acg
);
entry(inum
, str
, adbc
, db
, aibc
, ib
)
dp
= (struct direct
*)db
;
if((dp
->d_name
[i
] = str
[i
]) == 0)
newblk(adbc
, db
, aibc
, ib
, BSIZE
);
newblk(adbc
, db
, aibc
, ib
, size
)
printf("indirect block full\n");
int i
, c
= ip
->i_number
/ sblock
.fs_ipg
;
rdfs(cgtod(c
,&sblock
), sblock
.fs_cgsize
, (char *)&acg
);
setbit(acg
.cg_iused
, ip
->i_number
);
wtfs(cgtod(c
,&sblock
), sblock
.fs_cgsize
, (char *)&acg
);
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
);
dp
= (struct dinode
*)buf
;
dp
+= itoo(ip
->i_number
);
dp
->di_mode
= ip
->i_mode
;
dp
->di_nlink
= ip
->i_nlink
;
dp
->di_size
= ip
->i_size
;
switch(ip
->i_mode
&IFMT
) {
ip
->i_un
.i_f
.i_db
[i
] = ib
[i
];
ip
->i_un
.i_f
.i_ib
[0] = alloc(BSIZE
);
for(i
=0; i
<NINDIR
-NDADDR
; i
++) {
ib
[i
+NDADDR
] = (daddr_t
)0;
wtfs(ip
->i_un
.i_f
.i_ib
[0], (char *)ib
);
ltol3(dp
->di_addr
, ip
->i_un
.i_f
.i_db
, NDADDR
+NIADDR
);
printf("bad mode %o\n", ip
->i_mode
);