version 1.24, 2007/03/14 12:13:58 |
version 1.24.2.1, 2007/03/29 19:27:55 |
Line 51 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 51 __KERNEL_RCSID(0, "$NetBSD$"); |
|
#include <miscfs/genfs/genfs_node.h> |
#include <miscfs/genfs/genfs_node.h> |
#include <miscfs/specfs/specdev.h> |
#include <miscfs/specfs/specdev.h> |
|
|
POOL_INIT(puffs_pnpool, sizeof(struct puffs_node), 0, 0, 0, "puffspnpl", |
struct pool puffs_pnpool; |
&pool_allocator_nointr, IPL_NONE); |
|
|
|
#ifdef PUFFSDEBUG |
#ifdef PUFFSDEBUG |
int puffsdebug; |
int puffsdebug; |
Line 223 puffs_newnode(struct mount *mp, struct v |
|
Line 222 puffs_newnode(struct mount *mp, struct v |
|
* XXX: technically this error check should punish the fs, |
* XXX: technically this error check should punish the fs, |
* not the caller. |
* not the caller. |
*/ |
*/ |
simple_lock(&pmp->pmp_lock); |
mutex_enter(&pmp->pmp_lock); |
if (cookie == pmp->pmp_rootcookie |
if (cookie == pmp->pmp_rootcookie |
|| puffs_cookie2pnode(pmp, cookie) != NULL) { |
|| puffs_cookie2pnode(pmp, cookie) != NULL) { |
simple_unlock(&pmp->pmp_lock); |
mutex_exit(&pmp->pmp_lock); |
error = EEXIST; |
error = EEXIST; |
return error; |
return error; |
} |
} |
simple_unlock(&pmp->pmp_lock); |
mutex_exit(&pmp->pmp_lock); |
|
|
error = puffs_getvnode(dvp->v_mount, cookie, type, 0, rdev, &vp); |
error = puffs_getvnode(dvp->v_mount, cookie, type, 0, rdev, &vp); |
if (error) |
if (error) |
Line 329 puffs_pnode2vnode(struct puffs_mount *pm |
|
Line 328 puffs_pnode2vnode(struct puffs_mount *pm |
|
if (lock) |
if (lock) |
vgetflags |= LK_EXCLUSIVE | LK_RETRY; |
vgetflags |= LK_EXCLUSIVE | LK_RETRY; |
|
|
simple_lock(&pmp->pmp_lock); |
mutex_enter(&pmp->pmp_lock); |
pnode = puffs_cookie2pnode(pmp, cookie); |
pnode = puffs_cookie2pnode(pmp, cookie); |
|
|
if (pnode == NULL) { |
if (pnode == NULL) { |
simple_unlock(&pmp->pmp_lock); |
mutex_exit(&pmp->pmp_lock); |
return NULL; |
return NULL; |
} |
} |
vp = pnode->pn_vp; |
vp = pnode->pn_vp; |
|
|
simple_lock(&vp->v_interlock); |
simple_lock(&vp->v_interlock); |
simple_unlock(&pmp->pmp_lock); |
mutex_exit(&pmp->pmp_lock); |
|
|
if (vget(vp, vgetflags)) |
if (vget(vp, vgetflags)) |
return NULL; |
return NULL; |
Line 418 puffs_gop_markupdate(struct vnode *vp, i |
|
Line 417 puffs_gop_markupdate(struct vnode *vp, i |
|
void |
void |
puffs_updatenode(struct vnode *vp, int flags) |
puffs_updatenode(struct vnode *vp, int flags) |
{ |
{ |
|
struct puffs_node *pn; |
struct timespec ts; |
struct timespec ts; |
struct puffs_vnreq_setattr *setattr_arg; |
|
|
|
if (flags == 0) |
if (flags == 0) |
return; |
return; |
|
|
setattr_arg = malloc(sizeof(struct puffs_vnreq_setattr), M_PUFFS, |
pn = VPTOPP(vp); |
M_NOWAIT | M_ZERO); |
|
if (setattr_arg == NULL) |
|
return; /* 2bad */ |
|
|
|
nanotime(&ts); |
nanotime(&ts); |
|
|
VATTR_NULL(&setattr_arg->pvnr_va); |
if (flags & PUFFS_UPDATEATIME) { |
if (flags & PUFFS_UPDATEATIME) |
pn->pn_mc_atime = ts; |
setattr_arg->pvnr_va.va_atime = ts; |
pn->pn_stat |= PNODE_METACACHE_ATIME; |
if (flags & PUFFS_UPDATECTIME) |
} |
setattr_arg->pvnr_va.va_ctime = ts; |
if (flags & PUFFS_UPDATECTIME) { |
if (flags & PUFFS_UPDATEMTIME) |
pn->pn_mc_ctime = ts; |
setattr_arg->pvnr_va.va_mtime = ts; |
pn->pn_stat |= PNODE_METACACHE_CTIME; |
if (flags & PUFFS_UPDATESIZE) |
} |
setattr_arg->pvnr_va.va_size = vp->v_size; |
if (flags & PUFFS_UPDATEMTIME) { |
|
pn->pn_mc_mtime = ts; |
setattr_arg->pvnr_pid = 0; |
pn->pn_stat |= PNODE_METACACHE_MTIME; |
puffs_credcvt(&setattr_arg->pvnr_cred, NOCRED); |
} |
|
if (flags & PUFFS_UPDATESIZE) { |
/* setattr_arg ownership shifted to callee */ |
pn->pn_mc_size = vp->v_size; |
puffs_vntouser_faf(MPTOPUFFSMP(vp->v_mount), PUFFS_VN_SETATTR, |
pn->pn_stat |= PNODE_METACACHE_SIZE; |
setattr_arg, sizeof(struct puffs_vnreq_setattr), VPTOPNC(vp)); |
} |
} |
} |
|
|
void |
void |
Line 460 puffs_updatevpsize(struct vnode *vp) |
|
Line 455 puffs_updatevpsize(struct vnode *vp) |
|
if (va.va_size != VNOVAL) |
if (va.va_size != VNOVAL) |
vp->v_size = va.va_size; |
vp->v_size = va.va_size; |
} |
} |
|
|
/* |
|
* We're dead, kaput, RIP, slightly more than merely pining for the |
|
* fjords, belly-up, fallen, lifeless, finished, expired, gone to meet |
|
* our maker, ceased to be, etcetc. YASD. It's a dead FS! |
|
* |
|
* Caller must hold puffs spinlock. |
|
*/ |
|
void |
|
puffs_userdead(struct puffs_mount *pmp) |
|
{ |
|
struct puffs_park *park; |
|
struct buf *bp; |
|
|
|
/* |
|
* Mark filesystem status as dying so that operations don't |
|
* attempt to march to userspace any longer. |
|
*/ |
|
pmp->pmp_status = PUFFSTAT_DYING; |
|
|
|
/* and wakeup processes waiting for a reply from userspace */ |
|
TAILQ_FOREACH(park, &pmp->pmp_req_replywait, park_entries) { |
|
if (park->park_preq) |
|
park->park_preq->preq_rv = ENXIO; |
|
TAILQ_REMOVE(&pmp->pmp_req_replywait, park, park_entries); |
|
if (park->park_flags & PUFFS_PARKFLAG_ASYNCBIOREAD) { |
|
bp = park->park_bp; |
|
bp->b_error = ENXIO; |
|
bp->b_flags |= B_ERROR; |
|
biodone(bp); |
|
} else { |
|
wakeup(park); |
|
} |
|
} |
|
|
|
/* wakeup waiters for completion of vfs/vnode requests */ |
|
TAILQ_FOREACH(park, &pmp->pmp_req_touser, park_entries) { |
|
if (park->park_preq) |
|
park->park_preq->preq_rv = ENXIO; |
|
TAILQ_REMOVE(&pmp->pmp_req_touser, park, park_entries); |
|
if (park->park_flags & PUFFS_PARKFLAG_ASYNCBIOREAD) { |
|
bp = park->park_bp; |
|
bp->b_error = ENXIO; |
|
bp->b_flags |= B_ERROR; |
|
biodone(bp); |
|
} else { |
|
wakeup(park); |
|
} |
|
} |
|
} |
|
|
|
/* |
|
* Converts a non-FAF op to a FAF. This simply involves making copies |
|
* of the park and request structures and tagging the request as a FAF. |
|
* It is safe to block here, since the original op is not a FAF. |
|
*/ |
|
struct puffs_park * |
|
puffs_reqtofaf(struct puffs_park *ppark) |
|
{ |
|
struct puffs_park *newpark; |
|
struct puffs_req *newpreq; |
|
|
|
KASSERT((ppark->park_preq->preq_opclass & PUFFSOPFLAG_FAF) == 0); |
|
|
|
MALLOC(newpark, struct puffs_park *, sizeof(struct puffs_park), |
|
M_PUFFS, M_ZERO | M_WAITOK); |
|
MALLOC(newpreq, struct puffs_req *, sizeof(struct puffs_req), |
|
M_PUFFS, M_ZERO | M_WAITOK); |
|
|
|
memcpy(newpark, ppark, sizeof(struct puffs_park)); |
|
memcpy(newpreq, ppark->park_preq, sizeof(struct puffs_req)); |
|
|
|
newpark->park_preq = newpreq; |
|
newpark->park_preq->preq_opclass |= PUFFSOPFLAG_FAF; |
|
|
|
return newpark; |
|
} |
|