Change the way unmounting happens to guarantee that the

client programs are allowed to finish up (coda_call is
forced to complete) and release their locks.  Thus there
is a reasonable chance that the vflush implicit in the
unmount will not get hung on held locks.
This commit is contained in:
rvb 1998-10-28 20:31:13 +00:00
parent ff30297a7a
commit dc7a9e560a
4 changed files with 122 additions and 42 deletions

View File

@ -27,7 +27,7 @@
* Mellon the rights to redistribute these changes without encumbrance.
*
* @(#) src/sys/coda/coda_psdev.c,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $
* $Id: coda_psdev.c,v 1.6 1998/09/28 20:52:58 rvb Exp $
* $Id: coda_psdev.c,v 1.7 1998/09/29 20:19:45 rvb Exp $
*
*/
@ -53,6 +53,11 @@
/*
* HISTORY
* $Log: coda_psdev.c,v $
* Revision 1.7 1998/09/29 20:19:45 rvb
* Fixes for lkm:
* 1. use VFS_LKM vs ACTUALLY_LKM_NOT_KERNEL
* 2. don't pass -DCODA to lkm build
*
* Revision 1.6 1998/09/28 20:52:58 rvb
* Cleanup and fix THE bug
*
@ -195,6 +200,13 @@ extern int coda_nc_initialized; /* Set if cache has been initialized */
#define CTL_C
int coda_psdev_print_entry = 0;
static
int outstanding_upcalls = 0;
int coda_call_sleep = PZERO - 1;
#ifdef CTL_C
int coda_pcatch = PCATCH;
#else
#endif
#define ENTRY if(coda_psdev_print_entry) myprintf(("Entered %s\n",__FUNCTION__))
@ -283,16 +295,17 @@ vc_nb_close (dev, flag, mode, p)
* Put this before WAKEUPs to avoid queuing new messages between
* the WAKEUP and the unmount (which can happen if we're unlucky)
*/
if (mi->mi_rootvp) {
/* Let unmount know this is for real */
VTOC(mi->mi_rootvp)->c_flags |= C_UNMOUNTING;
coda_unmounting(mi->mi_vfsp);
err = dounmount(mi->mi_vfsp, flag, p);
if (err)
myprintf(("Error %d unmounting vfs in vcclose(%d)\n",
err, minor(dev)));
if (!mi->mi_rootvp) {
/* just a simple open/close w no mount */
MARK_VC_CLOSED(vcp);
return 0;
}
/* Let unmount know this is for real */
VTOC(mi->mi_rootvp)->c_flags |= C_UNMOUNTING;
coda_unmounting(mi->mi_vfsp);
outstanding_upcalls = 0;
/* Wakeup clients so they can return. */
for (vmp = (struct vmsg *)GETNEXT(vcp->vc_requests);
!EOQ(vmp, vcp->vc_requests);
@ -305,18 +318,34 @@ vc_nb_close (dev, flag, mode, p)
CODA_FREE((caddr_t)vmp, (u_int)sizeof(struct vmsg));
continue;
}
outstanding_upcalls++;
wakeup(&vmp->vm_sleep);
}
for (vmp = (struct vmsg *)GETNEXT(vcp->vc_replys);
!EOQ(vmp, vcp->vc_replys);
vmp = (struct vmsg *)GETNEXT(vmp->vm_chain))
{
outstanding_upcalls++;
wakeup(&vmp->vm_sleep);
}
MARK_VC_CLOSED(vcp);
if (outstanding_upcalls) {
#ifdef CODA_VERBOSE
printf("presleep: outstanding_upcalls = %d\n", outstanding_upcalls);
(void) tsleep(&outstanding_upcalls, coda_call_sleep, "coda_umount", 0);
printf("postsleep: outstanding_upcalls = %d\n", outstanding_upcalls);
#else
(void) tsleep(&outstanding_upcalls, coda_call_sleep, "coda_umount", 0);
#endif
}
err = dounmount(mi->mi_vfsp, flag, p);
if (err)
myprintf(("Error %d unmounting vfs in vcclose(%d)\n",
err, minor(dev)));
return 0;
}
@ -554,12 +583,6 @@ struct coda_clstat coda_clstat;
* (e.g. kill -9).
*/
int coda_call_sleep = PZERO - 1;
#ifdef CTL_C
int coda_pcatch = PCATCH;
#else
#endif
int
coda_call(mntinfo, inSize, outSize, buffer)
struct coda_mntinfo *mntinfo; int inSize; int *outSize; caddr_t buffer;
@ -636,6 +659,11 @@ coda_call(mntinfo, inSize, outSize, buffer)
p->p_sigmask |= p->p_siglist;
#ifdef CODA_VERBOSE
printf("coda_call: tsleep returns %d SIGIO, cnt %d\n", error, i);
#endif
} else if (p->p_siglist == sigmask(SIGALRM)) {
p->p_sigmask |= p->p_siglist;
#ifdef CODA_VERBOSE
printf("coda_call: tsleep returns %d SIGALRM, cnt %d\n", error, i);
#endif
} else {
printf("coda_call: tsleep returns %d, cnt %d\n", error, i);
@ -650,7 +678,7 @@ coda_call(mntinfo, inSize, outSize, buffer)
p->p_siglist & ~p->p_sigmask);
#endif
}
} while (error && i++ < 128);
} while (error && i++ < 128 && VC_OPEN(vcp));
p->p_sigmask = psig_omask;
#else
(void) tsleep(&vmp->vm_sleep, coda_call_sleep, "coda_call", 0);
@ -724,6 +752,9 @@ coda_call(mntinfo, inSize, outSize, buffer)
CODA_FREE(vmp, sizeof(struct vmsg));
if (outstanding_upcalls > 0 && (--outstanding_upcalls == 0))
wakeup(&outstanding_upcalls);
if (!error)
error = ((struct coda_out_hdr *)buffer)->result;
return(error);

