* The nlookup code temporarily busies the target mount when diving a
mount point in cases where the base of the mount is not resolved
in the namecache.
* Fix a deadlock which can occur between the namecache structural lock
and the vfs_busy() on the mount structure by reordering the lock.
* Generally only occured if an attempt was made to unmount a filesystem
on which programs are still doing active operations (verses just
passively holding references to the filesystem). For example, a
umount on the target filesystem occuring while a cpdup using an
absolute path is running.
Reported-by: ftigeot
(mp = cache_findmount(&nch)) != NULL
) {
struct vnode *tdp;
+ int vfs_do_busy = 0;
+ /*
+ * VFS must be busied before the namecache entry is locked,
+ * but we don't want to waste time calling vfs_busy() if the
+ * mount point is already resolved.
+ */
+again:
cache_put(&nch);
+ if (vfs_do_busy) {
+ while (vfs_busy(mp, 0))
+ ;
+ }
cache_get(&mp->mnt_ncmountpt, &nch);
if (nch.ncp->nc_flag & NCF_UNRESOLVED) {
- while (vfs_busy(mp, 0))
- ;
+ if (vfs_do_busy == 0) {
+ vfs_do_busy = 1;
+ goto again;
+ }
error = VFS_ROOT(mp, &tdp);
vfs_unbusy(mp);
+ vfs_do_busy = 0;
if (error) {
cache_dropmount(mp);
break;
cache_setvp(&nch, tdp);
vput(tdp);
}
+ if (vfs_do_busy)
+ vfs_unbusy(mp);
cache_dropmount(mp);
}
if (error) {