From 753df37eb58e35e1d577c069e1975f131caf97d7 Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Tue, 20 Mar 2012 15:10:02 -0700 Subject: [PATCH] kernel - Add argument to nvtruncbuf() * Add a 'trivial' arg to nvtruncbuf() that works similarly to nvextendbuf(). This will allow hammer2 to tell nvtruncbuf() not to mess with the buffer that overlaps EOF, so hammer2 can mess with it atomically. --- sys/kern/vfs_vm.c | 8 ++++++-- sys/sys/vnode.h | 3 ++- sys/vfs/hammer/hammer_inode.c | 2 +- sys/vfs/hammer/hammer_vnops.c | 6 ++++-- sys/vfs/nfs/nfs_bio.c | 2 +- sys/vfs/puffs/puffs_node.c | 2 +- sys/vfs/tmpfs/tmpfs_subr.c | 2 +- sys/vfs/ufs/ffs_inode.c | 2 +- 8 files changed, 17 insertions(+), 10 deletions(-) diff --git a/sys/kern/vfs_vm.c b/sys/kern/vfs_vm.c index 137ec542cc..2c5dae565f 100644 --- a/sys/kern/vfs_vm.c +++ b/sys/kern/vfs_vm.c @@ -128,7 +128,7 @@ struct truncbuf_info { }; int -nvtruncbuf(struct vnode *vp, off_t length, int blksize, int boff) +nvtruncbuf(struct vnode *vp, off_t length, int blksize, int boff, int trivial) { struct truncbuf_info info; off_t truncboffset; @@ -173,8 +173,11 @@ nvtruncbuf(struct vnode *vp, off_t length, int blksize, int boff) * the block. * * The VFS is responsible for dealing with the actual truncation. + * + * Only do this if trivial is zero, otherwise it is up to the + * VFS to handle the block straddling the EOF. */ - if (boff) { + if (boff && trivial == 0) { truncboffset = length - boff; error = bread(vp, truncboffset, blksize, &bp); if (error == 0) { @@ -345,6 +348,7 @@ nvtruncbuf_bp_metasync(struct buf *bp, void *data) * If the caller intends to immediately write into the newly extended * space pass trivial == 1. If trivial is 0 the original buffer will be * zero-filled as necessary to clean out any junk in the extended space. + * If non-zero the original buffer (straddling EOF) is not touched. * * When zero-filling we must bdwrite() to avoid a window of opportunity * where the kernel might throw away a clean buffer and the filesystem diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index 6b4cb67ba3..b829510c9c 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -434,7 +434,8 @@ int vrevoke (struct vnode *vp, struct ucred *cred); int vinvalbuf (struct vnode *vp, int save, int slpflag, int slptimeo); int vtruncbuf (struct vnode *vp, off_t length, int blksize); void vnode_pager_setsize (struct vnode *, vm_ooffset_t); -int nvtruncbuf (struct vnode *vp, off_t length, int blksize, int boff); +int nvtruncbuf (struct vnode *vp, off_t length, int blksize, int boff, + int trivial); int nvextendbuf(struct vnode *vp, off_t olength, off_t nlength, int oblksize, int nblksize, int oboff, int nboff, int trivial); diff --git a/sys/vfs/hammer/hammer_inode.c b/sys/vfs/hammer/hammer_inode.c index dd594443a7..21b505a40e 100644 --- a/sys/vfs/hammer/hammer_inode.c +++ b/sys/vfs/hammer/hammer_inode.c @@ -3200,7 +3200,7 @@ hammer_inode_unloadable_check(hammer_inode_t ip, int getvp) * Final cleanup */ if (ip->vp) - nvtruncbuf(ip->vp, 0, HAMMER_BUFSIZE, 0); + nvtruncbuf(ip->vp, 0, HAMMER_BUFSIZE, 0, 0); if (getvp) vput(vp); } diff --git a/sys/vfs/hammer/hammer_vnops.c b/sys/vfs/hammer/hammer_vnops.c index 515554973b..b260dd35b0 100644 --- a/sys/vfs/hammer/hammer_vnops.c +++ b/sys/vfs/hammer/hammer_vnops.c @@ -780,7 +780,8 @@ hammer_vop_write(struct vop_write_args *ap) if (fixsize) { nvtruncbuf(ap->a_vp, ip->ino_data.size, hammer_blocksize(ip->ino_data.size), - hammer_blockoff(ip->ino_data.size)); + hammer_blockoff(ip->ino_data.size), + 0); } break; } @@ -2305,7 +2306,8 @@ hammer_vop_setattr(struct vop_setattr_args *ap) if (vap->va_size < ip->ino_data.size) { nvtruncbuf(ap->a_vp, vap->va_size, blksize, - hammer_blockoff(vap->va_size)); + hammer_blockoff(vap->va_size), + 0); truncating = 1; kflags |= NOTE_WRITE; } else { diff --git a/sys/vfs/nfs/nfs_bio.c b/sys/vfs/nfs/nfs_bio.c index 13be1aaeea..95801ed672 100644 --- a/sys/vfs/nfs/nfs_bio.c +++ b/sys/vfs/nfs/nfs_bio.c @@ -1289,7 +1289,7 @@ nfs_meta_setsize(struct vnode *vp, struct thread *td, off_t nsize, int trivial) np->n_size = nsize; if (nsize < osize) { - error = nvtruncbuf(vp, nsize, biosize, -1); + error = nvtruncbuf(vp, nsize, biosize, -1, 0); } else { error = nvextendbuf(vp, osize, nsize, biosize, biosize, -1, -1, diff --git a/sys/vfs/puffs/puffs_node.c b/sys/vfs/puffs/puffs_node.c index 53d4fc241a..4f6c35978e 100644 --- a/sys/vfs/puffs/puffs_node.c +++ b/sys/vfs/puffs/puffs_node.c @@ -413,7 +413,7 @@ puffs_meta_setsize(struct vnode *vp, off_t nsize, int trivial) return 0; if (nsize < osize) { - error = nvtruncbuf(vp, nsize, biosize, -1); + error = nvtruncbuf(vp, nsize, biosize, -1, 0); } else { error = nvextendbuf(vp, osize, nsize, biosize, biosize, -1, -1, diff --git a/sys/vfs/tmpfs/tmpfs_subr.c b/sys/vfs/tmpfs/tmpfs_subr.c index 727b33c3f5..c5ae546e8b 100644 --- a/sys/vfs/tmpfs/tmpfs_subr.c +++ b/sys/vfs/tmpfs/tmpfs_subr.c @@ -977,7 +977,7 @@ tmpfs_reg_resize(struct vnode *vp, off_t newsize, int trivial) vm_pindex_t nsize; vm_object_t aobj; - error = nvtruncbuf(vp, newsize, BSIZE, -1); + error = nvtruncbuf(vp, newsize, BSIZE, -1, 0); aobj = node->tn_reg.tn_aobj; if (aobj) { osize = aobj->size; diff --git a/sys/vfs/ufs/ffs_inode.c b/sys/vfs/ufs/ffs_inode.c index 81497cc9df..fddf0cbca6 100644 --- a/sys/vfs/ufs/ffs_inode.c +++ b/sys/vfs/ufs/ffs_inode.c @@ -251,7 +251,7 @@ ffs_truncate(struct vnode *vp, off_t length, int flags, struct ucred *cred) * of the block. */ allerror = nvtruncbuf(ovp, length, blkoffsize(fs, oip, length), - blkoff(fs, length)); + blkoff(fs, length), 0); offset = blkoff(fs, length); if (offset == 0) { oip->i_size = length; -- 2.41.0