extern void mvfs_linux_umount_begin( struct vfsmount * mnt, int flags ) #endif { VNODE_T *vp; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) || \ LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) struct vfsmount *mnt; #else /* * Since 2.6.18 and before 2.6.27 we have mnt as a parameter. * But we still need super_p. */ SUPER_T *super_p = mnt->mnt_sb; #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) int mount_count = 0; #endif ASSERT(super_p != NULL); ASSERT(super_p->s_root != NULL); vp = ITOV(super_p->s_root->d_inode); ASSERT(vp != NULL); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) || \ LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) mnt = VTOVFSMNT(vp); #else /* Check that the mountpoint passed in matches the one * from the vp that we are going to clear. Skip it otherwise. * We know from experience that this can happen when unmounting * loopback (bind) mounts. */ if (mnt != VTOVFSMNT(vp)) return; #endif /* Note that there is no mechanism for restoring the mount pointer * in the vnode if an error happens later on in the umount. This is * the only callback into the mvfs during umount. So far this has not * been a problem and if we don't do this here, the umount will never * succeed because the Linux code expects the mnt_count to be 2. * The count is 3 at this point from the initial allocation of the * vfsmnt structure, the path_lookup call in this umount call and * from when we placed the pointer in the vp. */ if (mnt == NULL) { MDKI_VFS_LOG(VFS_LOG_ERR, "%s: mnt is NULL\n", __FUNCTION__); return; } #if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) mount_count = MDKI_READ_MNT_COUNT(mnt); if (mount_count == 3) { MDKI_MNTPUT(mnt); SET_VTOVFSMNT(vp, NULL); } #else /* * may_umount returns !0 when the ref counter is 2 (and other conditions). * We took an extra ref, I'll drop it to test may_umount. If it is not * ready to be unmounted, the put is reverted. */ MDKI_MNTPUT(mnt); if (may_umount(mnt)) { SET_VTOVFSMNT(vp, NULL); } else { /* not ready yet */ MDKI_MNTGET(mnt); } #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) */ }
extern void mvfs_linux_umount_begin( struct vfsmount * mnt, int flags ) #endif { VNODE_T *vp; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) || \ LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) struct vfsmount *mnt; #else /* * Since 2.6.18 and before 2.6.27 we have mnt as a parameter. * But we still need super_p. */ SUPER_T *super_p = mnt->mnt_sb; #endif int mount_count = 0; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) && defined(CONFIG_SMP) int cpu; #endif ASSERT(super_p != NULL); ASSERT(super_p->s_root != NULL); vp = ITOV(super_p->s_root->d_inode); ASSERT(vp != NULL); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) || \ LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) mnt = VTOVFSMNT(vp); #else /* Check that the mountpoint passed in matches the one * from the vp that we are going to clear. Skip it otherwise. * We know from experience that this can happen when unmounting * loopback (bind) mounts. */ if (mnt != VTOVFSMNT(vp)) return; #endif /* Note that there is no mechanism for restoring the mount pointer * in the vnode if an error happens later on in the umount. This is * the only callback into the mvfs during umount. So far this has not * been a problem and if we don't do this here, the umount will never * succeed because the Linux code expects the mnt_count to be 2. * The count is 3 at this point from the initial allocation of the * vfsmnt structure, the path_lookup call in this umount call and * from when we placed the pointer in the vp. */ if (mnt == NULL) { MDKI_VFS_LOG(VFS_LOG_ERR, "%s: mnt is NULL\n", __FUNCTION__); return; } #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38) mount_count = atomic_read(&mnt->mnt_count); #else # ifdef CONFIG_SMP br_read_lock(vfsmount_lock); for_each_possible_cpu(cpu) { mount_count += per_cpu_ptr(mnt->mnt_pcp, cpu)->mnt_count; } br_read_unlock(vfsmount_lock); # else /* CONFIG_SMP */ mount_count = mnt->mnt_count; # endif /* else CONFIG_SMP */ #endif /* else < KERNEL_VERSION(2,6,38) */ if (mount_count == 3) { MDKI_MNTPUT(mnt); SET_VTOVFSMNT(vp, NULL); } }