vnode: move write cluster support data to inodes.
The data is only needed by filesystems that 1. use buffer cache 2. utilize clustering write support. Requested by: mjg Reviewed by: asomers (previous version), fsu (ext2 parts), mckusick Tested by: pho Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D28679
This commit is contained in:
parent
d485c77f20
commit
2bfd8992c7
@ -1229,6 +1229,7 @@ ext2_vget(struct mount *mp, ino_t ino, int flags, struct vnode **vpp)
|
||||
ip->i_e2fs = fs = ump->um_e2fs;
|
||||
ip->i_ump = ump;
|
||||
ip->i_number = ino;
|
||||
cluster_init_vn(&ip->i_clusterw);
|
||||
|
||||
lockmgr(vp->v_vnlock, LK_EXCLUSIVE, NULL);
|
||||
error = insmntque(vp, mp);
|
||||
|
@ -2313,7 +2313,8 @@ ext2_write(struct vop_write_args *ap)
|
||||
} else if (xfersize + blkoffset == fs->e2fs_fsize) {
|
||||
if ((vp->v_mount->mnt_flag & MNT_NOCLUSTERW) == 0) {
|
||||
bp->b_flags |= B_CLUSTEROK;
|
||||
cluster_write(vp, bp, ip->i_size, seqcount, 0);
|
||||
cluster_write(vp, &ip->i_clusterw, bp,
|
||||
ip->i_size, seqcount, 0);
|
||||
} else {
|
||||
bawrite(bp);
|
||||
}
|
||||
|
@ -44,6 +44,7 @@
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/buf.h>
|
||||
|
||||
#include <fs/ext2fs/ext2_extents.h>
|
||||
|
||||
@ -118,6 +119,8 @@ struct inode {
|
||||
};
|
||||
|
||||
struct ext4_extent_cache i_ext_cache; /* cache for ext4 extent */
|
||||
|
||||
struct vn_clusterw i_clusterw; /* Buffer clustering information */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -870,7 +870,8 @@ fuse_write_biobackend(struct vnode *vp, struct uio *uio,
|
||||
bp->b_flags |= B_CLUSTEROK;
|
||||
SDT_PROBE2(fusefs, , io, write_biobackend_issue,
|
||||
4, bp);
|
||||
cluster_write(vp, bp, filesize, seqcount, 0);
|
||||
cluster_write(vp, &fvdat->clusterw, bp,
|
||||
filesize, seqcount, 0);
|
||||
} else {
|
||||
SDT_PROBE2(fusefs, , io, write_biobackend_issue,
|
||||
5, bp);
|
||||
|
@ -164,6 +164,7 @@ fuse_vnode_init(struct vnode *vp, struct fuse_vnode_data *fvdat,
|
||||
}
|
||||
vp->v_type = vtyp;
|
||||
vp->v_data = fvdat;
|
||||
cluster_init_vn(&fvdat->clusterw);
|
||||
|
||||
counter_u64_add(fuse_node_count, 1);
|
||||
}
|
||||
|
@ -68,6 +68,7 @@
|
||||
#include <sys/fnv_hash.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/buf.h>
|
||||
|
||||
#include "fuse_file.h"
|
||||
|
||||
@ -118,6 +119,7 @@ struct fuse_vnode_data {
|
||||
struct vattr cached_attrs;
|
||||
uint64_t nlookup;
|
||||
enum vtype vtype;
|
||||
struct vn_clusterw clusterw;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -52,6 +52,8 @@
|
||||
#ifndef _FS_MSDOSFS_DENODE_H_
|
||||
#define _FS_MSDOSFS_DENODE_H_
|
||||
|
||||
#include <sys/buf.h>
|
||||
|
||||
/*
|
||||
* This is the pc filesystem specific portion of the vnode structure.
|
||||
*
|
||||
@ -142,6 +144,7 @@ struct fatcache {
|
||||
*/
|
||||
struct denode {
|
||||
struct vnode *de_vnode; /* addr of vnode we are part of */
|
||||
struct vn_clusterw de_clusterw; /* buffer clustering information */
|
||||
u_long de_flag; /* flag bits */
|
||||
u_long de_dirclust; /* cluster of the directory file containing this entry */
|
||||
u_long de_diroffset; /* offset of this entry in the directory cluster */
|
||||
|
@ -162,6 +162,7 @@ deget(struct msdosfsmount *pmp, u_long dirclust, u_long diroffset,
|
||||
ldep->de_dirclust = dirclust;
|
||||
ldep->de_diroffset = diroffset;
|
||||
ldep->de_inode = inode;
|
||||
cluster_init_vn(&ldep->de_clusterw);
|
||||
lockmgr(nvp->v_vnlock, LK_EXCLUSIVE, NULL);
|
||||
fc_purge(ldep, 0); /* init the FAT cache for this denode */
|
||||
error = insmntque(nvp, mntp);
|
||||
|
@ -796,8 +796,8 @@ msdosfs_write(struct vop_write_args *ap)
|
||||
bawrite(bp);
|
||||
else if (n + croffset == pmp->pm_bpcluster) {
|
||||
if ((vp->v_mount->mnt_flag & MNT_NOCLUSTERW) == 0)
|
||||
cluster_write(vp, bp, dep->de_FileSize,
|
||||
seqcount, 0);
|
||||
cluster_write(vp, &dep->de_clusterw, bp,
|
||||
dep->de_FileSize, seqcount, 0);
|
||||
else
|
||||
bawrite(bp);
|
||||
} else
|
||||
|
@ -59,7 +59,7 @@ static uma_zone_t cluster_pbuf_zone;
|
||||
|
||||
static void cluster_init(void *);
|
||||
static struct cluster_save *cluster_collectbufs(struct vnode *vp,
|
||||
struct buf *last_bp, int gbflags);
|
||||
struct vn_clusterw *vnc, struct buf *last_bp, int gbflags);
|
||||
static struct buf *cluster_rbuild(struct vnode *vp, u_quad_t filesize,
|
||||
daddr_t lbn, daddr_t blkno, long size, int run, int gbflags,
|
||||
struct buf *fbp);
|
||||
@ -643,8 +643,8 @@ cluster_wbuild_wb(struct vnode *vp, long size, daddr_t start_lbn, int len,
|
||||
* 4. end of a cluster - asynchronously write cluster
|
||||
*/
|
||||
void
|
||||
cluster_write(struct vnode *vp, struct buf *bp, u_quad_t filesize, int seqcount,
|
||||
int gbflags)
|
||||
cluster_write(struct vnode *vp, struct vn_clusterw *vnc, struct buf *bp,
|
||||
u_quad_t filesize, int seqcount, int gbflags)
|
||||
{
|
||||
daddr_t lbn;
|
||||
int maxclen, cursize;
|
||||
@ -666,12 +666,12 @@ cluster_write(struct vnode *vp, struct buf *bp, u_quad_t filesize, int seqcount,
|
||||
|
||||
/* Initialize vnode to beginning of file. */
|
||||
if (lbn == 0)
|
||||
vp->v_lasta = vp->v_clen = vp->v_cstart = vp->v_lastw = 0;
|
||||
vnc->v_lasta = vnc->v_clen = vnc->v_cstart = vnc->v_lastw = 0;
|
||||
|
||||
if (vp->v_clen == 0 || lbn != vp->v_lastw + 1 ||
|
||||
(bp->b_blkno != vp->v_lasta + btodb(lblocksize))) {
|
||||
if (vnc->v_clen == 0 || lbn != vnc->v_lastw + 1 ||
|
||||
(bp->b_blkno != vnc->v_lasta + btodb(lblocksize))) {
|
||||
maxclen = vp->v_mount->mnt_iosize_max / lblocksize - 1;
|
||||
if (vp->v_clen != 0) {
|
||||
if (vnc->v_clen != 0) {
|
||||
/*
|
||||
* Next block is not sequential.
|
||||
*
|
||||
@ -688,18 +688,19 @@ cluster_write(struct vnode *vp, struct buf *bp, u_quad_t filesize, int seqcount,
|
||||
* later on in the buf_daemon or update daemon
|
||||
* flush.
|
||||
*/
|
||||
cursize = vp->v_lastw - vp->v_cstart + 1;
|
||||
if (((u_quad_t) bp->b_offset + lblocksize) != filesize ||
|
||||
lbn != vp->v_lastw + 1 || vp->v_clen <= cursize) {
|
||||
cursize = vnc->v_lastw - vnc->v_cstart + 1;
|
||||
if ((u_quad_t)bp->b_offset + lblocksize != filesize ||
|
||||
lbn != vnc->v_lastw + 1 || vnc->v_clen <= cursize) {
|
||||
if (!async && seqcount > 0) {
|
||||
cluster_wbuild_wb(vp, lblocksize,
|
||||
vp->v_cstart, cursize, gbflags);
|
||||
vnc->v_cstart, cursize, gbflags);
|
||||
}
|
||||
} else {
|
||||
struct buf **bpp, **endbp;
|
||||
struct cluster_save *buflist;
|
||||
|
||||
buflist = cluster_collectbufs(vp, bp, gbflags);
|
||||
buflist = cluster_collectbufs(vp, vnc, bp,
|
||||
gbflags);
|
||||
if (buflist == NULL) {
|
||||
/*
|
||||
* Cluster build failed so just write
|
||||
@ -725,7 +726,7 @@ cluster_write(struct vnode *vp, struct buf *bp, u_quad_t filesize, int seqcount,
|
||||
free(buflist, M_SEGMENT);
|
||||
if (seqcount > 1) {
|
||||
cluster_wbuild_wb(vp,
|
||||
lblocksize, vp->v_cstart,
|
||||
lblocksize, vnc->v_cstart,
|
||||
cursize, gbflags);
|
||||
}
|
||||
} else {
|
||||
@ -736,8 +737,8 @@ cluster_write(struct vnode *vp, struct buf *bp, u_quad_t filesize, int seqcount,
|
||||
bpp <= endbp; bpp++)
|
||||
bdwrite(*bpp);
|
||||
free(buflist, M_SEGMENT);
|
||||
vp->v_lastw = lbn;
|
||||
vp->v_lasta = bp->b_blkno;
|
||||
vnc->v_lastw = lbn;
|
||||
vnc->v_lasta = bp->b_blkno;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -747,27 +748,27 @@ cluster_write(struct vnode *vp, struct buf *bp, u_quad_t filesize, int seqcount,
|
||||
* cluster as large as possible, otherwise find size of
|
||||
* existing cluster.
|
||||
*/
|
||||
if ((vp->v_type == VREG) &&
|
||||
((u_quad_t) bp->b_offset + lblocksize) != filesize &&
|
||||
(bp->b_blkno == bp->b_lblkno) &&
|
||||
(VOP_BMAP(vp, lbn, NULL, &bp->b_blkno, &maxclen, NULL) ||
|
||||
bp->b_blkno == -1)) {
|
||||
if (vp->v_type == VREG &&
|
||||
(u_quad_t) bp->b_offset + lblocksize != filesize &&
|
||||
bp->b_blkno == bp->b_lblkno &&
|
||||
(VOP_BMAP(vp, lbn, NULL, &bp->b_blkno, &maxclen,
|
||||
NULL) != 0 || bp->b_blkno == -1)) {
|
||||
bawrite(bp);
|
||||
vp->v_clen = 0;
|
||||
vp->v_lasta = bp->b_blkno;
|
||||
vp->v_cstart = lbn + 1;
|
||||
vp->v_lastw = lbn;
|
||||
vnc->v_clen = 0;
|
||||
vnc->v_lasta = bp->b_blkno;
|
||||
vnc->v_cstart = lbn + 1;
|
||||
vnc->v_lastw = lbn;
|
||||
return;
|
||||
}
|
||||
vp->v_clen = maxclen;
|
||||
vnc->v_clen = maxclen;
|
||||
if (!async && maxclen == 0) { /* I/O not contiguous */
|
||||
vp->v_cstart = lbn + 1;
|
||||
vnc->v_cstart = lbn + 1;
|
||||
bawrite(bp);
|
||||
} else { /* Wait for rest of cluster */
|
||||
vp->v_cstart = lbn;
|
||||
vnc->v_cstart = lbn;
|
||||
bdwrite(bp);
|
||||
}
|
||||
} else if (lbn == vp->v_cstart + vp->v_clen) {
|
||||
} else if (lbn == vnc->v_cstart + vnc->v_clen) {
|
||||
/*
|
||||
* At end of cluster, write it out if seqcount tells us we
|
||||
* are operating sequentially, otherwise let the buf or
|
||||
@ -775,11 +776,11 @@ cluster_write(struct vnode *vp, struct buf *bp, u_quad_t filesize, int seqcount,
|
||||
*/
|
||||
bdwrite(bp);
|
||||
if (seqcount > 1) {
|
||||
cluster_wbuild_wb(vp, lblocksize, vp->v_cstart,
|
||||
vp->v_clen + 1, gbflags);
|
||||
cluster_wbuild_wb(vp, lblocksize, vnc->v_cstart,
|
||||
vnc->v_clen + 1, gbflags);
|
||||
}
|
||||
vp->v_clen = 0;
|
||||
vp->v_cstart = lbn + 1;
|
||||
vnc->v_clen = 0;
|
||||
vnc->v_cstart = lbn + 1;
|
||||
} else if (vm_page_count_severe()) {
|
||||
/*
|
||||
* We are low on memory, get it going NOW
|
||||
@ -791,8 +792,8 @@ cluster_write(struct vnode *vp, struct buf *bp, u_quad_t filesize, int seqcount,
|
||||
*/
|
||||
bdwrite(bp);
|
||||
}
|
||||
vp->v_lastw = lbn;
|
||||
vp->v_lasta = bp->b_blkno;
|
||||
vnc->v_lastw = lbn;
|
||||
vnc->v_lasta = bp->b_blkno;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1039,19 +1040,20 @@ cluster_wbuild(struct vnode *vp, long size, daddr_t start_lbn, int len,
|
||||
* Plus add one additional buffer.
|
||||
*/
|
||||
static struct cluster_save *
|
||||
cluster_collectbufs(struct vnode *vp, struct buf *last_bp, int gbflags)
|
||||
cluster_collectbufs(struct vnode *vp, struct vn_clusterw *vnc,
|
||||
struct buf *last_bp, int gbflags)
|
||||
{
|
||||
struct cluster_save *buflist;
|
||||
struct buf *bp;
|
||||
daddr_t lbn;
|
||||
int i, j, len, error;
|
||||
|
||||
len = vp->v_lastw - vp->v_cstart + 1;
|
||||
len = vnc->v_lastw - vnc->v_cstart + 1;
|
||||
buflist = malloc(sizeof(struct buf *) * (len + 1) + sizeof(*buflist),
|
||||
M_SEGMENT, M_WAITOK);
|
||||
buflist->bs_nchildren = 0;
|
||||
buflist->bs_children = (struct buf **) (buflist + 1);
|
||||
for (lbn = vp->v_cstart, i = 0; i < len; lbn++, i++) {
|
||||
for (lbn = vnc->v_cstart, i = 0; i < len; lbn++, i++) {
|
||||
error = bread_gb(vp, lbn, last_bp->b_bcount, NOCRED,
|
||||
gbflags, &bp);
|
||||
if (error != 0) {
|
||||
@ -1075,3 +1077,12 @@ cluster_collectbufs(struct vnode *vp, struct buf *last_bp, int gbflags)
|
||||
buflist->bs_nchildren = i + 1;
|
||||
return (buflist);
|
||||
}
|
||||
|
||||
void
|
||||
cluster_init_vn(struct vn_clusterw *vnc)
|
||||
{
|
||||
vnc->v_lasta = 0;
|
||||
vnc->v_clen = 0;
|
||||
vnc->v_cstart = 0;
|
||||
vnc->v_lastw = 0;
|
||||
}
|
||||
|
@ -1823,7 +1823,6 @@ freevnode(struct vnode *vp)
|
||||
vp->v_unpcb = NULL;
|
||||
vp->v_rdev = NULL;
|
||||
vp->v_fifoinfo = NULL;
|
||||
vp->v_lasta = vp->v_clen = vp->v_cstart = vp->v_lastw = 0;
|
||||
vp->v_iflag = 0;
|
||||
vp->v_vflag = 0;
|
||||
bo->bo_flag = 0;
|
||||
|
@ -407,6 +407,16 @@ struct cluster_save {
|
||||
struct buf **bs_children; /* List of associated buffers. */
|
||||
};
|
||||
|
||||
/*
|
||||
* Vnode clustering tracker
|
||||
*/
|
||||
struct vn_clusterw {
|
||||
daddr_t v_cstart; /* v start block of cluster */
|
||||
daddr_t v_lasta; /* v last allocation */
|
||||
daddr_t v_lastw; /* v last write */
|
||||
int v_clen; /* v length of cur. cluster */
|
||||
};
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
static __inline int
|
||||
@ -571,10 +581,14 @@ void bd_speedup(void);
|
||||
extern uma_zone_t pbuf_zone;
|
||||
uma_zone_t pbuf_zsecond_create(const char *name, int max);
|
||||
|
||||
struct vn_clusterw;
|
||||
|
||||
void cluster_init_vn(struct vn_clusterw *vnc);
|
||||
int cluster_read(struct vnode *, u_quad_t, daddr_t, long,
|
||||
struct ucred *, long, int, int, struct buf **);
|
||||
int cluster_wbuild(struct vnode *, long, daddr_t, int, int);
|
||||
void cluster_write(struct vnode *, struct buf *, u_quad_t, int, int);
|
||||
void cluster_write(struct vnode *, struct vn_clusterw *, struct buf *,
|
||||
u_quad_t, int, int);
|
||||
void vfs_bio_brelse(struct buf *bp, int ioflags);
|
||||
void vfs_bio_bzero_buf(struct buf *bp, int base, int size);
|
||||
void vfs_bio_clrbuf(struct buf *);
|
||||
|
@ -163,14 +163,6 @@ struct vnode {
|
||||
struct lockf *v_lockf; /* Byte-level advisory lock list */
|
||||
struct rangelock v_rl; /* Byte-range lock */
|
||||
|
||||
/*
|
||||
* clustering stuff
|
||||
*/
|
||||
daddr_t v_cstart; /* v start block of cluster */
|
||||
daddr_t v_lasta; /* v last allocation */
|
||||
daddr_t v_lastw; /* v last write */
|
||||
int v_clen; /* v length of cur. cluster */
|
||||
|
||||
u_int v_holdcnt; /* I prevents recycling. */
|
||||
u_int v_usecount; /* I ref count of users */
|
||||
u_short v_iflag; /* i vnode flags (see below) */
|
||||
|
@ -354,7 +354,7 @@ ffs_truncate(vp, length, flags, cred)
|
||||
panic("ffs_truncate: read-only filesystem");
|
||||
if (IS_SNAPSHOT(ip))
|
||||
ffs_snapremove(vp);
|
||||
vp->v_lasta = vp->v_clen = vp->v_cstart = vp->v_lastw = 0;
|
||||
cluster_init_vn(&ip->i_clusterw);
|
||||
osize = ip->i_size;
|
||||
/*
|
||||
* Lengthen the size of the file. We must ensure that the
|
||||
|
@ -2011,6 +2011,7 @@ ffs_vgetf(mp, ino, flags, vpp, ffs_flags)
|
||||
ip->i_nextclustercg = -1;
|
||||
ip->i_flag = fs->fs_magic == FS_UFS1_MAGIC ? 0 : IN_UFS2;
|
||||
ip->i_mode = 0; /* ensure error cases below throw away vnode */
|
||||
cluster_init_vn(&ip->i_clusterw);
|
||||
#ifdef DIAGNOSTIC
|
||||
ufs_init_trackers(ip);
|
||||
#endif
|
||||
|
@ -976,8 +976,8 @@ ffs_write(ap)
|
||||
} else if (xfersize + blkoffset == fs->fs_bsize) {
|
||||
if ((vp->v_mount->mnt_flag & MNT_NOCLUSTERW) == 0) {
|
||||
bp->b_flags |= B_CLUSTEROK;
|
||||
cluster_write(vp, bp, ip->i_size, seqcount,
|
||||
GB_UNMAPPED);
|
||||
cluster_write(vp, &ip->i_clusterw, bp,
|
||||
ip->i_size, seqcount, GB_UNMAPPED);
|
||||
} else {
|
||||
bawrite(bp);
|
||||
}
|
||||
|
@ -47,6 +47,7 @@
|
||||
#ifdef DIAGNOSTIC
|
||||
#include <sys/stack.h>
|
||||
#endif
|
||||
#include <sys/buf.h>
|
||||
|
||||
/*
|
||||
* This must agree with the definition in <ufs/ufs/dir.h>.
|
||||
@ -115,6 +116,8 @@ struct inode {
|
||||
|
||||
int i_nextclustercg; /* last cg searched for cluster */
|
||||
|
||||
struct vn_clusterw i_clusterw; /* Buffer clustering information */
|
||||
|
||||
/*
|
||||
* Data for extended attribute modification.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user