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:
parent
f8c7085d31
commit
cd0ef8f0f0
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user