* Copyright (c) 1982, 1986, 1989 Regents of the University of California.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* @(#)ufs_bmap.c 7.13 (Berkeley) 5/8/91
* Bmap converts a the logical block number of a file
* to its physical block number on the disk. The conversion
* is done by using the logical block number to index into
* the array of block pointers described by the dinode.
register struct inode
*ip
;
* The first NDADDR blocks are direct blocks
* Determine the number of levels of indirection.
for (j
= NIADDR
; j
> 0; j
--) {
* Fetch through the indirect blocks.
nb
= ip
->i_ib
[NIADDR
- j
];
for (; j
<= NIADDR
; j
++) {
if (error
= bread(ip
->i_devvp
, fsbtodb(fs
, nb
),
(int)fs
->fs_bsize
, NOCRED
, &bp
)) {
i
= (bn
/ sh
) % NINDIR(fs
);
* Balloc defines the structure of file system storage
* by allocating the physical blocks on a device given
* the inode and the logical block number in a file.
balloc(ip
, bn
, size
, bpp
, flags
)
register struct inode
*ip
;
struct vnode
*vp
= ITOV(ip
);
int osize
, nsize
, i
, j
, sh
, error
;
daddr_t newb
, 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
, nb
,
blkpref(ip
, nb
, (int)nb
, &ip
->i_db
[0]),
osize
, (int)fs
->fs_bsize
, &bp
);
ip
->i_size
= (nb
+ 1) * fs
->fs_bsize
;
vnode_pager_setsize(ITOV(ip
), (u_long
)ip
->i_size
);
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
) {
error
= bread(vp
, bn
, fs
->fs_bsize
, NOCRED
, &bp
);
* Consider need to reallocate a fragment.
osize
= fragroundup(fs
, blkoff(fs
, ip
->i_size
));
nsize
= fragroundup(fs
, size
);
error
= bread(vp
, bn
, osize
, NOCRED
, &bp
);
error
= realloccg(ip
, bn
,
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]),
bp
= getblk(vp
, bn
, nsize
);
bp
->b_blkno
= fsbtodb(fs
, newb
);
ip
->i_db
[bn
] = dbtofsb(fs
, bp
->b_blkno
);
* Determine the number of levels of indirection.
for (j
= NIADDR
; j
> 0; j
--) {
* Fetch the first indirect block allocating if necessary.
nb
= ip
->i_ib
[NIADDR
- j
];
pref
= blkpref(ip
, lbn
, 0, (daddr_t
*)0);
if (error
= alloc(ip
, lbn
, pref
, (int)fs
->fs_bsize
, &newb
))
bp
= getblk(ip
->i_devvp
, fsbtodb(fs
, nb
), fs
->fs_bsize
);
* Write synchronously so that indirect blocks
* never point at garbage.
if (error
= bwrite(bp
)) {
blkfree(ip
, nb
, fs
->fs_bsize
);
ip
->i_ib
[NIADDR
- j
] = nb
;
* Fetch through the indirect blocks, allocating as necessary.
error
= bread(ip
->i_devvp
, fsbtodb(fs
, nb
),
(int)fs
->fs_bsize
, NOCRED
, &bp
);
i
= (bn
/ sh
) % NINDIR(fs
);
pref
= blkpref(ip
, lbn
, 0, (daddr_t
*)0);
if (error
= alloc(ip
, lbn
, pref
, (int)fs
->fs_bsize
, &newb
)) {
nbp
= getblk(ip
->i_devvp
, fsbtodb(fs
, nb
), fs
->fs_bsize
);
* Write synchronously so that indirect blocks
* never point at garbage.
if (error
= bwrite(nbp
)) {
blkfree(ip
, nb
, fs
->fs_bsize
);
* If required, write synchronously, otherwise use
* delayed write. If this is the first instance of
* the delayed write, reassociate the buffer with the
* file so it will be written if the file is sync'ed.
} else if (bp
->b_flags
& B_DELWRI
) {
* Get the data block, allocating if necessary.
pref
= blkpref(ip
, lbn
, i
, &bap
[0]);
if (error
= alloc(ip
, lbn
, pref
, (int)fs
->fs_bsize
, &newb
)) {
nbp
= getblk(vp
, lbn
, fs
->fs_bsize
);
nbp
->b_blkno
= fsbtodb(fs
, nb
);
* If required, write synchronously, otherwise use
* delayed write. If this is the first instance of
* the delayed write, reassociate the buffer with the
* file so it will be written if the file is sync'ed.
} else if (bp
->b_flags
& B_DELWRI
) {
error
= bread(vp
, lbn
, (int)fs
->fs_bsize
, NOCRED
, &nbp
);
nbp
= getblk(vp
, lbn
, fs
->fs_bsize
);
nbp
->b_blkno
= fsbtodb(fs
, nb
);