diff --git a/sys/fs/ext2fs/ext2_inode.c b/sys/fs/ext2fs/ext2_inode.c --- a/sys/fs/ext2fs/ext2_inode.c +++ b/sys/fs/ext2fs/ext2_inode.c @@ -536,6 +536,7 @@ return (error); vnode_pager_setsize(ovp, length); + cluster_init_vn(&oip->i_clusterw); oip->i_size = length; oip->i_flag |= IN_CHANGE | IN_UPDATE; diff --git a/sys/fs/ext2fs/ext2_vfsops.c b/sys/fs/ext2fs/ext2_vfsops.c --- a/sys/fs/ext2fs/ext2_vfsops.c +++ b/sys/fs/ext2fs/ext2_vfsops.c @@ -1229,6 +1229,7 @@ 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); diff --git a/sys/fs/ext2fs/ext2_vnops.c b/sys/fs/ext2fs/ext2_vnops.c --- a/sys/fs/ext2fs/ext2_vnops.c +++ b/sys/fs/ext2fs/ext2_vnops.c @@ -2313,7 +2313,8 @@ } 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); } diff --git a/sys/fs/ext2fs/inode.h b/sys/fs/ext2fs/inode.h --- a/sys/fs/ext2fs/inode.h +++ b/sys/fs/ext2fs/inode.h @@ -44,6 +44,7 @@ #include #include #include +#include #include @@ -118,6 +119,8 @@ }; struct ext4_extent_cache i_ext_cache; /* cache for ext4 extent */ + + struct vn_clusterw i_clusterw; }; /* diff --git a/sys/fs/fuse/fuse_io.c b/sys/fs/fuse/fuse_io.c --- a/sys/fs/fuse/fuse_io.c +++ b/sys/fs/fuse/fuse_io.c @@ -870,7 +870,8 @@ 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); diff --git a/sys/fs/fuse/fuse_node.h b/sys/fs/fuse/fuse_node.h --- a/sys/fs/fuse/fuse_node.h +++ b/sys/fs/fuse/fuse_node.h @@ -68,6 +68,7 @@ #include #include #include +#include #include "fuse_file.h" @@ -118,6 +119,7 @@ struct vattr cached_attrs; uint64_t nlookup; enum vtype vtype; + struct vn_clusterw clusterw; }; /* diff --git a/sys/fs/fuse/fuse_node.c b/sys/fs/fuse/fuse_node.c --- a/sys/fs/fuse/fuse_node.c +++ b/sys/fs/fuse/fuse_node.c @@ -164,6 +164,7 @@ } vp->v_type = vtyp; vp->v_data = fvdat; + cluster_init_vn(&fvdat->clusterw); counter_u64_add(fuse_node_count, 1); } diff --git a/sys/fs/msdosfs/denode.h b/sys/fs/msdosfs/denode.h --- a/sys/fs/msdosfs/denode.h +++ b/sys/fs/msdosfs/denode.h @@ -142,6 +142,7 @@ */ struct denode { struct vnode *de_vnode; /* addr of vnode we are part of */ + struct vn_clusterw de_clusterw; 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 */ diff --git a/sys/fs/msdosfs/msdosfs_denode.c b/sys/fs/msdosfs/msdosfs_denode.c --- a/sys/fs/msdosfs/msdosfs_denode.c +++ b/sys/fs/msdosfs/msdosfs_denode.c @@ -162,6 +162,7 @@ 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); diff --git a/sys/fs/msdosfs/msdosfs_vnops.c b/sys/fs/msdosfs/msdosfs_vnops.c --- a/sys/fs/msdosfs/msdosfs_vnops.c +++ b/sys/fs/msdosfs/msdosfs_vnops.c @@ -796,8 +796,8 @@ 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 diff --git a/sys/kern/vfs_cluster.c b/sys/kern/vfs_cluster.c --- a/sys/kern/vfs_cluster.c +++ b/sys/kern/vfs_cluster.c @@ -67,7 +67,7 @@ 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); @@ -651,8 +651,8 @@ * 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; @@ -674,12 +674,12 @@ /* 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. * @@ -696,18 +696,19 @@ * 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 @@ -733,7 +734,7 @@ free(buflist, M_SEGMENT); if (seqcount > 1) { cluster_wbuild_wb(vp, - lblocksize, vp->v_cstart, + lblocksize, vnc->v_cstart, cursize, gbflags); } } else { @@ -744,8 +745,8 @@ 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; } } @@ -755,27 +756,27 @@ * 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 @@ -783,11 +784,11 @@ */ 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 @@ -799,8 +800,8 @@ */ bdwrite(bp); } - vp->v_lastw = lbn; - vp->v_lasta = bp->b_blkno; + vnc->v_lastw = lbn; + vnc->v_lasta = bp->b_blkno; } /* @@ -1047,19 +1048,20 @@ * 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) { @@ -1083,3 +1085,12 @@ 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; +} diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -1823,7 +1823,6 @@ 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; diff --git a/sys/sys/buf.h b/sys/sys/buf.h --- a/sys/sys/buf.h +++ b/sys/sys/buf.h @@ -500,6 +500,14 @@ #define GB_NOSPARSE 0x0040 /* Do not instantiate holes */ #define GB_CVTENXIO 0x0080 /* Convert errors to ENXIO */ +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 extern int nbuf; /* The number of buffer headers */ extern u_long maxswzone; /* Max KVA for swap structures */ @@ -570,10 +578,12 @@ extern uma_zone_t pbuf_zone; uma_zone_t pbuf_zsecond_create(const char *name, int max); +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 *); diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -163,14 +163,6 @@ 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) */ diff --git a/sys/ufs/ffs/ffs_inode.c b/sys/ufs/ffs/ffs_inode.c --- a/sys/ufs/ffs/ffs_inode.c +++ b/sys/ufs/ffs/ffs_inode.c @@ -354,7 +354,7 @@ 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 diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c --- a/sys/ufs/ffs/ffs_vfsops.c +++ b/sys/ufs/ffs/ffs_vfsops.c @@ -2011,6 +2011,7 @@ 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 diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c --- a/sys/ufs/ffs/ffs_vnops.c +++ b/sys/ufs/ffs/ffs_vnops.c @@ -976,8 +976,8 @@ } 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); } diff --git a/sys/ufs/ufs/inode.h b/sys/ufs/ufs/inode.h --- a/sys/ufs/ufs/inode.h +++ b/sys/ufs/ufs/inode.h @@ -42,6 +42,7 @@ #include #include +#include #include #include #ifdef DIAGNOSTIC @@ -115,6 +116,8 @@ int i_nextclustercg; /* last cg searched for cluster */ + struct vn_clusterw i_clusterw; + /* * Data for extended attribute modification. */