Changeset View
Changeset View
Standalone View
Standalone View
sys/fs/ext2fs/ext2_balloc.c
Show All 36 Lines | |||||
* @(#)ffs_balloc.c 8.4 (Berkeley) 9/23/93 | * @(#)ffs_balloc.c 8.4 (Berkeley) 9/23/93 | ||||
* $FreeBSD$ | * $FreeBSD$ | ||||
*/ | */ | ||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <sys/bio.h> | #include <sys/bio.h> | ||||
#include <sys/buf.h> | #include <sys/buf.h> | ||||
#include <sys/limits.h> | |||||
#include <sys/lock.h> | #include <sys/lock.h> | ||||
#include <sys/mount.h> | #include <sys/mount.h> | ||||
#include <sys/vnode.h> | #include <sys/vnode.h> | ||||
#include <fs/ext2fs/fs.h> | #include <fs/ext2fs/fs.h> | ||||
#include <fs/ext2fs/inode.h> | #include <fs/ext2fs/inode.h> | ||||
#include <fs/ext2fs/ext2fs.h> | #include <fs/ext2fs/ext2fs.h> | ||||
#include <fs/ext2fs/ext2_dinode.h> | #include <fs/ext2fs/ext2_dinode.h> | ||||
#include <fs/ext2fs/ext2_extern.h> | #include <fs/ext2fs/ext2_extern.h> | ||||
#include <fs/ext2fs/ext2_mount.h> | #include <fs/ext2fs/ext2_mount.h> | ||||
static int | static int | ||||
ext2_ext_balloc(struct inode *ip, uint32_t lbn, int size, | ext2_ext_balloc(struct inode *ip, uint32_t lbn, int size, | ||||
struct ucred *cred, struct buf **bpp, int flags) | struct ucred *cred, struct buf **bpp, int flags) | ||||
{ | { | ||||
struct m_ext2fs *fs; | struct m_ext2fs *fs; | ||||
struct buf *bp = NULL; | struct buf *bp = NULL; | ||||
struct vnode *vp = ITOV(ip); | struct vnode *vp = ITOV(ip); | ||||
uint32_t nb; | daddr_t newblk; | ||||
int osize, nsize, blks, error, allocated; | int osize, nsize, blks, error, allocated; | ||||
fs = ip->i_e2fs; | fs = ip->i_e2fs; | ||||
blks = howmany(size, fs->e2fs_bsize); | blks = howmany(size, fs->e2fs_bsize); | ||||
error = ext4_ext_get_blocks(ip, lbn, blks, cred, NULL, &allocated, &nb); | error = ext4_ext_get_blocks(ip, lbn, blks, cred, NULL, &allocated, &newblk); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
if (allocated) { | if (allocated) { | ||||
if (ip->i_size < (lbn + 1) * fs->e2fs_bsize) | if (ip->i_size < (lbn + 1) * fs->e2fs_bsize) | ||||
nsize = fragroundup(fs, size); | nsize = fragroundup(fs, size); | ||||
else | else | ||||
nsize = fs->e2fs_bsize; | nsize = fs->e2fs_bsize; | ||||
bp = getblk(vp, lbn, nsize, 0, 0, 0); | bp = getblk(vp, lbn, nsize, 0, 0, 0); | ||||
if(!bp) | if(!bp) | ||||
return (EIO); | return (EIO); | ||||
bp->b_blkno = fsbtodb(fs, nb); | bp->b_blkno = fsbtodb(fs, newblk); | ||||
if (flags & BA_CLRBUF) | if (flags & BA_CLRBUF) | ||||
vfs_bio_clrbuf(bp); | vfs_bio_clrbuf(bp); | ||||
} else { | } else { | ||||
if (ip->i_size >= (lbn + 1) * fs->e2fs_bsize) { | if (ip->i_size >= (lbn + 1) * fs->e2fs_bsize) { | ||||
error = bread(vp, lbn, fs->e2fs_bsize, NOCRED, &bp); | error = bread(vp, lbn, fs->e2fs_bsize, NOCRED, &bp); | ||||
if (error) { | if (error) { | ||||
brelse(bp); | brelse(bp); | ||||
return (error); | return (error); | ||||
} | } | ||||
bp->b_blkno = fsbtodb(fs, nb); | bp->b_blkno = fsbtodb(fs, newblk); | ||||
*bpp = bp; | *bpp = bp; | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Consider need to reallocate a fragment. | * Consider need to reallocate a fragment. | ||||
*/ | */ | ||||
osize = fragroundup(fs, blkoff(fs, ip->i_size)); | osize = fragroundup(fs, blkoff(fs, ip->i_size)); | ||||
nsize = fragroundup(fs, size); | nsize = fragroundup(fs, size); | ||||
if (nsize <= osize) { | if (nsize <= osize) | ||||
error = bread(vp, lbn, osize, NOCRED, &bp); | error = bread(vp, lbn, osize, NOCRED, &bp); | ||||
if (error) { | else | ||||
brelse(bp); | |||||
return (error); | |||||
} | |||||
bp->b_blkno = fsbtodb(fs, nb); | |||||
} else { | |||||
error = bread(vp, lbn, fs->e2fs_bsize, NOCRED, &bp); | error = bread(vp, lbn, fs->e2fs_bsize, NOCRED, &bp); | ||||
if (error) { | if (error) { | ||||
brelse(bp); | brelse(bp); | ||||
return (error); | return (error); | ||||
} | } | ||||
bp->b_blkno = fsbtodb(fs, nb); | bp->b_blkno = fsbtodb(fs, newblk); | ||||
} | } | ||||
} | |||||
*bpp = bp; | *bpp = bp; | ||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* Balloc defines the structure of filesystem storage | * Balloc defines the structure of filesystem storage | ||||
▲ Show 20 Lines • Show All 85 Lines • ▼ Show 20 Lines | */ | ||||
else | else | ||||
nsize = fs->e2fs_bsize; | nsize = fs->e2fs_bsize; | ||||
EXT2_LOCK(ump); | EXT2_LOCK(ump); | ||||
error = ext2_alloc(ip, lbn, | error = ext2_alloc(ip, lbn, | ||||
ext2_blkpref(ip, lbn, (int)lbn, &ip->i_db[0], 0), | ext2_blkpref(ip, lbn, (int)lbn, &ip->i_db[0], 0), | ||||
nsize, cred, &newb); | nsize, cred, &newb); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
/* | |||||
* If the newly allocated block exceeds 32-bit limit, | |||||
* we can not use it in file block maps. | |||||
*/ | |||||
if (newb > UINT_MAX) | |||||
return (EFBIG); | |||||
bp = getblk(vp, lbn, nsize, 0, 0, 0); | bp = getblk(vp, lbn, nsize, 0, 0, 0); | ||||
bp->b_blkno = fsbtodb(fs, newb); | bp->b_blkno = fsbtodb(fs, newb); | ||||
if (flags & BA_CLRBUF) | if (flags & BA_CLRBUF) | ||||
vfs_bio_clrbuf(bp); | vfs_bio_clrbuf(bp); | ||||
} | } | ||||
ip->i_db[lbn] = dbtofsb(fs, bp->b_blkno); | ip->i_db[lbn] = dbtofsb(fs, bp->b_blkno); | ||||
ip->i_flag |= IN_CHANGE | IN_UPDATE; | ip->i_flag |= IN_CHANGE | IN_UPDATE; | ||||
*bpp = bp; | *bpp = bp; | ||||
Show All 16 Lines | #endif | ||||
nb = ip->i_ib[indirs[0].in_off]; | nb = ip->i_ib[indirs[0].in_off]; | ||||
if (nb == 0) { | if (nb == 0) { | ||||
EXT2_LOCK(ump); | EXT2_LOCK(ump); | ||||
pref = ext2_blkpref(ip, lbn, indirs[0].in_off + | pref = ext2_blkpref(ip, lbn, indirs[0].in_off + | ||||
EXT2_NDIR_BLOCKS, &ip->i_db[0], 0); | EXT2_NDIR_BLOCKS, &ip->i_db[0], 0); | ||||
if ((error = ext2_alloc(ip, lbn, pref, fs->e2fs_bsize, cred, | if ((error = ext2_alloc(ip, lbn, pref, fs->e2fs_bsize, cred, | ||||
&newb))) | &newb))) | ||||
return (error); | return (error); | ||||
if (newb > UINT_MAX) | |||||
return (EFBIG); | |||||
nb = newb; | nb = newb; | ||||
bp = getblk(vp, indirs[1].in_lbn, fs->e2fs_bsize, 0, 0, 0); | bp = getblk(vp, indirs[1].in_lbn, fs->e2fs_bsize, 0, 0, 0); | ||||
bp->b_blkno = fsbtodb(fs, newb); | bp->b_blkno = fsbtodb(fs, newb); | ||||
vfs_bio_clrbuf(bp); | vfs_bio_clrbuf(bp); | ||||
/* | /* | ||||
* Write synchronously so that indirect blocks | * Write synchronously so that indirect blocks | ||||
* never point at garbage. | * never point at garbage. | ||||
*/ | */ | ||||
Show All 27 Lines | for (i = 1;;) { | ||||
if (pref == 0) | if (pref == 0) | ||||
pref = ext2_blkpref(ip, lbn, indirs[i].in_off, bap, | pref = ext2_blkpref(ip, lbn, indirs[i].in_off, bap, | ||||
bp->b_lblkno); | bp->b_lblkno); | ||||
error = ext2_alloc(ip, lbn, pref, (int)fs->e2fs_bsize, cred, &newb); | error = ext2_alloc(ip, lbn, pref, (int)fs->e2fs_bsize, cred, &newb); | ||||
if (error) { | if (error) { | ||||
brelse(bp); | brelse(bp); | ||||
return (error); | return (error); | ||||
} | } | ||||
if (newb > UINT_MAX) | |||||
return (EFBIG); | |||||
nb = newb; | nb = newb; | ||||
nbp = getblk(vp, indirs[i].in_lbn, fs->e2fs_bsize, 0, 0, 0); | nbp = getblk(vp, indirs[i].in_lbn, fs->e2fs_bsize, 0, 0, 0); | ||||
nbp->b_blkno = fsbtodb(fs, nb); | nbp->b_blkno = fsbtodb(fs, nb); | ||||
vfs_bio_clrbuf(nbp); | vfs_bio_clrbuf(nbp); | ||||
/* | /* | ||||
* Write synchronously so that indirect blocks | * Write synchronously so that indirect blocks | ||||
* never point at garbage. | * never point at garbage. | ||||
*/ | */ | ||||
Show All 23 Lines | if (nb == 0) { | ||||
EXT2_LOCK(ump); | EXT2_LOCK(ump); | ||||
pref = ext2_blkpref(ip, lbn, indirs[i].in_off, &bap[0], | pref = ext2_blkpref(ip, lbn, indirs[i].in_off, &bap[0], | ||||
bp->b_lblkno); | bp->b_lblkno); | ||||
if ((error = ext2_alloc(ip, | if ((error = ext2_alloc(ip, | ||||
lbn, pref, (int)fs->e2fs_bsize, cred, &newb)) != 0) { | lbn, pref, (int)fs->e2fs_bsize, cred, &newb)) != 0) { | ||||
brelse(bp); | brelse(bp); | ||||
return (error); | return (error); | ||||
} | } | ||||
if (newb > UINT_MAX) | |||||
return (EFBIG); | |||||
nb = newb; | nb = newb; | ||||
nbp = getblk(vp, lbn, fs->e2fs_bsize, 0, 0, 0); | nbp = getblk(vp, lbn, fs->e2fs_bsize, 0, 0, 0); | ||||
nbp->b_blkno = fsbtodb(fs, nb); | nbp->b_blkno = fsbtodb(fs, nb); | ||||
if (flags & BA_CLRBUF) | if (flags & BA_CLRBUF) | ||||
vfs_bio_clrbuf(nbp); | vfs_bio_clrbuf(nbp); | ||||
bap[indirs[i].in_off] = nb; | bap[indirs[i].in_off] = nb; | ||||
/* | /* | ||||
* If required, write synchronously, otherwise use | * If required, write synchronously, otherwise use | ||||
Show All 34 Lines |