mirror of
https://git.openafs.org/openafs.git
synced 2025-01-19 07:20:11 +00:00
Solaris: prevent AFS umount while busy
Return EBUSY from unmount if someone still references stuff in AFS. This prevents kernel panics that can occur on shutdown if we umount while there is a file in AFS open. Normally a process can hold a file in AFS open, AFS is unmounted, and the file is closed, triggering our code which explodes if called after we're unmounted. This adds VFS_HOLD/VFS_RELE calls whenever we 'create' a vcache, or retire an old one, to keep track if anyone has an open reference to us. Change-Id: I95d8cf7e7e4d32a05bee97e06832a530b40af217 Reviewed-on: http://gerrit.openafs.org/1880 Reviewed-by: Derrick Brashear <shadow@dementia.org> Tested-by: Derrick Brashear <shadow@dementia.org>
This commit is contained in:
parent
34b7fd4a49
commit
fc8ab5cfd6
@ -56,7 +56,23 @@ local_osi_Time()
|
||||
#undef afs_osi_Alloc_NoSleep
|
||||
extern void *afs_osi_Alloc_NoSleep(size_t size);
|
||||
|
||||
#ifdef AFS_SUN58_ENV
|
||||
# define osi_vnhold(avc, r) do { \
|
||||
struct vnode *vp = AFSTOV(avc); \
|
||||
uint_t prevcount; \
|
||||
\
|
||||
mutex_enter(&vp->v_lock); \
|
||||
prevcount = vp->v_count++; \
|
||||
mutex_exit(&vp->v_lock); \
|
||||
\
|
||||
if (prevcount == 0) { \
|
||||
VFS_HOLD(afs_globalVFS); \
|
||||
} \
|
||||
} while(0)
|
||||
#else /* !AFS_SUN58_ENV */
|
||||
# define osi_vnhold(avc, r) do { VN_HOLD(AFSTOV(avc)); } while(0)
|
||||
#endif /* !AFS_SUN58_ENV */
|
||||
|
||||
#define gop_rdwr(rw,gp,base,len,offset,segflg,ioflag,ulimit,cr,aresid) \
|
||||
vn_rdwr((rw),(gp),(base),(len),(offset),(segflg),(ioflag),(ulimit),(cr),(aresid))
|
||||
#define gop_lookupname(fnamep,segflg,followlink,compvpp) \
|
||||
|
@ -67,4 +67,11 @@ osi_PostPopulateVCache(struct vcache *avc) {
|
||||
AFSTOV(avc)->v_op = afs_ops;
|
||||
AFSTOV(avc)->v_vfsp = afs_globalVFS;
|
||||
vSetType(avc, VREG);
|
||||
|
||||
#ifdef AFS_SUN58_ENV
|
||||
/* Normally we do this in osi_vnhold when we notice the ref count went from
|
||||
* 0 -> 1. But if we just setup or reused a vcache, we set the refcount to
|
||||
* 1 directly. So, we must explicitly VFS_HOLD here. */
|
||||
VFS_HOLD(afs_globalVFS);
|
||||
#endif
|
||||
}
|
||||
|
@ -96,6 +96,20 @@ afs_unmount(struct vfs *afsp, afs_ucred_t *credp)
|
||||
AFS_GUNLOCK();
|
||||
return ENOTSUP;
|
||||
}
|
||||
|
||||
/* We should have one reference from the caller, and one reference for the
|
||||
* root vnode; any more and someone is still referencing something */
|
||||
if (afsp->vfs_count > 2) {
|
||||
AFS_GUNLOCK();
|
||||
return EBUSY;
|
||||
}
|
||||
|
||||
/* The root vnode should have one ref for the mount; any more, and someone
|
||||
* else is using the root vnode */
|
||||
if (afs_globalVp && VREFCOUNT_GT(afs_globalVp, 1)) {
|
||||
AFS_GUNLOCK();
|
||||
return EBUSY;
|
||||
}
|
||||
#endif /* AFS_SUN58_ENV */
|
||||
|
||||
afs_globalVFS = 0;
|
||||
|
@ -1815,6 +1815,11 @@ afs_inactive(struct vcache *avc, afs_ucred_t *acred)
|
||||
avc->opens = avc->execsOrWriters = 0;
|
||||
|
||||
afs_InactiveVCache(avc, acred);
|
||||
|
||||
#ifdef AFS_SUN58_ENV
|
||||
VFS_RELE(afs_globalVFS);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user