ufs: support unmapped bufs for indirect blocks in bmap
Use unmapped bufs for indirect block buffers in bmap, and use sf_bufs for transient mapping them when we need to read the specific pointer. [kib note: I changed the original patch to use sf_buf instead of explicit DMAP utilization, making the change MI]. Tested by: pho Reviewed by: kib MFC after: 1 week Differential revision: https://reviews.freebsd.org/D53424
This commit is contained in:
committed by
Konstantin Belousov
parent
cb31a26616
commit
bab04ddf1f
+134
-9
@@ -34,7 +34,6 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bio.h>
|
||||
#include <sys/buf.h>
|
||||
@@ -44,10 +43,13 @@
|
||||
#include <sys/mount.h>
|
||||
#include <sys/racct.h>
|
||||
#include <sys/resourcevar.h>
|
||||
#include <sys/sched.h>
|
||||
#include <sys/sf_buf.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_object.h>
|
||||
#include <vm/vm_page.h>
|
||||
#include <vm/vnode_pager.h>
|
||||
|
||||
#include <ufs/ufs/extattr.h>
|
||||
@@ -59,6 +61,11 @@
|
||||
static ufs_lbn_t lbn_count(struct ufsmount *, int);
|
||||
static int readindir(struct vnode *, ufs_lbn_t, ufs2_daddr_t, struct buf **);
|
||||
|
||||
static int ufs_bmap_use_unmapped = 1;
|
||||
|
||||
SYSCTL_INT(_vfs_ufs, OID_AUTO, bmap_use_unmapped, CTLFLAG_RWTUN,
|
||||
&ufs_bmap_use_unmapped, 0, "UFS bmap uses unmapped bufs");
|
||||
|
||||
/*
|
||||
* Bmap converts the logical block number of a file to its physical block
|
||||
* number on the disk. The conversion is done by using the logical block
|
||||
@@ -102,12 +109,15 @@ readindir(struct vnode *vp,
|
||||
struct buf *bp;
|
||||
struct mount *mp;
|
||||
struct ufsmount *ump;
|
||||
int error;
|
||||
struct inode *ip;
|
||||
int error, gbflags;
|
||||
|
||||
mp = vp->v_mount;
|
||||
ump = VFSTOUFS(mp);
|
||||
ip = VTOI(vp);
|
||||
|
||||
bp = getblk(vp, lbn, mp->mnt_stat.f_iosize, 0, 0, 0);
|
||||
gbflags = !I_IS_UFS1(ip) && ufs_bmap_use_unmapped ? GB_UNMAPPED : 0;
|
||||
bp = getblk(vp, lbn, mp->mnt_stat.f_iosize, 0, 0, gbflags);
|
||||
if ((bp->b_flags & B_CACHE) == 0) {
|
||||
KASSERT(daddr != 0,
|
||||
("readindir: indirect block not in cache"));
|
||||
@@ -151,6 +161,24 @@ readindir(struct vnode *vp,
|
||||
* next block and the disk address of the block (if it is assigned).
|
||||
*/
|
||||
|
||||
static void *
|
||||
ufs_bm_sf_get(struct buf *bp, int32_t pgidx, struct sf_buf **sfp)
|
||||
{
|
||||
struct sf_buf *sf;
|
||||
|
||||
sched_pin();
|
||||
sf = sf_buf_alloc(bp->b_pages[pgidx], SFB_CPUPRIVATE);
|
||||
*sfp = sf;
|
||||
return (sf_buf_kva(sf));
|
||||
}
|
||||
|
||||
static void
|
||||
ufs_bm_sf_put(struct sf_buf *sf)
|
||||
{
|
||||
sf_buf_free(sf);
|
||||
sched_unpin();
|
||||
}
|
||||
|
||||
int
|
||||
ufs_bmaparray(struct vnode *vp,
|
||||
ufs2_daddr_t bn,
|
||||
@@ -164,10 +192,16 @@ ufs_bmaparray(struct vnode *vp,
|
||||
struct ufsmount *ump;
|
||||
struct mount *mp;
|
||||
struct indir a[UFS_NIADDR+1], *ap;
|
||||
struct sf_buf *sf;
|
||||
ufs2_daddr_t daddr;
|
||||
ufs_lbn_t metalbn;
|
||||
int error, num, maxrun = 0;
|
||||
int *nump;
|
||||
ufs1_daddr_t *daddr1p;
|
||||
ufs2_daddr_t pgbn, daddrppg, prevdaddr, *daddr2p;
|
||||
int32_t daddrsz, boff, pgidx, pgoff;
|
||||
void *pgaddr;
|
||||
bool isseq;
|
||||
|
||||
ap = NULL;
|
||||
ip = VTOI(vp);
|
||||
@@ -261,17 +295,71 @@ ufs_bmaparray(struct vnode *vp,
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
if (I_IS_UFS1(ip))
|
||||
daddr = ((ufs1_daddr_t *)bp->b_data)[ap->in_off];
|
||||
else
|
||||
daddr = ((ufs2_daddr_t *)bp->b_data)[ap->in_off];
|
||||
daddrsz = I_IS_UFS1(ip) ? sizeof(ufs1_daddr_t) : sizeof(ufs2_daddr_t);
|
||||
if (!buf_mapped(bp)) {
|
||||
boff = ap->in_off * daddrsz;
|
||||
pgidx = boff / PAGE_SIZE;
|
||||
pgoff = (boff & PAGE_MASK) / daddrsz;
|
||||
pgaddr = ufs_bm_sf_get(bp, pgidx, &sf);
|
||||
if (I_IS_UFS1(ip))
|
||||
daddr = ((ufs1_daddr_t *)pgaddr)[pgoff];
|
||||
else
|
||||
daddr = ((ufs2_daddr_t *)pgaddr)[pgoff];
|
||||
ufs_bm_sf_put(sf);
|
||||
} else {
|
||||
if (I_IS_UFS1(ip))
|
||||
daddr = ((ufs1_daddr_t *)bp->b_data)[ap->in_off];
|
||||
else
|
||||
daddr = ((ufs2_daddr_t *)bp->b_data)[ap->in_off];
|
||||
}
|
||||
|
||||
if ((error = UFS_CHECK_BLKNO(mp, ip->i_number, daddr,
|
||||
mp->mnt_stat.f_iosize)) != 0) {
|
||||
bqrelse(bp);
|
||||
return (error);
|
||||
}
|
||||
if (num > 1 || daddr == 0 || runp == NULL)
|
||||
continue;
|
||||
|
||||
daddrppg = PAGE_SIZE / daddrsz;
|
||||
if (I_IS_UFS1(ip)) {
|
||||
if (num == 1 && daddr && runp) {
|
||||
if (!buf_mapped(bp)) {
|
||||
prevdaddr = daddr;
|
||||
isseq = true;
|
||||
for (bn = ap->in_off + 1;
|
||||
bn < MNINDIR(ump) && *runp < maxrun && isseq; ) {
|
||||
boff = bn * daddrsz;
|
||||
pgidx = boff / PAGE_SIZE;
|
||||
pgoff = (boff & PAGE_MASK) / daddrsz;
|
||||
KASSERT(pgidx >= 0 && pgidx < bp->b_npages,
|
||||
("pgidx %d vs b_npages %d", pgidx, bp->b_npages));
|
||||
pgaddr = ufs_bm_sf_get(bp, pgidx, &sf);
|
||||
daddr1p = (ufs1_daddr_t *)pgaddr;
|
||||
for (pgbn = pgoff;
|
||||
pgbn < daddrppg && *runp < maxrun &&
|
||||
(isseq = is_sequential(ump, prevdaddr, daddr1p[pgbn]));
|
||||
prevdaddr = daddr1p[pgbn], ++pgbn, ++bn, ++*runp);
|
||||
ufs_bm_sf_put(sf);
|
||||
}
|
||||
prevdaddr = daddr;
|
||||
bn = ap->in_off;
|
||||
if (runb && bn) {
|
||||
isseq = true;
|
||||
for (--bn; bn >= 0 && *runb < maxrun && isseq; ) {
|
||||
boff = bn * daddrsz;
|
||||
pgidx = boff / PAGE_SIZE;
|
||||
pgoff = (boff & PAGE_MASK) / daddrsz;
|
||||
KASSERT(pgidx >= 0 && pgidx < bp->b_npages,
|
||||
("pgidx %d vs b_npages %d", pgidx, bp->b_npages));
|
||||
pgaddr = ufs_bm_sf_get(bp, pgidx, &sf);
|
||||
daddr1p = (ufs1_daddr_t *)pgaddr;
|
||||
for (pgbn = pgoff; pgbn >= 0 && *runb < maxrun &&
|
||||
(isseq = is_sequential(ump, daddr1p[pgbn], prevdaddr));
|
||||
prevdaddr = daddr1p[pgbn], --pgbn, --bn, ++*runb);
|
||||
ufs_bm_sf_put(sf);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (bn = ap->in_off + 1;
|
||||
bn < MNINDIR(ump) && *runp < maxrun &&
|
||||
is_sequential(ump,
|
||||
@@ -289,7 +377,44 @@ ufs_bmaparray(struct vnode *vp,
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (num == 1 && daddr && runp) {
|
||||
|
||||
if (!buf_mapped(bp)) {
|
||||
prevdaddr = daddr;
|
||||
isseq = true;
|
||||
for (bn = ap->in_off + 1;
|
||||
bn < MNINDIR(ump) && *runp < maxrun && isseq; ) {
|
||||
boff = bn * daddrsz;
|
||||
pgidx = boff / PAGE_SIZE;
|
||||
pgoff = (boff & PAGE_MASK) / daddrsz;
|
||||
KASSERT(pgidx >= 0 && pgidx < bp->b_npages,
|
||||
("pgidx %d vs b_npages %d", pgidx, bp->b_npages));
|
||||
pgaddr = ufs_bm_sf_get(bp, pgidx, &sf);
|
||||
daddr2p = (ufs2_daddr_t *)pgaddr;
|
||||
for (pgbn = pgoff;
|
||||
pgbn < daddrppg && *runp < maxrun &&
|
||||
(isseq = is_sequential(ump, prevdaddr, daddr2p[pgbn]));
|
||||
prevdaddr = daddr2p[pgbn], ++pgbn, ++bn, ++*runp);
|
||||
ufs_bm_sf_put(sf);
|
||||
}
|
||||
prevdaddr = daddr;
|
||||
bn = ap->in_off;
|
||||
if (runb && bn) {
|
||||
isseq = true;
|
||||
for (--bn; bn >= 0 && *runb < maxrun && isseq; ) {
|
||||
boff = bn * daddrsz;
|
||||
pgidx = boff / PAGE_SIZE;
|
||||
pgoff = (boff & PAGE_MASK) / daddrsz;
|
||||
KASSERT(pgidx >= 0 && pgidx < bp->b_npages,
|
||||
("pgidx %d vs b_npages %d", pgidx, bp->b_npages));
|
||||
pgaddr = ufs_bm_sf_get(bp, pgidx, &sf);
|
||||
daddr2p = (ufs2_daddr_t *)pgaddr;
|
||||
for (pgbn = pgoff; pgbn >= 0 && *runb < maxrun &&
|
||||
(isseq = is_sequential(ump, daddr2p[pgbn], prevdaddr));
|
||||
prevdaddr = daddr2p[pgbn], --pgbn, --bn, ++*runb);
|
||||
ufs_bm_sf_put(sf);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (bn = ap->in_off + 1;
|
||||
bn < MNINDIR(ump) && *runp < maxrun &&
|
||||
is_sequential(ump,
|
||||
|
||||
Reference in New Issue
Block a user