/* lfs_balloc.c 5.2 82/09/25 */
* Bmap defines the structure of file system storage
* by returning the physical block number on a device given the
* inode and the logical block number in a file.
* When convenient, it also leaves the physical
* block number of the next block of the file in rablock
bmap(ip
, bn
, rwflg
, size
)
register struct inode
*ip
;
int size
; /* supplied only when rwflg == B_WRITE */
daddr_t nb
, lbn
, *bap
, pref
, blkpref();
rasize
= 0; /* conservative */
* If the next write will extend the file into a new block,
* and the file is currently composed of a fragment
* this fragment has to be extended to be a full block.
nb
= lblkno(fs
, ip
->i_size
);
if (rwflg
== B_WRITE
&& nb
< NDADDR
&& nb
< bn
) {
osize
= blksize(fs
, ip
, nb
);
if (osize
< fs
->fs_bsize
&& osize
> 0) {
bp
= realloccg(ip
, ip
->i_db
[nb
],
blkpref(ip
, nb
, nb
, &ip
->i_db
[0]),
ip
->i_size
= (nb
+ 1) * fs
->fs_bsize
;
ip
->i_db
[nb
] = dbtofsb(fs
, bp
->b_blkno
);
* The first NDADDR blocks are direct blocks
if (nb
== 0 || ip
->i_size
< (bn
+ 1) * fs
->fs_bsize
) {
/* consider need to reallocate a frag */
osize
= fragroundup(fs
, blkoff(fs
, ip
->i_size
));
nsize
= fragroundup(fs
, size
);
blkpref(ip
, bn
, bn
, &ip
->i_db
[0]),
if (ip
->i_size
< (bn
+ 1) * fs
->fs_bsize
)
nsize
= fragroundup(fs
, size
);
blkpref(ip
, bn
, bn
, &ip
->i_db
[0]),
nb
= dbtofsb(fs
, bp
->b_blkno
);
if ((ip
->i_mode
&IFMT
) == IFDIR
)
* Write directory blocks synchronously
* so they never appear with garbage in
rablock
= fsbtodb(fs
, ip
->i_db
[bn
+ 1]);
rasize
= blksize(fs
, ip
, bn
+ 1);
* Determine how many levels of indirection.
for (j
= NIADDR
; j
>0; j
--) {
* fetch the first indirect block
nb
= ip
->i_ib
[NIADDR
- j
];
pref
= blkpref(ip
, lbn
, 0, 0);
bp
= alloc(ip
, pref
, fs
->fs_bsize
);
nb
= dbtofsb(fs
, bp
->b_blkno
);
* Write synchronously so that indirect blocks
* never point at garbage.
ip
->i_ib
[NIADDR
- j
] = nb
;
* fetch through the indirect blocks
for (; j
<= NIADDR
; j
++) {
bp
= bread(ip
->i_dev
, fsbtodb(fs
, nb
), fs
->fs_bsize
);
if (bp
->b_flags
& B_ERROR
) {
i
= (bn
/ sh
) % NINDIR(fs
);
pref
= blkpref(ip
, lbn
, 0, 0);
pref
= blkpref(ip
, lbn
, i
, &bap
[0]);
nbp
= alloc(ip
, pref
, fs
->fs_bsize
);
nb
= dbtofsb(fs
, nbp
->b_blkno
);
if (j
< NIADDR
|| (ip
->i_mode
&IFMT
) == IFDIR
)
* Write synchronously so indirect blocks
* never point at garbage and blocks
* in directories never contain garbage.
if (i
< NINDIR(fs
) - 1) {
rablock
= fsbtodb(fs
, bap
[i
+1]);