msdosfs: add doscheckpath lock
Similar to the UFS revision 8df4bc48c8
Reviewed by: mckusick
Tested by: pho
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
Differential revision: https://reviews.freebsd.org/D31464
This commit is contained in:
parent
95d42526e9
commit
6ae13c0feb
@ -813,6 +813,7 @@ doscheckpath(struct denode *source, struct denode *target, daddr_t *wait_scn)
|
||||
*wait_scn = 0;
|
||||
|
||||
pmp = target->de_pmp;
|
||||
lockmgr_assert(&pmp->pm_checkpath_lock, KA_XLOCKED);
|
||||
KASSERT(pmp == source->de_pmp,
|
||||
("doscheckpath: source and target on different filesystems"));
|
||||
|
||||
|
@ -469,6 +469,7 @@ mountmsdosfs(struct vnode *devvp, struct mount *mp)
|
||||
pmp->pm_bo = bo;
|
||||
|
||||
lockinit(&pmp->pm_fatlock, 0, msdosfs_lock_msg, 0, 0);
|
||||
lockinit(&pmp->pm_checkpath_lock, 0, "msdoscp", 0, 0);
|
||||
|
||||
/*
|
||||
* Initialize ownerships and permissions, since nothing else will
|
||||
@ -740,6 +741,7 @@ mountmsdosfs(struct vnode *devvp, struct mount *mp)
|
||||
}
|
||||
if (pmp) {
|
||||
lockdestroy(&pmp->pm_fatlock);
|
||||
lockdestroy(&pmp->pm_checkpath_lock);
|
||||
free(pmp->pm_inusemap, M_MSDOSFSFAT);
|
||||
free(pmp, M_MSDOSFSMNT);
|
||||
mp->mnt_data = NULL;
|
||||
@ -829,6 +831,7 @@ msdosfs_unmount(struct mount *mp, int mntflags)
|
||||
dev_rel(pmp->pm_dev);
|
||||
free(pmp->pm_inusemap, M_MSDOSFSFAT);
|
||||
lockdestroy(&pmp->pm_fatlock);
|
||||
lockdestroy(&pmp->pm_checkpath_lock);
|
||||
free(pmp, M_MSDOSFSMNT);
|
||||
mp->mnt_data = NULL;
|
||||
MNT_ILOCK(mp);
|
||||
|
@ -942,7 +942,7 @@ msdosfs_rename(struct vop_rename_args *ap)
|
||||
struct denode *fdip, *fip, *tdip, *tip, *nip;
|
||||
u_char toname[12], oldname[11];
|
||||
u_long from_diroffset, to_diroffset;
|
||||
bool doingdirectory, newparent;
|
||||
bool checkpath_locked, doingdirectory, newparent;
|
||||
u_char to_count;
|
||||
int error;
|
||||
u_long cn, pcl, blkoff;
|
||||
@ -991,6 +991,8 @@ msdosfs_rename(struct vop_rename_args *ap)
|
||||
if (tvp != NULL && tvp != tdvp)
|
||||
VOP_UNLOCK(tvp);
|
||||
|
||||
checkpath_locked = false;
|
||||
|
||||
relock:
|
||||
doingdirectory = newparent = false;
|
||||
|
||||
@ -1113,8 +1115,12 @@ msdosfs_rename(struct vop_rename_args *ap)
|
||||
if (doingdirectory && newparent) {
|
||||
if (error != 0) /* write access check above */
|
||||
goto unlock;
|
||||
lockmgr(&pmp->pm_checkpath_lock, LK_EXCLUSIVE, NULL);
|
||||
checkpath_locked = true;
|
||||
error = doscheckpath(fip, tdip, &wait_scn);
|
||||
if (wait_scn != 0) {
|
||||
lockmgr(&pmp->pm_checkpath_lock, LK_RELEASE, NULL);
|
||||
checkpath_locked = false;
|
||||
VOP_UNLOCK(fdvp);
|
||||
VOP_UNLOCK(tdvp);
|
||||
VOP_UNLOCK(fvp);
|
||||
@ -1268,6 +1274,8 @@ msdosfs_rename(struct vop_rename_args *ap)
|
||||
cache_purge(fvp);
|
||||
|
||||
unlock:
|
||||
if (checkpath_locked)
|
||||
lockmgr(&pmp->pm_checkpath_lock, LK_RELEASE, NULL);
|
||||
vput(fdvp);
|
||||
vput(fvp);
|
||||
if (tvp != NULL) {
|
||||
@ -1279,6 +1287,7 @@ msdosfs_rename(struct vop_rename_args *ap)
|
||||
vput(tdvp);
|
||||
return (error);
|
||||
releout:
|
||||
MPASS(!checkpath_locked);
|
||||
vrele(tdvp);
|
||||
if (tvp != NULL)
|
||||
vrele(tvp);
|
||||
|
@ -114,6 +114,7 @@ struct msdosfsmount {
|
||||
void *pm_d2u; /* DOS->Local iconv handle */
|
||||
#ifndef MAKEFS
|
||||
struct lock pm_fatlock; /* lockmgr protecting allocations */
|
||||
struct lock pm_checkpath_lock; /* protects doscheckpath result */
|
||||
#endif
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user