version 1.293, 2014/03/05 09:37:29 |
version 1.294, 2014/03/17 09:29:55 |
Line 1603 ffs_statvfs(struct mount *mp, struct sta |
|
Line 1603 ffs_statvfs(struct mount *mp, struct sta |
|
int |
int |
ffs_sync(struct mount *mp, int waitfor, kauth_cred_t cred) |
ffs_sync(struct mount *mp, int waitfor, kauth_cred_t cred) |
{ |
{ |
struct vnode *vp, *mvp, *nvp; |
struct vnode *vp; |
struct inode *ip; |
struct inode *ip; |
struct ufsmount *ump = VFSTOUFS(mp); |
struct ufsmount *ump = VFSTOUFS(mp); |
struct fs *fs; |
struct fs *fs; |
|
struct vnode_iterator *marker; |
int error, allerror = 0; |
int error, allerror = 0; |
bool is_suspending; |
bool is_suspending; |
|
|
Line 1616 ffs_sync(struct mount *mp, int waitfor, |
|
Line 1617 ffs_sync(struct mount *mp, int waitfor, |
|
panic("update: rofs mod"); |
panic("update: rofs mod"); |
} |
} |
|
|
/* Allocate a marker vnode. */ |
|
mvp = vnalloc(mp); |
|
|
|
fstrans_start(mp, FSTRANS_SHARED); |
fstrans_start(mp, FSTRANS_SHARED); |
is_suspending = (fstrans_getstate(mp) == FSTRANS_SUSPENDING); |
is_suspending = (fstrans_getstate(mp) == FSTRANS_SUSPENDING); |
/* |
/* |
* Write back each (modified) inode. |
* Write back each (modified) inode. |
*/ |
*/ |
mutex_enter(&mntvnode_lock); |
vfs_vnode_iterator_init(mp, &marker); |
loop: |
while (vfs_vnode_iterator_next(marker, &vp)) { |
/* |
error = vn_lock(vp, LK_EXCLUSIVE); |
* NOTE: not using the TAILQ_FOREACH here since in this loop vgone() |
if (error) { |
* and vclean() can be called indirectly |
vrele(vp); |
*/ |
|
for (vp = TAILQ_FIRST(&mp->mnt_vnodelist); vp; vp = nvp) { |
|
nvp = TAILQ_NEXT(vp, v_mntvnodes); |
|
/* |
|
* If the vnode that we are about to sync is no longer |
|
* associated with this mount point, start over. |
|
*/ |
|
if (vp->v_mount != mp) |
|
goto loop; |
|
/* |
|
* Don't interfere with concurrent scans of this FS. |
|
*/ |
|
if (vismarker(vp)) |
|
continue; |
continue; |
mutex_enter(vp->v_interlock); |
} |
ip = VTOI(vp); |
ip = VTOI(vp); |
|
|
/* |
/* |
* Skip the vnode/inode if inaccessible. |
* Skip the vnode/inode if inaccessible. |
*/ |
*/ |
if (ip == NULL || (vp->v_iflag & (VI_XLOCK | VI_CLEAN)) != 0 || |
if (ip == NULL || vp->v_type == VNON) { |
vp->v_type == VNON) { |
vput(vp); |
mutex_exit(vp->v_interlock); |
|
continue; |
continue; |
} |
} |
|
|
|
|
IN_MODIFY | IN_MODIFIED | IN_ACCESSED)) == 0 && |
IN_MODIFY | IN_MODIFIED | IN_ACCESSED)) == 0 && |
(waitfor == MNT_LAZY || (LIST_EMPTY(&vp->v_dirtyblkhd) && |
(waitfor == MNT_LAZY || (LIST_EMPTY(&vp->v_dirtyblkhd) && |
UVM_OBJ_IS_CLEAN(&vp->v_uobj)))) { |
UVM_OBJ_IS_CLEAN(&vp->v_uobj)))) { |
mutex_exit(vp->v_interlock); |
vput(vp); |
continue; |
continue; |
} |
} |
if (vp->v_type == VBLK && is_suspending) { |
if (vp->v_type == VBLK && is_suspending) { |
mutex_exit(vp->v_interlock); |
vput(vp); |
continue; |
|
} |
|
vmark(mvp, vp); |
|
mutex_exit(&mntvnode_lock); |
|
error = vget(vp, LK_EXCLUSIVE | LK_NOWAIT); |
|
if (error) { |
|
mutex_enter(&mntvnode_lock); |
|
nvp = vunmark(mvp); |
|
if (error == ENOENT) { |
|
goto loop; |
|
} |
|
continue; |
continue; |
} |
} |
if (waitfor == MNT_LAZY) { |
if (waitfor == MNT_LAZY) { |
|
|
if (error) |
if (error) |
allerror = error; |
allerror = error; |
vput(vp); |
vput(vp); |
mutex_enter(&mntvnode_lock); |
|
nvp = vunmark(mvp); |
|
} |
} |
mutex_exit(&mntvnode_lock); |
vfs_vnode_iterator_destroy(marker); |
|
|
/* |
/* |
* Force stale file system control information to be flushed. |
* Force stale file system control information to be flushed. |
*/ |
*/ |
|
|
0, 0)) != 0) |
0, 0)) != 0) |
allerror = error; |
allerror = error; |
VOP_UNLOCK(ump->um_devvp); |
VOP_UNLOCK(ump->um_devvp); |
if (allerror == 0 && waitfor == MNT_WAIT && !mp->mnt_wapbl) { |
|
mutex_enter(&mntvnode_lock); |
|
goto loop; |
|
} |
|
} |
} |
#if defined(QUOTA) || defined(QUOTA2) |
#if defined(QUOTA) || defined(QUOTA2) |
qsync(mp); |
qsync(mp); |
|
|
#endif |
#endif |
|
|
fstrans_done(mp); |
fstrans_done(mp); |
vnfree(mvp); |
|
return (allerror); |
return (allerror); |
} |
} |
|
|