static char *sccsid
= "@(#)mkfs.c 2.12 (Berkeley) %G%";
* make file system for cylinder-group style file systems
* usage: mkfs special size [ nsect ntrak bsize fsize cpg minfree rps nbpi ]
* The following constants set the defaults used for the number
* of sectors (fs_nsect), and number of tracks (fs_ntrak).
* The following two constants set the default block and fragment sizes.
* Both constants must be a power of 2 and meet the following constraints:
* MINBSIZE <= DESBLKSIZE <= MAXBSIZE
* DEV_BSIZE <= DESFRAGSIZE <= DESBLKSIZE
* DESBLKSIZE / DESFRAGSIZE <= 8
* Cylinder groups may have up to MAXCPG cylinders. The actual
* number used depends upon how much information can be stored
* on a single cylinder. The default is to used 16 cylinders
#define DESCPG 16 /* desired fs_cpg */
* MINFREE gives the minimum acceptable percentage of file system
* blocks which may be free. If the freelist drops below this level
* only the superuser may continue to allocate blocks. This may
* be set to 0 if no reserve of free blocks is deemed necessary,
* however throughput drops by fifty percent if the file system
* is run at between 90% and 100% full; thus the default value of
* ROTDELAY gives the minimum number of milliseconds to initiate
* another disk transfer on the same cylinder. It is used in
* determining the rotationally optimal layout for disk blocks
* within a file; the default of fs_rotdelay is 2ms.
* MAXCONTIG sets the default for the maximum number of blocks
* that may be allocated sequentially. Since UNIX drivers are
* not capable of scheduling multi-block transfers, this defaults
* to 1 (ie no contiguous blocks are allocated).
* MAXBLKPG determines the maximum number of data blocks which are
* placed in a single cylinder group. This is currently a function
* of the block and fragment size of the file system.
#define MAXBLKPG(fs) ((fs)->fs_fsize / sizeof(daddr_t))
* Each file system has a number of inodes statically allocated.
* We allocate one inode slot per NBPI bytes, expecting this
* to be far more than we will ever need.
* Disks are assumed to rotate at 60HZ, unless otherwise specified.
#define MAXINOPB (MAXBSIZE / sizeof(struct dinode))
#define POWEROF2(num) (((num) & ((num) - 1)) == 0)
struct dinode zino
[MAXIPG
];
long cylno
, rpos
, blk
, i
, j
, inos
, fssize
, warn
= 0;
printf("usage: mkfs special size [ nsect ntrak bsize fsize cpg minfree rps nbpi ]\n");
printf("%s: cannot create\n", fsys
);
printf("%s: cannot open\n", fsys
);
printf("file sys size: ");
} while (fso
< 0 || fsi
< 0);
* Validate the given file system size.
* Verify that its last block can actually be accessed.
printf("preposterous size %d\n", fssize
), exit(1);
wtfs(fssize
- 1, DEV_BSIZE
, (char *)&sblock
);
* collect and verify the sector and track info
sblock
.fs_nsect
= atoi(argv
[2]);
sblock
.fs_nsect
= DFLNSECT
;
sblock
.fs_ntrak
= atoi(argv
[3]);
sblock
.fs_ntrak
= DFLNTRAK
;
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);
sblock
.fs_spc
= sblock
.fs_ntrak
* sblock
.fs_nsect
;
* collect and verify the block and fragment sizes
sblock
.fs_bsize
= atoi(argv
[4]);
sblock
.fs_bsize
= DESBLKSIZE
;
sblock
.fs_fsize
= atoi(argv
[5]);
sblock
.fs_fsize
= DESFRAGSIZE
;
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
< 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
);
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);
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
/ DEV_BSIZE
;
for (sblock
.fs_fsbtodb
= 0, i
= sblock
.fs_nspf
; 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
, sblock
.fs_fsize
/ DEV_BSIZE
),
for (sblock
.fs_cgmask
= 0xffffffff, i
= sblock
.fs_ntrak
; i
> 1; i
>>= 1)
if (!POWEROF2(sblock
.fs_ntrak
))
for (sblock
.fs_cpc
= NSPB(&sblock
), i
= sblock
.fs_spc
;
sblock
.fs_cpc
> 1 && (i
& 1) == 0;
sblock
.fs_cpc
>>= 1, i
>>= 1)
if (sblock
.fs_cpc
> MAXCPG
) {
printf("maximum block size with nsect %d and ntrak %d is %d\n",
sblock
.fs_nsect
, sblock
.fs_ntrak
,
sblock
.fs_bsize
/ (sblock
.fs_cpc
/ MAXCPG
));
* collect and verify the number of cylinders per group
sblock
.fs_cpg
= atoi(argv
[6]);
sblock
.fs_fpg
= (sblock
.fs_cpg
* sblock
.fs_spc
) / NSPF(&sblock
);
sblock
.fs_cpg
= MAX(sblock
.fs_cpc
, DESCPG
);
sblock
.fs_fpg
= (sblock
.fs_cpg
* sblock
.fs_spc
) / NSPF(&sblock
);
while (sblock
.fs_fpg
/ sblock
.fs_frag
> MAXBPG(&sblock
) &&
sblock
.fs_cpg
> sblock
.fs_cpc
) {
sblock
.fs_cpg
-= sblock
.fs_cpc
;
(sblock
.fs_cpg
* sblock
.fs_spc
) / NSPF(&sblock
);
printf("cylinder groups must have at least 1 cylinder\n");
if (sblock
.fs_cpg
> MAXCPG
) {
printf("cylinder groups are limited to %d cylinders\n", MAXCPG
);
if (sblock
.fs_cpg
% sblock
.fs_cpc
!= 0) {
printf("cylinder groups must have a multiple of %d cylinders\n",
* 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
if (sblock
.fs_ntrak
== 1) {
if (sblock
.fs_spc
* sblock
.fs_cpc
> MAXBPC
* NSPB(&sblock
) ||
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");
* calculate the available blocks for each rotational position
for (cylno
= 0; cylno
< MAXCPG
; cylno
++)
for (rpos
= 0; rpos
< NRPOS
; rpos
++)
sblock
.fs_postbl
[cylno
][rpos
] = -1;
blk
= sblock
.fs_spc
* sblock
.fs_cpc
/ NSPF(&sblock
);
for (i
= 0; i
< blk
; i
+= sblock
.fs_frag
)
for (i
-= sblock
.fs_frag
; i
>= 0; i
-= sblock
.fs_frag
) {
cylno
= cbtocylno(&sblock
, i
);
rpos
= cbtorpos(&sblock
, i
);
blk
= i
/ sblock
.fs_frag
;
if (sblock
.fs_postbl
[cylno
][rpos
] == -1)
sblock
.fs_rotbl
[blk
] = 0;
sblock
.fs_postbl
[cylno
][rpos
] - blk
;
sblock
.fs_postbl
[cylno
][rpos
] = blk
;
* Validate specified/determined cpg.
if (sblock
.fs_spc
> MAXBPG(&sblock
) * NSPB(&sblock
)) {
printf("too many sectors per cylinder (%d sectors)\n",
while(sblock
.fs_spc
> MAXBPG(&sblock
) * NSPB(&sblock
)) {
if (sblock
.fs_frag
< MAXFRAG
)
printf("nsect %d, and ntrak %d, requires block size of %d,\n",
sblock
.fs_nsect
, sblock
.fs_ntrak
, sblock
.fs_bsize
);
printf("\tand fragment size of %d\n", sblock
.fs_fsize
);
if (sblock
.fs_fpg
> MAXBPG(&sblock
) * sblock
.fs_frag
) {
printf("cylinder group too large (%d cylinders); ",
printf("max: %d cylinders per group\n",
MAXBPG(&sblock
) * sblock
.fs_frag
/
(sblock
.fs_fpg
/ sblock
.fs_cpg
));
sblock
.fs_cgsize
= fragroundup(&sblock
,
sizeof(struct cg
) + howmany(sblock
.fs_fpg
, NBBY
));
* 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_spc
* 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
);
* Compute number of inode blocks per cylinder group.
* Start with one inode per NBPI bytes; adjust as necessary.
inos
= MAX(NBPI
, sblock
.fs_fsize
);
printf("%s: bogus nbpi reset to %d\n", argv
[9], inos
);
i
= sblock
.fs_iblkno
+ MAXIPG
/ INOPF(&sblock
);
inos
= (fssize
- sblock
.fs_ncg
* i
) * sblock
.fs_fsize
/ inos
/
sblock
.fs_ipg
= ((inos
/ sblock
.fs_ncg
) + 1) * INOPB(&sblock
);
if (sblock
.fs_ipg
> MAXIPG
)
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 must be increased\n");
if ((i
= fssize
- j
* sblock
.fs_fpg
) < sblock
.fs_fpg
&&
cgdmin(&sblock
, j
) - cgbase(&sblock
, j
) > i
) {
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)
howmany(sblock
.fs_spc
* sblock
.fs_cpc
, NSPB(&sblock
));
sblock
.fs_sbsize
= fragroundup(&sblock
, i
);
fscs
= (struct csum
*)calloc(1, sblock
.fs_cssize
);
sblock
.fs_magic
= FS_MAGIC
;
sblock
.fs_rotdelay
= ROTDELAY
;
sblock
.fs_minfree
= atoi(argv
[7]);
if (sblock
.fs_minfree
< 0 || sblock
.fs_minfree
> 99) {
printf("%s: bogus minfree reset to %d%%\n", argv
[7],
sblock
.fs_minfree
= MINFREE
;
sblock
.fs_minfree
= MINFREE
;
sblock
.fs_maxcontig
= MAXCONTIG
;
sblock
.fs_maxbpg
= MAXBLKPG(&sblock
);
sblock
.fs_rps
= atoi(argv
[8]);
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 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,
* 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(SBLOCK
, 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
);
* 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
;
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
;
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
);
for (i
= 0; i
< ROOTINO
; i
++) {
lseek(fso
, fsbtodb(&sblock
, cgimin(&sblock
, cylno
)) * 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", numfrags(&sblock
, tell(fso
)));
for (i
= 0; i
< MAXCPG
; i
++) {
for (j
= 0; j
< NRPOS
; j
++)
* reserve space for summary info and Boot block
dupper
+= howmany(sblock
.fs_cssize
, sblock
.fs_fsize
);
for (d
= 0; d
< dlower
; d
+= sblock
.fs_frag
)
clrblock(&sblock
, acg
.cg_free
, d
/sblock
.fs_frag
);
for (d
= 0; d
< dlower
; d
+= sblock
.fs_frag
) {
setblock(&sblock
, acg
.cg_free
, d
/sblock
.fs_frag
);
acg
.cg_btot
[cbtocylno(&sblock
, d
)]++;
acg
.cg_b
[cbtocylno(&sblock
, d
)][cbtorpos(&sblock
, d
)]++;
sblock
.fs_dsize
+= dlower
;
sblock
.fs_dsize
+= acg
.cg_ndblk
- dupper
;
for (; d
< dupper
; d
+= sblock
.fs_frag
)
clrblock(&sblock
, acg
.cg_free
, d
/sblock
.fs_frag
);
acg
.cg_frsum
[d
- dupper
]++;
for (i
= d
- 1; i
>= dupper
; i
--) {
while ((d
+ sblock
.fs_frag
) <= dmax
- cbase
) {
setblock(&sblock
, acg
.cg_free
, d
/sblock
.fs_frag
);
acg
.cg_btot
[cbtocylno(&sblock
, d
)]++;
acg
.cg_b
[cbtocylno(&sblock
, d
)][cbtorpos(&sblock
, d
)]++;
acg
.cg_frsum
[dmax
- cbase
- d
]++;
for (; d
< dmax
- cbase
; d
++) {
for (; d
% sblock
.fs_frag
!= 0; d
++)
for (d
/= sblock
.fs_frag
; d
< MAXBPG(&sblock
); d
++)
clrblock(&sblock
, acg
.cg_free
, 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
), 1, "." },
{ ROOTINO
, sizeof(struct direct
), 2, ".." },
{ LOSTFOUNDINO
, sizeof(struct direct
), 10, "lost+found" },
struct direct lost_found_dir
[] = {
{ LOSTFOUNDINO
, sizeof(struct direct
), 1, "." },
{ ROOTINO
, sizeof(struct direct
), 2, ".." },
* create the lost+found directory
(void)makedir(lost_found_dir
, 2);
for (i
= DIRBLKSIZ
; i
< sblock
.fs_bsize
; i
+= DIRBLKSIZ
)
bcopy(&lost_found_dir
[2], &buf
[i
], DIRSIZ(&lost_found_dir
[2]));
node
.i_number
= LOSTFOUNDINO
;
node
.i_mode
= IFDIR
| UMASK
;
node
.i_size
= sblock
.fs_bsize
;
node
.i_db
[0] = alloc(node
.i_size
, node
.i_mode
);
node
.i_blocks
= howmany(node
.i_size
, DEV_BSIZE
);
wtfs(fsbtodb(&sblock
, node
.i_db
[0]), node
.i_size
, buf
);
* create the root directory
node
.i_mode
= IFDIR
| UMASK
;
node
.i_nlink
= PREDEFDIR
;
node
.i_size
= makedir(root_dir
, PREDEFDIR
);
node
.i_db
[0] = alloc(sblock
.fs_fsize
, node
.i_mode
);
node
.i_blocks
= howmany(node
.i_size
, DEV_BSIZE
);
wtfs(fsbtodb(&sblock
, node
.i_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(&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(&protodir
[i
]));
cp
+= DIRSIZ(&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
, 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_btot
[cbtocylno(&sblock
, d
)]--;
acg
.cg_b
[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(acg
.cg_free
, d
+ i
);
wtfs(fsbtodb(&sblock
, cgtod(&sblock
, 0)), sblock
.fs_cgsize
,
* Allocate an inode on the disk
register struct inode
*ip
;
struct dinode buf
[MAXINOPB
];
c
= itog(&sblock
, ip
->i_number
);
rdfs(fsbtodb(&sblock
, cgtod(&sblock
, 0)), sblock
.fs_cgsize
,
if (acg
.cg_magic
!= CG_MAGIC
) {
printf("cg 0: bad magic number\n");
setbit(acg
.cg_iused
, ip
->i_number
);
wtfs(fsbtodb(&sblock
, cgtod(&sblock
, 0)), sblock
.fs_cgsize
,
sblock
.fs_cstotal
.cs_nifree
--;
if(ip
->i_number
>= sblock
.fs_ipg
* sblock
.fs_ncg
) {
printf("fsinit: inode value out of range (%d).\n",
d
= fsbtodb(&sblock
, itod(&sblock
, ip
->i_number
));
rdfs(d
, sblock
.fs_bsize
, buf
);
buf
[itoo(&sblock
, ip
->i_number
)].di_ic
= ip
->i_ic
;
wtfs(d
, sblock
.fs_bsize
, buf
);
* read a block from the file system
if (lseek(fsi
, bno
* DEV_BSIZE
, 0) < 0) {
printf("seek error: %ld\n", bno
);
printf("read error: %ld\n", bno
);
* write a block to the file system
if (lseek(fso
, bno
* DEV_BSIZE
, 0) < 0) {
printf("seek error: %ld\n", bno
);
n
= write(fso
, bf
, size
);
printf("write error: %D\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
);