* Copyright (c) 1982, 1986, 1989, 1993
* The Regents of the University of California. All rights reserved.
* 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
* @(#)ffs_balloc.c 8.4 (Berkeley) 9/23/93
#include <ufs/ufs/quota.h>
#include <ufs/ufs/inode.h>
#include <ufs/ufs/ufs_extern.h>
#include <ufs/ffs/ffs_extern.h>
* 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.
ffs_balloc(ip
, bn
, size
, cred
, bpp
, flags
)
register struct inode
*ip
;
struct vnode
*vp
= ITOV(ip
);
struct indir indirs
[NIADDR
+ 2];
daddr_t newb
, lbn
, *bap
, pref
;
int osize
, nsize
, num
, i
, error
;
* 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
= ffs_realloccg(ip
, nb
,
ffs_blkpref(ip
, nb
, (int)nb
, &ip
->i_db
[0]),
osize
, (int)fs
->fs_bsize
, cred
, &bp
);
ip
->i_size
= (nb
+ 1) * fs
->fs_bsize
;
vnode_pager_setsize(vp
, (u_long
)ip
->i_size
);
ip
->i_db
[nb
] = dbtofsb(fs
, bp
->b_blkno
);
ip
->i_flag
|= IN_CHANGE
| IN_UPDATE
;
* 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
= ffs_realloccg(ip
, bn
,
ffs_blkpref(ip
, bn
, (int)bn
, &ip
->i_db
[0]),
osize
, nsize
, cred
, &bp
);
if (ip
->i_size
< (bn
+ 1) * fs
->fs_bsize
)
nsize
= fragroundup(fs
, size
);
error
= ffs_alloc(ip
, bn
,
ffs_blkpref(ip
, bn
, (int)bn
, &ip
->i_db
[0]),
bp
= getblk(vp
, bn
, nsize
, 0, 0);
bp
->b_blkno
= fsbtodb(fs
, newb
);
ip
->i_db
[bn
] = dbtofsb(fs
, bp
->b_blkno
);
ip
->i_flag
|= IN_CHANGE
| IN_UPDATE
;
* Determine the number of levels of indirection.
if (error
= ufs_getlbns(vp
, bn
, indirs
, &num
))
panic ("ffs_balloc: ufs_bmaparray returned indirect block\n");
* Fetch the first indirect block allocating if necessary.
nb
= ip
->i_ib
[indirs
[0].in_off
];
pref
= ffs_blkpref(ip
, lbn
, 0, (daddr_t
*)0);
if (error
= ffs_alloc(ip
, lbn
, pref
, (int)fs
->fs_bsize
,
bp
= getblk(vp
, indirs
[1].in_lbn
, fs
->fs_bsize
, 0, 0);
bp
->b_blkno
= fsbtodb(fs
, newb
);
* Write synchronously so that indirect blocks
* never point at garbage.
if (error
= bwrite(bp
)) {
ffs_blkfree(ip
, nb
, fs
->fs_bsize
);
ip
->i_ib
[indirs
[0].in_off
] = newb
;
ip
->i_flag
|= IN_CHANGE
| IN_UPDATE
;
* Fetch through the indirect blocks, allocating as necessary.
indirs
[i
].in_lbn
, (int)fs
->fs_bsize
, NOCRED
, &bp
);
bap
= (daddr_t
*)bp
->b_data
;
nb
= bap
[indirs
[i
].in_off
];
pref
= ffs_blkpref(ip
, lbn
, 0, (daddr_t
*)0);
ffs_alloc(ip
, lbn
, pref
, (int)fs
->fs_bsize
, cred
, &newb
)) {
nbp
= getblk(vp
, indirs
[i
].in_lbn
, fs
->fs_bsize
, 0, 0);
nbp
->b_blkno
= fsbtodb(fs
, nb
);
* Write synchronously so that indirect blocks
* never point at garbage.
if (error
= bwrite(nbp
)) {
ffs_blkfree(ip
, nb
, fs
->fs_bsize
);
bap
[indirs
[i
- 1].in_off
] = nb
;
* If required, write synchronously, otherwise use
* Get the data block, allocating if necessary.
pref
= ffs_blkpref(ip
, lbn
, indirs
[i
].in_off
, &bap
[0]);
if (error
= ffs_alloc(ip
,
lbn
, pref
, (int)fs
->fs_bsize
, cred
, &newb
)) {
nbp
= getblk(vp
, lbn
, fs
->fs_bsize
, 0, 0);
nbp
->b_blkno
= fsbtodb(fs
, nb
);
bap
[indirs
[i
].in_off
] = nb
;
* If required, write synchronously, otherwise use
error
= bread(vp
, lbn
, (int)fs
->fs_bsize
, NOCRED
, &nbp
);
nbp
= getblk(vp
, lbn
, fs
->fs_bsize
, 0, 0);
nbp
->b_blkno
= fsbtodb(fs
, nb
);