UFS support of the unmapped i/o for the user data buffers.

Sponsored by:	The FreeBSD Foundation
Tested by:	pho, scottl, jhb, bf
This commit is contained in:
Konstantin Belousov 2013-03-19 15:08:15 +00:00
parent 2649fcc1d8
commit 59a01b70af
5 changed files with 62 additions and 35 deletions

View File

@ -254,7 +254,7 @@ ffs_realloccg(ip, lbprev, bprev, bpref, osize, nsize, flags, cred, bpp)
struct buf *bp;
struct ufsmount *ump;
u_int cg, request, reclaimed;
int error;
int error, gbflags;
ufs2_daddr_t bno;
static struct timeval lastfail;
static int curfail;
@ -265,6 +265,8 @@ ffs_realloccg(ip, lbprev, bprev, bpref, osize, nsize, flags, cred, bpp)
fs = ip->i_fs;
bp = NULL;
ump = ip->i_ump;
gbflags = (flags & BA_UNMAPPED) != 0 ? GB_UNMAPPED : 0;
mtx_assert(UFS_MTX(ump), MA_OWNED);
#ifdef INVARIANTS
if (vp->v_mount->mnt_kern_flag & MNTK_SUSPENDED)
@ -296,7 +298,7 @@ ffs_realloccg(ip, lbprev, bprev, bpref, osize, nsize, flags, cred, bpp)
/*
* Allocate the extra space in the buffer.
*/
error = bread(vp, lbprev, osize, NOCRED, &bp);
error = bread_gb(vp, lbprev, osize, NOCRED, gbflags, &bp);
if (error) {
brelse(bp);
return (error);
@ -332,7 +334,7 @@ ffs_realloccg(ip, lbprev, bprev, bpref, osize, nsize, flags, cred, bpp)
ip->i_flag |= IN_CHANGE | IN_UPDATE;
allocbuf(bp, nsize);
bp->b_flags |= B_DONE;
bzero(bp->b_data + osize, nsize - osize);
vfs_bio_bzero_buf(bp, osize, nsize - osize);
if ((bp->b_flags & (B_MALLOC | B_VMIO)) == B_VMIO)
vfs_bio_set_valid(bp, osize, nsize - osize);
*bpp = bp;
@ -400,7 +402,7 @@ ffs_realloccg(ip, lbprev, bprev, bpref, osize, nsize, flags, cred, bpp)
ip->i_flag |= IN_CHANGE | IN_UPDATE;
allocbuf(bp, nsize);
bp->b_flags |= B_DONE;
bzero(bp->b_data + osize, nsize - osize);
vfs_bio_bzero_buf(bp, osize, nsize - osize);
if ((bp->b_flags & (B_MALLOC | B_VMIO)) == B_VMIO)
vfs_bio_set_valid(bp, osize, nsize - osize);
*bpp = bp;

View File

@ -107,7 +107,7 @@ ffs_balloc_ufs1(struct vnode *vp, off_t startoffset, int size,
int saved_inbdflush;
static struct timeval lastfail;
static int curfail;
int reclaimed;
int gbflags, reclaimed;
ip = VTOI(vp);
dp = ip->i_din1;
@ -123,6 +123,7 @@ ffs_balloc_ufs1(struct vnode *vp, off_t startoffset, int size,
return (EOPNOTSUPP);
if (lbn < 0)
return (EFBIG);
gbflags = (flags & BA_UNMAPPED) != 0 ? GB_UNMAPPED : 0;
if (DOINGSOFTDEP(vp))
softdep_prealloc(vp, MNT_WAIT);
@ -211,7 +212,7 @@ ffs_balloc_ufs1(struct vnode *vp, off_t startoffset, int size,
nsize, flags, cred, &newb);
if (error)
return (error);
bp = getblk(vp, lbn, nsize, 0, 0, 0);
bp = getblk(vp, lbn, nsize, 0, 0, gbflags);
bp->b_blkno = fsbtodb(fs, newb);
if (flags & BA_CLRBUF)
vfs_bio_clrbuf(bp);
@ -255,7 +256,7 @@ ffs_balloc_ufs1(struct vnode *vp, off_t startoffset, int size,
nb = newb;
*allocblk++ = nb;
*lbns_remfree++ = indirs[1].in_lbn;
bp = getblk(vp, indirs[1].in_lbn, fs->fs_bsize, 0, 0, 0);
bp = getblk(vp, indirs[1].in_lbn, fs->fs_bsize, 0, 0, gbflags);
bp->b_blkno = fsbtodb(fs, nb);
vfs_bio_clrbuf(bp);
if (DOINGSOFTDEP(vp)) {
@ -389,7 +390,7 @@ ffs_balloc_ufs1(struct vnode *vp, off_t startoffset, int size,
nb = newb;
*allocblk++ = nb;
*lbns_remfree++ = lbn;
nbp = getblk(vp, lbn, fs->fs_bsize, 0, 0, 0);
nbp = getblk(vp, lbn, fs->fs_bsize, 0, 0, gbflags);
nbp->b_blkno = fsbtodb(fs, nb);
if (flags & BA_CLRBUF)
vfs_bio_clrbuf(nbp);
@ -418,16 +419,17 @@ ffs_balloc_ufs1(struct vnode *vp, off_t startoffset, int size,
if (seqcount && (vp->v_mount->mnt_flag & MNT_NOCLUSTERR) == 0) {
error = cluster_read(vp, ip->i_size, lbn,
(int)fs->fs_bsize, NOCRED,
MAXBSIZE, seqcount, 0, &nbp);
MAXBSIZE, seqcount, gbflags, &nbp);
} else {
error = bread(vp, lbn, (int)fs->fs_bsize, NOCRED, &nbp);
error = bread_gb(vp, lbn, (int)fs->fs_bsize, NOCRED,
gbflags, &nbp);
}
if (error) {
brelse(nbp);
goto fail;
}
} else {
nbp = getblk(vp, lbn, fs->fs_bsize, 0, 0, 0);
nbp = getblk(vp, lbn, fs->fs_bsize, 0, 0, gbflags);
nbp->b_blkno = fsbtodb(fs, nb);
}
curthread_pflags_restore(saved_inbdflush);
@ -539,7 +541,7 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size,
int saved_inbdflush;
static struct timeval lastfail;
static int curfail;
int reclaimed;
int gbflags, reclaimed;
ip = VTOI(vp);
dp = ip->i_din2;
@ -553,6 +555,7 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size,
*bpp = NULL;
if (lbn < 0)
return (EFBIG);
gbflags = (flags & BA_UNMAPPED) != 0 ? GB_UNMAPPED : 0;
if (DOINGSOFTDEP(vp))
softdep_prealloc(vp, MNT_WAIT);
@ -603,7 +606,8 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size,
panic("ffs_balloc_ufs2: BA_METAONLY for ext block");
nb = dp->di_extb[lbn];
if (nb != 0 && dp->di_extsize >= smalllblktosize(fs, lbn + 1)) {
error = bread(vp, -1 - lbn, fs->fs_bsize, NOCRED, &bp);
error = bread_gb(vp, -1 - lbn, fs->fs_bsize, NOCRED,
gbflags, &bp);
if (error) {
brelse(bp);
return (error);
@ -620,7 +624,8 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size,
osize = fragroundup(fs, blkoff(fs, dp->di_extsize));
nsize = fragroundup(fs, size);
if (nsize <= osize) {
error = bread(vp, -1 - lbn, osize, NOCRED, &bp);
error = bread_gb(vp, -1 - lbn, osize, NOCRED,
gbflags, &bp);
if (error) {
brelse(bp);
return (error);
@ -653,7 +658,7 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size,
nsize, flags, cred, &newb);
if (error)
return (error);
bp = getblk(vp, -1 - lbn, nsize, 0, 0, 0);
bp = getblk(vp, -1 - lbn, nsize, 0, 0, gbflags);
bp->b_blkno = fsbtodb(fs, newb);
bp->b_xflags |= BX_ALTDATA;
if (flags & BA_CLRBUF)
@ -707,7 +712,8 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size,
panic("ffs_balloc_ufs2: BA_METAONLY for direct block");
nb = dp->di_db[lbn];
if (nb != 0 && ip->i_size >= smalllblktosize(fs, lbn + 1)) {
error = bread(vp, lbn, fs->fs_bsize, NOCRED, &bp);
error = bread_gb(vp, lbn, fs->fs_bsize, NOCRED,
gbflags, &bp);
if (error) {
brelse(bp);
return (error);
@ -723,7 +729,8 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size,
osize = fragroundup(fs, blkoff(fs, ip->i_size));
nsize = fragroundup(fs, size);
if (nsize <= osize) {
error = bread(vp, lbn, osize, NOCRED, &bp);
error = bread_gb(vp, lbn, osize, NOCRED,
gbflags, &bp);
if (error) {
brelse(bp);
return (error);
@ -753,7 +760,7 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size,
&dp->di_db[0]), nsize, flags, cred, &newb);
if (error)
return (error);
bp = getblk(vp, lbn, nsize, 0, 0, 0);
bp = getblk(vp, lbn, nsize, 0, 0, gbflags);
bp->b_blkno = fsbtodb(fs, newb);
if (flags & BA_CLRBUF)
vfs_bio_clrbuf(bp);
@ -797,7 +804,8 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size,
nb = newb;
*allocblk++ = nb;
*lbns_remfree++ = indirs[1].in_lbn;
bp = getblk(vp, indirs[1].in_lbn, fs->fs_bsize, 0, 0, 0);
bp = getblk(vp, indirs[1].in_lbn, fs->fs_bsize, 0, 0,
GB_UNMAPPED);
bp->b_blkno = fsbtodb(fs, nb);
vfs_bio_clrbuf(bp);
if (DOINGSOFTDEP(vp)) {
@ -862,7 +870,8 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size,
nb = newb;
*allocblk++ = nb;
*lbns_remfree++ = indirs[i].in_lbn;
nbp = getblk(vp, indirs[i].in_lbn, fs->fs_bsize, 0, 0, 0);
nbp = getblk(vp, indirs[i].in_lbn, fs->fs_bsize, 0, 0,
GB_UNMAPPED);
nbp->b_blkno = fsbtodb(fs, nb);
vfs_bio_clrbuf(nbp);
if (DOINGSOFTDEP(vp)) {
@ -931,7 +940,7 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size,
nb = newb;
*allocblk++ = nb;
*lbns_remfree++ = lbn;
nbp = getblk(vp, lbn, fs->fs_bsize, 0, 0, 0);
nbp = getblk(vp, lbn, fs->fs_bsize, 0, 0, gbflags);
nbp->b_blkno = fsbtodb(fs, nb);
if (flags & BA_CLRBUF)
vfs_bio_clrbuf(nbp);
@ -966,16 +975,17 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size,
if (seqcount && (vp->v_mount->mnt_flag & MNT_NOCLUSTERR) == 0) {
error = cluster_read(vp, ip->i_size, lbn,
(int)fs->fs_bsize, NOCRED,
MAXBSIZE, seqcount, 0, &nbp);
MAXBSIZE, seqcount, gbflags, &nbp);
} else {
error = bread(vp, lbn, (int)fs->fs_bsize, NOCRED, &nbp);
error = bread_gb(vp, lbn, (int)fs->fs_bsize,
NOCRED, gbflags, &nbp);
}
if (error) {
brelse(nbp);
goto fail;
}
} else {
nbp = getblk(vp, lbn, fs->fs_bsize, 0, 0, 0);
nbp = getblk(vp, lbn, fs->fs_bsize, 0, 0, gbflags);
nbp->b_blkno = fsbtodb(fs, nb);
}
curthread_pflags_restore(saved_inbdflush);

View File

@ -1076,7 +1076,7 @@ ffs_mountfs(devvp, mp, td)
*/
MNT_ILOCK(mp);
mp->mnt_kern_flag |= MNTK_LOOKUP_SHARED | MNTK_EXTENDED_SHARED |
MNTK_NO_IOPF;
MNTK_NO_IOPF | MNTK_UNMAPPED_BUFS;
MNT_IUNLOCK(mp);
#ifdef UFS_EXTATTR
#ifdef UFS_EXTATTR_AUTOSTART
@ -2110,6 +2110,7 @@ ffs_bufwrite(struct buf *bp)
* set b_lblkno and BKGRDMARKER before calling bgetvp()
* to avoid confusing the splay tree and gbincore().
*/
KASSERT((bp->b_flags & B_UNMAPPED) == 0, ("Unmapped cg"));
memcpy(newbp->b_data, bp->b_data, bp->b_bufsize);
newbp->b_lblkno = bp->b_lblkno;
newbp->b_xflags |= BX_BKGRDMARKER;

View File

@ -509,7 +509,8 @@ ffs_read(ap)
/*
* Don't do readahead if this is the end of the file.
*/
error = bread(vp, lbn, size, NOCRED, &bp);
error = bread_gb(vp, lbn, size, NOCRED,
GB_UNMAPPED, &bp);
} else if ((vp->v_mount->mnt_flag & MNT_NOCLUSTERR) == 0) {
/*
* Otherwise if we are allowed to cluster,
@ -520,7 +521,7 @@ ffs_read(ap)
*/
error = cluster_read(vp, ip->i_size, lbn,
size, NOCRED, blkoffset + uio->uio_resid,
seqcount, 0, &bp);
seqcount, GB_UNMAPPED, &bp);
} else if (seqcount > 1) {
/*
* If we are NOT allowed to cluster, then
@ -531,15 +532,16 @@ ffs_read(ap)
* the 6th argument.
*/
int nextsize = blksize(fs, ip, nextlbn);
error = breadn(vp, lbn,
size, &nextlbn, &nextsize, 1, NOCRED, &bp);
error = breadn_flags(vp, lbn, size, &nextlbn,
&nextsize, 1, NOCRED, GB_UNMAPPED, &bp);
} else {
/*
* Failing all of the above, just read what the
* user asked for. Interestingly, the same as
* the first option above.
*/
error = bread(vp, lbn, size, NOCRED, &bp);
error = bread_gb(vp, lbn, size, NOCRED,
GB_UNMAPPED, &bp);
}
if (error) {
brelse(bp);
@ -570,8 +572,13 @@ ffs_read(ap)
xfersize = size;
}
error = vn_io_fault_uiomove((char *)bp->b_data + blkoffset,
(int)xfersize, uio);
if ((bp->b_flags & B_UNMAPPED) == 0) {
error = vn_io_fault_uiomove((char *)bp->b_data +
blkoffset, (int)xfersize, uio);
} else {
error = vn_io_fault_pgmove(bp->b_pages, blkoffset,
(int)xfersize, uio);
}
if (error)
break;
@ -702,6 +709,7 @@ ffs_write(ap)
flags = seqcount << BA_SEQSHIFT;
if ((ioflag & IO_SYNC) && !DOINGASYNC(vp))
flags |= IO_SYNC;
flags |= BA_UNMAPPED;
for (error = 0; uio->uio_resid > 0;) {
lbn = lblkno(fs, uio->uio_offset);
@ -741,8 +749,13 @@ ffs_write(ap)
if (size < xfersize)
xfersize = size;
error = vn_io_fault_uiomove((char *)bp->b_data + blkoffset,
(int)xfersize, uio);
if ((bp->b_flags & B_UNMAPPED) == 0) {
error = vn_io_fault_uiomove((char *)bp->b_data +
blkoffset, (int)xfersize, uio);
} else {
error = vn_io_fault_pgmove(bp->b_pages, blkoffset,
(int)xfersize, uio);
}
/*
* If the buffer is not already filled and we encounter an
* error while trying to fill it, we have to clear out any
@ -786,7 +799,7 @@ ffs_write(ap)
if ((vp->v_mount->mnt_flag & MNT_NOCLUSTERW) == 0) {
bp->b_flags |= B_CLUSTEROK;
cluster_write(vp, bp, ip->i_size, seqcount,
0);
GB_UNMAPPED);
} else {
bawrite(bp);
}

View File

@ -121,6 +121,7 @@ void softdep_revert_rmdir(struct inode *, struct inode *);
*/
#define BA_CLRBUF 0x00010000 /* Clear invalid areas of buffer. */
#define BA_METAONLY 0x00020000 /* Return indirect block buffer. */
#define BA_UNMAPPED 0x00040000 /* Do not mmap resulted buffer. */
#define BA_SEQMASK 0x7F000000 /* Bits holding seq heuristic. */
#define BA_SEQSHIFT 24
#define BA_SEQMAX 0x7F