version 1.65, 2007/10/11 23:04:21 |
version 1.65.4.3, 2008/02/18 21:06:40 |
Line 43 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 43 __KERNEL_RCSID(0, "$NetBSD$"); |
|
#include <sys/fstrans.h> |
#include <sys/fstrans.h> |
#include <sys/proc.h> |
#include <sys/proc.h> |
|
|
#include <lib/libkern/libkern.h> |
#include <dev/putter/putter_sys.h> |
|
|
|
#include <miscfs/genfs/genfs.h> |
|
|
#include <fs/puffs/puffs_msgif.h> |
#include <fs/puffs/puffs_msgif.h> |
#include <fs/puffs/puffs_sys.h> |
#include <fs/puffs/puffs_sys.h> |
|
|
#include <nfs/nfsproto.h> /* for fh sizes */ |
#include <lib/libkern/libkern.h> |
|
|
VFS_PROTOS(puffs); |
#include <nfs/nfsproto.h> /* for fh sizes */ |
|
|
MALLOC_JUSTDEFINE(M_PUFFS, "puffs", "Pass-to-Userspace Framework File System"); |
VFS_PROTOS(puffs_vfsop); |
|
|
#ifndef PUFFS_PNODEBUCKETS |
#ifndef PUFFS_PNODEBUCKETS |
#define PUFFS_PNODEBUCKETS 256 |
#define PUFFS_PNODEBUCKETS 256 |
Line 63 MALLOC_JUSTDEFINE(M_PUFFS, "puffs", "Pas |
|
Line 65 MALLOC_JUSTDEFINE(M_PUFFS, "puffs", "Pas |
|
int puffs_pnodebuckets_default = PUFFS_PNODEBUCKETS; |
int puffs_pnodebuckets_default = PUFFS_PNODEBUCKETS; |
int puffs_maxpnodebuckets = PUFFS_MAXPNODEBUCKETS; |
int puffs_maxpnodebuckets = PUFFS_MAXPNODEBUCKETS; |
|
|
|
#define BUCKETALLOC(a) (sizeof(struct puffs_pnode_hashlist *) * (a)) |
|
|
|
static struct putter_ops puffs_putter = { |
|
.pop_getout = puffs_msgif_getout, |
|
.pop_releaseout = puffs_msgif_releaseout, |
|
.pop_waitcount = puffs_msgif_waitcount, |
|
.pop_dispatch = puffs_msgif_dispatch, |
|
.pop_close = puffs_msgif_close, |
|
}; |
|
|
int |
int |
puffs_mount(struct mount *mp, const char *path, void *data, size_t *data_len, |
puffs_vfsop_mount(struct mount *mp, const char *path, void *data, |
struct lwp *l) |
size_t *data_len) |
{ |
{ |
struct puffs_mount *pmp = NULL; |
struct puffs_mount *pmp = NULL; |
struct puffs_kargs *args; |
struct puffs_kargs *args; |
char fstype[_VFS_NAMELEN]; |
char fstype[_VFS_NAMELEN]; |
char *p; |
char *p; |
int error = 0, i; |
int error = 0, i; |
|
pid_t mntpid = curlwp->l_proc->p_pid; |
|
|
if (*data_len < sizeof *args) |
if (*data_len < sizeof *args) |
return EINVAL; |
return EINVAL; |
Line 93 puffs_mount(struct mount *mp, const char |
|
Line 106 puffs_mount(struct mount *mp, const char |
|
if (!data) |
if (!data) |
return EINVAL; |
return EINVAL; |
|
|
MALLOC(args, struct puffs_kargs *, sizeof(struct puffs_kargs), |
error = fstrans_mount(mp); |
M_PUFFS, M_WAITOK); |
if (error) |
|
return error; |
*args = *(struct puffs_kargs *)data; |
args = (struct puffs_kargs *)data; |
|
|
/* devel phase */ |
/* devel phase */ |
if (args->pa_vers != (PUFFSVERSION | PUFFSDEVELVERS)) { |
if (args->pa_vers != (PUFFSVERSION | PUFFSDEVELVERS)) { |
Line 189 puffs_mount(struct mount *mp, const char |
|
Line 202 puffs_mount(struct mount *mp, const char |
|
} |
} |
|
|
error = set_statvfs_info(path, UIO_USERSPACE, args->pa_mntfromname, |
error = set_statvfs_info(path, UIO_USERSPACE, args->pa_mntfromname, |
UIO_SYSSPACE, fstype, mp, l); |
UIO_SYSSPACE, fstype, mp, curlwp); |
if (error) |
if (error) |
goto out; |
goto out; |
mp->mnt_stat.f_iosize = DEV_BSIZE; |
mp->mnt_stat.f_iosize = DEV_BSIZE; |
Line 202 puffs_mount(struct mount *mp, const char |
|
Line 215 puffs_mount(struct mount *mp, const char |
|
copy_statvfs_info(&args->pa_svfsb, mp); |
copy_statvfs_info(&args->pa_svfsb, mp); |
(void)memcpy(&mp->mnt_stat, &args->pa_svfsb, sizeof(mp->mnt_stat)); |
(void)memcpy(&mp->mnt_stat, &args->pa_svfsb, sizeof(mp->mnt_stat)); |
|
|
MALLOC(pmp, struct puffs_mount *, sizeof(struct puffs_mount), |
pmp = kmem_zalloc(sizeof(struct puffs_mount), KM_SLEEP); |
M_PUFFS, M_WAITOK | M_ZERO); |
|
|
|
mp->mnt_fs_bshift = DEV_BSHIFT; |
mp->mnt_fs_bshift = DEV_BSHIFT; |
mp->mnt_dev_bshift = DEV_BSHIFT; |
mp->mnt_dev_bshift = DEV_BSHIFT; |
Line 217 puffs_mount(struct mount *mp, const char |
|
Line 229 puffs_mount(struct mount *mp, const char |
|
pmp->pmp_args = *args; |
pmp->pmp_args = *args; |
|
|
pmp->pmp_npnodehash = args->pa_nhashbuckets; |
pmp->pmp_npnodehash = args->pa_nhashbuckets; |
pmp->pmp_pnodehash = malloc |
pmp->pmp_pnodehash = kmem_alloc(BUCKETALLOC(pmp->pmp_npnodehash), KM_SLEEP); |
(sizeof(struct puffs_pnode_hashlist *) * pmp->pmp_npnodehash, |
|
M_PUFFS, M_WAITOK); |
|
for (i = 0; i < pmp->pmp_npnodehash; i++) |
for (i = 0; i < pmp->pmp_npnodehash; i++) |
LIST_INIT(&pmp->pmp_pnodehash[i]); |
LIST_INIT(&pmp->pmp_pnodehash[i]); |
LIST_INIT(&pmp->pmp_newcookie); |
LIST_INIT(&pmp->pmp_newcookie); |
Line 229 puffs_mount(struct mount *mp, const char |
|
Line 239 puffs_mount(struct mount *mp, const char |
|
* If it doesn't know about anyone with our pid/fd having the |
* If it doesn't know about anyone with our pid/fd having the |
* device open, punt |
* device open, punt |
*/ |
*/ |
if (puffs_setpmp(l->l_proc->p_pid, args->pa_fd, pmp)) { |
if ((pmp->pmp_pi |
|
= putter_attach(mntpid, args->pa_fd, pmp, &puffs_putter)) == NULL) { |
error = ENOENT; |
error = ENOENT; |
goto out; |
goto out; |
} |
} |
Line 253 puffs_mount(struct mount *mp, const char |
|
Line 264 puffs_mount(struct mount *mp, const char |
|
vfs_getnewfsid(mp); |
vfs_getnewfsid(mp); |
|
|
out: |
out: |
|
if (error) |
|
fstrans_unmount(mp); |
if (error && pmp && pmp->pmp_pnodehash) |
if (error && pmp && pmp->pmp_pnodehash) |
free(pmp->pmp_pnodehash, M_PUFFS); |
kmem_free(pmp->pmp_pnodehash, BUCKETALLOC(pmp->pmp_npnodehash)); |
if (error && pmp) |
if (error && pmp) |
FREE(pmp, M_PUFFS); |
kmem_free(pmp, sizeof(struct puffs_mount)); |
FREE(args, M_PUFFS); |
|
return error; |
return error; |
} |
} |
|
|
int |
int |
puffs_start(struct mount *mp, int flags, struct lwp *l) |
puffs_vfsop_start(struct mount *mp, int flags) |
{ |
{ |
struct puffs_mount *pmp = MPTOPUFFSMP(mp); |
struct puffs_mount *pmp = MPTOPUFFSMP(mp); |
|
|
Line 273 puffs_start(struct mount *mp, int flags, |
|
Line 285 puffs_start(struct mount *mp, int flags, |
|
} |
} |
|
|
int |
int |
puffs_unmount(struct mount *mp, int mntflags, struct lwp *l) |
puffs_vfsop_unmount(struct mount *mp, int mntflags) |
{ |
{ |
PUFFS_MSG_VARS(vfs, unmount); |
PUFFS_MSG_VARS(vfs, unmount); |
struct puffs_mount *pmp; |
struct puffs_mount *pmp; |
Line 308 puffs_unmount(struct mount *mp, int mntf |
|
Line 320 puffs_unmount(struct mount *mp, int mntf |
|
mutex_exit(&pmp->pmp_lock); |
mutex_exit(&pmp->pmp_lock); |
|
|
PUFFS_MSG_ALLOC(vfs, unmount); |
PUFFS_MSG_ALLOC(vfs, unmount); |
|
puffs_msg_setinfo(park_unmount, |
|
PUFFSOP_VFS, PUFFS_VFS_UNMOUNT, NULL); |
unmount_msg->pvfsr_flags = mntflags; |
unmount_msg->pvfsr_flags = mntflags; |
puffs_cidcvt(&unmount_msg->pvfsr_cid, l); |
|
|
|
error = puffs_msg_vfs(pmp, park_unmount, PUFFS_VFS_UNMOUNT); |
PUFFS_MSG_ENQUEUEWAIT(pmp, park_unmount, error); |
PUFFS_MSG_RELEASE(unmount); |
PUFFS_MSG_RELEASE(unmount); |
|
|
error = checkerr(pmp, error, __func__); |
error = checkerr(pmp, error, __func__); |
Line 329 puffs_unmount(struct mount *mp, int mntf |
|
Line 342 puffs_unmount(struct mount *mp, int mntf |
|
if (error == 0 || force) { |
if (error == 0 || force) { |
/* tell waiters & other resources to go unwait themselves */ |
/* tell waiters & other resources to go unwait themselves */ |
puffs_userdead(pmp); |
puffs_userdead(pmp); |
puffs_nukebypmp(pmp); |
putter_detach(pmp->pmp_pi); |
|
|
/* |
/* |
* Wait until there are no more users for the mount resource. |
* Wait until there are no more users for the mount resource. |
Line 349 puffs_unmount(struct mount *mp, int mntf |
|
Line 362 puffs_unmount(struct mount *mp, int mntf |
|
cv_destroy(&pmp->pmp_msg_waiter_cv); |
cv_destroy(&pmp->pmp_msg_waiter_cv); |
mutex_destroy(&pmp->pmp_lock); |
mutex_destroy(&pmp->pmp_lock); |
|
|
free(pmp->pmp_pnodehash, M_PUFFS); |
fstrans_unmount(mp); |
FREE(pmp, M_PUFFS); |
kmem_free(pmp->pmp_pnodehash, BUCKETALLOC(pmp->pmp_npnodehash)); |
|
kmem_free(pmp, sizeof(struct puffs_mount)); |
error = 0; |
error = 0; |
} else { |
} else { |
mutex_exit(&pmp->pmp_lock); |
mutex_exit(&pmp->pmp_lock); |
Line 365 puffs_unmount(struct mount *mp, int mntf |
|
Line 379 puffs_unmount(struct mount *mp, int mntf |
|
* This doesn't need to travel to userspace |
* This doesn't need to travel to userspace |
*/ |
*/ |
int |
int |
puffs_root(struct mount *mp, struct vnode **vpp) |
puffs_vfsop_root(struct mount *mp, struct vnode **vpp) |
{ |
{ |
struct puffs_mount *pmp = MPTOPUFFSMP(mp); |
struct puffs_mount *pmp = MPTOPUFFSMP(mp); |
int rv; |
int rv; |
Line 376 puffs_root(struct mount *mp, struct vnod |
|
Line 390 puffs_root(struct mount *mp, struct vnod |
|
} |
} |
|
|
int |
int |
puffs_statvfs(struct mount *mp, struct statvfs *sbp, struct lwp *l) |
puffs_vfsop_statvfs(struct mount *mp, struct statvfs *sbp) |
{ |
{ |
PUFFS_MSG_VARS(vfs, statvfs); |
PUFFS_MSG_VARS(vfs, statvfs); |
struct puffs_mount *pmp; |
struct puffs_mount *pmp; |
Line 394 puffs_statvfs(struct mount *mp, struct s |
|
Line 408 puffs_statvfs(struct mount *mp, struct s |
|
return EINPROGRESS; |
return EINPROGRESS; |
|
|
PUFFS_MSG_ALLOC(vfs, statvfs); |
PUFFS_MSG_ALLOC(vfs, statvfs); |
puffs_cidcvt(&statvfs_msg->pvfsr_cid, l); |
puffs_msg_setinfo(park_statvfs, PUFFSOP_VFS, PUFFS_VFS_STATVFS, NULL); |
|
|
error = puffs_msg_vfs(pmp, park_statvfs, PUFFS_VFS_STATVFS); |
PUFFS_MSG_ENQUEUEWAIT(pmp, park_statvfs, error); |
error = checkerr(pmp, error, __func__); |
error = checkerr(pmp, error, __func__); |
statvfs_msg->pvfsr_sb.f_iosize = DEV_BSIZE; |
statvfs_msg->pvfsr_sb.f_iosize = DEV_BSIZE; |
|
|
Line 419 puffs_statvfs(struct mount *mp, struct s |
|
Line 433 puffs_statvfs(struct mount *mp, struct s |
|
} |
} |
|
|
static int |
static int |
pageflush(struct mount *mp, kauth_cred_t cred, |
pageflush(struct mount *mp, kauth_cred_t cred, int waitfor, int suspending) |
int waitfor, int suspending, struct lwp *l) |
|
{ |
{ |
struct puffs_node *pn; |
struct puffs_node *pn; |
struct vnode *vp, *nvp; |
struct vnode *vp, *mvp; |
int error, rv; |
int error, rv; |
|
|
KASSERT(((waitfor == MNT_WAIT) && suspending) == 0); |
KASSERT(((waitfor == MNT_WAIT) && suspending) == 0); |
Line 433 pageflush(struct mount *mp, kauth_cred_t |
|
Line 446 pageflush(struct mount *mp, kauth_cred_t |
|
|
|
error = 0; |
error = 0; |
|
|
|
/* Allocate a marker vnode. */ |
|
if ((mvp = vnalloc(mp)) == NULL) |
|
return ENOMEM; |
|
|
/* |
/* |
* Sync all cached data from regular vnodes (which are not |
* Sync all cached data from regular vnodes (which are not |
* currently locked, see below). After this we call VFS_SYNC |
* currently locked, see below). After this we call VFS_SYNC |
* for the fs server, which should handle data and metadata for |
* for the fs server, which should handle data and metadata for |
* all the nodes it knows to exist. |
* all the nodes it knows to exist. |
*/ |
*/ |
simple_lock(&mntvnode_slock); |
mutex_enter(&mntvnode_lock); |
loop: |
loop: |
for (vp = TAILQ_FIRST(&mp->mnt_vnodelist); vp; vp = nvp) { |
for (vp = TAILQ_FIRST(&mp->mnt_vnodelist); vp; vp = vunmark(mvp)) { |
/* check if we're on the right list */ |
vmark(mvp, vp); |
if (vp->v_mount != mp) |
if (vp->v_mount != mp || vismarker(vp)) |
goto loop; |
continue; |
|
|
simple_lock(&vp->v_interlock); |
mutex_enter(&vp->v_interlock); |
pn = VPTOPP(vp); |
pn = VPTOPP(vp); |
nvp = TAILQ_NEXT(vp, v_mntvnodes); |
|
|
|
if (vp->v_type != VREG || UVM_OBJ_IS_CLEAN(&vp->v_uobj)) { |
if (vp->v_type != VREG || UVM_OBJ_IS_CLEAN(&vp->v_uobj)) { |
simple_unlock(&vp->v_interlock); |
mutex_exit(&vp->v_interlock); |
continue; |
continue; |
} |
} |
|
|
simple_unlock(&mntvnode_slock); |
mutex_exit(&mntvnode_lock); |
|
|
/* |
/* |
* Here we try to get a reference to the vnode and to |
* Here we try to get a reference to the vnode and to |
Line 477 pageflush(struct mount *mp, kauth_cred_t |
|
Line 492 pageflush(struct mount *mp, kauth_cred_t |
|
*/ |
*/ |
rv = vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK); |
rv = vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK); |
if (rv) { |
if (rv) { |
simple_lock(&mntvnode_slock); |
mutex_enter(&mntvnode_lock); |
if (rv == ENOENT) |
if (rv == ENOENT) { |
|
(void)vunmark(mvp); |
goto loop; |
goto loop; |
|
} |
continue; |
continue; |
} |
} |
|
|
Line 505 pageflush(struct mount *mp, kauth_cred_t |
|
Line 522 pageflush(struct mount *mp, kauth_cred_t |
|
* TODO: Maybe also hint the user server of this twist? |
* TODO: Maybe also hint the user server of this twist? |
*/ |
*/ |
if (suspending || waitfor == MNT_LAZY) { |
if (suspending || waitfor == MNT_LAZY) { |
simple_lock(&vp->v_interlock); |
mutex_enter(&vp->v_interlock); |
pn->pn_stat |= PNODE_SUSPEND; |
pn->pn_stat |= PNODE_SUSPEND; |
simple_unlock(&vp->v_interlock); |
mutex_exit(&vp->v_interlock); |
} |
} |
rv = VOP_FSYNC(vp, cred, waitfor, 0, 0, l); |
rv = VOP_FSYNC(vp, cred, waitfor, 0, 0); |
if (suspending || waitfor == MNT_LAZY) { |
if (suspending || waitfor == MNT_LAZY) { |
simple_lock(&vp->v_interlock); |
mutex_enter(&vp->v_interlock); |
pn->pn_stat &= ~PNODE_SUSPEND; |
pn->pn_stat &= ~PNODE_SUSPEND; |
simple_unlock(&vp->v_interlock); |
mutex_exit(&vp->v_interlock); |
} |
} |
if (rv) |
if (rv) |
error = rv; |
error = rv; |
vput(vp); |
vput(vp); |
simple_lock(&mntvnode_slock); |
mutex_enter(&mntvnode_lock); |
} |
} |
simple_unlock(&mntvnode_slock); |
mutex_exit(&mntvnode_lock); |
|
vnfree(mvp); |
|
|
return error; |
return error; |
} |
} |
|
|
int |
int |
puffs_sync(struct mount *mp, int waitfor, struct kauth_cred *cred, |
puffs_vfsop_sync(struct mount *mp, int waitfor, struct kauth_cred *cred) |
struct lwp *l) |
|
{ |
{ |
PUFFS_MSG_VARS(vfs, sync); |
PUFFS_MSG_VARS(vfs, sync); |
struct puffs_mount *pmp = MPTOPUFFSMP(mp); |
struct puffs_mount *pmp = MPTOPUFFSMP(mp); |
int error, rv; |
int error, rv; |
|
|
error = pageflush(mp, cred, waitfor, 0, l); |
error = pageflush(mp, cred, waitfor, 0); |
|
|
/* sync fs */ |
/* sync fs */ |
PUFFS_MSG_ALLOC(vfs, sync); |
PUFFS_MSG_ALLOC(vfs, sync); |
sync_msg->pvfsr_waitfor = waitfor; |
sync_msg->pvfsr_waitfor = waitfor; |
puffs_credcvt(&sync_msg->pvfsr_cred, cred); |
puffs_credcvt(&sync_msg->pvfsr_cred, cred); |
puffs_cidcvt(&sync_msg->pvfsr_cid, l); |
puffs_msg_setinfo(park_sync, PUFFSOP_VFS, PUFFS_VFS_SYNC, NULL); |
|
|
rv = puffs_msg_vfs(pmp, park_sync, PUFFS_VFS_SYNC); |
PUFFS_MSG_ENQUEUEWAIT(pmp, park_sync, rv); |
rv = checkerr(pmp, rv, __func__); |
rv = checkerr(pmp, rv, __func__); |
if (rv) |
if (rv) |
error = rv; |
error = rv; |
Line 551 puffs_sync(struct mount *mp, int waitfor |
|
Line 568 puffs_sync(struct mount *mp, int waitfor |
|
} |
} |
|
|
int |
int |
puffs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp) |
puffs_vfsop_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp) |
{ |
{ |
PUFFS_MSG_VARS(vfs, fhtonode); |
PUFFS_MSG_VARS(vfs, fhtonode); |
struct puffs_mount *pmp = MPTOPUFFSMP(mp); |
struct puffs_mount *pmp = MPTOPUFFSMP(mp); |
Line 580 puffs_fhtovp(struct mount *mp, struct fi |
|
Line 597 puffs_fhtovp(struct mount *mp, struct fi |
|
} |
} |
|
|
argsize = sizeof(struct puffs_vfsmsg_fhtonode) + fhlen; |
argsize = sizeof(struct puffs_vfsmsg_fhtonode) + fhlen; |
puffs_msgmem_alloc(argsize, &park_fhtonode, (void **)&fhtonode_msg, 1); |
puffs_msgmem_alloc(argsize, &park_fhtonode, (void *)&fhtonode_msg, 1); |
fhtonode_msg->pvfsr_dsize = fhlen; |
fhtonode_msg->pvfsr_dsize = fhlen; |
memcpy(fhtonode_msg->pvfsr_data, fhdata, fhlen); |
memcpy(fhtonode_msg->pvfsr_data, fhdata, fhlen); |
|
puffs_msg_setinfo(park_fhtonode, PUFFSOP_VFS, PUFFS_VFS_FHTOVP, NULL); |
|
|
error = puffs_msg_vfs(pmp, park_fhtonode, PUFFS_VFS_FHTOVP); |
PUFFS_MSG_ENQUEUEWAIT(pmp, park_fhtonode, error); |
error = checkerr(pmp, error, __func__); |
error = checkerr(pmp, error, __func__); |
if (error) |
if (error) |
goto out; |
goto out; |
Line 610 puffs_fhtovp(struct mount *mp, struct fi |
|
Line 628 puffs_fhtovp(struct mount *mp, struct fi |
|
} |
} |
|
|
int |
int |
puffs_vptofh(struct vnode *vp, struct fid *fhp, size_t *fh_size) |
puffs_vfsop_vptofh(struct vnode *vp, struct fid *fhp, size_t *fh_size) |
{ |
{ |
PUFFS_MSG_VARS(vfs, nodetofh); |
PUFFS_MSG_VARS(vfs, nodetofh); |
struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); |
struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount); |
Line 634 puffs_vptofh(struct vnode *vp, struct fi |
|
Line 652 puffs_vptofh(struct vnode *vp, struct fi |
|
fhlen = PUFFS_FROMFHSIZE(*fh_size); |
fhlen = PUFFS_FROMFHSIZE(*fh_size); |
|
|
argsize = sizeof(struct puffs_vfsmsg_nodetofh) + fhlen; |
argsize = sizeof(struct puffs_vfsmsg_nodetofh) + fhlen; |
puffs_msgmem_alloc(argsize, &park_nodetofh, (void **)&nodetofh_msg, 1); |
puffs_msgmem_alloc(argsize, &park_nodetofh, (void *)&nodetofh_msg, 1); |
nodetofh_msg->pvfsr_fhcookie = VPTOPNC(vp); |
nodetofh_msg->pvfsr_fhcookie = VPTOPNC(vp); |
nodetofh_msg->pvfsr_dsize = fhlen; |
nodetofh_msg->pvfsr_dsize = fhlen; |
|
puffs_msg_setinfo(park_nodetofh, PUFFSOP_VFS, PUFFS_VFS_VPTOFH, NULL); |
|
|
error = puffs_msg_vfs(pmp, park_nodetofh, PUFFS_VFS_VPTOFH); |
PUFFS_MSG_ENQUEUEWAIT(pmp, park_nodetofh, error); |
error = checkerr(pmp, error, __func__); |
error = checkerr(pmp, error, __func__); |
|
|
if (pmp->pmp_args.pa_fhflags & PUFFS_FHFLAG_PASSTHROUGH) |
if (pmp->pmp_args.pa_fhflags & PUFFS_FHFLAG_PASSTHROUGH) |
Line 655 puffs_vptofh(struct vnode *vp, struct fi |
|
Line 674 puffs_vptofh(struct vnode *vp, struct fi |
|
} |
} |
|
|
if (fhlen > FHANDLE_SIZE_MAX) { |
if (fhlen > FHANDLE_SIZE_MAX) { |
puffs_msg_errnotify(pmp, PUFFS_ERR_VPTOFH, E2BIG, |
puffs_senderr(pmp, PUFFS_ERR_VPTOFH, E2BIG, |
"file handle too big", VPTOPNC(vp)); |
"file handle too big", VPTOPNC(vp)); |
error = EPROTO; |
error = EPROTO; |
goto out; |
goto out; |
Line 684 puffs_vptofh(struct vnode *vp, struct fi |
|
Line 703 puffs_vptofh(struct vnode *vp, struct fi |
|
} |
} |
|
|
void |
void |
puffs_init() |
puffs_vfsop_init() |
{ |
{ |
|
|
/* some checks depend on this */ |
/* some checks depend on this */ |
KASSERT(VNOVAL == VSIZENOTSET); |
KASSERT(VNOVAL == VSIZENOTSET); |
|
|
malloc_type_attach(M_PUFFS); |
|
|
|
pool_init(&puffs_pnpool, sizeof(struct puffs_node), 0, 0, 0, |
pool_init(&puffs_pnpool, sizeof(struct puffs_node), 0, 0, 0, |
"puffpnpl", &pool_allocator_nointr, IPL_NONE); |
"puffpnpl", &pool_allocator_nointr, IPL_NONE); |
puffs_transport_init(); |
|
puffs_msgif_init(); |
puffs_msgif_init(); |
} |
} |
|
|
void |
void |
puffs_done() |
puffs_vfsop_done() |
{ |
{ |
|
|
puffs_msgif_destroy(); |
puffs_msgif_destroy(); |
puffs_transport_destroy(); |
|
pool_destroy(&puffs_pnpool); |
pool_destroy(&puffs_pnpool); |
|
|
malloc_type_detach(M_PUFFS); |
|
} |
} |
|
|
int |
int |
puffs_snapshot(struct mount *mp, struct vnode *vp, struct timespec *ts) |
puffs_vfsop_snapshot(struct mount *mp, struct vnode *vp, struct timespec *ts) |
{ |
{ |
|
|
return EOPNOTSUPP; |
return EOPNOTSUPP; |
} |
} |
|
|
int |
int |
puffs_suspendctl(struct mount *mp, int cmd) |
puffs_vfsop_suspendctl(struct mount *mp, int cmd) |
{ |
{ |
PUFFS_MSG_VARS(vfs, suspend); |
PUFFS_MSG_VARS(vfs, suspend); |
struct puffs_mount *pmp; |
struct puffs_mount *pmp; |
Line 732 puffs_suspendctl(struct mount *mp, int c |
|
Line 745 puffs_suspendctl(struct mount *mp, int c |
|
PUFFS_MSG_ALLOC(vfs, suspend); |
PUFFS_MSG_ALLOC(vfs, suspend); |
puffs_msg_setfaf(park_suspend); |
puffs_msg_setfaf(park_suspend); |
suspend_msg->pvfsr_status = PUFFS_SUSPEND_START; |
suspend_msg->pvfsr_status = PUFFS_SUSPEND_START; |
puffs_msg_vfs(pmp, park_suspend, PUFFS_VFS_SUSPEND); |
puffs_msg_setinfo(park_suspend, PUFFSOP_VFS, |
|
PUFFS_VFS_SUSPEND, NULL); |
|
|
|
puffs_msg_enqueue(pmp, park_suspend); |
PUFFS_MSG_RELEASE(suspend); |
PUFFS_MSG_RELEASE(suspend); |
|
|
error = pageflush(mp, FSCRED, 0, 1, curlwp); |
error = pageflush(mp, FSCRED, 0, 1); |
if (error == 0) |
if (error == 0) |
error = fstrans_setstate(mp, FSTRANS_SUSPENDED); |
error = fstrans_setstate(mp, FSTRANS_SUSPENDED); |
|
|
Line 743 puffs_suspendctl(struct mount *mp, int c |
|
Line 759 puffs_suspendctl(struct mount *mp, int c |
|
PUFFS_MSG_ALLOC(vfs, suspend); |
PUFFS_MSG_ALLOC(vfs, suspend); |
puffs_msg_setfaf(park_suspend); |
puffs_msg_setfaf(park_suspend); |
suspend_msg->pvfsr_status = PUFFS_SUSPEND_ERROR; |
suspend_msg->pvfsr_status = PUFFS_SUSPEND_ERROR; |
puffs_msg_vfs(pmp, park_suspend, PUFFS_VFS_SUSPEND); |
puffs_msg_setinfo(park_suspend, PUFFSOP_VFS, |
|
PUFFS_VFS_SUSPEND, NULL); |
|
|
|
puffs_msg_enqueue(pmp, park_suspend); |
PUFFS_MSG_RELEASE(suspend); |
PUFFS_MSG_RELEASE(suspend); |
(void) fstrans_setstate(mp, FSTRANS_NORMAL); |
(void) fstrans_setstate(mp, FSTRANS_NORMAL); |
break; |
break; |
Line 752 puffs_suspendctl(struct mount *mp, int c |
|
Line 771 puffs_suspendctl(struct mount *mp, int c |
|
PUFFS_MSG_ALLOC(vfs, suspend); |
PUFFS_MSG_ALLOC(vfs, suspend); |
puffs_msg_setfaf(park_suspend); |
puffs_msg_setfaf(park_suspend); |
suspend_msg->pvfsr_status = PUFFS_SUSPEND_SUSPENDED; |
suspend_msg->pvfsr_status = PUFFS_SUSPEND_SUSPENDED; |
puffs_msg_vfs(pmp, park_suspend, PUFFS_VFS_SUSPEND); |
puffs_msg_setinfo(park_suspend, PUFFSOP_VFS, |
|
PUFFS_VFS_SUSPEND, NULL); |
|
|
|
puffs_msg_enqueue(pmp, park_suspend); |
PUFFS_MSG_RELEASE(suspend); |
PUFFS_MSG_RELEASE(suspend); |
|
|
break; |
break; |
Line 764 puffs_suspendctl(struct mount *mp, int c |
|
Line 786 puffs_suspendctl(struct mount *mp, int c |
|
PUFFS_MSG_ALLOC(vfs, suspend); |
PUFFS_MSG_ALLOC(vfs, suspend); |
puffs_msg_setfaf(park_suspend); |
puffs_msg_setfaf(park_suspend); |
suspend_msg->pvfsr_status = PUFFS_SUSPEND_RESUME; |
suspend_msg->pvfsr_status = PUFFS_SUSPEND_RESUME; |
puffs_msg_vfs(pmp, park_suspend, PUFFS_VFS_SUSPEND); |
puffs_msg_setinfo(park_suspend, PUFFSOP_VFS, |
|
PUFFS_VFS_SUSPEND, NULL); |
|
|
|
puffs_msg_enqueue(pmp, park_suspend); |
PUFFS_MSG_RELEASE(suspend); |
PUFFS_MSG_RELEASE(suspend); |
break; |
break; |
|
|
Line 788 const struct vnodeopv_desc * const puffs |
|
Line 813 const struct vnodeopv_desc * const puffs |
|
struct vfsops puffs_vfsops = { |
struct vfsops puffs_vfsops = { |
MOUNT_PUFFS, |
MOUNT_PUFFS, |
sizeof (struct puffs_kargs), |
sizeof (struct puffs_kargs), |
puffs_mount, /* mount */ |
puffs_vfsop_mount, /* mount */ |
puffs_start, /* start */ |
puffs_vfsop_start, /* start */ |
puffs_unmount, /* unmount */ |
puffs_vfsop_unmount, /* unmount */ |
puffs_root, /* root */ |
puffs_vfsop_root, /* root */ |
(void *)eopnotsupp, /* quotactl */ |
(void *)eopnotsupp, /* quotactl */ |
puffs_statvfs, /* statvfs */ |
puffs_vfsop_statvfs, /* statvfs */ |
puffs_sync, /* sync */ |
puffs_vfsop_sync, /* sync */ |
(void *)eopnotsupp, /* vget */ |
(void *)eopnotsupp, /* vget */ |
puffs_fhtovp, /* fhtovp */ |
puffs_vfsop_fhtovp, /* fhtovp */ |
puffs_vptofh, /* vptofh */ |
puffs_vfsop_vptofh, /* vptofh */ |
puffs_init, /* init */ |
puffs_vfsop_init, /* init */ |
NULL, /* reinit */ |
NULL, /* reinit */ |
puffs_done, /* done */ |
puffs_vfsop_done, /* done */ |
NULL, /* mountroot */ |
NULL, /* mountroot */ |
puffs_snapshot, /* snapshot */ |
puffs_vfsop_snapshot, /* snapshot */ |
vfs_stdextattrctl, /* extattrctl */ |
vfs_stdextattrctl, /* extattrctl */ |
puffs_suspendctl, /* suspendctl */ |
puffs_vfsop_suspendctl, /* suspendctl */ |
puffs_vnodeopv_descs, /* vnodeops */ |
genfs_renamelock_enter, |
0, /* refcount */ |
genfs_renamelock_exit, |
|
puffs_vnodeopv_descs, /* vnodeops */ |
|
0, /* refcount */ |
{ NULL, NULL } |
{ NULL, NULL } |
}; |
}; |
VFS_ATTACH(puffs_vfsops); |
VFS_ATTACH(puffs_vfsops); |