1
0
Files
irix-657m-src/irix/kern/fs/procfs/pr_relocation.c
2022-09-29 17:59:04 +03:00

463 lines
11 KiB
C

/**************************************************************************
* *
* Copyright (C) 1995-1997 Silicon Graphics, Inc. *
* *
* These coded instructions, statements, and computer programs contain *
* unpublished proprietary information of Silicon Graphics, Inc., and *
* are protected by Federal copyright law. They may not be disclosed *
* to third parties or copied or duplicated in any form, in whole or *
* in part, without the prior written consent of Silicon Graphics, Inc. *
* *
**************************************************************************/
#ident "$Id: pr_relocation.c,v 1.8 1997/12/19 21:27:15 beck Exp $"
#include "pr_relocation.h"
#include "procfs_private.h"
#include "os/proc/cell/pproc_migrate.h"
extern void phfree(struct pollhead *);
/*
* prnode relocation
*
* Some explanation is deserved because a number of (callout) routines
* are involved here (in time-ordered calling sequence):
* prnode_proc_emigrate_start
* is called by the pproc relocation code during the
* source_prepare step to commence relocation on any procfs
* vnodes associated with a migrating process. It is
* responsible for adding any such to the object manifest.
* prnode_proc_immigrate_start
* is called by the pproc relocation code during the
* target_prepare step to read descriptions of any procfs
* vnodes from the object manifest and create embryonic
* vnode servers.
* prnode_proc_emigrate
* is called by the pproc relocation code during the
* source_bag step to package any physical prnodes.
* prnode_bhv_source_bag
* is called from the cfs behavior relocation code (itself
* called by KORE) to package a physical prnode.
* In fact, there'e nothing to do because the prnode
* is owned by the proc and has been bagged already.
* prnode_proc_immigrate
* is called by the pproc relocation code during the
* traget_unbag step to instantiate any target prnode.
* prnode_bhv_target_unbag
* is called from the cfs behavior relocation code to
* instantiate the target prnode. Again, there's nothing to do.
* prnode_proc_emigrate_end
* is called by the pproc relocation code during the
* source_end step. The destruction of any prnodes
* is deffered until ...
* prnode_bhv_source_end
* is called from the cfs behavior relocation code to
* destroy a source prnode.
* prnode_bhv_{source,target}_abort
* are called in failure cases - XXX to panic.
*/
/*
* Internal utility routines:
****************************
*/
/*
* Count the number of linked prnodes.
*/
PRIVATE int
prnode_list_count(
prnode_t *pnp)
{
int i;
/*
* While counting, take an additional vnode reference.
*/
for (i = 0; pnp != NULL; pnp = pnp->pr_next, i++)
VN_HOLD(pnp->pr_vnode);
return i;
}
/*
* Put into manifest vnodes associated with linked prnodes.
*/
PRIVATE void
prnode_list_mft_put(
obj_manifest_t *mftp,
prnode_t **pnpp)
{
prnode_t *pnp = *pnpp;
int error;
/*
* Call KORE to relocate each vnode.
* Note that once an object is registered with KORE, the source_bag
* and source_end callouts will be made at the appropriate time.
* In the case of prnodes, however, there's little or nothing
* to do because prnodes are relocated along with the proc.
*/
while (pnp != NULL) {
error = obj_mft_put(mftp, (void *) pnp->pr_vnode,
SVC_CFS, OBJ_RMODE_SERVER);
ASSERT_NONZERO(error);
pnp = pnp->pr_next;
}
}
/*
* Get from manifest a given number of vnodes and relink prnodes.
*/
PRIVATE void
prnode_list_mft_get(
obj_manifest_t *mftp,
#ifdef PRCLEAR
proc_t *p,
#endif
prnode_t **pnpp,
int npn)
{
int i;
int error;
prnode_t *pnp;
vnode_t *vp;
bhv_desc_t *bdp;
/*
* Call KORE to instantiate the embryonic vnodes and plug them
* into the appropriate embryonic proc object hierarchy.
* Note that once registered with KORE, it will make the target_unbag
* callout at the appropriate time.
*/
for (i = npn; i > 0; i--) {
error = obj_mft_get(mftp, (void **) &vp);
ASSERT_NONZERO(error);
pnp = prnode_alloc();
*pnpp = pnp;
pnpp = &pnp->pr_next;
pnp->pr_vnode = vp;
#ifdef PRCLEAR
pnp->pr_listproc = p;
#endif
/*
* Insert the embryonic prnode behavior into vnode bhv chain.
*/
bdp = PRNODETOBHV(pnp);
bhv_desc_init(bdp, pnp, vp, &prvnodeops);
(void) vn_bhv_insert(VN_BHV_HEAD(vp), bdp);
}
}
/*
* Stuff details of prnodes in list into a bag.
*/
PRIVATE void
prnode_list_bag(
obj_bag_t bag,
prnode_t **pnpp)
{
prnode_t *pnp = *pnpp;
prnode_bag_t prnode_bag;
int error;
while (pnp != NULL) {
prnode_bag.pr_tpid = pnp->pr_tpid;
prnode_bag.pr_type = pnp->pr_type;
prnode_bag.pr_mode = pnp->pr_mode;
prnode_bag.pr_opens = pnp->pr_opens;
prnode_bag.pr_writers = pnp->pr_writers;
prnode_bag.pr_pflags = pnp->pr_pflags;
error = obj_bag_put(bag, OBJ_TAG_CFS_PRNODE,
(void *) &prnode_bag, sizeof(prnode_bag_t));
ASSERT_NONZERO(error);
pnp = pnp->pr_next;
}
}
/*
* Instantiate prnodes in a list with details from a bag.
*/
PRIVATE void
prnode_list_unbag(
obj_bag_t bag,
prnode_t **pnpp)
{
prnode_t *pnp = *pnpp;
prnode_bag_t prnode_bag;
int error;
while (pnp != NULL) {
/*
* Extract the expected data item from the bag.
*/
obj_bag_get_here(bag, OBJ_TAG_CFS_PRNODE,
&prnode_bag, sizeof(prnode_bag_t), error);
ASSERT_NONZERO(error);
pnp->pr_proc = NULL;
pnp->pr_pollhead = NULL; /* polls restart */
pnp->pr_tpid = prnode_bag.pr_tpid;
pnp->pr_type = prnode_bag.pr_type;
pnp->pr_mode = prnode_bag.pr_mode;
pnp->pr_opens = prnode_bag.pr_opens;
pnp->pr_writers = prnode_bag.pr_writers;
pnp->pr_pflags = prnode_bag.pr_pflags;
pnp = pnp->pr_next;
}
}
/*
* Hooks called from proc migration to deal with any attached prnodes.
*********************************************************************
*/
int
prnode_proc_emigrate_start(
proc_t *p, /* IN proc */
obj_manifest_t *mftp) /* IN/OUT object manifest */
{
prnode_info_t prnode_info;
int error;
int spl;
spl = p_lock(p);
/*
* Determine what procfs vnodes we have attached to the
* the migrating process. Put a summary item in the manifest.
* This summary is a count of the prnodes - valid and invalid.
*/
prnode_info.ntrace = prnode_list_count(p->p_trace);
prnode_info.npstrace = prnode_list_count(p->p_pstrace);
error = obj_bag_put(obj_mft_src_info(mftp), OBJ_TAG_CFS_PRNODE_INFO,
(void *) &prnode_info, sizeof(prnode_info));
ASSERT_NONZERO(error);
/*
* Put prnode/vnode lists into object manifest.
*/
prnode_list_mft_put(mftp, &p->p_trace);
prnode_list_mft_put(mftp, &p->p_pstrace);
p_unlock(p, spl);
return 0;
}
int
prnode_proc_immigrate_start(
proc_t *p, /* IN proc */
obj_manifest_t *mftp) /* IN object manifest */
{
prnode_info_t prnode_info;
int error;
/*
* Fetch the item from the manifest summarizing what, if any,
* procfs vnode are to be relocated.
*/
obj_bag_get_here(obj_mft_src_info(mftp), OBJ_TAG_CFS_PRNODE_INFO,
(void *) &prnode_info, sizeof(prnode_info), error);
ASSERT_NONZERO(error);
/*
* Re-create lists of embryonic prnodes/vnodes.
* No locking deemed necssary at this point.
*/
#ifdef PRCLEAR
prnode_list_mft_get(mftp, p, &p->p_trace, prnode_info.ntrace);
prnode_list_mft_get(mftp, p, &p->p_pstrace, prnode_info.npstrace);
#else
prnode_list_mft_get(mftp, &p->p_trace, prnode_info.ntrace);
prnode_list_mft_get(mftp, &p->p_pstrace, prnode_info.npstrace);
#endif
return 0;
}
void
prnode_proc_emigrate(
proc_t *p, /* IN proc */
obj_bag_t bag) /* IN object bag */
{
int spl;
spl = p_lock(p); /* XXX - necessary? */
/*
* Package up prnodes.
*/
prnode_list_bag(bag, &p->p_trace);
prnode_list_bag(bag, &p->p_pstrace);
p_unlock(p, spl);
}
void
prnode_proc_immigrate(
proc_t *p, /* IN proc */
obj_bag_t bag) /* IN object bag */
{
/*
* Unpackage prnodes.
*/
prnode_list_unbag(bag, &p->p_trace);
prnode_list_unbag(bag, &p->p_pstrace);
}
void
prnode_proc_emigrate_end(
proc_t *p) /* IN proc */
{
p->p_trace = NULL;
p->p_pstrace = NULL;
/* We leave it to the cfs bhv callout to destroy the prnodes. */
return;
}
/*
* Callout routines invoked from CFS behavior-dependent code.
************************************************************
*/
/*
* Package up a prnode.
* This has mostly been done by the proc bagging.
*/
/* ARGSUSED */
int
prnode_bhv_source_bag(
bhv_desc_t *bdp, /* IN bhv descriptor */
obj_bag_t bag) /* IN object bag */
{
prnode_t *pnp;
struct pollhead *php;
ASSERT(BHV_IDENTITY(bdp)->bi_id == VN_BHV_PR);
ASSERT(BHV_IDENTITY(bdp)->bi_position == VNODE_POSITION_BASE);
DVN_KTRACE4(DVN_TRACE_RELOCATE, "prnode_bhv_source_bag",
BHV_TO_VNODE(bdp), "bhv", bdp);
pnp = BHVTOPRNODE(bdp);
/*
* Check for pending poll/selects on this prnode.
* If so, we must wakeup all interested threads and cause them to
* delete their polldata entries from this pollhead.
* These threads will retry their VOP_POLL and be sent to the target
* cell where they will block till we're done.
*/
php = pnp->pr_pollhead;
if (php != NULL) {
/*
* Restart polls and wait for poll list to emptied.
*/
pollrestart(php);
while (php->ph_list != NULL) {
delay(1);
}
ASSERT(!php->ph_next);
phfree(php);
pnp->pr_pollhead = NULL;
}
return 0;
}
/*
* Unbag and re-instantiate a prnode for given vnode from given bag
* ... but this was done early by the owning proc.
*/
/* ARGSUSED */
int
prnode_bhv_target_unbag(
vnode_t *vp, /* IN vnode */
obj_bag_t bag) /* IN object bag */
{
DVN_KTRACE2(DVN_TRACE_RELOCATE, "prnode_bhv_target_unbag", vp);
return 0;
}
/*
* Relocation complete for a prnode - destroy it.
* We don't bother about neatly removing from the prnode list
* rooted in the proc since the proc exists no longer.
* Nor do we remove the prnode from the behavior chain since
* it is no longer attached to the vnode.
*/
int
prnode_bhv_source_end(
bhv_desc_t *bdp) /* IN bhv descriptor */
{
prnode_t *pnp;
vnode_t *vp;
ASSERT(BHV_IDENTITY(bdp)->bi_id == VN_BHV_PR);
ASSERT(BHV_IDENTITY(bdp)->bi_position == VNODE_POSITION_BASE);
vp = BHV_TO_VNODE(bdp);
DVN_KTRACE4(DVN_TRACE_RELOCATE, "prnode_bhv_source_end", vp,
"bhv", bdp);
pnp = BHVTOPRNODE(bdp);
ASSERT(pnp->pr_pollhead == NULL);
pnp->pr_next = NULL;
#ifdef PRCLEAR
pnp->pr_listproc = NULL;
#endif
prnode_free(pnp);
VN_RELE(vp); /* hold taken in source prepare */
return 0;
}
/*
* Relocation of given behavior failed - fix it up.
*/
int
prnode_bhv_source_abort(
bhv_desc_t *bdp) /* IN bhv descriptor */
{
panic("prnode_bhv_source_abort: bdp 0x%x", bdp);
/* NOTREACHED */
}
/*
* Relocation of given behavior failed - destroy it.
*/
int
prnode_bhv_target_abort(
bhv_desc_t *bdp) /* IN bhv descriptor */
{
panic("prnode_bhv_target_abort: bdp 0x%x", bdp);
/* NOTREACHED */
}
/*
* Callout table exported to cfs_relocation.
*/
cfs_vn_kore_if_t prnode_obj_bhv_iface = {
prnode_bhv_source_bag,
prnode_bhv_target_unbag,
prnode_bhv_source_end,
prnode_bhv_source_abort,
prnode_bhv_target_abort
};