View File

@ -27,7 +27,7 @@
* Mellon the rights to redistribute these changes without encumbrance.
*
* @(#) src/sys/coda/coda_vnops.c,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $
* $Id: coda_vnops.c,v 1.6 1998/09/28 20:52:58 rvb Exp $
* $Id: coda_vnops.c,v 1.7 1998/10/25 17:44:41 phk Exp $
*
*/
@ -48,6 +48,10 @@
/*
* HISTORY
* $Log: coda_vnops.c,v $
* Revision 1.7 1998/10/25 17:44:41 phk
* Nitpicking and dusting performed on a train. Removes trivial warnings
* about unused variables, labels and other lint.
*
* Revision 1.6 1998/09/28 20:52:58 rvb
* Cleanup and fix THE bug
*
@ -527,7 +531,12 @@ coda_close(v)
printf("coda_close: destroying container ref %d, ufs vp %p of vp %p/cp %p\n",
vp->v_usecount, cp->c_ovp, vp, cp);
#endif
#ifdef hmm
vgone(cp->c_ovp);
#else
VOP_CLOSE(cp->c_ovp, flag, cred, p); /* Do errors matter here? */
vrele(cp->c_ovp);
#endif
} else {
#ifdef CODA_VERBOSE
printf("coda_close: NO container vp %p/cp %p\n", vp, cp);

View File

@ -27,7 +27,7 @@
* Mellon the rights to redistribute these changes without encumbrance.
*
* @(#) src/sys/coda/coda_psdev.c,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $
* $Id: coda_psdev.c,v 1.6 1998/09/28 20:52:58 rvb Exp $
* $Id: coda_psdev.c,v 1.7 1998/09/29 20:19:45 rvb Exp $
*
*/
@ -53,6 +53,11 @@
/*
* HISTORY
* $Log: coda_psdev.c,v $
* Revision 1.7 1998/09/29 20:19:45 rvb
* Fixes for lkm:
* 1. use VFS_LKM vs ACTUALLY_LKM_NOT_KERNEL
* 2. don't pass -DCODA to lkm build
*
* Revision 1.6 1998/09/28 20:52:58 rvb
* Cleanup and fix THE bug
*
@ -195,6 +200,13 @@ extern int coda_nc_initialized; /* Set if cache has been initialized */
#define CTL_C
int coda_psdev_print_entry = 0;
static
int outstanding_upcalls = 0;
int coda_call_sleep = PZERO - 1;
#ifdef CTL_C
int coda_pcatch = PCATCH;
#else
#endif
#define ENTRY if(coda_psdev_print_entry) myprintf(("Entered %s\n",__FUNCTION__))
@ -283,16 +295,17 @@ vc_nb_close (dev, flag, mode, p)
* Put this before WAKEUPs to avoid queuing new messages between
* the WAKEUP and the unmount (which can happen if we're unlucky)
*/
if (mi->mi_rootvp) {
/* Let unmount know this is for real */
VTOC(mi->mi_rootvp)->c_flags |= C_UNMOUNTING;
coda_unmounting(mi->mi_vfsp);
err = dounmount(mi->mi_vfsp, flag, p);
if (err)
myprintf(("Error %d unmounting vfs in vcclose(%d)\n",
err, minor(dev)));
if (!mi->mi_rootvp) {
/* just a simple open/close w no mount */
MARK_VC_CLOSED(vcp);
return 0;
}
/* Let unmount know this is for real */
VTOC(mi->mi_rootvp)->c_flags |= C_UNMOUNTING;
coda_unmounting(mi->mi_vfsp);
outstanding_upcalls = 0;
/* Wakeup clients so they can return. */
for (vmp = (struct vmsg *)GETNEXT(vcp->vc_requests);
!EOQ(vmp, vcp->vc_requests);
@ -305,18 +318,34 @@ vc_nb_close (dev, flag, mode, p)
CODA_FREE((caddr_t)vmp, (u_int)sizeof(struct vmsg));
continue;
}
outstanding_upcalls++;
wakeup(&vmp->vm_sleep);
}
for (vmp = (struct vmsg *)GETNEXT(vcp->vc_replys);
!EOQ(vmp, vcp->vc_replys);
vmp = (struct vmsg *)GETNEXT(vmp->vm_chain))
{
outstanding_upcalls++;
wakeup(&vmp->vm_sleep);
}
MARK_VC_CLOSED(vcp);
if (outstanding_upcalls) {
#ifdef CODA_VERBOSE
printf("presleep: outstanding_upcalls = %d\n", outstanding_upcalls);
(void) tsleep(&outstanding_upcalls, coda_call_sleep, "coda_umount", 0);
printf("postsleep: outstanding_upcalls = %d\n", outstanding_upcalls);
#else
(void) tsleep(&outstanding_upcalls, coda_call_sleep, "coda_umount", 0);
#endif
}
err = dounmount(mi->mi_vfsp, flag, p);
if (err)
myprintf(("Error %d unmounting vfs in vcclose(%d)\n",
err, minor(dev)));
return 0;
}
@ -554,12 +583,6 @@ struct coda_clstat coda_clstat;
* (e.g. kill -9).
*/
int coda_call_sleep = PZERO - 1;
#ifdef CTL_C
int coda_pcatch = PCATCH;
#else
#endif
int
coda_call(mntinfo, inSize, outSize, buffer)
struct coda_mntinfo *mntinfo; int inSize; int *outSize; caddr_t buffer;
@ -636,6 +659,11 @@ coda_call(mntinfo, inSize, outSize, buffer)
p->p_sigmask |= p->p_siglist;
#ifdef CODA_VERBOSE
printf("coda_call: tsleep returns %d SIGIO, cnt %d\n", error, i);
#endif
} else if (p->p_siglist == sigmask(SIGALRM)) {
p->p_sigmask |= p->p_siglist;
#ifdef CODA_VERBOSE
printf("coda_call: tsleep returns %d SIGALRM, cnt %d\n", error, i);
#endif
} else {
printf("coda_call: tsleep returns %d, cnt %d\n", error, i);
@ -650,7 +678,7 @@ coda_call(mntinfo, inSize, outSize, buffer)
p->p_siglist & ~p->p_sigmask);
#endif
}
} while (error && i++ < 128);
} while (error && i++ < 128 && VC_OPEN(vcp));
p->p_sigmask = psig_omask;
#else
(void) tsleep(&vmp->vm_sleep, coda_call_sleep, "coda_call", 0);
@ -724,6 +752,9 @@ coda_call(mntinfo, inSize, outSize, buffer)
CODA_FREE(vmp, sizeof(struct vmsg));
if (outstanding_upcalls > 0 && (--outstanding_upcalls == 0))
wakeup(&outstanding_upcalls);
if (!error)
error = ((struct coda_out_hdr *)buffer)->result;
return(error);

