Changeset View
Changeset View
Standalone View
Standalone View
sys/fs/ext2fs/ext2_bmap.c
Show First 20 Lines • Show All 133 Lines • ▼ Show 20 Lines | if(ep) { | ||||
} | } | ||||
} | } | ||||
ext4_ext_path_free(path); | ext4_ext_path_free(path); | ||||
return (error); | return (error); | ||||
} | } | ||||
static int | |||||
readindir(struct vnode *vp, e2fs_lbn_t lbn, e2fs_daddr_t daddr, struct buf **bpp) | |||||
{ | |||||
struct buf *bp; | |||||
struct mount *mp; | |||||
struct ext2mount *ump; | |||||
int error; | |||||
mp = vp->v_mount; | |||||
ump = VFSTOEXT2(mp); | |||||
bp = getblk(vp, lbn, mp->mnt_stat.f_iosize, 0, 0, 0); | |||||
if ((bp->b_flags & B_CACHE) == 0) { | |||||
KASSERT(daddr != 0, | |||||
("readindir: indirect block not in cache")); | |||||
bp->b_blkno = blkptrtodb(ump, daddr); | |||||
bp->b_iocmd = BIO_READ; | |||||
bp->b_flags &= ~B_INVAL; | |||||
bp->b_ioflags &= ~BIO_ERROR; | |||||
vfs_busy_pages(bp, 0); | |||||
bp->b_iooffset = dbtob(bp->b_blkno); | |||||
bstrategy(bp); | |||||
#ifdef RACCT | |||||
if (racct_enable) { | |||||
PROC_LOCK(curproc); | |||||
racct_add_buf(curproc, bp, 0); | |||||
PROC_UNLOCK(curproc); | |||||
} | |||||
#endif | |||||
curthread->td_ru.ru_inblock++; | |||||
error = bufwait(bp); | |||||
if (error != 0) { | |||||
brelse(bp); | |||||
return (error); | |||||
} | |||||
} | |||||
*bpp = bp; | |||||
return (0); | |||||
} | |||||
/* | /* | ||||
* Indirect blocks are now on the vnode for the file. They are given negative | * Indirect blocks are now on the vnode for the file. They are given negative | ||||
* logical block numbers. Indirect blocks are addressed by the negative | * logical block numbers. Indirect blocks are addressed by the negative | ||||
* address of the first data block to which they point. Double indirect blocks | * address of the first data block to which they point. Double indirect blocks | ||||
* are addressed by one less than the address of the first indirect block to | * are addressed by one less than the address of the first indirect block to | ||||
* which they point. Triple indirect blocks are addressed by one less than | * which they point. Triple indirect blocks are addressed by one less than | ||||
* the address of the first double indirect block to which they point. | * the address of the first double indirect block to which they point. | ||||
* | * | ||||
▲ Show 20 Lines • Show All 73 Lines • ▼ Show 20 Lines | for (bp = NULL, ++ap; --num; ++ap) { | ||||
if ((daddr == 0 && !incore(&vp->v_bufobj, metalbn)) || metalbn == bn) | if ((daddr == 0 && !incore(&vp->v_bufobj, metalbn)) || metalbn == bn) | ||||
break; | break; | ||||
/* | /* | ||||
* If we get here, we've either got the block in the cache | * If we get here, we've either got the block in the cache | ||||
* or we have a disk address for it, go fetch it. | * or we have a disk address for it, go fetch it. | ||||
*/ | */ | ||||
if (bp) | if (bp) | ||||
bqrelse(bp); | bqrelse(bp); | ||||
error = readindir(vp, metalbn, daddr, &bp); | |||||
bp = getblk(vp, metalbn, bsize, 0, 0, 0); | if (error != 0) | ||||
if ((bp->b_flags & B_CACHE) == 0) { | |||||
#ifdef INVARIANTS | |||||
if (!daddr) | |||||
panic("ext2_bmaparray: indirect block not in cache"); | |||||
#endif | |||||
bp->b_blkno = blkptrtodb(ump, daddr); | |||||
bp->b_iocmd = BIO_READ; | |||||
bp->b_flags &= ~B_INVAL; | |||||
bp->b_ioflags &= ~BIO_ERROR; | |||||
vfs_busy_pages(bp, 0); | |||||
bp->b_iooffset = dbtob(bp->b_blkno); | |||||
bstrategy(bp); | |||||
#ifdef RACCT | |||||
if (racct_enable) { | |||||
PROC_LOCK(curproc); | |||||
racct_add_buf(curproc, bp, 0); | |||||
PROC_UNLOCK(curproc); | |||||
} | |||||
#endif | |||||
curthread->td_ru.ru_inblock++; | |||||
error = bufwait(bp); | |||||
if (error) { | |||||
brelse(bp); | |||||
return (error); | return (error); | ||||
} | |||||
} | |||||
daddr = ((e2fs_daddr_t *)bp->b_data)[ap->in_off]; | daddr = ((e2fs_daddr_t *)bp->b_data)[ap->in_off]; | ||||
if (num == 1 && daddr && runp) { | if (num == 1 && daddr && runp) { | ||||
for (bn = ap->in_off + 1; | for (bn = ap->in_off + 1; | ||||
bn < MNINDIR(ump) && *runp < maxrun && | bn < MNINDIR(ump) && *runp < maxrun && | ||||
is_sequential(ump, | is_sequential(ump, | ||||
((e2fs_daddr_t *)bp->b_data)[bn - 1], | ((e2fs_daddr_t *)bp->b_data)[bn - 1], | ||||
((e2fs_daddr_t *)bp->b_data)[bn]); | ((e2fs_daddr_t *)bp->b_data)[bn]); | ||||
Show All 22 Lines | if ((ip->i_flags & SF_SNAPSHOT) && daddr > 0 && daddr < ump->um_seqinc) { | ||||
*bnp = -1; | *bnp = -1; | ||||
return (0); | return (0); | ||||
} | } | ||||
*bnp = blkptrtodb(ump, daddr); | *bnp = blkptrtodb(ump, daddr); | ||||
if (*bnp == 0) { | if (*bnp == 0) { | ||||
*bnp = -1; | *bnp = -1; | ||||
} | } | ||||
return (0); | return (0); | ||||
} | |||||
static e2fs_lbn_t | |||||
lbn_count(struct ext2mount *ump, int level) | |||||
{ | |||||
e2fs_lbn_t blockcnt; | |||||
for (blockcnt = 1; level > 0; level--) | |||||
blockcnt *= MNINDIR(ump); | |||||
return (blockcnt); | |||||
} | |||||
int | |||||
ext2_bmap_seekdata(struct vnode *vp, off_t *offp) | |||||
{ | |||||
struct buf *bp; | |||||
struct indir a[EXT2_NIADDR + 1], *ap; | |||||
struct inode *ip; | |||||
struct mount *mp; | |||||
struct ext2mount *ump; | |||||
e2fs_daddr_t bn, daddr, nextbn; | |||||
uint64_t bsize; | |||||
off_t numblks; | |||||
int error, num, num1, off; | |||||
bp = NULL; | |||||
error = 0; | |||||
ip = VTOI(vp); | |||||
mp = vp->v_mount; | |||||
ump = VFSTOEXT2(mp); | |||||
if (vp->v_type != VREG || (ip->i_flags & SF_SNAPSHOT) != 0) | |||||
return (EINVAL); | |||||
if (*offp < 0 || *offp >= ip->i_size) | |||||
return (ENXIO); | |||||
bsize = mp->mnt_stat.f_iosize; | |||||
for (bn = *offp / bsize, numblks = howmany(ip->i_size, bsize); | |||||
bn < numblks; bn = nextbn) { | |||||
if (bn < EXT2_NDADDR) { | |||||
daddr = ip->i_db[bn]; | |||||
if (daddr != 0) | |||||
break; | |||||
nextbn = bn + 1; | |||||
continue; | |||||
} | |||||
ap = a; | |||||
error = ext2_getlbns(vp, bn, ap, &num); | |||||
if (error != 0) | |||||
break; | |||||
MPASS(num >= 2); | |||||
daddr = ip->i_ib[ap->in_off]; | |||||
ap++, num--; | |||||
for (nextbn = EXT2_NDADDR, num1 = num - 1; num1 > 0; num1--) | |||||
nextbn += lbn_count(ump, num1); | |||||
if (daddr == 0) { | |||||
nextbn += lbn_count(ump, num); | |||||
continue; | |||||
} | |||||
for (; daddr != 0 && num > 0; ap++, num--) { | |||||
if (bp != NULL) | |||||
bqrelse(bp); | |||||
error = readindir(vp, ap->in_lbn, daddr, &bp); | |||||
if (error != 0) | |||||
return (error); | |||||
/* | |||||
* Scan the indirect block until we find a non-zero | |||||
* pointer. | |||||
*/ | |||||
off = ap->in_off; | |||||
do { | |||||
daddr = ((e2fs_daddr_t *)bp->b_data)[off]; | |||||
} while (daddr == 0 && ++off < MNINDIR(ump)); | |||||
nextbn += off * lbn_count(ump, num - 1); | |||||
/* | |||||
* We need to recompute the LBNs of indirect | |||||
* blocks, so restart with the updated block offset. | |||||
*/ | |||||
if (off != ap->in_off) | |||||
break; | |||||
} | |||||
if (num == 0) { | |||||
/* | |||||
* We found a data block. | |||||
*/ | |||||
bn = nextbn; | |||||
break; | |||||
} | |||||
} | |||||
if (bp != NULL) | |||||
bqrelse(bp); | |||||
if (bn >= numblks) | |||||
error = ENXIO; | |||||
if (error == 0 && *offp < bn * bsize) | |||||
*offp = bn * bsize; | |||||
return (error); | |||||
} | } | ||||
/* | /* | ||||
* Create an array of logical block number/offset pairs which represent the | * Create an array of logical block number/offset pairs which represent the | ||||
* path of indirect blocks required to access a data block. The first "pair" | * path of indirect blocks required to access a data block. The first "pair" | ||||
* contains the logical block number of the appropriate single, double or | * contains the logical block number of the appropriate single, double or | ||||
* triple indirect block and the offset into the inode indirect block array. | * triple indirect block and the offset into the inode indirect block array. | ||||
* Note, the logical block number of the inode single/double/triple indirect | * Note, the logical block number of the inode single/double/triple indirect | ||||
▲ Show 20 Lines • Show All 79 Lines • Show Last 20 Lines |