cleanup of vfs shutdown logic; makes clean unmounts easier (but
needs checking if fp_wd or fp_rd is NULL before use)
This commit is contained in:
parent
b7e23b70e8
commit
fd7ef243e4
8 changed files with 107 additions and 49 deletions
|
@ -10,8 +10,8 @@ EXTERN struct fproc {
|
||||||
|
|
||||||
mode_t fp_umask; /* mask set by umask system call */
|
mode_t fp_umask; /* mask set by umask system call */
|
||||||
|
|
||||||
struct vnode *fp_wd; /* working directory */
|
struct vnode *fp_wd; /* working directory; NULL during reboot */
|
||||||
struct vnode *fp_rd; /* root directory */
|
struct vnode *fp_rd; /* root directory; NULL during reboot */
|
||||||
|
|
||||||
struct filp *fp_filp[OPEN_MAX];/* the file descriptor table */
|
struct filp *fp_filp[OPEN_MAX];/* the file descriptor table */
|
||||||
|
|
||||||
|
|
|
@ -104,12 +104,12 @@ PUBLIC int main()
|
||||||
|
|
||||||
/* Check for special control messages first. */
|
/* Check for special control messages first. */
|
||||||
if ((call_nr & NOTIFY_MESSAGE)) {
|
if ((call_nr & NOTIFY_MESSAGE)) {
|
||||||
if (call_nr == PROC_EVENT)
|
if (call_nr == PROC_EVENT && who_e == PM_PROC_NR)
|
||||||
{
|
{
|
||||||
/* PM tries to get FS to do something */
|
/* PM tries to get FS to do something */
|
||||||
service_pm();
|
service_pm();
|
||||||
}
|
}
|
||||||
else if (call_nr == SYN_ALARM)
|
else if (call_nr == SYN_ALARM && who_e == CLOCK)
|
||||||
{
|
{
|
||||||
/* Alarm timer expired. Used only for select().
|
/* Alarm timer expired. Used only for select().
|
||||||
* Check it.
|
* Check it.
|
||||||
|
|
|
@ -298,6 +298,33 @@ PUBLIC int do_fsync()
|
||||||
return(OK);
|
return(OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void unmount_all(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int found = 0, worked = 0, remain = 0;
|
||||||
|
/* Unmount all filesystems. File systems are mounted on other file systems,
|
||||||
|
* so you have to pull off the loose bits repeatedly to get it all undone.
|
||||||
|
*/
|
||||||
|
for (i= 0; i < NR_SUPERS; i++) {
|
||||||
|
struct vmnt *vmp;
|
||||||
|
/* Unmount at least one. */
|
||||||
|
worked = remain = 0;
|
||||||
|
for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++) {
|
||||||
|
if (vmp->m_dev != NO_DEV) {
|
||||||
|
found++;
|
||||||
|
CHECK_VREFS;
|
||||||
|
if(unmount(vmp->m_dev) == OK)
|
||||||
|
worked++;
|
||||||
|
else
|
||||||
|
remain++;
|
||||||
|
CHECK_VREFS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("VFS: worked: %d remain: %d\n", worked, remain);
|
||||||
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* pm_reboot *
|
* pm_reboot *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
@ -305,7 +332,6 @@ PUBLIC void pm_reboot()
|
||||||
{
|
{
|
||||||
/* Perform the FS side of the reboot call. */
|
/* Perform the FS side of the reboot call. */
|
||||||
int i;
|
int i;
|
||||||
struct vmnt *vmp;
|
|
||||||
|
|
||||||
do_sync();
|
do_sync();
|
||||||
|
|
||||||
|
@ -316,27 +342,17 @@ PUBLIC void pm_reboot()
|
||||||
* will tell us about it).
|
* will tell us about it).
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < NR_PROCS; i++)
|
for (i = 0; i < NR_PROCS; i++)
|
||||||
if((m_in.endpt1 = fproc[i].fp_endpoint) != NONE)
|
if((m_in.endpt1 = fproc[i].fp_endpoint) != NONE) {
|
||||||
free_proc(&fproc[i], FP_EXITING);
|
/* No FP_EXITING, just free the resources, otherwise
|
||||||
|
* consistency check for fp_endpoint (set to NONE) will
|
||||||
|
* fail if process wants to do something in the (short)
|
||||||
|
* future.
|
||||||
|
*/
|
||||||
|
free_proc(&fproc[i], 0);
|
||||||
|
}
|
||||||
CHECK_VREFS;
|
CHECK_VREFS;
|
||||||
|
|
||||||
/* The root file system is mounted onto itself, which keeps it from being
|
unmount_all();
|
||||||
* unmounted. Pull an inode out of thin air and put the root on it.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Unmount all filesystems. File systems are mounted on other file systems,
|
|
||||||
* so you have to pull off the loose bits repeatedly to get it all undone.
|
|
||||||
*/
|
|
||||||
for (i= 0; i < NR_SUPERS; i++) {
|
|
||||||
/* Unmount at least one. */
|
|
||||||
for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++) {
|
|
||||||
if (vmp->m_dev != NO_DEV) {
|
|
||||||
CHECK_VREFS;
|
|
||||||
(void) unmount(vmp->m_dev);
|
|
||||||
CHECK_VREFS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CHECK_VREFS;
|
CHECK_VREFS;
|
||||||
|
|
||||||
|
@ -378,6 +394,7 @@ int cpid; /* Child process id */
|
||||||
/* Increase the counters in the 'filp' table. */
|
/* Increase the counters in the 'filp' table. */
|
||||||
cp = &fproc[childno];
|
cp = &fproc[childno];
|
||||||
fp = &fproc[parentno];
|
fp = &fproc[parentno];
|
||||||
|
|
||||||
for (i = 0; i < OPEN_MAX; i++)
|
for (i = 0; i < OPEN_MAX; i++)
|
||||||
if (cp->fp_filp[i] != NIL_FILP) cp->fp_filp[i]->filp_count++;
|
if (cp->fp_filp[i] != NIL_FILP) cp->fp_filp[i]->filp_count++;
|
||||||
|
|
||||||
|
@ -404,8 +421,8 @@ int cpid; /* Child process id */
|
||||||
cp->fp_execced = 0;
|
cp->fp_execced = 0;
|
||||||
|
|
||||||
/* Record the fact that both root and working dir have another user. */
|
/* Record the fact that both root and working dir have another user. */
|
||||||
dup_vnode(cp->fp_rd);
|
if(cp->fp_rd) dup_vnode(cp->fp_rd);
|
||||||
dup_vnode(cp->fp_wd);
|
if(cp->fp_wd) dup_vnode(cp->fp_wd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
|
@ -421,6 +438,10 @@ PRIVATE void free_proc(struct fproc *exiter, int flags)
|
||||||
|
|
||||||
fp = exiter; /* get_filp() needs 'fp' */
|
fp = exiter; /* get_filp() needs 'fp' */
|
||||||
|
|
||||||
|
if(fp->fp_endpoint == NONE) {
|
||||||
|
panic(__FILE__, "free_proc: already free", NO_NUM);
|
||||||
|
}
|
||||||
|
|
||||||
if (fp->fp_suspended == SUSPENDED) {
|
if (fp->fp_suspended == SUSPENDED) {
|
||||||
task = -fp->fp_task;
|
task = -fp->fp_task;
|
||||||
if (task == XPIPE || task == XPOPEN) susp_count--;
|
if (task == XPIPE || task == XPOPEN) susp_count--;
|
||||||
|
@ -433,12 +454,6 @@ PRIVATE void free_proc(struct fproc *exiter, int flags)
|
||||||
(void) close_fd(fp, i);
|
(void) close_fd(fp, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Release root and working directories. */
|
|
||||||
put_vnode(fp->fp_rd);
|
|
||||||
put_vnode(fp->fp_wd);
|
|
||||||
fp->fp_rd = NIL_VNODE;
|
|
||||||
fp->fp_wd = NIL_VNODE;
|
|
||||||
|
|
||||||
/* Check if any process is SUSPENDed on this driver.
|
/* Check if any process is SUSPENDed on this driver.
|
||||||
* If a driver exits, unmap its entries in the dmap table.
|
* If a driver exits, unmap its entries in the dmap table.
|
||||||
* (unmapping has to be done after the first step, because the
|
* (unmapping has to be done after the first step, because the
|
||||||
|
@ -446,6 +461,12 @@ PRIVATE void free_proc(struct fproc *exiter, int flags)
|
||||||
*/
|
*/
|
||||||
unsuspend_by_endpt(fp->fp_endpoint);
|
unsuspend_by_endpt(fp->fp_endpoint);
|
||||||
|
|
||||||
|
/* Release root and working directories. */
|
||||||
|
if(fp->fp_rd) { put_vnode(fp->fp_rd); fp->fp_rd = NIL_VNODE; }
|
||||||
|
if(fp->fp_wd) { put_vnode(fp->fp_wd); fp->fp_wd = NIL_VNODE; }
|
||||||
|
|
||||||
|
CHECK_VREFS;
|
||||||
|
|
||||||
/* The rest of these actions is only done when processes actually
|
/* The rest of these actions is only done when processes actually
|
||||||
* exit.
|
* exit.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -327,18 +327,14 @@ PRIVATE int mount_fs(endpoint_t fs_e)
|
||||||
if (tfp->fp_pid == PID_FREE)
|
if (tfp->fp_pid == PID_FREE)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (tfp->fp_rd == NULL)
|
#define MAKEROOT(what) { \
|
||||||
panic("fs", "do_mount: null rootdir", i);
|
put_vnode(what); \
|
||||||
if (tfp->fp_wd == NULL)
|
dup_vnode(root_node); \
|
||||||
panic("fs", "do_mount: null workdir", i);
|
what = root_node; \
|
||||||
|
}
|
||||||
|
|
||||||
put_vnode(tfp->fp_rd);
|
if(tfp->fp_rd) MAKEROOT(tfp->fp_rd);
|
||||||
dup_vnode(root_node);
|
if(tfp->fp_wd) MAKEROOT(tfp->fp_wd);
|
||||||
tfp->fp_rd = root_node;
|
|
||||||
|
|
||||||
put_vnode(tfp->fp_wd);
|
|
||||||
dup_vnode(root_node);
|
|
||||||
tfp->fp_wd = root_node;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CHECK_VREFS;
|
CHECK_VREFS;
|
||||||
|
@ -435,13 +431,11 @@ Dev_t dev;
|
||||||
for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; vp++) {
|
for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; vp++) {
|
||||||
if (vp->v_ref_count > 0 && vp->v_dev == dev) {
|
if (vp->v_ref_count > 0 && vp->v_dev == dev) {
|
||||||
|
|
||||||
#if 1
|
#if 0
|
||||||
int i;
|
int i;
|
||||||
struct fproc *tfp;
|
struct fproc *tfp;
|
||||||
if(!(vp->v_inode_nr == 1 && vp->v_ref_count == 1)) {
|
|
||||||
printf("unmount: vnode 0x%x/%d in use %d times\n",
|
printf("unmount: vnode 0x%x/%d in use %d times\n",
|
||||||
dev, vp->v_inode_nr, vp->v_ref_count);
|
dev, vp->v_inode_nr, vp->v_ref_count);
|
||||||
}
|
|
||||||
for (i= 0, tfp= fproc; i<NR_PROCS; i++, tfp++) {
|
for (i= 0, tfp= fproc; i<NR_PROCS; i++, tfp++) {
|
||||||
int n;
|
int n;
|
||||||
if (tfp->fp_pid == PID_FREE)
|
if (tfp->fp_pid == PID_FREE)
|
||||||
|
@ -465,7 +459,7 @@ Dev_t dev;
|
||||||
printf("\tvnode %d: is a mount point\n",
|
printf("\tvnode %d: is a mount point\n",
|
||||||
vp->v_inode_nr);
|
vp->v_inode_nr);
|
||||||
}
|
}
|
||||||
#if 0
|
#if 1
|
||||||
if(vmp_i->m_root_node == vp) {
|
if(vmp_i->m_root_node == vp) {
|
||||||
printf("\tvnode %d: is a root node\n",
|
printf("\tvnode %d: is a root node\n",
|
||||||
vp->v_inode_nr);
|
vp->v_inode_nr);
|
||||||
|
|
|
@ -251,6 +251,11 @@ int *created;
|
||||||
struct node_details res;
|
struct node_details res;
|
||||||
char lastc[PATH_MAX+1];
|
char lastc[PATH_MAX+1];
|
||||||
|
|
||||||
|
if(!fp->fp_rd || !fp->fp_wd) {
|
||||||
|
printf("VFS: %d: no rd/wd\n", fp->fp_endpoint);
|
||||||
|
return ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
start_vp = (user_fullpath[0] == '/' ? fp->fp_rd : fp->fp_wd);
|
start_vp = (user_fullpath[0] == '/' ? fp->fp_rd : fp->fp_wd);
|
||||||
dup_vnode(start_vp);
|
dup_vnode(start_vp);
|
||||||
|
|
||||||
|
|
|
@ -109,6 +109,11 @@ struct vnode **vpp;
|
||||||
*/
|
*/
|
||||||
struct vnode *vp;
|
struct vnode *vp;
|
||||||
|
|
||||||
|
if(!fp->fp_rd || !fp->fp_wd) {
|
||||||
|
printf("VFS: lookup_vp %d: no rd/wd\n", fp->fp_endpoint);
|
||||||
|
return ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
vp= (user_fullpath[0] == '/' ? fp->fp_rd : fp->fp_wd);
|
vp= (user_fullpath[0] == '/' ? fp->fp_rd : fp->fp_wd);
|
||||||
|
|
||||||
return lookup_rel_vp(vp, flags, use_realuid, vpp);
|
return lookup_rel_vp(vp, flags, use_realuid, vpp);
|
||||||
|
@ -207,6 +212,11 @@ struct vnode **vpp;
|
||||||
*/
|
*/
|
||||||
struct vnode *vp;
|
struct vnode *vp;
|
||||||
|
|
||||||
|
if(!fp->fp_rd || !fp->fp_wd) {
|
||||||
|
printf("VFS: lookup_lastdir %d: no rd/wd\n", fp->fp_endpoint);
|
||||||
|
return ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
vp= (user_fullpath[0] == '/' ? fp->fp_rd : fp->fp_wd);
|
vp= (user_fullpath[0] == '/' ? fp->fp_rd : fp->fp_wd);
|
||||||
return lookup_lastdir_rel(vp, use_realuid, vpp);
|
return lookup_lastdir_rel(vp, use_realuid, vpp);
|
||||||
}
|
}
|
||||||
|
@ -239,6 +249,11 @@ node_details_t *node;
|
||||||
return ENOENT;
|
return ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!fp->fp_rd || !fp->fp_wd) {
|
||||||
|
printf("VFS: lookup_rel %d: no rd/wd\n", fp->fp_endpoint);
|
||||||
|
return ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
fs_e = start_node->v_fs_e;
|
fs_e = start_node->v_fs_e;
|
||||||
path_off = 0;
|
path_off = 0;
|
||||||
dir_ino = start_node->v_inode_nr;
|
dir_ino = start_node->v_inode_nr;
|
||||||
|
|
|
@ -39,6 +39,12 @@ PUBLIC int do_fchdir()
|
||||||
struct filp *rfilp;
|
struct filp *rfilp;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
if(!fp->fp_wd || !fp->fp_rd) {
|
||||||
|
printf("VFS: do_fchdir: %d: no rd/wd\n",
|
||||||
|
fp->fp_endpoint);
|
||||||
|
return ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
/* Is the file descriptor valid? */
|
/* Is the file descriptor valid? */
|
||||||
if ( (rfilp = get_filp(m_in.fd)) == NIL_FILP) return(err_code);
|
if ( (rfilp = get_filp(m_in.fd)) == NIL_FILP) return(err_code);
|
||||||
|
|
||||||
|
@ -67,12 +73,23 @@ PUBLIC int do_chdir()
|
||||||
int r;
|
int r;
|
||||||
register struct fproc *rfp;
|
register struct fproc *rfp;
|
||||||
|
|
||||||
|
if(!fp->fp_wd || !fp->fp_rd) {
|
||||||
|
printf("VFS: do_chdir: %d: no rd/wd\n",
|
||||||
|
fp->fp_endpoint);
|
||||||
|
return ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
if (who_e == PM_PROC_NR) {
|
if (who_e == PM_PROC_NR) {
|
||||||
int slot;
|
int slot;
|
||||||
if(isokendpt(m_in.endpt1, &slot) != OK)
|
if(isokendpt(m_in.endpt1, &slot) != OK)
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
rfp = &fproc[slot];
|
rfp = &fproc[slot];
|
||||||
|
|
||||||
|
if(!rfp->fp_wd || !rfp->fp_rd) {
|
||||||
|
printf("VFS: do_chdir: %d: no other rd/wd\n", fp->fp_endpoint);
|
||||||
|
return ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
put_vnode(fp->fp_rd);
|
put_vnode(fp->fp_rd);
|
||||||
dup_vnode(fp->fp_rd = rfp->fp_rd);
|
dup_vnode(fp->fp_rd = rfp->fp_rd);
|
||||||
put_vnode(fp->fp_wd);
|
put_vnode(fp->fp_wd);
|
||||||
|
@ -107,6 +124,12 @@ PUBLIC int do_chroot()
|
||||||
|
|
||||||
if (!super_user) return(EPERM); /* only su may chroot() */
|
if (!super_user) return(EPERM); /* only su may chroot() */
|
||||||
|
|
||||||
|
if(!fp->fp_wd || !fp->fp_rd) {
|
||||||
|
printf("VFS: do_chroot: %d: no rd/wd\n",
|
||||||
|
fp->fp_endpoint);
|
||||||
|
return ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
r = change(&fp->fp_rd, m_in.name, m_in.name_length);
|
r = change(&fp->fp_rd, m_in.name, m_in.name_length);
|
||||||
return(r);
|
return(r);
|
||||||
}
|
}
|
||||||
|
|
|
@ -189,8 +189,8 @@ PUBLIC int check_vrefs()
|
||||||
for (rfp=&fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
|
for (rfp=&fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
|
||||||
if (rfp->fp_pid == PID_FREE)
|
if (rfp->fp_pid == PID_FREE)
|
||||||
continue;
|
continue;
|
||||||
REFVP(rfp->fp_rd);
|
if(rfp->fp_rd) REFVP(rfp->fp_rd);
|
||||||
REFVP(rfp->fp_wd);
|
if(rfp->fp_wd) REFVP(rfp->fp_wd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Count references from filedescriptors */
|
/* Count references from filedescriptors */
|
||||||
|
|
Loading…
Reference in a new issue