* Copyright (c) 1982, 1986, 1989 Regents of the University of California.
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
* @(#)ffs_balloc.c 7.4 (Berkeley) %G%
#include "../ufs/inode.h"
* 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
, bnp
, rablockp
, rasizep
)
register struct inode
*ip
;
* The first NDADDR blocks are direct blocks
if (rablockp
&& rasizep
) {
*rablockp
= fsbtodb(fs
, ip
->i_db
[bn
+ 1]);
*rasizep
= 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
];
* fetch through the indirect blocks
for (; j
<= NIADDR
; j
++) {
if (error
= bread(ip
->i_devvp
, fsbtodb(fs
, nb
),
(int)fs
->fs_bsize
, &bp
)) {
i
= (bn
/ sh
) % NINDIR(fs
);
if (rablockp
&& rasizep
) {
if (i
< NINDIR(fs
) - 1) {
*rablockp
= fsbtodb(fs
, bap
[i
+ 1]);
* Balloc 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 unallocated entries are found, new physical blocks
balloc(ip
, bn
, size
, bnp
, flags
)
register struct inode
*ip
;
int osize
, nsize
, i
, j
, sh
, error
;
daddr_t lbn
, *bap
, pref
, blkpref();
* 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 (nb
< NDADDR
&& nb
< bn
) {
osize
= blksize(fs
, ip
, nb
);
if (osize
< fs
->fs_bsize
&& osize
> 0) {
error
= realloccg(ip
, ip
->i_db
[nb
],
blkpref(ip
, nb
, (int)nb
, &ip
->i_db
[0]),
osize
, (int)fs
->fs_bsize
, &bp
);
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
);
error
= realloccg(ip
, nb
,
blkpref(ip
, bn
, (int)bn
, &ip
->i_db
[0]),
if (ip
->i_size
< (bn
+ 1) * fs
->fs_bsize
)
nsize
= fragroundup(fs
, size
);
blkpref(ip
, bn
, (int)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
* NB: Should free space and return error
* if bwrite returns an error.
* 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, (daddr_t
*)0);
error
= alloc(ip
, pref
, (int)fs
->fs_bsize
, &bp
, B_CLRBUF
);
nb
= dbtofsb(fs
, bp
->b_blkno
);
* Write synchronously so that indirect blocks
* never point at garbage.
* NB: Should free space and return error
* if bwrite returns an error.
ip
->i_ib
[NIADDR
- j
] = nb
;
* fetch through the indirect blocks
for (; j
<= NIADDR
; j
++) {
bp
= bread(ip
->i_dev
, fsbtodb(fs
, nb
), (int)fs
->fs_bsize
,
if (error
= bread(ip
->i_devvp
, fsbtodb(fs
, nb
),
(int)fs
->fs_bsize
, &bp
)) {
i
= (bn
/ sh
) % NINDIR(fs
);
pref
= blkpref(ip
, lbn
, 0,
pref
= blkpref(ip
, lbn
, i
, &bap
[0]);
error
= alloc(ip
, pref
, (int)fs
->fs_bsize
, &nbp
,
(j
< NIADDR
) ? B_CLRBUF
: flags
);
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.
* NB: Should free space and return error
* if bwrite returns an error.