From 40854ff54694c7014e7a850ece8bd1ae46addea6 Mon Sep 17 00:00:00 2001 From: Poul-Henning Kamp Date: Tue, 8 Feb 2005 16:25:50 +0000 Subject: [PATCH] For snapshots we need all VOP_LOCKs to be exclusive. The "business class upgrade" was implemented in UFS's VOP_LOCK implementation ufs_lock() which is the wrong layer, so move it to ffs_lock(). Also, as long as we have not abandonned advanced vfs-stacking we should not preclude it from happening: instead of implementing a copy locally, use the VOP_LOCK_APV(&ufs) to correctly arrive at vop_stdlock() at the bottom. --- sys/ufs/ffs/ffs_balloc.c | 10 ++++------ sys/ufs/ffs/ffs_extern.h | 3 ++- sys/ufs/ffs/ffs_inode.c | 6 +++--- sys/ufs/ffs/ffs_rawread.c | 3 ++- sys/ufs/ffs/ffs_snapshot.c | 18 +++++++++--------- sys/ufs/ffs/ffs_softdep.c | 26 +++++++++----------------- sys/ufs/ffs/ffs_vfsops.c | 3 +-- sys/ufs/ffs/ffs_vnops.c | 22 ++++++++++++---------- 8 files changed, 42 insertions(+), 49 deletions(-) diff --git a/sys/ufs/ffs/ffs_balloc.c b/sys/ufs/ffs/ffs_balloc.c index 8ffe4fe77955..97f4fdae9d1e 100644 --- a/sys/ufs/ffs/ffs_balloc.c +++ b/sys/ufs/ffs/ffs_balloc.c @@ -103,7 +103,6 @@ ffs_balloc_ufs1(struct vnode *vp, off_t startoffset, int size, ufs1_daddr_t *bap, pref; ufs1_daddr_t *allocib, *blkp, *allocblk, allociblk[NIADDR + 1]; int unwindidx = -1; - struct thread *td = curthread; /* XXX */ ip = VTOI(vp); dp = ip->i_din1; @@ -403,7 +402,7 @@ ffs_balloc_ufs1(struct vnode *vp, off_t startoffset, int size, * occurence. The error return from fsync is ignored as we already * have an error to return to the user. */ - (void) VOP_FSYNC(vp, MNT_WAIT, td); + (void) ffs_syncvnode(vp, MNT_WAIT); for (deallocated = 0, blkp = allociblk; blkp < allocblk; blkp++) { ffs_blkfree(ump, fs, ip->i_devvp, *blkp, fs->fs_bsize, ip->i_number); @@ -441,7 +440,7 @@ ffs_balloc_ufs1(struct vnode *vp, off_t startoffset, int size, dp->di_blocks -= btodb(deallocated); ip->i_flag |= IN_CHANGE | IN_UPDATE; } - (void) VOP_FSYNC(vp, MNT_WAIT, td); + (void) ffs_syncvnode(vp, MNT_WAIT); return (error); } @@ -467,7 +466,6 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size, ufs2_daddr_t *allocib, *blkp, *allocblk, allociblk[NIADDR + 1]; int deallocated, osize, nsize, num, i, error; int unwindidx = -1; - struct thread *td = curthread; /* XXX */ ip = VTOI(vp); dp = ip->i_din2; @@ -882,7 +880,7 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size, * occurence. The error return from fsync is ignored as we already * have an error to return to the user. */ - (void) VOP_FSYNC(vp, MNT_WAIT, td); + (void) ffs_syncvnode(vp, MNT_WAIT); for (deallocated = 0, blkp = allociblk; blkp < allocblk; blkp++) { ffs_blkfree(ump, fs, ip->i_devvp, *blkp, fs->fs_bsize, ip->i_number); @@ -920,6 +918,6 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size, dp->di_blocks -= btodb(deallocated); ip->i_flag |= IN_CHANGE | IN_UPDATE; } - (void) VOP_FSYNC(vp, MNT_WAIT, td); + (void) ffs_syncvnode(vp, MNT_WAIT); return (error); } diff --git a/sys/ufs/ffs/ffs_extern.h b/sys/ufs/ffs/ffs_extern.h index 4e27092ec1a1..b25f10e7234a 100644 --- a/sys/ufs/ffs/ffs_extern.h +++ b/sys/ufs/ffs/ffs_extern.h @@ -81,6 +81,7 @@ void ffs_snapshot_mount(struct mount *mp); void ffs_snapshot_unmount(struct mount *mp); vfs_statfs_t ffs_statfs; vfs_sync_t ffs_sync; +int ffs_syncvnode(struct vnode *vp, int waitfor); int ffs_truncate(struct vnode *, off_t, int, struct ucred *, struct thread *); vfs_unmount_t ffs_unmount; int ffs_update(struct vnode *, int); @@ -118,7 +119,7 @@ void softdep_setup_allocindir_meta(struct buf *, struct inode *, void softdep_setup_allocindir_page(struct inode *, ufs_lbn_t, struct buf *, int, ufs2_daddr_t, ufs2_daddr_t, struct buf *); void softdep_fsync_mountdev(struct vnode *); -int softdep_sync_metadata(struct vop_fsync_args *); +int softdep_sync_metadata(struct vnode *); int softdep_disk_prewrite(struct buf *bp); /* XXX incorrectly moved to mount.h - should be indirect function */ #if 0 diff --git a/sys/ufs/ffs/ffs_inode.c b/sys/ufs/ffs/ffs_inode.c index d881625aa02a..3d0145990260 100644 --- a/sys/ufs/ffs/ffs_inode.c +++ b/sys/ufs/ffs/ffs_inode.c @@ -195,7 +195,7 @@ ffs_truncate(vp, length, flags, cred, td) } else { if (length != 0) panic("ffs_truncate: partial trunc of extdata"); - if ((error = VOP_FSYNC(ovp, MNT_WAIT, td)) != 0) + if ((error = ffs_syncvnode(ovp, MNT_WAIT)) != 0) return (error); osize = oip->i_din2->di_extsize; oip->i_din2->di_blocks -= extblocks; @@ -265,7 +265,7 @@ ffs_truncate(vp, length, flags, cred, td) * rarely, we solve the problem by syncing the file * so that it will have no data structures left. */ - if ((error = VOP_FSYNC(ovp, MNT_WAIT, td)) != 0) + if ((error = ffs_syncvnode(ovp, MNT_WAIT)) != 0) return (error); UFS_LOCK(ump); if (oip->i_flag & IN_SPACECOUNTED) @@ -334,7 +334,7 @@ ffs_truncate(vp, length, flags, cred, td) */ if (DOINGSOFTDEP(ovp) && lbn < NDADDR && fragroundup(fs, blkoff(fs, length)) < fs->fs_bsize && - (error = VOP_FSYNC(ovp, MNT_WAIT, td)) != 0) + (error = ffs_syncvnode(ovp, MNT_WAIT)) != 0) return (error); oip->i_size = length; DIP_SET(oip, i_size, length); diff --git a/sys/ufs/ffs/ffs_rawread.c b/sys/ufs/ffs/ffs_rawread.c index e60b1c957f9e..e2d891bc7bb0 100644 --- a/sys/ufs/ffs/ffs_rawread.c +++ b/sys/ufs/ffs/ffs_rawread.c @@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -150,7 +151,7 @@ ffs_rawread_sync(struct vnode *vp, struct thread *td) if (bo->bo_dirty.bv_cnt > 0) { splx(spl); VI_UNLOCK(vp); - if ((error = VOP_FSYNC(vp, MNT_WAIT, td)) != 0) { + if ((error = ffs_syncvnode(vp, MNT_WAIT)) != 0) { if (upgraded != 0) VOP_LOCK(vp, LK_DOWNGRADE, td); return (error); diff --git a/sys/ufs/ffs/ffs_snapshot.c b/sys/ufs/ffs/ffs_snapshot.c index d74ed5ffe0d9..5184d4b3cccc 100644 --- a/sys/ufs/ffs/ffs_snapshot.c +++ b/sys/ufs/ffs/ffs_snapshot.c @@ -316,7 +316,7 @@ ffs_snapshot(mp, snapfile) * Since we have marked it as a snapshot it is safe to * unlock it as no process will be allowed to write to it. */ - if ((error = VOP_FSYNC(vp, MNT_WAIT, td)) != 0) + if ((error = ffs_syncvnode(vp, MNT_WAIT)) != 0) goto out; VOP_UNLOCK(vp, 0, td); /* @@ -700,7 +700,7 @@ ffs_snapshot(mp, snapfile) mp->mnt_flag = flag; if (error) (void) UFS_TRUNCATE(vp, (off_t)0, 0, NOCRED, td); - (void) VOP_FSYNC(vp, MNT_WAIT, td); + (void) ffs_syncvnode(vp, MNT_WAIT); if (error) vput(vp); else @@ -1727,7 +1727,7 @@ ffs_snapblkfree(fs, devvp, bno, size, inum) bcopy(savedcbp->b_data, cbp->b_data, fs->fs_bsize); bawrite(cbp); if (dopersistence && ip->i_effnlink > 0) - (void) VOP_FSYNC(vp, MNT_WAIT, td); + (void) ffs_syncvnode(vp, MNT_WAIT); continue; } /* @@ -1737,7 +1737,7 @@ ffs_snapblkfree(fs, devvp, bno, size, inum) bzero(cbp->b_data, fs->fs_bsize); bawrite(cbp); if (dopersistence && ip->i_effnlink > 0) - (void) VOP_FSYNC(vp, MNT_WAIT, td); + (void) ffs_syncvnode(vp, MNT_WAIT); break; } savedcbp = cbp; @@ -1751,7 +1751,7 @@ ffs_snapblkfree(fs, devvp, bno, size, inum) vp = savedcbp->b_vp; bawrite(savedcbp); if (dopersistence && VTOI(vp)->i_effnlink > 0) - (void) VOP_FSYNC(vp, MNT_WAIT, td); + (void) ffs_syncvnode(vp, MNT_WAIT); } /* * If we have been unable to allocate a block in which to do @@ -1813,7 +1813,7 @@ ffs_snapshot_mount(mp) } else { reason = "old format snapshot"; (void)UFS_TRUNCATE(vp, (off_t)0, 0, NOCRED, td); - (void)VOP_FSYNC(vp, MNT_WAIT, td); + (void)ffs_syncvnode(vp, MNT_WAIT); } printf("ffs_snapshot_mount: %s inode %d\n", reason, fs->fs_snapinum[snaploc]); @@ -2094,7 +2094,7 @@ ffs_copyonwrite(devvp, bp) bcopy(savedcbp->b_data, cbp->b_data, fs->fs_bsize); bawrite(cbp); if (dopersistence && ip->i_effnlink > 0) - (void) VOP_FSYNC(vp, MNT_WAIT, td); + (void) ffs_syncvnode(vp, MNT_WAIT); continue; } /* @@ -2104,7 +2104,7 @@ ffs_copyonwrite(devvp, bp) bzero(cbp->b_data, fs->fs_bsize); bawrite(cbp); if (dopersistence && ip->i_effnlink > 0) - (void) VOP_FSYNC(vp, MNT_WAIT, td); + (void) ffs_syncvnode(vp, MNT_WAIT); break; } savedcbp = cbp; @@ -2118,7 +2118,7 @@ ffs_copyonwrite(devvp, bp) vp = savedcbp->b_vp; bawrite(savedcbp); if (dopersistence && VTOI(vp)->i_effnlink > 0) - (void) VOP_FSYNC(vp, MNT_WAIT, td); + (void) ffs_syncvnode(vp, MNT_WAIT); } if (snapshot_locked) VOP_UNLOCK(vp, 0, td); diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c index c96467b3760a..0fc7fbabb6b1 100644 --- a/sys/ufs/ffs/ffs_softdep.c +++ b/sys/ufs/ffs/ffs_softdep.c @@ -4615,7 +4615,7 @@ softdep_fsync(vp) * doing a UFS_UPDATE. Pagedeps contained in indirect blocks * may require a complete sync'ing of the directory. So, we * try the cheap and fast UFS_UPDATE first, and if that fails, - * then we do the slower VOP_FSYNC of the directory. + * then we do the slower ffs_syncvnode of the directory. */ if (flushparent) { if ((error = UFS_UPDATE(pvp, 1)) != 0) { @@ -4623,7 +4623,7 @@ softdep_fsync(vp) return (error); } if ((pagedep->pd_state & NEWBLOCK) && - (error = VOP_FSYNC(pvp, MNT_WAIT, td))) { + (error = ffs_syncvnode(pvp, MNT_WAIT))) { vput(pvp); return (error); } @@ -4707,15 +4707,8 @@ softdep_fsync_mountdev(vp) * associated with the file. If any I/O errors occur, they are returned. */ int -softdep_sync_metadata(ap) - struct vop_fsync_args /* { - struct vnode *a_vp; - struct ucred *a_cred; - int a_waitfor; - struct thread *a_td; - } */ *ap; +softdep_sync_metadata(struct vnode *vp) { - struct vnode *vp = ap->a_vp; struct pagedep *pagedep; struct allocdirect *adp; struct allocindir *aip; @@ -5051,7 +5044,6 @@ flush_pagedep_deps(pvp, mp, diraddhdp) struct mount *mp; struct diraddhd *diraddhdp; { - struct thread *td = curthread; struct inodedep *inodedep; struct ufsmount *ump; struct diradd *dap; @@ -5083,7 +5075,7 @@ flush_pagedep_deps(pvp, mp, diraddhdp) * A newly allocated directory must have its "." and * ".." entries written out before its name can be * committed in its parent. We do not want or need - * the full semantics of a synchronous VOP_FSYNC as + * the full semantics of a synchronous ffs_syncvnode as * that may end up here again, once for each directory * level in the filesystem. Instead, we push the blocks * and wait for them to clear. We have to fsync twice @@ -5096,8 +5088,8 @@ flush_pagedep_deps(pvp, mp, diraddhdp) FREE_LOCK(&lk); if ((error = VFS_VGET(mp, inum, LK_EXCLUSIVE, &vp))) break; - if ((error=VOP_FSYNC(vp, MNT_NOWAIT, td)) || - (error=VOP_FSYNC(vp, MNT_NOWAIT, td))) { + if ((error=ffs_syncvnode(vp, MNT_NOWAIT)) || + (error=ffs_syncvnode(vp, MNT_NOWAIT))) { vput(vp); break; } @@ -5379,7 +5371,7 @@ clear_remove(td) ACQUIRE_LOCK(&lk); return; } - if ((error = VOP_FSYNC(vp, MNT_NOWAIT, td))) + if ((error = ffs_syncvnode(vp, MNT_NOWAIT))) softdep_error("clear_remove: fsync", error); VI_LOCK(vp); drain_output(vp); @@ -5456,10 +5448,10 @@ clear_inodedeps(td) return; } if (ino == lastino) { - if ((error = VOP_FSYNC(vp, MNT_WAIT, td))) + if ((error = ffs_syncvnode(vp, MNT_WAIT))) softdep_error("clear_inodedeps: fsync1", error); } else { - if ((error = VOP_FSYNC(vp, MNT_NOWAIT, td))) + if ((error = ffs_syncvnode(vp, MNT_NOWAIT))) softdep_error("clear_inodedeps: fsync2", error); VI_LOCK(vp); drain_output(vp); diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c index ee926b50259b..f54f15e5f206 100644 --- a/sys/ufs/ffs/ffs_vfsops.c +++ b/sys/ufs/ffs/ffs_vfsops.c @@ -49,7 +49,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include @@ -1116,7 +1115,7 @@ ffs_sync(mp, waitfor, td) goto loop; continue; } - if ((error = VOP_FSYNC(vp, waitfor, td)) != 0) + if ((error = ffs_syncvnode(vp, waitfor)) != 0) allerror = error; VOP_UNLOCK(vp, 0, td); vrele(vp); diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c index f9a7994ac0a2..3a9e49d6ea59 100644 --- a/sys/ufs/ffs/ffs_vnops.c +++ b/sys/ufs/ffs/ffs_vnops.c @@ -155,22 +155,24 @@ struct vop_vector ffs_fifoops = { */ /* ARGSUSED */ static int -ffs_fsync(ap) - struct vop_fsync_args /* { - struct vnode *a_vp; - struct ucred *a_cred; - int a_waitfor; - struct thread *a_td; - } */ *ap; +ffs_fsync(struct vop_fsync_args *ap) +{ + int error; + + error = ffs_syncvnode(ap->a_vp, ap->a_waitfor); + return (error); +} + +int +ffs_syncvnode(struct vnode *vp, int waitfor) { - struct vnode *vp = ap->a_vp; struct inode *ip = VTOI(vp); struct buf *bp; struct buf *nbp; int s, error, wait, passes, skipmeta; ufs_lbn_t lbn; - wait = (ap->a_waitfor == MNT_WAIT); + wait = (waitfor == MNT_WAIT); lbn = lblkno(ip->i_fs, (ip->i_size + ip->i_fs->fs_bsize - 1)); /* @@ -277,7 +279,7 @@ ffs_fsync(ap) * with the vnode has been written. */ splx(s); - if ((error = softdep_sync_metadata(ap)) != 0) + if ((error = softdep_sync_metadata(vp)) != 0) return (error); s = splbio();