static int ntfs_unmount(struct mount *mp, int mntflags) { struct ntfsmount *ntmp; int error, ronly, flags, i; dprintf(("ntfs_unmount: unmounting...\n")); ntmp = VFSTONTFS(mp); ronly = (mp->mnt_flag & MNT_RDONLY) != 0; flags = 0; if(mntflags & MNT_FORCE) flags |= FORCECLOSE; dprintf(("ntfs_unmount: vflushing...\n")); error = vflush(mp, 0, flags | SKIPSYSTEM); if (error) { kprintf("ntfs_unmount: vflush failed: %d\n",error); return (error); } /* Check if only system vnodes are left */ for(i=0;i<NTFS_SYSNODESNUM;i++) if((ntmp->ntm_sysvn[i]) && (VREFCNT(ntmp->ntm_sysvn[i]) > 1)) return (EBUSY); /* Dereference all system vnodes */ for(i=0;i<NTFS_SYSNODESNUM;i++) if(ntmp->ntm_sysvn[i]) vrele(ntmp->ntm_sysvn[i]); /* vflush system vnodes */ error = vflush(mp, 0, flags); if (error) kprintf("ntfs_unmount: vflush failed(sysnodes): %d\n",error); /* Check if the type of device node isn't VBAD before * touching v_cdevinfo. If the device vnode is revoked, the * field is NULL and touching it causes null pointer derefercence. */ if (ntmp->ntm_devvp->v_type != VBAD) ntmp->ntm_devvp->v_rdev->si_mountpoint = NULL; vn_lock(ntmp->ntm_devvp, LK_EXCLUSIVE | LK_RETRY); vinvalbuf(ntmp->ntm_devvp, V_SAVE, 0, 0); error = VOP_CLOSE(ntmp->ntm_devvp, ronly ? FREAD : FREAD|FWRITE, NULL); vn_unlock(ntmp->ntm_devvp); vrele(ntmp->ntm_devvp); /* free the toupper table, if this has been last mounted ntfs volume */ ntfs_toupper_unuse(); dprintf(("ntfs_umount: freeing memory...\n")); ntfs_u28_uninit(ntmp); ntfs_82u_uninit(ntmp); mp->mnt_data = (qaddr_t)0; mp->mnt_flag &= ~MNT_LOCAL; kfree(ntmp->ntm_ad, M_NTFSMNT); kfree(ntmp, M_NTFSMNT); return (error); }
static int ntfs_unmount( struct mount *mp, int mntflags) { struct lwp *l = curlwp; struct ntfsmount *ntmp; int error, ronly = 0, flags, i; dprintf(("ntfs_unmount: unmounting...\n")); ntmp = VFSTONTFS(mp); flags = 0; if(mntflags & MNT_FORCE) flags |= FORCECLOSE; dprintf(("ntfs_unmount: vflushing...\n")); error = vflush(mp,NULLVP,flags | SKIPSYSTEM); if (error) { dprintf(("ntfs_unmount: vflush failed: %d\n",error)); return (error); } /* Check if only system vnodes are rest */ for(i=0;i<NTFS_SYSNODESNUM;i++) if((ntmp->ntm_sysvn[i]) && (ntmp->ntm_sysvn[i]->v_usecount > 1)) return (EBUSY); /* Dereference all system vnodes */ for(i=0;i<NTFS_SYSNODESNUM;i++) if(ntmp->ntm_sysvn[i]) vrele(ntmp->ntm_sysvn[i]); /* vflush system vnodes */ error = vflush(mp,NULLVP,flags); if (error) { panic("ntfs_unmount: vflush failed(sysnodes): %d\n",error); } /* Check if the type of device node isn't VBAD before * touching v_specinfo. If the device vnode is revoked, the * field is NULL and touching it causes null pointer derefercence. */ if (ntmp->ntm_devvp->v_type != VBAD) spec_node_setmountedfs(ntmp->ntm_devvp, NULL); error = vinvalbuf(ntmp->ntm_devvp, V_SAVE, NOCRED, l, 0, 0); KASSERT(error == 0); /* lock the device vnode before calling VOP_CLOSE() */ vn_lock(ntmp->ntm_devvp, LK_EXCLUSIVE | LK_RETRY); error = VOP_CLOSE(ntmp->ntm_devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED); KASSERT(error == 0); VOP_UNLOCK(ntmp->ntm_devvp); vrele(ntmp->ntm_devvp); /* free the toupper table, if this has been last mounted ntfs volume */ ntfs_toupper_unuse(); dprintf(("ntfs_umount: freeing memory...\n")); mp->mnt_data = NULL; mp->mnt_flag &= ~MNT_LOCAL; free(ntmp->ntm_ad, M_NTFSMNT); free(ntmp, M_NTFSMNT); return (0); }