version 1.82, 2006/10/12 01:32:51 |
version 1.86.4.10, 2007/08/24 23:28:45 |
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 100 const struct vnodeopv_entry_desc ffs_vno |
|
Line 101 const struct vnodeopv_entry_desc ffs_vno |
|
{ &vop_abortop_desc, ufs_abortop }, /* abortop */ |
{ &vop_abortop_desc, ufs_abortop }, /* abortop */ |
{ &vop_inactive_desc, ufs_inactive }, /* inactive */ |
{ &vop_inactive_desc, ufs_inactive }, /* inactive */ |
{ &vop_reclaim_desc, ffs_reclaim }, /* reclaim */ |
{ &vop_reclaim_desc, ffs_reclaim }, /* reclaim */ |
{ &vop_lock_desc, ufs_lock }, /* lock */ |
{ &vop_lock_desc, ffs_lock }, /* lock */ |
{ &vop_unlock_desc, ufs_unlock }, /* unlock */ |
{ &vop_unlock_desc, ffs_unlock }, /* unlock */ |
{ &vop_bmap_desc, ufs_bmap }, /* bmap */ |
{ &vop_bmap_desc, ufs_bmap }, /* bmap */ |
{ &vop_strategy_desc, ufs_strategy }, /* strategy */ |
{ &vop_strategy_desc, ufs_strategy }, /* strategy */ |
{ &vop_print_desc, ufs_print }, /* print */ |
{ &vop_print_desc, ufs_print }, /* print */ |
{ &vop_islocked_desc, ufs_islocked }, /* islocked */ |
{ &vop_islocked_desc, ffs_islocked }, /* islocked */ |
{ &vop_pathconf_desc, ufs_pathconf }, /* pathconf */ |
{ &vop_pathconf_desc, ufs_pathconf }, /* pathconf */ |
{ &vop_advlock_desc, ufs_advlock }, /* advlock */ |
{ &vop_advlock_desc, ufs_advlock }, /* advlock */ |
{ &vop_bwrite_desc, vn_bwrite }, /* bwrite */ |
{ &vop_bwrite_desc, vn_bwrite }, /* bwrite */ |
{ &vop_getpages_desc, ffs_getpages }, /* getpages */ |
{ &vop_getpages_desc, genfs_getpages }, /* getpages */ |
{ &vop_putpages_desc, genfs_putpages }, /* putpages */ |
{ &vop_putpages_desc, genfs_putpages }, /* putpages */ |
{ &vop_openextattr_desc, ffs_openextattr }, /* openextattr */ |
{ &vop_openextattr_desc, ffs_openextattr }, /* openextattr */ |
{ &vop_closeextattr_desc, ffs_closeextattr }, /* closeextattr */ |
{ &vop_closeextattr_desc, ffs_closeextattr }, /* closeextattr */ |
Line 155 const struct vnodeopv_entry_desc ffs_spe |
|
Line 156 const struct vnodeopv_entry_desc ffs_spe |
|
{ &vop_abortop_desc, spec_abortop }, /* abortop */ |
{ &vop_abortop_desc, spec_abortop }, /* abortop */ |
{ &vop_inactive_desc, ufs_inactive }, /* inactive */ |
{ &vop_inactive_desc, ufs_inactive }, /* inactive */ |
{ &vop_reclaim_desc, ffs_reclaim }, /* reclaim */ |
{ &vop_reclaim_desc, ffs_reclaim }, /* reclaim */ |
{ &vop_lock_desc, ufs_lock }, /* lock */ |
{ &vop_lock_desc, ffs_lock }, /* lock */ |
{ &vop_unlock_desc, ufs_unlock }, /* unlock */ |
{ &vop_unlock_desc, ffs_unlock }, /* unlock */ |
{ &vop_bmap_desc, spec_bmap }, /* bmap */ |
{ &vop_bmap_desc, spec_bmap }, /* bmap */ |
{ &vop_strategy_desc, spec_strategy }, /* strategy */ |
{ &vop_strategy_desc, spec_strategy }, /* strategy */ |
{ &vop_print_desc, ufs_print }, /* print */ |
{ &vop_print_desc, ufs_print }, /* print */ |
{ &vop_islocked_desc, ufs_islocked }, /* islocked */ |
{ &vop_islocked_desc, ffs_islocked }, /* islocked */ |
{ &vop_pathconf_desc, spec_pathconf }, /* pathconf */ |
{ &vop_pathconf_desc, spec_pathconf }, /* pathconf */ |
{ &vop_advlock_desc, spec_advlock }, /* advlock */ |
{ &vop_advlock_desc, spec_advlock }, /* advlock */ |
{ &vop_bwrite_desc, vn_bwrite }, /* bwrite */ |
{ &vop_bwrite_desc, vn_bwrite }, /* bwrite */ |
Line 210 const struct vnodeopv_entry_desc ffs_fif |
|
Line 211 const struct vnodeopv_entry_desc ffs_fif |
|
{ &vop_abortop_desc, fifo_abortop }, /* abortop */ |
{ &vop_abortop_desc, fifo_abortop }, /* abortop */ |
{ &vop_inactive_desc, ufs_inactive }, /* inactive */ |
{ &vop_inactive_desc, ufs_inactive }, /* inactive */ |
{ &vop_reclaim_desc, ffs_reclaim }, /* reclaim */ |
{ &vop_reclaim_desc, ffs_reclaim }, /* reclaim */ |
{ &vop_lock_desc, ufs_lock }, /* lock */ |
{ &vop_lock_desc, ffs_lock }, /* lock */ |
{ &vop_unlock_desc, ufs_unlock }, /* unlock */ |
{ &vop_unlock_desc, ffs_unlock }, /* unlock */ |
{ &vop_bmap_desc, fifo_bmap }, /* bmap */ |
{ &vop_bmap_desc, fifo_bmap }, /* bmap */ |
{ &vop_strategy_desc, fifo_strategy }, /* strategy */ |
{ &vop_strategy_desc, fifo_strategy }, /* strategy */ |
{ &vop_print_desc, ufs_print }, /* print */ |
{ &vop_print_desc, ufs_print }, /* print */ |
{ &vop_islocked_desc, ufs_islocked }, /* islocked */ |
{ &vop_islocked_desc, ffs_islocked }, /* islocked */ |
{ &vop_pathconf_desc, fifo_pathconf }, /* pathconf */ |
{ &vop_pathconf_desc, fifo_pathconf }, /* pathconf */ |
{ &vop_advlock_desc, fifo_advlock }, /* advlock */ |
{ &vop_advlock_desc, fifo_advlock }, /* advlock */ |
{ &vop_bwrite_desc, vn_bwrite }, /* bwrite */ |
{ &vop_bwrite_desc, vn_bwrite }, /* bwrite */ |
Line 245 ffs_fsync(void *v) |
|
Line 246 ffs_fsync(void *v) |
|
struct lwp *a_l; |
struct lwp *a_l; |
} */ *ap = v; |
} */ *ap = v; |
struct buf *bp; |
struct buf *bp; |
int s, num, error, i; |
int num, error, i; |
struct indir ia[NIADDR + 1]; |
struct indir ia[NIADDR + 1]; |
int bsize; |
int bsize; |
daddr_t blk_high; |
daddr_t blk_high; |
struct vnode *vp; |
struct vnode *vp; |
|
|
|
vp = ap->a_vp; |
|
|
|
fstrans_start(vp->v_mount, FSTRANS_LAZY); |
/* |
/* |
* 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 273 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; |
} |
} |
|
|
/* |
/* |
* Then, flush indirect blocks. |
* Then, flush indirect blocks. |
*/ |
*/ |
|
|
s = splbio(); |
|
if (blk_high >= NDADDR) { |
if (blk_high >= NDADDR) { |
error = ufs_getlbns(vp, blk_high, ia, &num); |
error = ufs_getlbns(vp, blk_high, ia, &num); |
if (error) { |
if (error) |
splx(s); |
goto out; |
return error; |
|
} |
mutex_enter(&bufcache_lock); |
for (i = 0; i < num; i++) { |
for (i = 0; i < num; i++) { |
bp = incore(vp, ia[i].in_lbn); |
if ((bp = incore(vp, ia[i].in_lbn)) == NULL) |
if (bp != NULL) { |
continue; |
simple_lock(&bp->b_interlock); |
if ((bp->b_cflags & BC_BUSY) != 0 || |
if (!(bp->b_flags & B_BUSY) && (bp->b_flags & B_DELWRI)) { |
(bp->b_oflags & BO_DELWRI) == 0) |
bp->b_flags |= B_BUSY | B_VFLUSH; |
continue; |
simple_unlock(&bp->b_interlock); |
bp->b_cflags |= BC_BUSY | BC_VFLUSH; |
splx(s); |
mutex_exit(&bufcache_lock); |
bawrite(bp); |
bawrite(bp); |
s = splbio(); |
mutex_enter(&bufcache_lock); |
} else { |
|
simple_unlock(&bp->b_interlock); |
|
} |
|
} |
|
} |
} |
|
mutex_exit(&bufcache_lock); |
} |
} |
|
|
if (ap->a_flags & FSYNC_WAIT) { |
if (ap->a_flags & FSYNC_WAIT) { |
simple_lock(&global_v_numoutput_slock); |
mutex_enter(&vp->v_interlock); |
while (vp->v_numoutput > 0) { |
while (vp->v_numoutput > 0) |
vp->v_flag |= VBWAIT; |
cv_wait(&vp->v_cv, &vp->v_interlock); |
ltsleep(&vp->v_numoutput, PRIBIO + 1, "fsync_range", 0, |
mutex_exit(&vp->v_interlock); |
&global_v_numoutput_slock); |
|
} |
|
simple_unlock(&global_v_numoutput_slock); |
|
} |
} |
splx(s); |
|
|
|
error = ffs_update(vp, NULL, NULL, |
error = ffs_update(vp, NULL, NULL, |
((ap->a_flags & (FSYNC_WAIT | FSYNC_DATAONLY)) == FSYNC_WAIT) |
((ap->a_flags & (FSYNC_WAIT | FSYNC_DATAONLY)) == FSYNC_WAIT) |
Line 326 ffs_fsync(void *v) |
|
Line 322 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 346 ffs_full_fsync(void *v) |
|
Line 344 ffs_full_fsync(void *v) |
|
} */ *ap = v; |
} */ *ap = v; |
struct vnode *vp = ap->a_vp; |
struct vnode *vp = ap->a_vp; |
struct buf *bp, *nbp; |
struct buf *bp, *nbp; |
int s, error, passes, skipmeta, inodedeps_only, waitfor; |
int error, passes, skipmeta, inodedeps_only, waitfor; |
|
|
if (vp->v_type == VBLK && |
if (vp->v_type == VBLK && |
vp->v_specmountpoint != NULL && |
vp->v_specmountpoint != NULL && |
(vp->v_specmountpoint->mnt_flag & MNT_SOFTDEP)) |
(vp->v_specmountpoint->mnt_flag & MNT_SOFTDEP)) |
softdep_fsync_mountdev(vp); |
softdep_fsync_mountdev(vp); |
|
|
|
mutex_enter(&vp->v_interlock); |
|
|
inodedeps_only = DOINGSOFTDEP(vp) && (ap->a_flags & FSYNC_RECLAIM) |
inodedeps_only = DOINGSOFTDEP(vp) && (ap->a_flags & FSYNC_RECLAIM) |
&& vp->v_uobj.uo_npages == 0 && LIST_EMPTY(&vp->v_dirtyblkhd); |
&& UVM_OBJ_IS_CLEAN(&vp->v_uobj) && LIST_EMPTY(&vp->v_dirtyblkhd); |
|
|
/* |
/* |
* Flush all dirty data associated with a vnode. |
* Flush all dirty data associated with a vnode. |
*/ |
*/ |
|
|
if (vp->v_type == VREG || vp->v_type == VBLK) { |
if (vp->v_type == VREG || vp->v_type == VBLK) { |
simple_lock(&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; |
} |
} |
} |
} else |
|
mutex_exit(&vp->v_interlock); |
|
|
passes = NIADDR + 1; |
passes = NIADDR + 1; |
skipmeta = 0; |
skipmeta = 0; |
if (ap->a_flags & FSYNC_WAIT) |
if (ap->a_flags & FSYNC_WAIT) |
skipmeta = 1; |
skipmeta = 1; |
s = splbio(); |
|
|
|
|
mutex_enter(&bufcache_lock); |
|
mutex_enter(&vp->v_interlock); |
loop: |
loop: |
LIST_FOREACH(bp, &vp->v_dirtyblkhd, b_vnbufs) |
LIST_FOREACH(bp, &vp->v_dirtyblkhd, b_vnbufs) { |
bp->b_flags &= ~B_SCANNED; |
bp->b_cflags &= ~BC_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); |
if (bp->b_cflags & (BC_BUSY | BC_SCANNED)) |
if (bp->b_flags & (B_BUSY | B_SCANNED)) { |
|
simple_unlock(&bp->b_interlock); |
|
continue; |
continue; |
} |
if ((bp->b_oflags & BO_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); |
|
continue; |
continue; |
} |
mutex_exit(&vp->v_interlock); |
simple_unlock(&bp->b_interlock); |
bp->b_cflags |= BC_BUSY | BC_VFLUSH | BC_SCANNED; |
bp->b_flags |= B_BUSY | B_VFLUSH | B_SCANNED; |
mutex_exit(&bufcache_lock); |
splx(s); |
|
/* |
/* |
* On our final pass through, do all I/O synchronously |
* On our final pass through, do all I/O synchronously |
* so that we can find out if our flush is failing |
* so that we can find out if our flush is failing |
|
|
(void) bawrite(bp); |
(void) bawrite(bp); |
else if ((error = bwrite(bp)) != 0) |
else if ((error = bwrite(bp)) != 0) |
return (error); |
return (error); |
s = splbio(); |
|
/* |
/* |
* Since we may have slept during the I/O, we need |
* Since we unlocked during the I/O, we need |
* to start from a known point. |
* to start from a known point. |
*/ |
*/ |
|
mutex_enter(&bufcache_lock); |
|
mutex_enter(&vp->v_interlock); |
nbp = LIST_FIRST(&vp->v_dirtyblkhd); |
nbp = LIST_FIRST(&vp->v_dirtyblkhd); |
} |
} |
if (skipmeta) { |
if (skipmeta) { |
skipmeta = 0; |
skipmeta = 0; |
goto loop; |
goto loop; |
} |
} |
|
mutex_exit(&bufcache_lock); |
|
|
if (ap->a_flags & FSYNC_WAIT) { |
if (ap->a_flags & FSYNC_WAIT) { |
simple_lock(&global_v_numoutput_slock); |
|
while (vp->v_numoutput) { |
while (vp->v_numoutput) { |
vp->v_flag |= VBWAIT; |
cv_wait(&vp->v_cv, &vp->v_interlock); |
(void) ltsleep(&vp->v_numoutput, PRIBIO + 1, |
|
"ffsfsync", 0, &global_v_numoutput_slock); |
|
} |
} |
simple_unlock(&global_v_numoutput_slock); |
mutex_exit(&vp->v_interlock); |
splx(s); |
|
|
|
/* |
/* |
* Ensure that any filesystem metadata associated |
* Ensure that any filesystem metadata associated |
|
|
if ((error = softdep_sync_metadata(ap)) != 0) |
if ((error = softdep_sync_metadata(ap)) != 0) |
return (error); |
return (error); |
|
|
s = splbio(); |
|
if (!LIST_EMPTY(&vp->v_dirtyblkhd)) { |
if (!LIST_EMPTY(&vp->v_dirtyblkhd)) { |
/* |
/* |
* Block devices associated with filesystems may |
* Block devices associated with filesystems may |
|
|
vprint("ffs_fsync: dirty", vp); |
vprint("ffs_fsync: dirty", vp); |
#endif |
#endif |
} |
} |
} |
} else |
splx(s); |
mutex_exit(&vp->v_interlock); |
|
|
if (inodedeps_only) |
if (inodedeps_only) |
waitfor = 0; |
waitfor = 0; |
Line 480 ffs_reclaim(void *v) |
|
Line 477 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; |
|
void *data; |
int error; |
int error; |
|
|
if ((error = ufs_reclaim(vp, ap->a_l)) != 0) |
fstrans_start(mp, FSTRANS_LAZY); |
|
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 492 ffs_reclaim(void *v) |
|
Line 494 ffs_reclaim(void *v) |
|
pool_put(&ffs_dinode2_pool, ip->i_din.ffs2_din); |
pool_put(&ffs_dinode2_pool, ip->i_din.ffs2_din); |
} |
} |
/* |
/* |
|
* To interlock with ffs_sync(). |
|
*/ |
|
genfs_node_destroy(vp); |
|
mutex_enter(&vp->v_interlock); |
|
data = vp->v_data; |
|
vp->v_data = NULL; |
|
mutex_exit(&vp->v_interlock); |
|
|
|
/* |
* 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? |
*/ |
*/ |
pool_put(&ffs_inode_pool, vp->v_data); |
pool_put(&ffs_inode_pool, data); |
vp->v_data = NULL; |
fstrans_done(mp); |
return (0); |
return (0); |
} |
} |
|
|
|
#if 0 |
int |
int |
ffs_getpages(void *v) |
ffs_getpages(void *v) |
{ |
{ |
Line 528 ffs_getpages(void *v) |
|
Line 540 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; |
} |
} |
return genfs_getpages(v); |
return genfs_getpages(v); |
} |
} |
|
#endif |
|
|
/* |
/* |
* Return the last logical file offset that should be written for this file |
* Return the last logical file offset that should be written for this file |
Line 541 ffs_getpages(void *v) |
|
Line 554 ffs_getpages(void *v) |
|
*/ |
*/ |
|
|
void |
void |
ffs_gop_size(struct vnode *vp, off_t size, off_t *eobp, int flags __unused) |
ffs_gop_size(struct vnode *vp, off_t size, off_t *eobp, int flags) |
{ |
{ |
struct inode *ip = VTOI(vp); |
struct inode *ip = VTOI(vp); |
struct fs *fs = ip->i_fs; |
struct fs *fs = ip->i_fs; |
Line 607 ffs_getextattr(void *v) |
|
Line 620 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; |
|
|
|
fstrans_start(vp->v_mount, FSTRANS_SHARED); |
|
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 652 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; |
|
|
|
fstrans_start(vp->v_mount, FSTRANS_SHARED); |
|
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 704 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; |
|
|
|
fstrans_start(vp->v_mount, FSTRANS_SHARED); |
|
error = ufs_deleteextattr(ap); |
|
fstrans_done(vp->v_mount); |
|
return error; |
#else |
#else |
return (EOPNOTSUPP); |
return (EOPNOTSUPP); |
#endif |
#endif |
Line 693 ffs_deleteextattr(void *v) |
|
Line 724 ffs_deleteextattr(void *v) |
|
/* XXX Not implemented for UFS2 file systems. */ |
/* XXX Not implemented for UFS2 file systems. */ |
return (EOPNOTSUPP); |
return (EOPNOTSUPP); |
} |
} |
|
|
|
/* |
|
* Lock the node. |
|
*/ |
|
int |
|
ffs_lock(void *v) |
|
{ |
|
struct vop_lock_args /* { |
|
struct vnode *a_vp; |
|
int a_flags; |
|
} */ *ap = v; |
|
struct vnode *vp = ap->a_vp; |
|
struct mount *mp = vp->v_mount; |
|
|
|
/* |
|
* Fake lock during file system suspension. |
|
*/ |
|
if ((vp->v_type == VREG || vp->v_type == VDIR) && |
|
fstrans_is_owner(mp) && |
|
fstrans_getstate(mp) == FSTRANS_SUSPENDING) { |
|
if ((ap->a_flags & LK_INTERLOCK) != 0) |
|
mutex_exit(&vp->v_interlock); |
|
return 0; |
|
} |
|
return (lockmgr(vp->v_vnlock, ap->a_flags, &vp->v_interlock)); |
|
} |
|
|
|
/* |
|
* Unlock the node. |
|
*/ |
|
int |
|
ffs_unlock(void *v) |
|
{ |
|
struct vop_unlock_args /* { |
|
struct vnode *a_vp; |
|
int a_flags; |
|
} */ *ap = v; |
|
struct vnode *vp = ap->a_vp; |
|
struct mount *mp = vp->v_mount; |
|
|
|
/* |
|
* Fake unlock during file system suspension. |
|
*/ |
|
if ((vp->v_type == VREG || vp->v_type == VDIR) && |
|
fstrans_is_owner(mp) && |
|
fstrans_getstate(mp) == FSTRANS_SUSPENDING) { |
|
if ((ap->a_flags & LK_INTERLOCK) != 0) |
|
mutex_exit(&vp->v_interlock); |
|
return 0; |
|
} |
|
return (lockmgr(vp->v_vnlock, ap->a_flags | LK_RELEASE, |
|
&vp->v_interlock)); |
|
} |
|
|
|
/* |
|
* Return whether or not the node is locked. |
|
*/ |
|
int |
|
ffs_islocked(void *v) |
|
{ |
|
struct vop_islocked_args /* { |
|
struct vnode *a_vp; |
|
} */ *ap = v; |
|
struct vnode *vp = ap->a_vp; |
|
|
|
return (lockstatus(vp->v_vnlock)); |
|
} |