version 1.69.4.2, 2006/12/30 20:51:01 |
version 1.86.4.1, 2007/03/13 17:51:21 |
Line 48 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 48 __KERNEL_RCSID(0, "$NetBSD$"); |
|
#include <sys/pool.h> |
#include <sys/pool.h> |
#include <sys/signalvar.h> |
#include <sys/signalvar.h> |
#include <sys/kauth.h> |
#include <sys/kauth.h> |
|
#include <sys/fstrans.h> |
|
|
#include <miscfs/fifofs/fifo.h> |
#include <miscfs/fifofs/fifo.h> |
#include <miscfs/genfs/genfs.h> |
#include <miscfs/genfs/genfs.h> |
Line 251 ffs_fsync(void *v) |
|
Line 252 ffs_fsync(void *v) |
|
daddr_t blk_high; |
daddr_t blk_high; |
struct vnode *vp; |
struct vnode *vp; |
|
|
|
vp = ap->a_vp; |
|
|
|
if ((error = fstrans_start(vp->v_mount, FSTRANS_LAZY)) != 0) |
|
return error; |
/* |
/* |
* XXX no easy way to sync a range in a file with softdep. |
* XXX no easy way to sync a range in a file with softdep. |
*/ |
*/ |
if ((ap->a_offlo == 0 && ap->a_offhi == 0) || DOINGSOFTDEP(ap->a_vp) || |
if ((ap->a_offlo == 0 && ap->a_offhi == 0) || DOINGSOFTDEP(vp) || |
(ap->a_vp->v_type != VREG)) |
(vp->v_type != VREG)) { |
return ffs_full_fsync(v); |
error = ffs_full_fsync(v); |
|
goto out; |
vp = ap->a_vp; |
} |
|
|
bsize = ap->a_vp->v_mount->mnt_stat.f_iosize; |
bsize = vp->v_mount->mnt_stat.f_iosize; |
blk_high = ap->a_offhi / bsize; |
blk_high = ap->a_offhi / bsize; |
if (ap->a_offhi % bsize != 0) |
if (ap->a_offhi % bsize != 0) |
blk_high++; |
blk_high++; |
Line 269 ffs_fsync(void *v) |
|
Line 274 ffs_fsync(void *v) |
|
* First, flush all pages in range. |
* First, flush all pages in range. |
*/ |
*/ |
|
|
simple_lock(&vp->v_interlock); |
mutex_enter(&vp->v_interlock); |
error = VOP_PUTPAGES(vp, trunc_page(ap->a_offlo), |
error = VOP_PUTPAGES(vp, trunc_page(ap->a_offlo), |
round_page(ap->a_offhi), PGO_CLEANIT | |
round_page(ap->a_offhi), PGO_CLEANIT | |
((ap->a_flags & FSYNC_WAIT) ? PGO_SYNCIO : 0)); |
((ap->a_flags & FSYNC_WAIT) ? PGO_SYNCIO : 0)); |
if (error) { |
if (error) { |
return error; |
goto out; |
} |
} |
|
|
/* |
/* |
Line 286 ffs_fsync(void *v) |
|
Line 291 ffs_fsync(void *v) |
|
error = ufs_getlbns(vp, blk_high, ia, &num); |
error = ufs_getlbns(vp, blk_high, ia, &num); |
if (error) { |
if (error) { |
splx(s); |
splx(s); |
return error; |
goto out; |
} |
} |
for (i = 0; i < num; i++) { |
for (i = 0; i < num; i++) { |
bp = incore(vp, ia[i].in_lbn); |
bp = incore(vp, ia[i].in_lbn); |
if (bp != NULL) { |
if (bp != NULL) { |
simple_lock(&bp->b_interlock); |
mutex_enter(&bp->b_interlock); |
if (!(bp->b_flags & B_BUSY) && (bp->b_flags & B_DELWRI)) { |
if (!(bp->b_flags & B_BUSY) && (bp->b_flags & B_DELWRI)) { |
bp->b_flags |= B_BUSY | B_VFLUSH; |
bp->b_flags |= B_BUSY | B_VFLUSH; |
simple_unlock(&bp->b_interlock); |
mutex_exit(&bp->b_interlock); |
splx(s); |
splx(s); |
bawrite(bp); |
bawrite(bp); |
s = splbio(); |
s = splbio(); |
} else { |
} else { |
simple_unlock(&bp->b_interlock); |
mutex_exit(&bp->b_interlock); |
} |
} |
} |
} |
} |
} |
} |
} |
|
|
if (ap->a_flags & FSYNC_WAIT) { |
if (ap->a_flags & FSYNC_WAIT) { |
simple_lock(&global_v_numoutput_slock); |
mutex_enter(&global_v_numoutput_lock); |
while (vp->v_numoutput > 0) { |
while (vp->v_numoutput > 0) { |
vp->v_flag |= VBWAIT; |
vp->v_flag |= VBWAIT; |
ltsleep(&vp->v_numoutput, PRIBIO + 1, "fsync_range", 0, |
mtsleep(&vp->v_numoutput, PRIBIO + 1, "fsync_range", 0, |
&global_v_numoutput_slock); |
&global_v_numoutput_lock); |
} |
} |
simple_unlock(&global_v_numoutput_slock); |
mutex_exit(&global_v_numoutput_lock); |
} |
} |
splx(s); |
splx(s); |
|
|
Line 326 ffs_fsync(void *v) |
|
Line 331 ffs_fsync(void *v) |
|
ap->a_l->l_cred, ap->a_l); |
ap->a_l->l_cred, ap->a_l); |
} |
} |
|
|
|
out: |
|
fstrans_done(vp->v_mount); |
return error; |
return error; |
} |
} |
|
|
Line 361 ffs_full_fsync(void *v) |
|
Line 368 ffs_full_fsync(void *v) |
|
*/ |
*/ |
|
|
if (vp->v_type == VREG || vp->v_type == VBLK) { |
if (vp->v_type == VREG || vp->v_type == VBLK) { |
simple_lock(&vp->v_interlock); |
mutex_enter(&vp->v_interlock); |
error = VOP_PUTPAGES(vp, 0, 0, PGO_ALLPAGES | PGO_CLEANIT | |
error = VOP_PUTPAGES(vp, 0, 0, PGO_ALLPAGES | PGO_CLEANIT | |
((ap->a_flags & FSYNC_WAIT) ? PGO_SYNCIO : 0)); |
((ap->a_flags & FSYNC_WAIT) ? PGO_SYNCIO : 0) | |
|
(fstrans_getstate(vp->v_mount) == FSTRANS_SUSPENDING ? |
|
PGO_FREE : 0)); |
if (error) { |
if (error) { |
return error; |
return error; |
} |
} |
|
|
bp->b_flags &= ~B_SCANNED; |
bp->b_flags &= ~B_SCANNED; |
for (bp = LIST_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) { |
for (bp = LIST_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) { |
nbp = LIST_NEXT(bp, b_vnbufs); |
nbp = LIST_NEXT(bp, b_vnbufs); |
simple_lock(&bp->b_interlock); |
mutex_enter(&bp->b_interlock); |
if (bp->b_flags & (B_BUSY | B_SCANNED)) { |
if (bp->b_flags & (B_BUSY | B_SCANNED)) { |
simple_unlock(&bp->b_interlock); |
mutex_exit(&bp->b_interlock); |
continue; |
continue; |
} |
} |
if ((bp->b_flags & B_DELWRI) == 0) |
if ((bp->b_flags & B_DELWRI) == 0) |
panic("ffs_fsync: not dirty"); |
panic("ffs_fsync: not dirty"); |
if (skipmeta && bp->b_lblkno < 0) { |
if (skipmeta && bp->b_lblkno < 0) { |
simple_unlock(&bp->b_interlock); |
mutex_exit(&bp->b_interlock); |
continue; |
continue; |
} |
} |
simple_unlock(&bp->b_interlock); |
mutex_exit(&bp->b_interlock); |
bp->b_flags |= B_BUSY | B_VFLUSH | B_SCANNED; |
bp->b_flags |= B_BUSY | B_VFLUSH | B_SCANNED; |
splx(s); |
splx(s); |
/* |
/* |
|
|
goto loop; |
goto loop; |
} |
} |
if (ap->a_flags & FSYNC_WAIT) { |
if (ap->a_flags & FSYNC_WAIT) { |
simple_lock(&global_v_numoutput_slock); |
mutex_enter(&global_v_numoutput_lock); |
while (vp->v_numoutput) { |
while (vp->v_numoutput) { |
vp->v_flag |= VBWAIT; |
vp->v_flag |= VBWAIT; |
(void) ltsleep(&vp->v_numoutput, PRIBIO + 1, |
(void) mtsleep(&vp->v_numoutput, PRIBIO + 1, |
"ffsfsync", 0, &global_v_numoutput_slock); |
"ffsfsync", 0, &global_v_numoutput_lock); |
} |
} |
simple_unlock(&global_v_numoutput_slock); |
mutex_exit(&global_v_numoutput_lock); |
splx(s); |
splx(s); |
|
|
/* |
/* |
Line 480 ffs_reclaim(void *v) |
|
Line 489 ffs_reclaim(void *v) |
|
} */ *ap = v; |
} */ *ap = v; |
struct vnode *vp = ap->a_vp; |
struct vnode *vp = ap->a_vp; |
struct inode *ip = VTOI(vp); |
struct inode *ip = VTOI(vp); |
|
struct mount *mp = vp->v_mount; |
struct ufsmount *ump = ip->i_ump; |
struct ufsmount *ump = ip->i_ump; |
int error; |
int error; |
|
|
if ((error = ufs_reclaim(vp, ap->a_l)) != 0) |
if ((error = fstrans_start(mp, FSTRANS_LAZY)) != 0) |
|
return error; |
|
if ((error = ufs_reclaim(vp, ap->a_l)) != 0) { |
|
fstrans_done(mp); |
return (error); |
return (error); |
|
} |
if (ip->i_din.ffs1_din != NULL) { |
if (ip->i_din.ffs1_din != NULL) { |
if (ump->um_fstype == UFS1) |
if (ump->um_fstype == UFS1) |
pool_put(&ffs_dinode1_pool, ip->i_din.ffs1_din); |
pool_put(&ffs_dinode1_pool, ip->i_din.ffs1_din); |
Line 495 ffs_reclaim(void *v) |
|
Line 509 ffs_reclaim(void *v) |
|
* XXX MFS ends up here, too, to free an inode. Should we create |
* XXX MFS ends up here, too, to free an inode. Should we create |
* XXX a separate pool for MFS inodes? |
* XXX a separate pool for MFS inodes? |
*/ |
*/ |
|
genfs_node_destroy(vp); |
pool_put(&ffs_inode_pool, vp->v_data); |
pool_put(&ffs_inode_pool, vp->v_data); |
vp->v_data = NULL; |
vp->v_data = NULL; |
|
fstrans_done(mp); |
return (0); |
return (0); |
} |
} |
|
|
Line 528 ffs_getpages(void *v) |
|
Line 544 ffs_getpages(void *v) |
|
blkoff(fs, *ap->a_count << PAGE_SHIFT) != 0) && |
blkoff(fs, *ap->a_count << PAGE_SHIFT) != 0) && |
DOINGSOFTDEP(ap->a_vp)) { |
DOINGSOFTDEP(ap->a_vp)) { |
if ((ap->a_flags & PGO_LOCKED) == 0) { |
if ((ap->a_flags & PGO_LOCKED) == 0) { |
simple_unlock(&vp->v_interlock); |
mutex_exit(&vp->v_interlock); |
} |
} |
return EINVAL; |
return EINVAL; |
} |
} |
Line 607 ffs_getextattr(void *v) |
|
Line 623 ffs_getextattr(void *v) |
|
kauth_cred_t a_cred; |
kauth_cred_t a_cred; |
struct proc *a_p; |
struct proc *a_p; |
} */ *ap = v; |
} */ *ap = v; |
struct inode *ip = VTOI(ap->a_vp); |
struct vnode *vp = ap->a_vp; |
|
struct inode *ip = VTOI(vp); |
struct fs *fs = ip->i_fs; |
struct fs *fs = ip->i_fs; |
|
|
if (fs->fs_magic == FS_UFS1_MAGIC) { |
if (fs->fs_magic == FS_UFS1_MAGIC) { |
#ifdef UFS_EXTATTR |
#ifdef UFS_EXTATTR |
return (ufs_getextattr(ap)); |
int error; |
|
|
|
if ((error = fstrans_start(vp->v_mount, FSTRANS_SHARED)) != 0) |
|
return error; |
|
error = ufs_getextattr(ap); |
|
fstrans_done(vp->v_mount); |
|
return error; |
#else |
#else |
return (EOPNOTSUPP); |
return (EOPNOTSUPP); |
#endif |
#endif |
Line 633 ffs_setextattr(void *v) |
|
Line 656 ffs_setextattr(void *v) |
|
kauth_cred_t a_cred; |
kauth_cred_t a_cred; |
struct proc *a_p; |
struct proc *a_p; |
} */ *ap = v; |
} */ *ap = v; |
struct inode *ip = VTOI(ap->a_vp); |
struct vnode *vp = ap->a_vp; |
|
struct inode *ip = VTOI(vp); |
struct fs *fs = ip->i_fs; |
struct fs *fs = ip->i_fs; |
|
|
if (fs->fs_magic == FS_UFS1_MAGIC) { |
if (fs->fs_magic == FS_UFS1_MAGIC) { |
#ifdef UFS_EXTATTR |
#ifdef UFS_EXTATTR |
return (ufs_setextattr(ap)); |
int error; |
|
|
|
if ((error = fstrans_start(vp->v_mount, FSTRANS_SHARED)) != 0) |
|
return error; |
|
error = ufs_setextattr(ap); |
|
fstrans_done(vp->v_mount); |
|
return error; |
#else |
#else |
return (EOPNOTSUPP); |
return (EOPNOTSUPP); |
#endif |
#endif |
Line 679 ffs_deleteextattr(void *v) |
|
Line 709 ffs_deleteextattr(void *v) |
|
kauth_cred_t a_cred; |
kauth_cred_t a_cred; |
struct proc *a_p; |
struct proc *a_p; |
} */ *ap = v; |
} */ *ap = v; |
struct inode *ip = VTOI(ap->a_vp); |
struct vnode *vp = ap->a_vp; |
|
struct inode *ip = VTOI(vp); |
struct fs *fs = ip->i_fs; |
struct fs *fs = ip->i_fs; |
|
|
if (fs->fs_magic == FS_UFS1_MAGIC) { |
if (fs->fs_magic == FS_UFS1_MAGIC) { |
#ifdef UFS_EXTATTR |
#ifdef UFS_EXTATTR |
return (ufs_deleteextattr(ap)); |
int error; |
|
|
|
if ((error = fstrans_start(vp->v_mount, FSTRANS_SHARED)) != 0) |
|
return error; |
|
error = ufs_deleteextattr(ap); |
|
fstrans_done(vp->v_mount); |
|
return error; |
#else |
#else |
return (EOPNOTSUPP); |
return (EOPNOTSUPP); |
#endif |
#endif |