Changeset View
Changeset View
Standalone View
Standalone View
sys/fs/msdosfs/msdosfs_vfsops.c
Show First 20 Lines • Show All 242 Lines • ▼ Show 20 Lines | msdosfs_mount(struct mount *mp) | ||||
/* | /* | ||||
* If updating, check whether changing from read-only to | * If updating, check whether changing from read-only to | ||||
* read/write; if there is no device name, that's all we do. | * read/write; if there is no device name, that's all we do. | ||||
*/ | */ | ||||
if (mp->mnt_flag & MNT_UPDATE) { | if (mp->mnt_flag & MNT_UPDATE) { | ||||
pmp = VFSTOMSDOSFS(mp); | pmp = VFSTOMSDOSFS(mp); | ||||
if (!(pmp->pm_flags & MSDOSFSMNT_RONLY) && | if (!(pmp->pm_flags & MSDOSFSMNT_RONLY) && | ||||
vfs_flagopt(mp->mnt_optnew, "ro", NULL, 0)) { | vfs_flagopt(mp->mnt_optnew, "ro", NULL, 0)) { | ||||
error = VFS_SYNC(mp, MNT_WAIT); | if ((error = vn_start_write(NULL, &mp, V_WAIT)) != 0) | ||||
if (error) | |||||
return (error); | return (error); | ||||
error = vfs_write_suspend_umnt(mp); | |||||
if (error != 0) | |||||
return (error); | |||||
flags = WRITECLOSE; | flags = WRITECLOSE; | ||||
if (mp->mnt_flag & MNT_FORCE) | if (mp->mnt_flag & MNT_FORCE) | ||||
flags |= FORCECLOSE; | flags |= FORCECLOSE; | ||||
error = vflush(mp, 0, flags, td); | error = vflush(mp, 0, flags, td); | ||||
if (error) | if (error != 0) { | ||||
vfs_write_resume(mp, 0); | |||||
return (error); | return (error); | ||||
} | |||||
/* | /* | ||||
* Now the volume is clean. Mark it so while the | * Now the volume is clean. Mark it so while the | ||||
* device is still rw. | * device is still rw. | ||||
*/ | */ | ||||
error = markvoldirty(pmp, 0); | error = markvoldirty(pmp, 0); | ||||
if (error) { | if (error != 0) { | ||||
vfs_write_resume(mp, 0); | |||||
(void)markvoldirty(pmp, 1); | (void)markvoldirty(pmp, 1); | ||||
return (error); | return (error); | ||||
} | } | ||||
/* Downgrade the device from rw to ro. */ | /* Downgrade the device from rw to ro. */ | ||||
g_topology_lock(); | g_topology_lock(); | ||||
error = g_access(pmp->pm_cp, 0, -1, 0); | error = g_access(pmp->pm_cp, 0, -1, 0); | ||||
g_topology_unlock(); | g_topology_unlock(); | ||||
if (error) { | if (error) { | ||||
vfs_write_resume(mp, 0); | |||||
(void)markvoldirty(pmp, 1); | (void)markvoldirty(pmp, 1); | ||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* Backing out after an error was painful in the | * Backing out after an error was painful in the | ||||
* above. Now we are committed to succeeding. | * above. Now we are committed to succeeding. | ||||
*/ | */ | ||||
pmp->pm_fmod = 0; | pmp->pm_fmod = 0; | ||||
pmp->pm_flags |= MSDOSFSMNT_RONLY; | pmp->pm_flags |= MSDOSFSMNT_RONLY; | ||||
MNT_ILOCK(mp); | MNT_ILOCK(mp); | ||||
mp->mnt_flag |= MNT_RDONLY; | mp->mnt_flag |= MNT_RDONLY; | ||||
MNT_IUNLOCK(mp); | MNT_IUNLOCK(mp); | ||||
vfs_write_resume(mp, 0); | |||||
} else if ((pmp->pm_flags & MSDOSFSMNT_RONLY) && | } else if ((pmp->pm_flags & MSDOSFSMNT_RONLY) && | ||||
!vfs_flagopt(mp->mnt_optnew, "ro", NULL, 0)) { | !vfs_flagopt(mp->mnt_optnew, "ro", NULL, 0)) { | ||||
/* | /* | ||||
* If upgrade to read-write by non-root, then verify | * If upgrade to read-write by non-root, then verify | ||||
* that user has necessary permissions on the device. | * that user has necessary permissions on the device. | ||||
*/ | */ | ||||
devvp = pmp->pm_devvp; | devvp = pmp->pm_devvp; | ||||
vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); | vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); | ||||
▲ Show 20 Lines • Show All 447 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* Unmount the filesystem described by mp. | * Unmount the filesystem described by mp. | ||||
*/ | */ | ||||
static int | static int | ||||
msdosfs_unmount(struct mount *mp, int mntflags) | msdosfs_unmount(struct mount *mp, int mntflags) | ||||
{ | { | ||||
struct msdosfsmount *pmp; | struct msdosfsmount *pmp; | ||||
int error, flags; | int error, flags; | ||||
bool susp; | |||||
error = flags = 0; | error = flags = 0; | ||||
pmp = VFSTOMSDOSFS(mp); | pmp = VFSTOMSDOSFS(mp); | ||||
if ((pmp->pm_flags & MSDOSFSMNT_RONLY) == 0) | susp = (pmp->pm_flags & MSDOSFSMNT_RONLY) != 0; | ||||
error = msdosfs_sync(mp, MNT_WAIT); | |||||
if (susp) { | |||||
error = vfs_write_suspend_umnt(mp); | |||||
if (error != 0) | |||||
return (error); | |||||
} | |||||
if ((mntflags & MNT_FORCE) != 0) | if ((mntflags & MNT_FORCE) != 0) | ||||
flags |= FORCECLOSE; | flags |= FORCECLOSE; | ||||
else if (error != 0) | |||||
return (error); | |||||
error = vflush(mp, 0, flags, curthread); | error = vflush(mp, 0, flags, curthread); | ||||
if (error != 0 && error != ENXIO) | if (error != 0 && error != ENXIO) { | ||||
if (susp) | |||||
vfs_write_resume(mp, VR_START_WRITE); | |||||
return (error); | return (error); | ||||
if ((pmp->pm_flags & MSDOSFSMNT_RONLY) == 0) { | } | ||||
if (susp) { | |||||
error = markvoldirty(pmp, 0); | error = markvoldirty(pmp, 0); | ||||
if (error && error != ENXIO) { | if (error != 0 && error != ENXIO) { | ||||
if (susp) | |||||
vfs_write_resume(mp, VR_START_WRITE); | |||||
(void)markvoldirty(pmp, 1); | (void)markvoldirty(pmp, 1); | ||||
return (error); | return (error); | ||||
} | } | ||||
} | } | ||||
if (pmp->pm_flags & MSDOSFSMNT_KICONV && msdosfs_iconv) { | if (pmp->pm_flags & MSDOSFSMNT_KICONV && msdosfs_iconv) { | ||||
if (pmp->pm_w2u) | if (pmp->pm_w2u) | ||||
msdosfs_iconv->close(pmp->pm_w2u); | msdosfs_iconv->close(pmp->pm_w2u); | ||||
if (pmp->pm_u2w) | if (pmp->pm_u2w) | ||||
Show All 20 Lines | #ifdef MSDOSFS_DEBUG | ||||
printf("cleanblkhd %p, dirtyblkhd %p, numoutput %ld, type %d\n", | printf("cleanblkhd %p, dirtyblkhd %p, numoutput %ld, type %d\n", | ||||
TAILQ_FIRST(&vp->v_bufobj.bo_clean.bv_hd), | TAILQ_FIRST(&vp->v_bufobj.bo_clean.bv_hd), | ||||
TAILQ_FIRST(&vp->v_bufobj.bo_dirty.bv_hd), | TAILQ_FIRST(&vp->v_bufobj.bo_dirty.bv_hd), | ||||
vp->v_bufobj.bo_numoutput, vp->v_type); | vp->v_bufobj.bo_numoutput, vp->v_type); | ||||
VI_UNLOCK(vp); | VI_UNLOCK(vp); | ||||
BO_UNLOCK(bo); | BO_UNLOCK(bo); | ||||
} | } | ||||
#endif | #endif | ||||
if (susp) | |||||
vfs_write_resume(mp, VR_START_WRITE); | |||||
imp: Why do we need to resume writes if we're unmounting and near the end of that process? Is this a… | |||||
kibAuthorUnsubmitted Done Inline ActionsDraining mount point for safe state in vfs_mount_destroy() checks that there is no active writers when mp is destroyed. VFS guarantees that no new consumers can enter mp when VFS_UNMOUNT() is called, so this is a precaution against bugs in this area, and calls to vfs_write_resume() restore invariant that is assumed by the unmount code. kib: Draining mount point for safe state in vfs_mount_destroy() checks that there is no active… | |||||
g_topology_lock(); | g_topology_lock(); | ||||
g_vfs_close(pmp->pm_cp); | g_vfs_close(pmp->pm_cp); | ||||
g_topology_unlock(); | g_topology_unlock(); | ||||
atomic_store_rel_ptr((uintptr_t *)&pmp->pm_dev->si_mountpt, 0); | atomic_store_rel_ptr((uintptr_t *)&pmp->pm_dev->si_mountpt, 0); | ||||
vrele(pmp->pm_devvp); | vrele(pmp->pm_devvp); | ||||
dev_rel(pmp->pm_dev); | dev_rel(pmp->pm_dev); | ||||
free(pmp->pm_inusemap, M_MSDOSFSFAT); | free(pmp->pm_inusemap, M_MSDOSFSFAT); | ||||
lockdestroy(&pmp->pm_fatlock); | lockdestroy(&pmp->pm_fatlock); | ||||
▲ Show 20 Lines • Show All 134 Lines • ▼ Show 20 Lines | if (waitfor != MNT_LAZY) { | ||||
if (error) | if (error) | ||||
allerror = error; | allerror = error; | ||||
VOP_UNLOCK(pmp->pm_devvp); | VOP_UNLOCK(pmp->pm_devvp); | ||||
} | } | ||||
error = msdosfs_fsiflush(pmp, waitfor); | error = msdosfs_fsiflush(pmp, waitfor); | ||||
if (error != 0) | if (error != 0) | ||||
allerror = error; | allerror = error; | ||||
if (allerror == 0 && waitfor == MNT_SUSPEND) { | |||||
MNT_ILOCK(mp); | |||||
mp->mnt_kern_flag |= MNTK_SUSPEND2 | MNTK_SUSPENDED; | |||||
MNT_IUNLOCK(mp); | |||||
} | |||||
return (allerror); | return (allerror); | ||||
} | } | ||||
static int | static int | ||||
msdosfs_fhtovp(struct mount *mp, struct fid *fhp, int flags, struct vnode **vpp) | msdosfs_fhtovp(struct mount *mp, struct fid *fhp, int flags, struct vnode **vpp) | ||||
{ | { | ||||
struct msdosfsmount *pmp = VFSTOMSDOSFS(mp); | struct msdosfsmount *pmp = VFSTOMSDOSFS(mp); | ||||
struct defid *defhp = (struct defid *) fhp; | struct defid *defhp = (struct defid *) fhp; | ||||
Show All 25 Lines |
Why do we need to resume writes if we're unmounting and near the end of that process? Is this a precondition for something else?