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.
This commit is contained in:
Poul-Henning Kamp 2005-02-08 16:25:50 +00:00
parent d6f622cc2f
commit 40854ff546
8 changed files with 42 additions and 49 deletions

View File

@ -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);
}

View File

@ -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

View File

@ -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);

View File

@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$");
#include <ufs/ufs/ufsmount.h>
#include <ufs/ufs/ufs_extern.h>
#include <ufs/ffs/fs.h>
#include <ufs/ffs/ffs_extern.h>
#include <vm/vm.h>
#include <vm/vm_extern.h>
@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -49,7 +49,6 @@ __FBSDID("$FreeBSD$");
#include <sys/buf.h>
#include <sys/conf.h>
#include <sys/fcntl.h>
#include <sys/disk.h>
#include <sys/malloc.h>
#include <sys/mutex.h>
@ -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);

View File

@ -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();