View File

@ -27,7 +27,7 @@
* Mellon the rights to redistribute these changes without encumbrance.
*
* @(#) src/sys/coda/coda_vnops.c,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $
* $Id: coda_vnops.c,v 1.6 1998/09/28 20:52:58 rvb Exp $
* $Id: coda_vnops.c,v 1.7 1998/10/25 17:44:41 phk Exp $
*
*/
@ -48,6 +48,10 @@
/*
* HISTORY
* $Log: coda_vnops.c,v $
* Revision 1.7 1998/10/25 17:44:41 phk
* Nitpicking and dusting performed on a train. Removes trivial warnings
* about unused variables, labels and other lint.
*
* Revision 1.6 1998/09/28 20:52:58 rvb
* Cleanup and fix THE bug
*
@ -527,7 +531,12 @@ coda_close(v)
printf("coda_close: destroying container ref %d, ufs vp %p of vp %p/cp %p\n",
vp->v_usecount, cp->c_ovp, vp, cp);
#endif
#ifdef hmm
vgone(cp->c_ovp);
#else
VOP_CLOSE(cp->c_ovp, flag, cred, p); /* Do errors matter here? */
vrele(cp->c_ovp);
#endif
} else {
#ifdef CODA_VERBOSE
printf("coda_close: NO container vp %p/cp %p\n", vp, cp);