version 1.69, 2005/02/26 22:32:20 |
version 1.69.4.2, 2006/12/30 20:51:01 |
Line 47 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 47 __KERNEL_RCSID(0, "$NetBSD$"); |
|
#include <sys/vnode.h> |
#include <sys/vnode.h> |
#include <sys/pool.h> |
#include <sys/pool.h> |
#include <sys/signalvar.h> |
#include <sys/signalvar.h> |
|
#include <sys/kauth.h> |
|
|
#include <miscfs/fifofs/fifo.h> |
#include <miscfs/fifofs/fifo.h> |
#include <miscfs/genfs/genfs.h> |
#include <miscfs/genfs/genfs.h> |
Line 62 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 63 __KERNEL_RCSID(0, "$NetBSD$"); |
|
|
|
#include <uvm/uvm.h> |
#include <uvm/uvm.h> |
|
|
static int ffs_full_fsync __P((void *)); |
static int ffs_full_fsync(void *); |
|
|
/* Global vfs data structures for ufs. */ |
/* Global vfs data structures for ufs. */ |
int (**ffs_vnodeop_p) __P((void *)); |
int (**ffs_vnodeop_p)(void *); |
const struct vnodeopv_entry_desc ffs_vnodeop_entries[] = { |
const struct vnodeopv_entry_desc ffs_vnodeop_entries[] = { |
{ &vop_default_desc, vn_default_error }, |
{ &vop_default_desc, vn_default_error }, |
{ &vop_lookup_desc, ufs_lookup }, /* lookup */ |
{ &vop_lookup_desc, ufs_lookup }, /* lookup */ |
Line 107 const struct vnodeopv_entry_desc ffs_vno |
|
Line 108 const struct vnodeopv_entry_desc ffs_vno |
|
{ &vop_islocked_desc, ufs_islocked }, /* islocked */ |
{ &vop_islocked_desc, ufs_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_blkatoff_desc, ffs_blkatoff }, /* blkatoff */ |
|
{ &vop_valloc_desc, ffs_valloc }, /* valloc */ |
|
{ &vop_balloc_desc, ffs_balloc }, /* balloc */ |
|
{ &vop_reallocblks_desc, ffs_reallocblks }, /* reallocblks */ |
|
{ &vop_vfree_desc, ffs_vfree }, /* vfree */ |
|
{ &vop_truncate_desc, ffs_truncate }, /* truncate */ |
|
{ &vop_update_desc, ffs_update }, /* update */ |
|
{ &vop_bwrite_desc, vn_bwrite }, /* bwrite */ |
{ &vop_bwrite_desc, vn_bwrite }, /* bwrite */ |
{ &vop_getpages_desc, ffs_getpages }, /* getpages */ |
{ &vop_getpages_desc, ffs_getpages }, /* getpages */ |
{ &vop_putpages_desc, ffs_putpages }, /* putpages */ |
{ &vop_putpages_desc, genfs_putpages }, /* putpages */ |
|
{ &vop_openextattr_desc, ffs_openextattr }, /* openextattr */ |
|
{ &vop_closeextattr_desc, ffs_closeextattr }, /* closeextattr */ |
|
{ &vop_getextattr_desc, ffs_getextattr }, /* getextattr */ |
|
{ &vop_setextattr_desc, ffs_setextattr }, /* setextattr */ |
|
{ &vop_listextattr_desc, ffs_listextattr }, /* listextattr */ |
|
{ &vop_deleteextattr_desc, ffs_deleteextattr }, /* deleteextattr */ |
{ NULL, NULL } |
{ NULL, NULL } |
}; |
}; |
const struct vnodeopv_desc ffs_vnodeop_opv_desc = |
const struct vnodeopv_desc ffs_vnodeop_opv_desc = |
{ &ffs_vnodeop_p, ffs_vnodeop_entries }; |
{ &ffs_vnodeop_p, ffs_vnodeop_entries }; |
|
|
int (**ffs_specop_p) __P((void *)); |
int (**ffs_specop_p)(void *); |
const struct vnodeopv_entry_desc ffs_specop_entries[] = { |
const struct vnodeopv_entry_desc ffs_specop_entries[] = { |
{ &vop_default_desc, vn_default_error }, |
{ &vop_default_desc, vn_default_error }, |
{ &vop_lookup_desc, spec_lookup }, /* lookup */ |
{ &vop_lookup_desc, spec_lookup }, /* lookup */ |
Line 163 const struct vnodeopv_entry_desc ffs_spe |
|
Line 163 const struct vnodeopv_entry_desc ffs_spe |
|
{ &vop_islocked_desc, ufs_islocked }, /* islocked */ |
{ &vop_islocked_desc, ufs_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_blkatoff_desc, spec_blkatoff }, /* blkatoff */ |
|
{ &vop_valloc_desc, spec_valloc }, /* valloc */ |
|
{ &vop_reallocblks_desc, spec_reallocblks }, /* reallocblks */ |
|
{ &vop_vfree_desc, ffs_vfree }, /* vfree */ |
|
{ &vop_truncate_desc, spec_truncate }, /* truncate */ |
|
{ &vop_update_desc, ffs_update }, /* update */ |
|
{ &vop_bwrite_desc, vn_bwrite }, /* bwrite */ |
{ &vop_bwrite_desc, vn_bwrite }, /* bwrite */ |
{ &vop_getpages_desc, spec_getpages }, /* getpages */ |
{ &vop_getpages_desc, spec_getpages }, /* getpages */ |
{ &vop_putpages_desc, spec_putpages }, /* putpages */ |
{ &vop_putpages_desc, spec_putpages }, /* putpages */ |
|
{ &vop_openextattr_desc, ffs_openextattr }, /* openextattr */ |
|
{ &vop_closeextattr_desc, ffs_closeextattr }, /* closeextattr */ |
|
{ &vop_getextattr_desc, ffs_getextattr }, /* getextattr */ |
|
{ &vop_setextattr_desc, ffs_setextattr }, /* setextattr */ |
|
{ &vop_listextattr_desc, ffs_listextattr }, /* listextattr */ |
|
{ &vop_deleteextattr_desc, ffs_deleteextattr }, /* deleteextattr */ |
{ NULL, NULL } |
{ NULL, NULL } |
}; |
}; |
const struct vnodeopv_desc ffs_specop_opv_desc = |
const struct vnodeopv_desc ffs_specop_opv_desc = |
{ &ffs_specop_p, ffs_specop_entries }; |
{ &ffs_specop_p, ffs_specop_entries }; |
|
|
int (**ffs_fifoop_p) __P((void *)); |
int (**ffs_fifoop_p)(void *); |
const struct vnodeopv_entry_desc ffs_fifoop_entries[] = { |
const struct vnodeopv_entry_desc ffs_fifoop_entries[] = { |
{ &vop_default_desc, vn_default_error }, |
{ &vop_default_desc, vn_default_error }, |
{ &vop_lookup_desc, fifo_lookup }, /* lookup */ |
{ &vop_lookup_desc, fifo_lookup }, /* lookup */ |
Line 218 const struct vnodeopv_entry_desc ffs_fif |
|
Line 218 const struct vnodeopv_entry_desc ffs_fif |
|
{ &vop_islocked_desc, ufs_islocked }, /* islocked */ |
{ &vop_islocked_desc, ufs_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_blkatoff_desc, fifo_blkatoff }, /* blkatoff */ |
|
{ &vop_valloc_desc, fifo_valloc }, /* valloc */ |
|
{ &vop_reallocblks_desc, fifo_reallocblks }, /* reallocblks */ |
|
{ &vop_vfree_desc, ffs_vfree }, /* vfree */ |
|
{ &vop_truncate_desc, fifo_truncate }, /* truncate */ |
|
{ &vop_update_desc, ffs_update }, /* update */ |
|
{ &vop_bwrite_desc, vn_bwrite }, /* bwrite */ |
{ &vop_bwrite_desc, vn_bwrite }, /* bwrite */ |
{ &vop_putpages_desc, fifo_putpages }, /* putpages */ |
{ &vop_putpages_desc, fifo_putpages }, /* putpages */ |
|
{ &vop_openextattr_desc, ffs_openextattr }, /* openextattr */ |
|
{ &vop_closeextattr_desc, ffs_closeextattr }, /* closeextattr */ |
|
{ &vop_getextattr_desc, ffs_getextattr }, /* getextattr */ |
|
{ &vop_setextattr_desc, ffs_setextattr }, /* setextattr */ |
|
{ &vop_listextattr_desc, ffs_listextattr }, /* listextattr */ |
|
{ &vop_deleteextattr_desc, ffs_deleteextattr }, /* deleteextattr */ |
{ NULL, NULL } |
{ NULL, NULL } |
}; |
}; |
const struct vnodeopv_desc ffs_fifoop_opv_desc = |
const struct vnodeopv_desc ffs_fifoop_opv_desc = |
Line 234 const struct vnodeopv_desc ffs_fifoop_op |
|
Line 234 const struct vnodeopv_desc ffs_fifoop_op |
|
#include <ufs/ufs/ufs_readwrite.c> |
#include <ufs/ufs/ufs_readwrite.c> |
|
|
int |
int |
ffs_fsync(v) |
ffs_fsync(void *v) |
void *v; |
|
{ |
{ |
struct vop_fsync_args /* { |
struct vop_fsync_args /* { |
struct vnode *a_vp; |
struct vnode *a_vp; |
struct ucred *a_cred; |
kauth_cred_t a_cred; |
int a_flags; |
int a_flags; |
off_t a_offlo; |
off_t a_offlo; |
off_t a_offhi; |
off_t a_offhi; |
struct proc *a_p; |
struct lwp *a_l; |
} */ *ap = v; |
} */ *ap = v; |
struct buf *bp; |
struct buf *bp; |
int s, num, error, i; |
int s, num, error, i; |
|
|
} |
} |
splx(s); |
splx(s); |
|
|
error = VOP_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) |
? UPDATE_WAIT : 0); |
? UPDATE_WAIT : 0); |
|
|
if (error == 0 && ap->a_flags & FSYNC_CACHE) { |
if (error == 0 && ap->a_flags & FSYNC_CACHE) { |
int l = 0; |
int l = 0; |
VOP_IOCTL(VTOI(vp)->i_devvp, DIOCCACHESYNC, &l, FWRITE, |
VOP_IOCTL(VTOI(vp)->i_devvp, DIOCCACHESYNC, &l, FWRITE, |
ap->a_p->p_ucred, ap->a_p); |
ap->a_l->l_cred, ap->a_l); |
} |
} |
|
|
return error; |
return error; |
|
|
*/ |
*/ |
/* ARGSUSED */ |
/* ARGSUSED */ |
static int |
static int |
ffs_full_fsync(v) |
ffs_full_fsync(void *v) |
void *v; |
|
{ |
{ |
struct vop_fsync_args /* { |
struct vop_fsync_args /* { |
struct vnode *a_vp; |
struct vnode *a_vp; |
struct ucred *a_cred; |
kauth_cred_t a_cred; |
int a_flags; |
int a_flags; |
off_t a_offlo; |
off_t a_offlo; |
off_t a_offhi; |
off_t a_offhi; |
struct proc *a_p; |
struct lwp *a_l; |
} */ *ap = v; |
} */ *ap = v; |
struct vnode *vp = ap->a_vp; |
struct vnode *vp = ap->a_vp; |
struct buf *bp, *nbp; |
struct buf *bp, *nbp; |
Line 362 ffs_full_fsync(v) |
|
Line 360 ffs_full_fsync(v) |
|
* Flush all dirty data associated with a vnode. |
* Flush all dirty data associated with a vnode. |
*/ |
*/ |
|
|
if (vp->v_type == VREG) { |
if (vp->v_type == VREG || vp->v_type == VBLK) { |
simple_lock(&vp->v_interlock); |
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)); |
|
|
waitfor = 0; |
waitfor = 0; |
else |
else |
waitfor = (ap->a_flags & FSYNC_WAIT) ? UPDATE_WAIT : 0; |
waitfor = (ap->a_flags & FSYNC_WAIT) ? UPDATE_WAIT : 0; |
error = VOP_UPDATE(vp, NULL, NULL, waitfor); |
error = ffs_update(vp, NULL, NULL, waitfor); |
|
|
if (error == 0 && ap->a_flags & FSYNC_CACHE) { |
if (error == 0 && ap->a_flags & FSYNC_CACHE) { |
int i = 0; |
int i = 0; |
VOP_IOCTL(VTOI(vp)->i_devvp, DIOCCACHESYNC, &i, FWRITE, |
VOP_IOCTL(VTOI(vp)->i_devvp, DIOCCACHESYNC, &i, FWRITE, |
ap->a_p->p_ucred, ap->a_p); |
ap->a_l->l_cred, ap->a_l); |
} |
} |
|
|
return error; |
return error; |
|
|
* Reclaim an inode so that it can be used for other purposes. |
* Reclaim an inode so that it can be used for other purposes. |
*/ |
*/ |
int |
int |
ffs_reclaim(v) |
ffs_reclaim(void *v) |
void *v; |
|
{ |
{ |
struct vop_reclaim_args /* { |
struct vop_reclaim_args /* { |
struct vnode *a_vp; |
struct vnode *a_vp; |
struct proc *a_p; |
struct lwp *a_l; |
} */ *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 ufsmount *ump = ip->i_ump; |
struct ufsmount *ump = ip->i_ump; |
int error; |
int error; |
|
|
if ((error = ufs_reclaim(vp, ap->a_p)) != 0) |
if ((error = ufs_reclaim(vp, ap->a_l)) != 0) |
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) |
Line 538 ffs_getpages(void *v) |
|
Line 535 ffs_getpages(void *v) |
|
return genfs_getpages(v); |
return genfs_getpages(v); |
} |
} |
|
|
int |
|
ffs_putpages(void *v) |
|
{ |
|
struct vop_putpages_args /* { |
|
struct vnode *a_vp; |
|
voff_t a_offlo; |
|
voff_t a_offhi; |
|
int a_flags; |
|
} */ *ap = v; |
|
struct vnode *vp = ap->a_vp; |
|
struct uvm_object *uobj = &vp->v_uobj; |
|
struct inode *ip = VTOI(vp); |
|
struct fs *fs = ip->i_fs; |
|
struct vm_page *pg; |
|
off_t off; |
|
|
|
if (!DOINGSOFTDEP(vp) || (ap->a_flags & PGO_CLEANIT) == 0) { |
|
return genfs_putpages(v); |
|
} |
|
|
|
/* |
|
* for softdep files, force the pages in a block to be written together. |
|
* if we're the pagedaemon and we would have to wait for other pages, |
|
* just fail the request. the pagedaemon will pick a different page. |
|
*/ |
|
|
|
ap->a_offlo &= ~fs->fs_qbmask; |
|
ap->a_offhi = blkroundup(fs, ap->a_offhi); |
|
if (curproc == uvm.pagedaemon_proc) { |
|
for (off = ap->a_offlo; off < ap->a_offhi; off += PAGE_SIZE) { |
|
pg = uvm_pagelookup(uobj, off); |
|
|
|
/* |
|
* we only have missing pages here because the |
|
* calculation of offhi above doesn't account for |
|
* fragments. so once we see one missing page, |
|
* the rest should be missing as well, but we'll |
|
* check for the rest just to be paranoid. |
|
*/ |
|
|
|
if (pg == NULL) { |
|
continue; |
|
} |
|
if (pg->flags & PG_BUSY) { |
|
simple_unlock(&uobj->vmobjlock); |
|
return EBUSY; |
|
} |
|
} |
|
} |
|
return genfs_putpages(v); |
|
} |
|
|
|
/* |
/* |
* 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 |
* if we're doing a write that ends at "size". |
* if we're doing a write that ends at "size". |
Line 602 ffs_gop_size(struct vnode *vp, off_t siz |
|
Line 547 ffs_gop_size(struct vnode *vp, off_t siz |
|
struct fs *fs = ip->i_fs; |
struct fs *fs = ip->i_fs; |
daddr_t olbn, nlbn; |
daddr_t olbn, nlbn; |
|
|
KASSERT(flags & (GOP_SIZE_READ | GOP_SIZE_WRITE)); |
|
KASSERT((flags & (GOP_SIZE_READ | GOP_SIZE_WRITE)) |
|
!= (GOP_SIZE_READ | GOP_SIZE_WRITE)); |
|
|
|
olbn = lblkno(fs, ip->i_size); |
olbn = lblkno(fs, ip->i_size); |
nlbn = lblkno(fs, size); |
nlbn = lblkno(fs, size); |
if (nlbn < NDADDR && olbn <= nlbn) { |
if (nlbn < NDADDR && olbn <= nlbn) { |
Line 614 ffs_gop_size(struct vnode *vp, off_t siz |
|
Line 555 ffs_gop_size(struct vnode *vp, off_t siz |
|
*eobp = blkroundup(fs, size); |
*eobp = blkroundup(fs, size); |
} |
} |
} |
} |
|
|
|
int |
|
ffs_openextattr(void *v) |
|
{ |
|
struct vop_openextattr_args /* { |
|
struct vnode *a_vp; |
|
kauth_cred_t a_cred; |
|
struct proc *a_p; |
|
} */ *ap = v; |
|
struct inode *ip = VTOI(ap->a_vp); |
|
struct fs *fs = ip->i_fs; |
|
|
|
/* Not supported for UFS1 file systems. */ |
|
if (fs->fs_magic == FS_UFS1_MAGIC) |
|
return (EOPNOTSUPP); |
|
|
|
/* XXX Not implemented for UFS2 file systems. */ |
|
return (EOPNOTSUPP); |
|
} |
|
|
|
int |
|
ffs_closeextattr(void *v) |
|
{ |
|
struct vop_closeextattr_args /* { |
|
struct vnode *a_vp; |
|
int a_commit; |
|
kauth_cred_t a_cred; |
|
struct proc *a_p; |
|
} */ *ap = v; |
|
struct inode *ip = VTOI(ap->a_vp); |
|
struct fs *fs = ip->i_fs; |
|
|
|
/* Not supported for UFS1 file systems. */ |
|
if (fs->fs_magic == FS_UFS1_MAGIC) |
|
return (EOPNOTSUPP); |
|
|
|
/* XXX Not implemented for UFS2 file systems. */ |
|
return (EOPNOTSUPP); |
|
} |
|
|
|
int |
|
ffs_getextattr(void *v) |
|
{ |
|
struct vop_getextattr_args /* { |
|
struct vnode *a_vp; |
|
int a_attrnamespace; |
|
const char *a_name; |
|
struct uio *a_uio; |
|
size_t *a_size; |
|
kauth_cred_t a_cred; |
|
struct proc *a_p; |
|
} */ *ap = v; |
|
struct inode *ip = VTOI(ap->a_vp); |
|
struct fs *fs = ip->i_fs; |
|
|
|
if (fs->fs_magic == FS_UFS1_MAGIC) { |
|
#ifdef UFS_EXTATTR |
|
return (ufs_getextattr(ap)); |
|
#else |
|
return (EOPNOTSUPP); |
|
#endif |
|
} |
|
|
|
/* XXX Not implemented for UFS2 file systems. */ |
|
return (EOPNOTSUPP); |
|
} |
|
|
|
int |
|
ffs_setextattr(void *v) |
|
{ |
|
struct vop_setextattr_args /* { |
|
struct vnode *a_vp; |
|
int a_attrnamespace; |
|
const char *a_name; |
|
struct uio *a_uio; |
|
kauth_cred_t a_cred; |
|
struct proc *a_p; |
|
} */ *ap = v; |
|
struct inode *ip = VTOI(ap->a_vp); |
|
struct fs *fs = ip->i_fs; |
|
|
|
if (fs->fs_magic == FS_UFS1_MAGIC) { |
|
#ifdef UFS_EXTATTR |
|
return (ufs_setextattr(ap)); |
|
#else |
|
return (EOPNOTSUPP); |
|
#endif |
|
} |
|
|
|
/* XXX Not implemented for UFS2 file systems. */ |
|
return (EOPNOTSUPP); |
|
} |
|
|
|
int |
|
ffs_listextattr(void *v) |
|
{ |
|
struct vop_listextattr_args /* { |
|
struct vnode *a_vp; |
|
int a_attrnamespace; |
|
struct uio *a_uio; |
|
size_t *a_size; |
|
kauth_cred_t a_cred; |
|
struct proc *a_p; |
|
} */ *ap = v; |
|
struct inode *ip = VTOI(ap->a_vp); |
|
struct fs *fs = ip->i_fs; |
|
|
|
/* Not supported for UFS1 file systems. */ |
|
if (fs->fs_magic == FS_UFS1_MAGIC) |
|
return (EOPNOTSUPP); |
|
|
|
/* XXX Not implemented for UFS2 file systems. */ |
|
return (EOPNOTSUPP); |
|
} |
|
|
|
int |
|
ffs_deleteextattr(void *v) |
|
{ |
|
struct vop_deleteextattr_args /* { |
|
struct vnode *a_vp; |
|
int a_attrnamespace; |
|
kauth_cred_t a_cred; |
|
struct proc *a_p; |
|
} */ *ap = v; |
|
struct inode *ip = VTOI(ap->a_vp); |
|
struct fs *fs = ip->i_fs; |
|
|
|
if (fs->fs_magic == FS_UFS1_MAGIC) { |
|
#ifdef UFS_EXTATTR |
|
return (ufs_deleteextattr(ap)); |
|
#else |
|
return (EOPNOTSUPP); |
|
#endif |
|
} |
|
|
|
/* XXX Not implemented for UFS2 file systems. */ |
|
return (EOPNOTSUPP); |
|
} |