Currently the breadn_flags() and getblkx() interfaces are passed
the vnode, logical block number, and size of data block that is being requested. They then use the VOP_BMAP function to calculate the mapping from logical block number to physical block number from which to access the data. This change expands the interface to also pass the physical block number in cases where the VOP_MAP function may no longer work, for example when a file is being truncated. No functional change. Reviewed by: kib Tested by: Peter Holm Sponsored by: Netflix
This commit is contained in:
parent
49cbef7749
commit
d137f58263
@ -2126,10 +2126,17 @@ breada(struct vnode * vp, daddr_t * rablkno, int * rabsize, int cnt,
|
||||
* getblk(). Also starts asynchronous I/O on read-ahead blocks.
|
||||
*
|
||||
* Always return a NULL buffer pointer (in bpp) when returning an error.
|
||||
*
|
||||
* The blkno parameter is the logical block being requested. Normally
|
||||
* the mapping of logical block number to disk block address is done
|
||||
* by calling VOP_BMAP(). However, if the mapping is already known, the
|
||||
* disk block address can be passed using the dblkno parameter. If the
|
||||
* disk block address is not known, then the same value should be passed
|
||||
* for blkno and dblkno.
|
||||
*/
|
||||
int
|
||||
breadn_flags(struct vnode *vp, daddr_t blkno, int size, daddr_t *rablkno,
|
||||
int *rabsize, int cnt, struct ucred *cred, int flags,
|
||||
breadn_flags(struct vnode *vp, daddr_t blkno, daddr_t dblkno, int size,
|
||||
daddr_t *rablkno, int *rabsize, int cnt, struct ucred *cred, int flags,
|
||||
void (*ckhashfunc)(struct buf *), struct buf **bpp)
|
||||
{
|
||||
struct buf *bp;
|
||||
@ -2142,11 +2149,14 @@ breadn_flags(struct vnode *vp, daddr_t blkno, int size, daddr_t *rablkno,
|
||||
* Can only return NULL if GB_LOCK_NOWAIT or GB_SPARSE flags
|
||||
* are specified.
|
||||
*/
|
||||
error = getblkx(vp, blkno, size, 0, 0, flags, &bp);
|
||||
error = getblkx(vp, blkno, dblkno, size, 0, 0, flags, &bp);
|
||||
if (error != 0) {
|
||||
*bpp = NULL;
|
||||
return (error);
|
||||
}
|
||||
KASSERT(blkno == bp->b_lblkno,
|
||||
("getblkx returned buffer for blkno %jd instead of blkno %jd",
|
||||
(intmax_t)bp->b_lblkno, (intmax_t)blkno));
|
||||
flags &= ~GB_NOSPARSE;
|
||||
*bpp = bp;
|
||||
|
||||
@ -3791,7 +3801,7 @@ getblk(struct vnode *vp, daddr_t blkno, int size, int slpflag, int slptimeo,
|
||||
struct buf *bp;
|
||||
int error;
|
||||
|
||||
error = getblkx(vp, blkno, size, slpflag, slptimeo, flags, &bp);
|
||||
error = getblkx(vp, blkno, blkno, size, slpflag, slptimeo, flags, &bp);
|
||||
if (error != 0)
|
||||
return (NULL);
|
||||
return (bp);
|
||||
@ -3819,7 +3829,7 @@ getblk(struct vnode *vp, daddr_t blkno, int size, int slpflag, int slptimeo,
|
||||
* case it is returned with B_INVAL clear and B_CACHE set based on the
|
||||
* backing VM.
|
||||
*
|
||||
* getblk() also forces a bwrite() for any B_DELWRI buffer whos
|
||||
* getblk() also forces a bwrite() for any B_DELWRI buffer whose
|
||||
* B_CACHE bit is clear.
|
||||
*
|
||||
* What this means, basically, is that the caller should use B_CACHE to
|
||||
@ -3832,10 +3842,17 @@ getblk(struct vnode *vp, daddr_t blkno, int size, int slpflag, int slptimeo,
|
||||
* a write attempt or if it was a successful read. If the caller
|
||||
* intends to issue a READ, the caller must clear B_INVAL and BIO_ERROR
|
||||
* prior to issuing the READ. biodone() will *not* clear B_INVAL.
|
||||
*
|
||||
* The blkno parameter is the logical block being requested. Normally
|
||||
* the mapping of logical block number to disk block address is done
|
||||
* by calling VOP_BMAP(). However, if the mapping is already known, the
|
||||
* disk block address can be passed using the dblkno parameter. If the
|
||||
* disk block address is not known, then the same value should be passed
|
||||
* for blkno and dblkno.
|
||||
*/
|
||||
int
|
||||
getblkx(struct vnode *vp, daddr_t blkno, int size, int slpflag, int slptimeo,
|
||||
int flags, struct buf **bpp)
|
||||
getblkx(struct vnode *vp, daddr_t blkno, daddr_t dblkno, int size, int slpflag,
|
||||
int slptimeo, int flags, struct buf **bpp)
|
||||
{
|
||||
struct buf *bp;
|
||||
struct bufobj *bo;
|
||||
@ -3854,7 +3871,7 @@ getblkx(struct vnode *vp, daddr_t blkno, int size, int slpflag, int slptimeo,
|
||||
flags &= ~(GB_UNMAPPED | GB_KVAALLOC);
|
||||
|
||||
bo = &vp->v_bufobj;
|
||||
d_blkno = blkno;
|
||||
d_blkno = dblkno;
|
||||
loop:
|
||||
BO_RLOCK(bo);
|
||||
bp = gbincore(bo, blkno);
|
||||
|
@ -131,7 +131,7 @@ cluster_read(struct vnode *vp, u_quad_t filesize, daddr_t lblkno, long size,
|
||||
/*
|
||||
* get the requested block
|
||||
*/
|
||||
error = getblkx(vp, lblkno, size, 0, 0, gbflags, &bp);
|
||||
error = getblkx(vp, lblkno, lblkno, size, 0, 0, gbflags, &bp);
|
||||
if (error != 0) {
|
||||
*bpp = NULL;
|
||||
return (error);
|
||||
|
@ -520,15 +520,16 @@ int buf_dirty_count_severe(void);
|
||||
void bremfree(struct buf *);
|
||||
void bremfreef(struct buf *); /* XXX Force bremfree, only for nfs. */
|
||||
#define bread(vp, blkno, size, cred, bpp) \
|
||||
breadn_flags(vp, blkno, size, NULL, NULL, 0, cred, 0, NULL, bpp)
|
||||
breadn_flags(vp, blkno, blkno, size, NULL, NULL, 0, cred, 0, \
|
||||
NULL, bpp)
|
||||
#define bread_gb(vp, blkno, size, cred, gbflags, bpp) \
|
||||
breadn_flags(vp, blkno, size, NULL, NULL, 0, cred, \
|
||||
breadn_flags(vp, blkno, blkno, size, NULL, NULL, 0, cred, \
|
||||
gbflags, NULL, bpp)
|
||||
#define breadn(vp, blkno, size, rablkno, rabsize, cnt, cred, bpp) \
|
||||
breadn_flags(vp, blkno, size, rablkno, rabsize, cnt, cred, \
|
||||
breadn_flags(vp, blkno, blkno, size, rablkno, rabsize, cnt, cred, \
|
||||
0, NULL, bpp)
|
||||
int breadn_flags(struct vnode *, daddr_t, int, daddr_t *, int *, int,
|
||||
struct ucred *, int, void (*)(struct buf *), struct buf **);
|
||||
int breadn_flags(struct vnode *, daddr_t, daddr_t, int, daddr_t *, int *,
|
||||
int, struct ucred *, int, void (*)(struct buf *), struct buf **);
|
||||
void bdwrite(struct buf *);
|
||||
void bawrite(struct buf *);
|
||||
void babarrierwrite(struct buf *);
|
||||
@ -544,8 +545,8 @@ void vfs_busy_pages_release(struct buf *bp);
|
||||
struct buf *incore(struct bufobj *, daddr_t);
|
||||
struct buf *gbincore(struct bufobj *, daddr_t);
|
||||
struct buf *getblk(struct vnode *, daddr_t, int, int, int, int);
|
||||
int getblkx(struct vnode *vp, daddr_t blkno, int size, int slpflag,
|
||||
int slptimeo, int flags, struct buf **bpp);
|
||||
int getblkx(struct vnode *vp, daddr_t blkno, daddr_t dblkno, int size,
|
||||
int slpflag, int slptimeo, int flags, struct buf **bpp);
|
||||
struct buf *geteblk(int, int);
|
||||
int bufwait(struct buf *);
|
||||
int bufwrite(struct buf *);
|
||||
|
@ -2955,16 +2955,19 @@ ffs_getcg(fs, devvp, cg, flags, bpp, cgpp)
|
||||
struct buf *bp;
|
||||
struct cg *cgp;
|
||||
const struct statfs *sfs;
|
||||
daddr_t blkno;
|
||||
int error;
|
||||
|
||||
*bpp = NULL;
|
||||
*cgpp = NULL;
|
||||
if ((fs->fs_metackhash & CK_CYLGRP) != 0)
|
||||
flags |= GB_CKHASH;
|
||||
error = breadn_flags(devvp, devvp->v_type == VREG ?
|
||||
fragstoblks(fs, cgtod(fs, cg)) : fsbtodb(fs, cgtod(fs, cg)),
|
||||
(int)fs->fs_cgsize, NULL, NULL, 0, NOCRED, flags,
|
||||
ffs_ckhash_cg, &bp);
|
||||
if (devvp->v_type == VREG)
|
||||
blkno = fragstoblks(fs, cgtod(fs, cg));
|
||||
else
|
||||
blkno = fsbtodb(fs, cgtod(fs, cg));
|
||||
error = breadn_flags(devvp, blkno, blkno, (int)fs->fs_cgsize, NULL,
|
||||
NULL, 0, NOCRED, flags, ffs_ckhash_cg, &bp);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
cgp = (struct cg *)bp->b_data;
|
||||
|
@ -678,34 +678,14 @@ ffs_indirtrunc(ip, lbn, dbn, lastbn, level, countp)
|
||||
* Get buffer of block pointers, zero those entries corresponding
|
||||
* to blocks to be free'd, and update on disk copy first. Since
|
||||
* double(triple) indirect before single(double) indirect, calls
|
||||
* to bmap on these blocks will fail. However, we already have
|
||||
* the on disk address, so we have to set the b_blkno field
|
||||
* explicitly instead of letting bread do everything for us.
|
||||
* to VOP_BMAP() on these blocks will fail. However, we already
|
||||
* have the on-disk address, so we just pass it to bread() instead
|
||||
* of having bread() attempt to calculate it using VOP_BMAP().
|
||||
*/
|
||||
vp = ITOV(ip);
|
||||
bp = getblk(vp, lbn, (int)fs->fs_bsize, 0, 0, 0);
|
||||
if ((bp->b_flags & B_CACHE) == 0) {
|
||||
#ifdef RACCT
|
||||
if (racct_enable) {
|
||||
PROC_LOCK(curproc);
|
||||
racct_add_buf(curproc, bp, 0);
|
||||
PROC_UNLOCK(curproc);
|
||||
}
|
||||
#endif /* RACCT */
|
||||
curthread->td_ru.ru_inblock++; /* pay for read */
|
||||
bp->b_iocmd = BIO_READ;
|
||||
bp->b_flags &= ~B_INVAL;
|
||||
bp->b_ioflags &= ~BIO_ERROR;
|
||||
if (bp->b_bcount > bp->b_bufsize)
|
||||
panic("ffs_indirtrunc: bad buffer size");
|
||||
bp->b_blkno = dbn;
|
||||
vfs_busy_pages(bp, 0);
|
||||
bp->b_iooffset = dbtob(bp->b_blkno);
|
||||
bstrategy(bp);
|
||||
error = bufwait(bp);
|
||||
}
|
||||
error = breadn_flags(vp, lbn, dbn, (int)fs->fs_bsize, NULL, NULL, 0,
|
||||
NOCRED, 0, NULL, &bp);
|
||||
if (error) {
|
||||
brelse(bp);
|
||||
*countp = 0;
|
||||
return (error);
|
||||
}
|
||||
|
@ -6294,29 +6294,15 @@ setup_trunc_indir(freeblks, ip, lbn, lastlbn, blkno)
|
||||
return (0);
|
||||
mp = freeblks->fb_list.wk_mp;
|
||||
ump = VFSTOUFS(mp);
|
||||
bp = getblk(ITOV(ip), lbn, mp->mnt_stat.f_iosize, 0, 0, 0);
|
||||
if ((bp->b_flags & B_CACHE) == 0) {
|
||||
bp->b_blkno = blkptrtodb(VFSTOUFS(mp), blkno);
|
||||
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 /* RACCT */
|
||||
curthread->td_ru.ru_inblock++;
|
||||
error = bufwait(bp);
|
||||
if (error) {
|
||||
brelse(bp);
|
||||
return (error);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Here, calls to VOP_BMAP() will fail. However, we already have
|
||||
* the on-disk address, so we just pass it to bread() instead of
|
||||
* having bread() attempt to calculate it using VOP_BMAP().
|
||||
*/
|
||||
error = breadn_flags(ITOV(ip), lbn, blkptrtodb(ump, blkno),
|
||||
(int)mp->mnt_stat.f_iosize, NULL, NULL, 0, NOCRED, 0, NULL, &bp);
|
||||
if (error)
|
||||
return (error);
|
||||
level = lbn_level(lbn);
|
||||
lbnadd = lbn_offset(ump->um_fs, level);
|
||||
/*
|
||||
|
@ -603,7 +603,7 @@ ffs_read(ap)
|
||||
* the 6th argument.
|
||||
*/
|
||||
u_int nextsize = blksize(fs, ip, nextlbn);
|
||||
error = breadn_flags(vp, lbn, size, &nextlbn,
|
||||
error = breadn_flags(vp, lbn, lbn, size, &nextlbn,
|
||||
&nextsize, 1, NOCRED, bflag, NULL, &bp);
|
||||
} else {
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user