version 1.24.2.1, 2007/03/29 19:27:55 |
version 1.25, 2007/03/20 10:21:59 |
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> |
|
|
struct pool puffs_pnpool; |
POOL_INIT(puffs_pnpool, sizeof(struct puffs_node), 0, 0, 0, "puffspnpl", |
|
&pool_allocator_nointr, IPL_NONE); |
|
|
#ifdef PUFFSDEBUG |
#ifdef PUFFSDEBUG |
int puffsdebug; |
int puffsdebug; |
Line 222 puffs_newnode(struct mount *mp, struct v |
|
Line 223 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. |
*/ |
*/ |
mutex_enter(&pmp->pmp_lock); |
simple_lock(&pmp->pmp_lock); |
if (cookie == pmp->pmp_rootcookie |
if (cookie == pmp->pmp_rootcookie |
|| puffs_cookie2pnode(pmp, cookie) != NULL) { |
|| puffs_cookie2pnode(pmp, cookie) != NULL) { |
mutex_exit(&pmp->pmp_lock); |
simple_unlock(&pmp->pmp_lock); |
error = EEXIST; |
error = EEXIST; |
return error; |
return error; |
} |
} |
mutex_exit(&pmp->pmp_lock); |
simple_unlock(&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 328 puffs_pnode2vnode(struct puffs_mount *pm |
|
Line 329 puffs_pnode2vnode(struct puffs_mount *pm |
|
if (lock) |
if (lock) |
vgetflags |= LK_EXCLUSIVE | LK_RETRY; |
vgetflags |= LK_EXCLUSIVE | LK_RETRY; |
|
|
mutex_enter(&pmp->pmp_lock); |
simple_lock(&pmp->pmp_lock); |
pnode = puffs_cookie2pnode(pmp, cookie); |
pnode = puffs_cookie2pnode(pmp, cookie); |
|
|
if (pnode == NULL) { |
if (pnode == NULL) { |
mutex_exit(&pmp->pmp_lock); |
simple_unlock(&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); |
mutex_exit(&pmp->pmp_lock); |
simple_unlock(&pmp->pmp_lock); |
|
|
if (vget(vp, vgetflags)) |
if (vget(vp, vgetflags)) |
return NULL; |
return NULL; |
Line 455 puffs_updatevpsize(struct vnode *vp) |
|
Line 456 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; |
|
} |