Subject: Re: race conditions in dounmount...
To: Bill Sommerfeld <sommerfeld@orchard.medford.ma.us>
From: Paul Kranenburg <pk@cs.few.eur.nl>
List: tech-kern
Date: 06/20/1996 00:29:33
> Suggested *rough* fix [there are probably some bugs here, ...]:
> 
> 0) don't clear MNT_UNMOUNT; leave it set until the mp is freed..
> 
> 1) add a mp->mnt_waiters field
> 
> 2) change vfs_busy to be roughly:
> 
> 	mp->mnt_waiters++;
> 	while (mp->mnt_flag & <lock bit>) {
> 		mp->mnt_flag |= <want bit>;
> 		tsleep(&mp->mnt_flag, ...)
> 	}
> 	mp->mnt_waiters--;
> 	if (mp->mnt_flag & MNT_UNMOUNT) {
> 		wakeup(&mp->mnt_waiters, ...)
> 		return 1;
> 	}
> 
> add add a vfs_unbusy_final() called by dounmount, which is roughly:
> 	
> 	vfs_unbusy(mp);
> 	while (mp->mnt_waiters > 0) {
> 		tsleep(&mp->mnt_waiters, ...);
> 	}

This arrangement can lead to deadlock if more than two processes are
simultaneously trying to unmount the filesystem (or use vfs_busy() for
something else). Also, when attempting to unmount and you find that an
unmount is already in progress, you probably just want to wait until
the unmount is done and then return `success' (rather than EBUSY).

I think the best way to this is to have a `holdcount' incremented (ala vnode's)
as soon as you get hold of an `mp' (say from `vp->v_mount') to diddle with.
If `mp' is removed from the `mounted filesystem list' it would be flagged
as `gone', but only actually free()'ed if its holdcount drops to zero
again (after any waiters have released it).

This seems to be all the more important in SMP systems.

-pk