attach to genfs & support page cache. most noticeable effect is
mmap and therefore execution of binaries starting to work, some speed improvements with large file I/O also. caching semantics and error case handling most likely need revisiting.
This commit is contained in:
parent
e2c201cff5
commit
b3bdf665dd
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: puffs_msgif.c,v 1.3 2006/11/06 23:18:18 pooka Exp $ */
|
||||
/* $NetBSD: puffs_msgif.c,v 1.4 2006/11/07 22:10:18 pooka Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2005, 2006 Antti Kantee. All Rights Reserved.
|
||||
|
@ -33,7 +33,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: puffs_msgif.c,v 1.3 2006/11/06 23:18:18 pooka Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: puffs_msgif.c,v 1.4 2006/11/07 22:10:18 pooka Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/conf.h>
|
||||
|
@ -56,10 +56,10 @@ __KERNEL_RCSID(0, "$NetBSD: puffs_msgif.c,v 1.3 2006/11/06 23:18:18 pooka Exp $"
|
|||
* kernel-user-kernel waitqueues
|
||||
*/
|
||||
|
||||
static int touser(struct puffs_mount *, struct puffs_park *, unsigned int,
|
||||
static int touser(struct puffs_mount *, struct puffs_park *, uint64_t,
|
||||
struct vnode *, struct vnode *);
|
||||
|
||||
unsigned int
|
||||
uint64_t
|
||||
puffs_getreqid(struct puffs_mount *pmp)
|
||||
{
|
||||
unsigned int rv;
|
||||
|
@ -119,7 +119,7 @@ puffs_vntouser(struct puffs_mount *pmp, int optype,
|
|||
*/
|
||||
int
|
||||
puffs_vntouser_req(struct puffs_mount *pmp, int optype,
|
||||
void *kbuf, size_t buflen, void *cookie, unsigned int reqid,
|
||||
void *kbuf, size_t buflen, void *cookie, uint64_t reqid,
|
||||
struct vnode *vp1, struct vnode *vp2)
|
||||
{
|
||||
struct puffs_park park;
|
||||
|
@ -167,6 +167,33 @@ puffs_vntouser_adjbuf(struct puffs_mount *pmp, int optype,
|
|||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Notice: kbuf will be free'd later. I must be allocated from the
|
||||
* kernel heap and it's ownership is shifted to this function from
|
||||
* now on, i.e. the caller is not allowed to use it anymore!
|
||||
*/
|
||||
void
|
||||
puffs_vntouser_faf(struct puffs_mount *pmp, int optype,
|
||||
void *kbuf, size_t buflen, void *cookie)
|
||||
{
|
||||
struct puffs_park *ppark;
|
||||
|
||||
/* XXX: is it allowable to sleep here? */
|
||||
ppark = malloc(sizeof(struct puffs_park), M_PUFFS, M_NOWAIT | M_ZERO);
|
||||
if (ppark == NULL)
|
||||
return; /* 2bad */
|
||||
|
||||
ppark->park_opclass = PUFFSOP_VN | PUFFSOPFLAG_FAF;
|
||||
ppark->park_optype = optype;
|
||||
ppark->park_cookie = cookie;
|
||||
|
||||
ppark->park_kernbuf = kbuf;
|
||||
ppark->park_buflen = buflen;
|
||||
ppark->park_copylen = buflen;
|
||||
|
||||
(void)touser(pmp, ppark, 0, NULL, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait for the userspace ping-pong game in calling process context.
|
||||
*
|
||||
|
@ -178,7 +205,7 @@ puffs_vntouser_adjbuf(struct puffs_mount *pmp, int optype,
|
|||
* there's a slight ugly-factor also, but let's not worry about that.
|
||||
*/
|
||||
static int
|
||||
touser(struct puffs_mount *pmp, struct puffs_park *park, unsigned int reqid,
|
||||
touser(struct puffs_mount *pmp, struct puffs_park *ppark, uint64_t reqid,
|
||||
struct vnode *vp1, struct vnode *vp2)
|
||||
{
|
||||
|
||||
|
@ -189,9 +216,9 @@ touser(struct puffs_mount *pmp, struct puffs_park *park, unsigned int reqid,
|
|||
return ENXIO;
|
||||
}
|
||||
|
||||
park->park_id = reqid;
|
||||
ppark->park_id = reqid;
|
||||
|
||||
TAILQ_INSERT_TAIL(&pmp->pmp_req_touser, park, park_entries);
|
||||
TAILQ_INSERT_TAIL(&pmp->pmp_req_touser, ppark, park_entries);
|
||||
pmp->pmp_req_touser_waiters++;
|
||||
|
||||
/*
|
||||
|
@ -213,14 +240,16 @@ touser(struct puffs_mount *pmp, struct puffs_park *park, unsigned int reqid,
|
|||
/*
|
||||
* XXX: does releasing the lock here cause trouble? Can't hold
|
||||
* it, because otherwise the below would cause locking against
|
||||
* oneself-problems in the kqueue stuff
|
||||
* oneself-problems in the kqueue stuff. yes, it is a
|
||||
* theoretical race, so it must be solved
|
||||
*/
|
||||
simple_unlock(&pmp->pmp_lock);
|
||||
|
||||
wakeup(&pmp->pmp_req_touser);
|
||||
selnotify(pmp->pmp_sel, 0);
|
||||
|
||||
ltsleep(park, PUSER, "puffs1", 0, NULL);
|
||||
if (PUFFSOP_WANTREPLY(ppark->park_opclass))
|
||||
ltsleep(ppark, PUSER, "puffs1", 0, NULL);
|
||||
|
||||
#if 0
|
||||
/* relock */
|
||||
|
@ -230,7 +259,7 @@ touser(struct puffs_mount *pmp, struct puffs_park *park, unsigned int reqid,
|
|||
KASSERT(vn_lock(vp2, LK_EXCLUSIVE | LK_RETRY) == 0);
|
||||
#endif
|
||||
|
||||
return park->park_rv;
|
||||
return ppark->park_rv;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -751,9 +780,15 @@ puffsgetop(struct puffs_mount *pmp, struct puffs_req *preq, int nonblock)
|
|||
simple_unlock(&pmp->pmp_lock);
|
||||
return error;
|
||||
}
|
||||
simple_lock(&pmp->pmp_lock);
|
||||
TAILQ_INSERT_TAIL(&pmp->pmp_req_replywait, park, park_entries);
|
||||
simple_unlock(&pmp->pmp_lock);
|
||||
|
||||
if (PUFFSOP_WANTREPLY(park->park_opclass)) {
|
||||
simple_lock(&pmp->pmp_lock);
|
||||
TAILQ_INSERT_TAIL(&pmp->pmp_req_replywait, park, park_entries);
|
||||
simple_unlock(&pmp->pmp_lock);
|
||||
} else {
|
||||
free(park->park_kernbuf, M_PUFFS);
|
||||
free(park, M_PUFFS);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: puffs_msgif.h,v 1.4 2006/10/26 22:52:47 pooka Exp $ */
|
||||
/* $NetBSD: puffs_msgif.h,v 1.5 2006/11/07 22:10:18 pooka Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2005, 2006 Antti Kantee. All Rights Reserved.
|
||||
|
@ -47,6 +47,11 @@
|
|||
|
||||
#define PUFFSOP_VFS 1
|
||||
#define PUFFSOP_VN 2
|
||||
#define PUFFSOPFLAG_FAF 0x10 /* fire-and-forget */
|
||||
|
||||
#define PUFFSOP_OPCMASK 0x03
|
||||
#define PUFFSOP_OPCLASS(a) ((a) & PUFFSOP_OPCMASK)
|
||||
#define PUFFSOP_WANTREPLY(a) (((a) & PUFFSOPFLAG_FAF) == 0)
|
||||
|
||||
enum {
|
||||
PUFFS_VFS_MOUNT, PUFFS_VFS_START, PUFFS_VFS_UNMOUNT,
|
||||
|
@ -224,6 +229,7 @@ struct puffs_vnreq_lookup {
|
|||
struct puffs_cn pvnr_cn; /* OUT */
|
||||
void *pvnr_newnode; /* IN */
|
||||
enum vtype pvnr_vtype; /* IN */
|
||||
voff_t pvnr_size; /* IN */
|
||||
dev_t pvnr_rdev; /* IN */
|
||||
};
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: puffs_subr.c,v 1.6 2006/10/27 19:54:34 pooka Exp $ */
|
||||
/* $NetBSD: puffs_subr.c,v 1.7 2006/11/07 22:10:18 pooka Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2005, 2006 Antti Kantee. All Rights Reserved.
|
||||
|
@ -33,7 +33,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: puffs_subr.c,v 1.6 2006/10/27 19:54:34 pooka Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: puffs_subr.c,v 1.7 2006/11/07 22:10:18 pooka Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/conf.h>
|
||||
|
@ -47,17 +47,31 @@ __KERNEL_RCSID(0, "$NetBSD: puffs_subr.c,v 1.6 2006/10/27 19:54:34 pooka Exp $")
|
|||
#include <fs/puffs/puffs_msgif.h>
|
||||
#include <fs/puffs/puffs_sys.h>
|
||||
|
||||
#include <miscfs/genfs/genfs_node.h>
|
||||
#include <miscfs/specfs/specdev.h>
|
||||
|
||||
POOL_INIT(puffs_pnpool, sizeof(struct puffs_node), 0, 0, 0, "puffspnpl",
|
||||
&pool_allocator_nointr);
|
||||
|
||||
|
||||
static void puffs_gop_size(struct vnode *, off_t, off_t *, int);
|
||||
static void puffs_gop_markupdate(struct vnode *, int);
|
||||
|
||||
static const struct genfs_ops puffs_genfsops = {
|
||||
.gop_size = puffs_gop_size,
|
||||
.gop_write = genfs_gop_write,
|
||||
.gop_markupdate = puffs_gop_markupdate,
|
||||
#if 0
|
||||
.gop_alloc, should ask userspace
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* Grab a vnode, intialize all the puffs-dependant stuff.
|
||||
*/
|
||||
int
|
||||
puffs_getvnode(struct mount *mp, void *cookie, enum vtype type,
|
||||
dev_t rdev, struct vnode **vpp)
|
||||
voff_t vsize, dev_t rdev, struct vnode **vpp)
|
||||
{
|
||||
struct puffs_mount *pmp;
|
||||
struct vnode *vp, *nvp;
|
||||
|
@ -142,11 +156,16 @@ puffs_getvnode(struct mount *mp, void *cookie, enum vtype type,
|
|||
vp->v_mount = mp;
|
||||
}
|
||||
break;
|
||||
|
||||
case VFIFO:
|
||||
vp->v_op = puffs_fifoop_p;
|
||||
break;
|
||||
case VDIR:
|
||||
|
||||
case VREG:
|
||||
uvm_vnp_setsize(vp, vsize);
|
||||
break;
|
||||
|
||||
case VDIR:
|
||||
case VLNK:
|
||||
case VSOCK:
|
||||
break;
|
||||
|
@ -165,6 +184,7 @@ puffs_getvnode(struct mount *mp, void *cookie, enum vtype type,
|
|||
vp->v_type = type;
|
||||
pnode->pn_vp = vp;
|
||||
|
||||
genfs_node_init(vp, &puffs_genfsops);
|
||||
*vpp = vp;
|
||||
|
||||
DPRINTF(("new vnode at %p, pnode %p, cookie %p\n", vp,
|
||||
|
@ -187,7 +207,7 @@ puffs_newnode(struct mount *mp, struct vnode *dvp, struct vnode **vpp,
|
|||
return error;
|
||||
}
|
||||
|
||||
error = puffs_getvnode(dvp->v_mount, cookie, type, rdev, &vp);
|
||||
error = puffs_getvnode(dvp->v_mount, cookie, type, 0, rdev, &vp);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
|
@ -297,3 +317,59 @@ puffs_lwp2pid(struct lwp *l)
|
|||
|
||||
return l ? l->l_proc->p_pid : 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
puffs_gop_size(struct vnode *vp __unused, off_t size, off_t *eobp,
|
||||
int flags __unused)
|
||||
{
|
||||
|
||||
*eobp = size;
|
||||
}
|
||||
|
||||
static void
|
||||
puffs_gop_markupdate(struct vnode *vp, int flags)
|
||||
{
|
||||
int uflags = 0;
|
||||
|
||||
if (flags & GOP_UPDATE_ACCESSED)
|
||||
uflags |= PUFFS_UPDATEATIME;
|
||||
if (flags & GOP_UPDATE_MODIFIED)
|
||||
uflags |= PUFFS_UPDATEMTIME;
|
||||
|
||||
puffs_updatenode(vp, uflags);
|
||||
}
|
||||
|
||||
void
|
||||
puffs_updatenode(struct vnode *vp, int flags)
|
||||
{
|
||||
struct timespec ts;
|
||||
struct puffs_vnreq_setattr *setattr_arg;
|
||||
|
||||
if (flags == 0)
|
||||
return;
|
||||
|
||||
setattr_arg = malloc(sizeof(struct puffs_vnreq_setattr), M_PUFFS,
|
||||
M_NOWAIT | M_ZERO);
|
||||
if (setattr_arg == NULL)
|
||||
return; /* 2bad */
|
||||
|
||||
nanotime(&ts);
|
||||
|
||||
VATTR_NULL(&setattr_arg->pvnr_va);
|
||||
if (flags & PUFFS_UPDATEATIME)
|
||||
setattr_arg->pvnr_va.va_atime = ts;
|
||||
if (flags & PUFFS_UPDATECTIME)
|
||||
setattr_arg->pvnr_va.va_ctime = ts;
|
||||
if (flags & PUFFS_UPDATEMTIME)
|
||||
setattr_arg->pvnr_va.va_mtime = ts;
|
||||
if (flags & PUFFS_UPDATESIZE)
|
||||
setattr_arg->pvnr_va.va_size = vp->v_size;
|
||||
|
||||
setattr_arg->pvnr_pid = 0;
|
||||
puffs_credcvt(&setattr_arg->pvnr_cred, NOCRED);
|
||||
|
||||
/* setattr_arg ownership shifted to callee */
|
||||
puffs_vntouser_faf(MPTOPUFFSMP(vp->v_mount), PUFFS_VN_SETATTR,
|
||||
setattr_arg, sizeof(struct puffs_vnreq_setattr), VPTOPNC(vp));
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: puffs_sys.h,v 1.5 2006/11/06 23:18:18 pooka Exp $ */
|
||||
/* $NetBSD: puffs_sys.h,v 1.6 2006/11/07 22:10:18 pooka Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2005, 2006 Antti Kantee. All Rights Reserved.
|
||||
|
@ -45,6 +45,8 @@
|
|||
|
||||
#include <fs/puffs/puffs_msgif.h>
|
||||
|
||||
#include <miscfs/genfs/genfs_node.h>
|
||||
|
||||
extern int (**puffs_vnodeop_p)(void *);
|
||||
extern int (**puffs_specop_p)(void *);
|
||||
extern int (**puffs_fifoop_p)(void *);
|
||||
|
@ -141,6 +143,8 @@ struct puffs_mount {
|
|||
#define PNODE_LOCKED 0x02
|
||||
#define PNODE_WANTED 0x04
|
||||
struct puffs_node {
|
||||
struct genfs_node pn_gnode; /* genfs glue */
|
||||
|
||||
void *pn_cookie; /* userspace pnode cookie */
|
||||
struct vnode *pn_vp; /* backpointer to vnode */
|
||||
uint32_t pn_stat; /* node status */
|
||||
|
@ -153,13 +157,13 @@ int puffs_start2(struct puffs_mount *, struct puffs_vfsreq_start *);
|
|||
int puffs_vfstouser(struct puffs_mount *, int, void *, size_t);
|
||||
int puffs_vntouser(struct puffs_mount *, int, void *, size_t, void *,
|
||||
struct vnode *, struct vnode *);
|
||||
void puffs_vntouser_faf(struct puffs_mount *, int, void *, size_t, void *);
|
||||
int puffs_vntouser_req(struct puffs_mount *, int, void *, size_t,
|
||||
void *, unsigned int,
|
||||
struct vnode *, struct vnode *);
|
||||
void *, uint64_t, struct vnode *, struct vnode *);
|
||||
int puffs_vntouser_adjbuf(struct puffs_mount *, int, void **, size_t *,
|
||||
size_t, void *, struct vnode *, struct vnode *);
|
||||
|
||||
int puffs_getvnode(struct mount *, void *, enum vtype, dev_t,
|
||||
int puffs_getvnode(struct mount *, void *, enum vtype, voff_t, dev_t,
|
||||
struct vnode **);
|
||||
int puffs_newnode(struct mount *, struct vnode *, struct vnode **,
|
||||
void *, struct componentname *, enum vtype, dev_t);
|
||||
|
@ -169,10 +173,16 @@ void puffs_makecn(struct puffs_cn *, const struct componentname *);
|
|||
void puffs_credcvt(struct puffs_cred *, kauth_cred_t);
|
||||
pid_t puffs_lwp2pid(struct lwp *);
|
||||
|
||||
void puffs_updatenode(struct vnode *, int);
|
||||
#define PUFFS_UPDATEATIME 0x01
|
||||
#define PUFFS_UPDATECTIME 0x02
|
||||
#define PUFFS_UPDATEMTIME 0x04
|
||||
#define PUFFS_UPDATESIZE 0x08
|
||||
|
||||
int puffs_setpmp(pid_t, int, struct puffs_mount *);
|
||||
void puffs_nukebypmp(struct puffs_mount *);
|
||||
|
||||
unsigned int puffs_getreqid(struct puffs_mount *);
|
||||
uint64_t puffs_getreqid(struct puffs_mount *);
|
||||
void puffs_userdead(struct puffs_mount *);
|
||||
|
||||
extern int (**puffs_vnodeop_p)(void *);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: puffs_vfsops.c,v 1.5 2006/11/06 11:44:54 pooka Exp $ */
|
||||
/* $NetBSD: puffs_vfsops.c,v 1.6 2006/11/07 22:10:18 pooka Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2005, 2006 Antti Kantee. All Rights Reserved.
|
||||
|
@ -33,7 +33,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: puffs_vfsops.c,v 1.5 2006/11/06 11:44:54 pooka Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: puffs_vfsops.c,v 1.6 2006/11/07 22:10:18 pooka Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/mount.h>
|
||||
|
@ -104,7 +104,11 @@ puffs_mount(struct mount *mp, const char *path, void *data,
|
|||
MALLOC(pmp, struct puffs_mount *, sizeof(struct puffs_mount),
|
||||
M_PUFFS, M_WAITOK | M_ZERO);
|
||||
|
||||
mp->mnt_fs_bshift = DEV_BSHIFT;
|
||||
mp->mnt_dev_bshift = DEV_BSHIFT;
|
||||
mp->mnt_flag &= ~MNT_LOCAL; /* we don't really know, so ... */
|
||||
mp->mnt_data = pmp;
|
||||
|
||||
pmp->pmp_status = PUFFSTAT_MOUNTING;
|
||||
pmp->pmp_nextreq = 0;
|
||||
pmp->pmp_mp = mp;
|
||||
|
@ -278,7 +282,7 @@ puffs_root(struct mount *mp, struct vnode **vpp)
|
|||
* So, didn't have the magic root vnode available.
|
||||
* No matter, grab another an stuff it with the cookie.
|
||||
*/
|
||||
if (puffs_getvnode(mp, pmp->pmp_rootcookie, VDIR, 0, &vp))
|
||||
if (puffs_getvnode(mp, pmp->pmp_rootcookie, VDIR, 0, 0, &vp))
|
||||
panic("sloppy programming");
|
||||
|
||||
simple_lock(&pmp->pmp_lock);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: puffs_vnops.c,v 1.7 2006/10/27 19:01:48 pooka Exp $ */
|
||||
/* $NetBSD: puffs_vnops.c,v 1.8 2006/11/07 22:10:18 pooka Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2005, 2006 Antti Kantee. All Rights Reserved.
|
||||
|
@ -33,7 +33,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: puffs_vnops.c,v 1.7 2006/10/27 19:01:48 pooka Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: puffs_vnops.c,v 1.8 2006/11/07 22:10:18 pooka Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/vnode.h>
|
||||
|
@ -77,12 +77,10 @@ int puffs_inactive(void *);
|
|||
int puffs_print(void *);
|
||||
int puffs_pathconf(void *);
|
||||
int puffs_advlock(void *);
|
||||
int puffs_strategy(void *);
|
||||
int puffs_bmap(void *);
|
||||
|
||||
|
||||
/* Need to support */
|
||||
#define puffs_putpages puffs_generic
|
||||
#define puffs_getpages puffs_generic
|
||||
|
||||
/* VOP_LEASE() not included */
|
||||
|
||||
int puffs_generic(void *);
|
||||
|
@ -141,21 +139,19 @@ const struct vnodeopv_entry_desc puffs_vnodeop_entries[] = {
|
|||
{ &vop_reclaim_desc, puffs_reclaim }, /* reclaim */
|
||||
{ &vop_lock_desc, puffs_lock }, /* lock */
|
||||
{ &vop_unlock_desc, puffs_unlock }, /* unlock */
|
||||
{ &vop_bmap_desc, genfs_eopnotsupp }, /* bmap */
|
||||
{ &vop_strategy_desc, genfs_eopnotsupp }, /* strategy */
|
||||
{ &vop_bmap_desc, puffs_bmap }, /* bmap */
|
||||
{ &vop_strategy_desc, puffs_strategy }, /* strategy */
|
||||
{ &vop_print_desc, puffs_print }, /* print */
|
||||
{ &vop_islocked_desc, puffs_islocked }, /* islocked */
|
||||
{ &vop_pathconf_desc, puffs_pathconf }, /* pathconf */
|
||||
{ &vop_advlock_desc, puffs_advlock }, /* advlock */
|
||||
{ &vop_bwrite_desc, genfs_nullop }, /* bwrite */
|
||||
#if 0
|
||||
{ &vop_getpages_desc, puffs_getpages }, /* getpages */
|
||||
#endif
|
||||
{ &vop_putpages_desc, genfs_null_putpages }, /* putpages */
|
||||
{ &vop_getpages_desc, genfs_getpages }, /* getpages */
|
||||
{ &vop_putpages_desc, genfs_putpages }, /* putpages */
|
||||
{ &vop_mmap_desc, genfs_mmap }, /* mmap */
|
||||
|
||||
{ &vop_poll_desc, genfs_eopnotsupp }, /* poll XXX */
|
||||
{ &vop_poll_desc, genfs_eopnotsupp }, /* kqfilter XXX */
|
||||
{ &vop_mmap_desc, genfs_eopnotsupp }, /* mmap XXX */
|
||||
{ NULL, NULL }
|
||||
};
|
||||
const struct vnodeopv_desc puffs_vnodeop_opv_desc =
|
||||
|
@ -378,7 +374,7 @@ puffs_lookup(void *v)
|
|||
if (!vp) {
|
||||
error = puffs_getvnode(dvp->v_mount,
|
||||
lookup_arg.pvnr_newnode, lookup_arg.pvnr_vtype,
|
||||
lookup_arg.pvnr_rdev, &vp);
|
||||
lookup_arg.pvnr_size, lookup_arg.pvnr_rdev, &vp);
|
||||
if (error) {
|
||||
if (cnp->cn_flags & ISDOTDOT)
|
||||
if (vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY) != 0)
|
||||
|
@ -527,7 +523,6 @@ puffs_access(void *v)
|
|||
kauth_cred_t a_cred;
|
||||
struct lwp *a_l;
|
||||
} */ *ap = v;
|
||||
int error;
|
||||
|
||||
PUFFS_VNREQ(access);
|
||||
|
||||
|
@ -535,21 +530,8 @@ puffs_access(void *v)
|
|||
access_arg.pvnr_pid = puffs_lwp2pid(ap->a_l);
|
||||
puffs_credcvt(&access_arg.pvnr_cred, ap->a_cred);
|
||||
|
||||
error = puffs_vntouser(MPTOPUFFSMP(ap->a_vp->v_mount), PUFFS_VN_ACCESS,
|
||||
return puffs_vntouser(MPTOPUFFSMP(ap->a_vp->v_mount), PUFFS_VN_ACCESS,
|
||||
&access_arg, sizeof(access_arg), VPTOPNC(ap->a_vp), ap->a_vp, NULL);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
/*
|
||||
* XXXtothepeople: no execute permissions yet. Otherwise
|
||||
* all hell will break loose if we try to execute a file
|
||||
* without VOP_GETPAGES support. It is forthcoming, just
|
||||
* not there yet ...
|
||||
*/
|
||||
if (ap->a_mode == VEXEC && ap->a_vp->v_type != VDIR)
|
||||
return EACCES;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -584,15 +566,6 @@ puffs_getattr(void *v)
|
|||
|
||||
(void)memcpy(ap->a_vap, &getattr_arg.pvnr_va, sizeof(struct vattr));
|
||||
|
||||
/*
|
||||
* XXXtothepeople: adjust the return value so that we don't
|
||||
* advertise execute bits. Otherwise all hell will break
|
||||
* loose if we try to execute a file without VOP_GETPAGES
|
||||
* support. It is forthcoming, just not there yet ...
|
||||
*/
|
||||
if (ap->a_vp->v_type != VDIR)
|
||||
ap->a_vap->va_mode &= ~0111;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -606,6 +579,7 @@ puffs_setattr(void *v)
|
|||
kauth_cred_t a_cred;
|
||||
struct lwp *a_l;
|
||||
} */ *ap = v;
|
||||
int error;
|
||||
|
||||
PUFFS_VNREQ(setattr);
|
||||
|
||||
|
@ -613,9 +587,16 @@ puffs_setattr(void *v)
|
|||
puffs_credcvt(&setattr_arg.pvnr_cred, ap->a_cred);
|
||||
setattr_arg.pvnr_pid = puffs_lwp2pid(ap->a_l);
|
||||
|
||||
return puffs_vntouser(MPTOPUFFSMP(ap->a_vp->v_mount), PUFFS_VN_SETATTR,
|
||||
error = puffs_vntouser(MPTOPUFFSMP(ap->a_vp->v_mount), PUFFS_VN_SETATTR,
|
||||
&setattr_arg, sizeof(setattr_arg), VPTOPNC(ap->a_vp),
|
||||
ap->a_vp, NULL);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (ap->a_vap->va_size != VNOVAL)
|
||||
uvm_vnp_setsize(ap->a_vp, ap->a_vap->va_size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -637,6 +618,11 @@ puffs_revoke(void *v)
|
|||
return genfs_revoke(v);
|
||||
}
|
||||
|
||||
/*
|
||||
* There is no technical need to have this travel to userspace
|
||||
* synchronously. So once async reply support is in place, make this
|
||||
* async.
|
||||
*/
|
||||
int
|
||||
puffs_inactive(void *v)
|
||||
{
|
||||
|
@ -819,21 +805,59 @@ puffs_fsync(void *v)
|
|||
off_t a_offhi;
|
||||
struct lwp *a_l;
|
||||
} */ *ap = v;
|
||||
struct puffs_vnreq_fsync *fsync_argp;
|
||||
struct vnode *vp;
|
||||
int pflags, error;
|
||||
|
||||
PUFFS_VNREQ(fsync);
|
||||
|
||||
puffs_credcvt(&fsync_arg.pvnr_cred, ap->a_cred);
|
||||
fsync_arg.pvnr_flags = ap->a_flags;
|
||||
fsync_arg.pvnr_offlo = ap->a_offlo;
|
||||
fsync_arg.pvnr_offhi = ap->a_offhi;
|
||||
fsync_arg.pvnr_pid = puffs_lwp2pid(ap->a_l);
|
||||
vp = ap->a_vp;
|
||||
|
||||
pflags = PGO_CLEANIT;
|
||||
if (ap->a_flags & FSYNC_WAIT) {
|
||||
pflags |= PGO_SYNCIO;
|
||||
fsync_argp = &fsync_arg;
|
||||
} else {
|
||||
fsync_argp = malloc(sizeof(struct puffs_vnreq_fsync),
|
||||
M_PUFFS, M_ZERO | M_NOWAIT);
|
||||
if (fsync_argp == NULL)
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
* flush pages to avoid being overly dirty
|
||||
*/
|
||||
simple_lock(&vp->v_interlock);
|
||||
error = VOP_PUTPAGES(vp, trunc_page(ap->a_offlo),
|
||||
round_page(ap->a_offhi), pflags);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
puffs_credcvt(&fsync_argp->pvnr_cred, ap->a_cred);
|
||||
fsync_argp->pvnr_flags = ap->a_flags;
|
||||
fsync_argp->pvnr_offlo = ap->a_offlo;
|
||||
fsync_argp->pvnr_offhi = ap->a_offhi;
|
||||
fsync_argp->pvnr_pid = puffs_lwp2pid(ap->a_l);
|
||||
|
||||
/*
|
||||
* XXX: see comment at puffs_getattr about locking
|
||||
*
|
||||
* If we are not required to wait, do a FAF operation.
|
||||
* Otherwise block here.
|
||||
*/
|
||||
return puffs_vntouser(MPTOPUFFSMP(ap->a_vp->v_mount), PUFFS_VN_FSYNC,
|
||||
&fsync_arg, sizeof(fsync_arg), VPTOPNC(ap->a_vp),
|
||||
NULL /* XXXshouldbe: ap->a_vp */, NULL);
|
||||
if (ap->a_flags & FSYNC_WAIT) {
|
||||
error = puffs_vntouser(MPTOPUFFSMP(vp->v_mount),
|
||||
PUFFS_VN_FSYNC, fsync_argp, sizeof(*fsync_argp),
|
||||
VPTOPNC(vp), NULL /* XXXshouldbe: vp */, NULL);
|
||||
} else {
|
||||
/* FAF is always "succesful" */
|
||||
error = 0;
|
||||
puffs_vntouser_faf(MPTOPUFFSMP(vp->v_mount),
|
||||
PUFFS_VN_FSYNC, fsync_argp, sizeof(*fsync_argp),
|
||||
VPTOPNC(vp));
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -1102,52 +1126,98 @@ puffs_read(void *v)
|
|||
} */ *ap = v;
|
||||
struct puffs_vnreq_read *read_argp;
|
||||
struct puffs_mount *pmp;
|
||||
struct vnode *vp;
|
||||
struct uio *uio;
|
||||
void *win;
|
||||
size_t tomove, argsize;
|
||||
vsize_t bytelen;
|
||||
int error;
|
||||
|
||||
uio = ap->a_uio;
|
||||
|
||||
pmp = MPTOPUFFSMP(ap->a_vp->v_mount);
|
||||
tomove = PUFFS_TOMOVE(uio->uio_resid, pmp);
|
||||
argsize = sizeof(struct puffs_vnreq_read);
|
||||
read_argp = malloc(argsize, M_PUFFS, M_WAITOK | M_ZERO);
|
||||
|
||||
vp = ap->a_vp;
|
||||
read_argp = NULL;
|
||||
error = 0;
|
||||
while (uio->uio_resid > 0) {
|
||||
read_argp->pvnr_ioflag = ap->a_ioflag;
|
||||
read_argp->pvnr_resid = tomove;
|
||||
read_argp->pvnr_offset = uio->uio_offset;
|
||||
puffs_credcvt(&read_argp->pvnr_cred, ap->a_cred);
|
||||
|
||||
argsize = sizeof(struct puffs_vnreq_read);
|
||||
error = puffs_vntouser_adjbuf(pmp, PUFFS_VN_READ,
|
||||
(void **)&read_argp, &argsize,
|
||||
sizeof(struct puffs_vnreq_read), VPTOPNC(ap->a_vp),
|
||||
ap->a_vp, NULL);
|
||||
if (error)
|
||||
goto out;
|
||||
/* std sanity */
|
||||
if (uio->uio_resid == 0)
|
||||
return 0;
|
||||
if (uio->uio_offset < 0)
|
||||
return EINVAL;
|
||||
|
||||
if (read_argp->pvnr_resid > tomove) {
|
||||
error = EINVAL;
|
||||
goto out;
|
||||
if (vp->v_type == VREG) {
|
||||
const int advice = IO_ADV_DECODE(ap->a_ioflag);
|
||||
|
||||
while (uio->uio_resid > 0) {
|
||||
bytelen = MIN(uio->uio_resid,
|
||||
vp->v_size - uio->uio_offset);
|
||||
if (bytelen == 0)
|
||||
break;
|
||||
|
||||
win = ubc_alloc(&vp->v_uobj, uio->uio_offset,
|
||||
&bytelen, advice, UBC_READ);
|
||||
error = uiomove(win, bytelen, uio);
|
||||
ubc_release(win, UBC_WANT_UNMAP(vp) ? UBC_UNMAP : 0);
|
||||
if (error)
|
||||
break;
|
||||
}
|
||||
|
||||
error = uiomove(read_argp->pvnr_data,
|
||||
tomove - read_argp->pvnr_resid, uio);
|
||||
|
||||
if ((vp->v_mount->mnt_flag & MNT_NOATIME) == 0)
|
||||
puffs_updatenode(vp, PUFFS_UPDATEATIME);
|
||||
} else {
|
||||
#ifdef DIAGNOSTIC
|
||||
if (!(vp->v_type == VDIR || vp->v_type == VLNK))
|
||||
panic("puffs_read: bad vnode type %d\n", vp->v_type);
|
||||
#endif
|
||||
/*
|
||||
* in case the file is out of juice, resid from userspace
|
||||
* is != 0. and the error-case is quite obvious
|
||||
* in case it's not a regular file, do it in the
|
||||
* old-fashioned style, i.e. explicit read without going
|
||||
* through the page cache.
|
||||
*
|
||||
* XXX: this path is not really tested now
|
||||
*/
|
||||
if (error || read_argp->pvnr_resid)
|
||||
goto out;
|
||||
|
||||
pmp = MPTOPUFFSMP(ap->a_vp->v_mount);
|
||||
tomove = PUFFS_TOMOVE(uio->uio_resid, pmp);
|
||||
argsize = sizeof(struct puffs_vnreq_read);
|
||||
read_argp = malloc(argsize, M_PUFFS, M_WAITOK | M_ZERO);
|
||||
|
||||
error = 0;
|
||||
while (uio->uio_resid > 0) {
|
||||
read_argp->pvnr_ioflag = ap->a_ioflag;
|
||||
read_argp->pvnr_resid = tomove;
|
||||
read_argp->pvnr_offset = uio->uio_offset;
|
||||
puffs_credcvt(&read_argp->pvnr_cred, ap->a_cred);
|
||||
|
||||
argsize = sizeof(struct puffs_vnreq_read);
|
||||
error = puffs_vntouser_adjbuf(pmp, PUFFS_VN_READ,
|
||||
(void **)&read_argp, &argsize,
|
||||
sizeof(struct puffs_vnreq_read), VPTOPNC(ap->a_vp),
|
||||
ap->a_vp, NULL);
|
||||
if (error)
|
||||
break;
|
||||
|
||||
if (read_argp->pvnr_resid > tomove) {
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
error = uiomove(read_argp->pvnr_data,
|
||||
tomove - read_argp->pvnr_resid, uio);
|
||||
|
||||
/*
|
||||
* in case the file is out of juice, resid from
|
||||
* userspace is != 0. and the error-case is
|
||||
* quite obvious
|
||||
*/
|
||||
if (error || read_argp->pvnr_resid)
|
||||
break;
|
||||
|
||||
tomove = PUFFS_TOMOVE(uio->uio_resid, pmp);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
free(read_argp, M_PUFFS);
|
||||
if (read_argp)
|
||||
free(read_argp, M_PUFFS);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -1164,53 +1234,133 @@ puffs_write(void *v)
|
|||
struct puffs_vnreq_write *write_argp;
|
||||
struct puffs_mount *pmp;
|
||||
struct uio *uio;
|
||||
struct vnode *vp;
|
||||
void *win;
|
||||
size_t tomove, argsize;
|
||||
int error;
|
||||
off_t oldoff, newoff, origoff;
|
||||
vsize_t bytelen;
|
||||
int error, uflags;
|
||||
int async;
|
||||
|
||||
vp = ap->a_vp;
|
||||
uio = ap->a_uio;
|
||||
async = vp->v_mount->mnt_flag & MNT_ASYNC;
|
||||
error = uflags = 0;
|
||||
write_argp = NULL;
|
||||
|
||||
pmp = MPTOPUFFSMP(ap->a_vp->v_mount);
|
||||
tomove = PUFFS_TOMOVE(uio->uio_resid, pmp);
|
||||
argsize = sizeof(struct puffs_vnreq_write) + tomove;
|
||||
write_argp = malloc(argsize, M_PUFFS, M_WAITOK | M_ZERO);
|
||||
if (vp->v_type == VREG) {
|
||||
/*
|
||||
* userspace *should* be allowed to control this,
|
||||
* but with UBC it's a bit unclear how to handle it
|
||||
*/
|
||||
if (ap->a_ioflag & IO_APPEND)
|
||||
uio->uio_offset = vp->v_size;
|
||||
|
||||
error = 0;
|
||||
while (uio->uio_resid > 0) {
|
||||
write_argp->pvnr_ioflag = ap->a_ioflag;
|
||||
write_argp->pvnr_resid = tomove;
|
||||
write_argp->pvnr_offset = uio->uio_offset;
|
||||
puffs_credcvt(&write_argp->pvnr_cred, ap->a_cred);
|
||||
error = uiomove(write_argp->pvnr_data, tomove, ap->a_uio);
|
||||
if (error)
|
||||
goto out;
|
||||
origoff = uio->uio_offset;
|
||||
while (uio->uio_resid > 0) {
|
||||
uflags |= PUFFS_UPDATECTIME;
|
||||
uflags |= PUFFS_UPDATEMTIME;
|
||||
oldoff = uio->uio_offset;
|
||||
bytelen = uio->uio_resid;
|
||||
|
||||
error = puffs_vntouser(MPTOPUFFSMP(ap->a_vp->v_mount),
|
||||
PUFFS_VN_WRITE, write_argp, argsize, VPTOPNC(ap->a_vp),
|
||||
ap->a_vp, NULL);
|
||||
if (error) {
|
||||
/* restore uiomove */
|
||||
uio->uio_resid += tomove;
|
||||
uio->uio_offset -= tomove;
|
||||
goto out;
|
||||
}
|
||||
if (write_argp->pvnr_resid > tomove) {
|
||||
error = EINVAL;
|
||||
goto out;
|
||||
win = ubc_alloc(&vp->v_uobj, oldoff, &bytelen,
|
||||
UVM_ADV_NORMAL, UBC_WRITE);
|
||||
error = uiomove(win, bytelen, uio);
|
||||
|
||||
/*
|
||||
* did we grow the file?
|
||||
* XXX: should probably ask userspace to extend
|
||||
* it's idea of the *first* before growing it
|
||||
* here. Or we need some mechanism to "rollback"
|
||||
* in case putpages fails.
|
||||
*/
|
||||
newoff = oldoff + bytelen;
|
||||
if (vp->v_size < newoff) {
|
||||
uflags |= PUFFS_UPDATESIZE;
|
||||
uvm_vnp_setsize(vp, newoff);
|
||||
|
||||
/*
|
||||
* in case we couldn't copy data to the
|
||||
* window, zero it out so that we don't
|
||||
* have any random leftovers in there.
|
||||
*/
|
||||
if (error)
|
||||
memset(win, 0, bytelen);
|
||||
}
|
||||
|
||||
ubc_release(win, UBC_WANT_UNMAP(vp) ? UBC_UNMAP : 0);
|
||||
if (error)
|
||||
break;
|
||||
|
||||
/* ok, I really need to admit: why's this? */
|
||||
if (!async && oldoff >> 16 != uio->uio_offset >> 16) {
|
||||
simple_lock(&vp->v_interlock);
|
||||
error = VOP_PUTPAGES(vp, oldoff & ~0xffff,
|
||||
uio->uio_offset & ~0xffff, PGO_CLEANIT);
|
||||
if (error)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* didn't move everything? bad userspace. bail */
|
||||
if (write_argp->pvnr_resid != 0) {
|
||||
uio->uio_resid += write_argp->pvnr_resid;
|
||||
uio->uio_offset -= write_argp->pvnr_resid;
|
||||
error = EIO;
|
||||
break;
|
||||
if (error == 0 && ap->a_ioflag & IO_SYNC) {
|
||||
simple_lock(&vp->v_interlock);
|
||||
error = VOP_PUTPAGES(vp, trunc_page(origoff),
|
||||
round_page(uio->uio_offset),
|
||||
PGO_CLEANIT | PGO_SYNCIO);
|
||||
}
|
||||
|
||||
puffs_updatenode(vp, uflags);
|
||||
} else {
|
||||
|
||||
pmp = MPTOPUFFSMP(ap->a_vp->v_mount);
|
||||
tomove = PUFFS_TOMOVE(uio->uio_resid, pmp);
|
||||
argsize = sizeof(struct puffs_vnreq_write) + tomove;
|
||||
write_argp = malloc(argsize, M_PUFFS, M_WAITOK | M_ZERO);
|
||||
|
||||
while (uio->uio_resid > 0) {
|
||||
write_argp->pvnr_ioflag = ap->a_ioflag;
|
||||
write_argp->pvnr_resid = tomove;
|
||||
write_argp->pvnr_offset = uio->uio_offset;
|
||||
puffs_credcvt(&write_argp->pvnr_cred, ap->a_cred);
|
||||
error = uiomove(write_argp->pvnr_data, tomove, uio);
|
||||
if (error)
|
||||
break;
|
||||
|
||||
error = puffs_vntouser(MPTOPUFFSMP(ap->a_vp->v_mount),
|
||||
PUFFS_VN_WRITE, write_argp, argsize,
|
||||
VPTOPNC(ap->a_vp), ap->a_vp, NULL);
|
||||
if (error) {
|
||||
/* restore uiomove */
|
||||
uio->uio_resid += tomove;
|
||||
uio->uio_offset -= tomove;
|
||||
break;
|
||||
}
|
||||
if (write_argp->pvnr_resid > tomove) {
|
||||
/*
|
||||
* XXX: correct file size is a mystery,
|
||||
* we can only guess
|
||||
*/
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
/* adjust file size */
|
||||
uvm_vnp_setsize(vp, uio->uio_offset);
|
||||
|
||||
/* didn't move everything? bad userspace. bail */
|
||||
if (write_argp->pvnr_resid != 0) {
|
||||
uio->uio_resid += write_argp->pvnr_resid;
|
||||
uio->uio_offset -= write_argp->pvnr_resid;
|
||||
error = EIO;
|
||||
break;
|
||||
}
|
||||
|
||||
tomove = PUFFS_TOMOVE(uio->uio_resid, pmp);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
free(write_argp, M_PUFFS);
|
||||
if (write_argp)
|
||||
free(write_argp, M_PUFFS);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -1369,12 +1519,115 @@ puffs_advlock(void *v)
|
|||
return puffs_vntouser(MPTOPUFFSMP(ap->a_vp->v_mount), PUFFS_VN_ADVLOCK,
|
||||
&advlock_arg, sizeof(advlock_arg), VPTOPNC(ap->a_vp), NULL, NULL);
|
||||
}
|
||||
/*
|
||||
* This maps itself to PUFFS_VN_READ/WRITE for data transfer.
|
||||
*/
|
||||
int
|
||||
puffs_strategy(void *v)
|
||||
{
|
||||
struct vop_strategy_args /* {
|
||||
const struct vnodeop_desc *a_desc;
|
||||
struct vnode *a_vp;
|
||||
struct buf *a_bp;
|
||||
} */ *ap = v;
|
||||
struct puffs_mount *pmp;
|
||||
struct puffs_vnreq_read *read_argp;
|
||||
struct puffs_vnreq_write *write_argp;
|
||||
struct buf *bp;
|
||||
size_t argsize;
|
||||
int error;
|
||||
|
||||
pmp = MPTOPUFFSMP(ap->a_vp->v_mount);
|
||||
bp = ap->a_bp;
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
if (bp->b_bcount > pmp->pmp_req_maxsize - PUFFS_REQSTRUCT_MAX)
|
||||
panic("puffs_strategy: wildly inappropriate buf bcount %d",
|
||||
bp->b_bcount);
|
||||
#endif
|
||||
|
||||
if (bp->b_flags & B_READ) {
|
||||
argsize = sizeof(struct puffs_vnreq_read);
|
||||
read_argp = malloc(argsize, M_PUFFS, M_WAITOK | M_ZERO);
|
||||
read_argp->pvnr_ioflag = 0;
|
||||
read_argp->pvnr_resid = bp->b_bcount;
|
||||
read_argp->pvnr_offset = bp->b_blkno << DEV_BSHIFT;
|
||||
/* XXX: puffs_credcvt */
|
||||
|
||||
error = puffs_vntouser_adjbuf(pmp, PUFFS_VN_READ,
|
||||
(void **)&read_argp, &argsize, argsize,
|
||||
VPTOPNC(ap->a_vp), LOCKEDVP(ap->a_vp), NULL);
|
||||
|
||||
if (error)
|
||||
printf("virhe\n");
|
||||
|
||||
(void)memcpy(bp->b_data, read_argp->pvnr_data, bp->b_bcount);
|
||||
free(read_argp, M_PUFFS);
|
||||
} else {
|
||||
argsize = sizeof(struct puffs_vnreq_write) + bp->b_bcount;
|
||||
write_argp = malloc(argsize, M_PUFFS, M_WAITOK | M_ZERO);
|
||||
write_argp->pvnr_ioflag = 0;
|
||||
write_argp->pvnr_resid = bp->b_bcount;
|
||||
write_argp->pvnr_offset = bp->b_blkno << DEV_BSHIFT;
|
||||
/* XXX, stupid */
|
||||
(void)memcpy(&write_argp->pvnr_data, bp->b_data, bp->b_bcount);
|
||||
|
||||
error = puffs_vntouser(MPTOPUFFSMP(ap->a_vp->v_mount),
|
||||
PUFFS_VN_WRITE, write_argp, argsize,
|
||||
VPTOPNC(ap->a_vp), ap->a_vp, NULL);
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
/* XXX: if any of the following trigger, we're in trouble */
|
||||
|
||||
/* check 1 */
|
||||
if (write_argp->pvnr_resid != 0)
|
||||
error = EIO;
|
||||
|
||||
/* check 2 */
|
||||
if (write_argp->pvnr_resid > bp->b_bcount)
|
||||
error = EINVAL;
|
||||
}
|
||||
|
||||
out:
|
||||
biodone(ap->a_bp);
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* The rest don't get a free trip to userspace and back, they
|
||||
* have to stay within the kernel.
|
||||
*/
|
||||
|
||||
/*
|
||||
* bmap doesn't really make any sense for puffs, so just 1:1 map it.
|
||||
* well, maybe somehow, somewhere, some day ....
|
||||
*/
|
||||
int
|
||||
puffs_bmap(void *v)
|
||||
{
|
||||
struct vop_bmap_args /* {
|
||||
const struct vnodeop_desc *a_desc;
|
||||
struct vnode *a_vp;
|
||||
daddr_t a_bn;
|
||||
struct vnode **a_vpp;
|
||||
daddr_t *a_bnp;
|
||||
int *a_runp;
|
||||
} */ *ap = v;
|
||||
struct puffs_mount *pmp;
|
||||
|
||||
pmp = MPTOPUFFSMP(ap->a_vp->v_mount);
|
||||
|
||||
if (ap->a_vpp)
|
||||
*ap->a_vpp = ap->a_vp;
|
||||
if (ap->a_bnp)
|
||||
*ap->a_bnp = ap->a_bn;
|
||||
if (ap->a_runp)
|
||||
*ap->a_runp = pmp->pmp_req_maxsize - PUFFS_REQSTRUCT_MAX;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* moreXXX: yes, todo
|
||||
*/
|
||||
|
@ -1420,26 +1673,6 @@ puffs_islocked(void *v)
|
|||
return rv;
|
||||
}
|
||||
|
||||
#if 0
|
||||
int
|
||||
puffs_getpages(void *v)
|
||||
{
|
||||
struct vop_getpages_args /* {
|
||||
const struct vnodeop_desc *a_desc;
|
||||
struct vnode *a_vp;
|
||||
voff_t a_offset;
|
||||
struct vm_page **a_m;
|
||||
int *a_count;
|
||||
int a_centeridx;
|
||||
vm_prot_t a_access_type;
|
||||
int a_advice;
|
||||
int a_flags;
|
||||
} */ *ap = v;
|
||||
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
puffs_generic(void *v)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue