Skip to content

Instantly share code, notes, and snippets.

@7shi 7shi/gist:9167101
Created Feb 23, 2014

Embed
What would you like to do?
スタート低レイヤー #5の発表メモです。
kern/vnode_if.c
===============
int
VOP_WRITE(struct vnode *vp,
struct uio *uio,
int ioflag,
kauth_cred_t cred)
{
int error;
bool mpsafe;
struct vop_write_args a;
a.a_desc = VDESC(vop_write);
a.a_vp = vp;
a.a_uio = uio;
a.a_ioflag = ioflag;
a.a_cred = cred;
mpsafe = (vp->v_vflag & VV_MPSAFE);
if (!mpsafe) { KERNEL_LOCK(1, curlwp); }
error = (VCALL(vp, VOFFSET(vop_write), &a));
if (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }
return error;
}
miscfs/specfs/spec_vnops.c
==========================
/*
* Vnode op for write
*/
/* ARGSUSED */
int
spec_write(void *v)
{
struct vop_write_args /* {
struct vnode *a_vp;
struct uio *a_uio;
int a_ioflag;
kauth_cred_t a_cred;
} */ *ap = v;
struct vnode *vp = ap->a_vp;
struct uio *uio = ap->a_uio;
struct lwp *l = curlwp;
struct buf *bp;
daddr_t bn;
int bsize, bscale;
struct partinfo dpart;
int n, on;
int error = 0;
#ifdef DIAGNOSTIC
if (uio->uio_rw != UIO_WRITE)
panic("spec_write mode");
if (&uio->uio_vmspace->vm_map != kernel_map &&
uio->uio_vmspace != curproc->p_vmspace)
panic("spec_write proc");
#endif
switch (vp->v_type) {
case VCHR:
VOP_UNLOCK(vp);
error = cdev_write(vp->v_rdev, uio, ap->a_ioflag);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
return (error);
case VBLK:
KASSERT(vp == vp->v_specnode->sn_dev->sd_bdevvp);
if (uio->uio_resid == 0)
return (0);
if (uio->uio_offset < 0)
return (EINVAL);
bsize = BLKDEV_IOSIZE;
if (bdev_ioctl(vp->v_rdev, DIOCGPART, &dpart, FREAD, l) == 0) {
if (dpart.part->p_fstype == FS_BSDFFS &&
dpart.part->p_frag != 0 && dpart.part->p_fsize != 0)
bsize = dpart.part->p_frag *
dpart.part->p_fsize;
}
bscale = bsize >> DEV_BSHIFT;
do {
bn = (uio->uio_offset >> DEV_BSHIFT) &~ (bscale - 1);
on = uio->uio_offset % bsize;
n = min((unsigned)(bsize - on), uio->uio_resid);
if (n == bsize)
bp = getblk(vp, bn, bsize, 0, 0);
else
error = bread(vp, bn, bsize, NOCRED,
B_MODIFY, &bp);
if (error) {
brelse(bp, 0);
return (error);
}
n = min(n, bsize - bp->b_resid);
error = uiomove((char *)bp->b_data + on, n, uio);
if (error)
brelse(bp, 0);
else {
if (n + on == bsize)
bawrite(bp);
else
bdwrite(bp);
error = bp->b_error;
}
} while (error == 0 && uio->uio_resid > 0 && n != 0);
return (error);
default:
panic("spec_write type");
}
/* NOTREACHED */
}
-- VCALL .\sys\vnode.h 519;
/*
* VOCALL calls an op given an ops vector. We break it out because BSD's
* vclean changes the ops vector and then wants to call ops with the old
* vector.
*/
/*
* actually, vclean doesn't use it anymore, but nfs does,
* for device specials and fifos.
*/
#define VOCALL(OPSV,OFF,AP) (( *((OPSV)[(OFF)])) (AP))
/*
* This call works for vnodes in the kernel.
*/
#define VCALL(VP,OFF,AP) VOCALL((VP)->v_op,(OFF),(AP))
#define VDESC(OP) (& __CONCAT(OP,_desc))
#define VOFFSET(OP) (VDESC(OP)->vdesc_offset)
-- kern\vnode_if.c
const struct vnodeop_desc vop_write_desc = {
VOP_WRITE_DESCOFFSET,
"vop_write",
0,
vop_write_vp_offsets,
VDESC_NO_OFFSET,
VOPARG_OFFSETOF(struct vop_write_args, a_cred),
VDESC_NO_OFFSET,
};
-- sys\vnode_if.h:157
#define VOP_WRITE_DESCOFFSET 11
-- miscfs/specfs/spec_vnops.c:98
/*
* This vnode operations vector is used for special device nodes
* created from whole cloth by the kernel. For the ops vector for
* vnodes built from special devices found in a filesystem, see (e.g)
* ffs_specop_entries[] in ffs_vnops.c or the equivalent for other
* filesystems.
*/
int (**spec_vnodeop_p)(void *);
const struct vnodeopv_entry_desc spec_vnodeop_entries[] = {
{ &vop_default_desc, vn_default_error },
{ &vop_lookup_desc, spec_lookup }, /* lookup */
{ &vop_create_desc, spec_create }, /* create */
{ &vop_mknod_desc, spec_mknod }, /* mknod */
{ &vop_open_desc, spec_open }, /* open */
{ &vop_close_desc, spec_close }, /* close */
{ &vop_access_desc, spec_access }, /* access */
{ &vop_getattr_desc, spec_getattr }, /* getattr */
{ &vop_setattr_desc, spec_setattr }, /* setattr */
{ &vop_read_desc, spec_read }, /* read */
{ &vop_write_desc, spec_write }, /* write */
{ &vop_fcntl_desc, spec_fcntl }, /* fcntl */
{ &vop_ioctl_desc, spec_ioctl }, /* ioctl */
{ &vop_poll_desc, spec_poll }, /* poll */
{ &vop_kqfilter_desc, spec_kqfilter }, /* kqfilter */
{ &vop_revoke_desc, spec_revoke }, /* revoke */
{ &vop_mmap_desc, spec_mmap }, /* mmap */
{ &vop_fsync_desc, spec_fsync }, /* fsync */
{ &vop_seek_desc, spec_seek }, /* seek */
{ &vop_remove_desc, spec_remove }, /* remove */
{ &vop_link_desc, spec_link }, /* link */
{ &vop_rename_desc, spec_rename }, /* rename */
{ &vop_mkdir_desc, spec_mkdir }, /* mkdir */
{ &vop_rmdir_desc, spec_rmdir }, /* rmdir */
{ &vop_symlink_desc, spec_symlink }, /* symlink */
{ &vop_readdir_desc, spec_readdir }, /* readdir */
{ &vop_readlink_desc, spec_readlink }, /* readlink */
{ &vop_abortop_desc, spec_abortop }, /* abortop */
{ &vop_inactive_desc, spec_inactive }, /* inactive */
{ &vop_reclaim_desc, spec_reclaim }, /* reclaim */
{ &vop_lock_desc, spec_lock }, /* lock */
{ &vop_unlock_desc, spec_unlock }, /* unlock */
{ &vop_bmap_desc, spec_bmap }, /* bmap */
{ &vop_strategy_desc, spec_strategy }, /* strategy */
{ &vop_print_desc, spec_print }, /* print */
{ &vop_islocked_desc, spec_islocked }, /* islocked */
{ &vop_pathconf_desc, spec_pathconf }, /* pathconf */
{ &vop_advlock_desc, spec_advlock }, /* advlock */
{ &vop_bwrite_desc, spec_bwrite }, /* bwrite */
{ &vop_getpages_desc, spec_getpages }, /* getpages */
{ &vop_putpages_desc, spec_putpages }, /* putpages */
{ NULL, NULL }
};
const struct vnodeopv_desc spec_vnodeop_opv_desc =
{ &spec_vnodeop_p, spec_vnodeop_entries };
-- kern/vfs_init.c:103
/*
* These vnodeopv_descs are listed here because they are not
* associated with any particular file system, and thus cannot
* be initialized by vfs_attach().
*/
extern const struct vnodeopv_desc dead_vnodeop_opv_desc;
extern const struct vnodeopv_desc fifo_vnodeop_opv_desc;
extern const struct vnodeopv_desc spec_vnodeop_opv_desc;
extern const struct vnodeopv_desc sync_vnodeop_opv_desc;
const struct vnodeopv_desc * const vfs_special_vnodeopv_descs[] = {
&dead_vnodeop_opv_desc,
&fifo_vnodeop_opv_desc,
&spec_vnodeop_opv_desc,
&sync_vnodeop_opv_desc,
NULL,
};
arch/i386/i386/locore.S:255 start
-> sys/kern/init_main.c:279 main()
-> sys/kern/vfs_init.c:390 vfsinit() -> vfs_opv_init() -> vfs_opv_init_explicit()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.