Page MenuHomeFreeBSD

D50648.id156431.diff
No OneTemporary

D50648.id156431.diff

diff --git a/sys/fs/msdosfs/msdosfs_lookup.c b/sys/fs/msdosfs/msdosfs_lookup.c
--- a/sys/fs/msdosfs/msdosfs_lookup.c
+++ b/sys/fs/msdosfs/msdosfs_lookup.c
@@ -845,7 +845,6 @@
*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"));
diff --git a/sys/fs/msdosfs/msdosfs_vfsops.c b/sys/fs/msdosfs/msdosfs_vfsops.c
--- a/sys/fs/msdosfs/msdosfs_vfsops.c
+++ b/sys/fs/msdosfs/msdosfs_vfsops.c
@@ -575,7 +575,6 @@
pmp->pm_bo = bo;
lockinit(&pmp->pm_fatlock, 0, msdosfs_lock_msg, 0, 0);
- lockinit(&pmp->pm_checkpath_lock, 0, "msdoscp", 0, 0);
TASK_INIT(&pmp->pm_rw2ro_task, 0, msdosfs_remount_ro, pmp);
@@ -871,7 +870,6 @@
}
if (pmp != NULL) {
lockdestroy(&pmp->pm_fatlock);
- lockdestroy(&pmp->pm_checkpath_lock);
free(pmp->pm_inusemap, M_MSDOSFSFAT);
free(pmp, M_MSDOSFSMNT);
mp->mnt_data = NULL;
@@ -971,7 +969,6 @@
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;
return (error);
diff --git a/sys/fs/msdosfs/msdosfs_vnops.c b/sys/fs/msdosfs/msdosfs_vnops.c
--- a/sys/fs/msdosfs/msdosfs_vnops.c
+++ b/sys/fs/msdosfs/msdosfs_vnops.c
@@ -945,7 +945,7 @@
struct denode *fdip, *fip, *tdip, *tip, *nip;
u_char toname[12], oldname[11];
u_long to_diroffset;
- bool checkpath_locked, doingdirectory, newparent;
+ bool doingdirectory, newparent;
int error;
u_long cn, pcl, blkoff;
daddr_t bn, wait_scn, scn;
@@ -986,8 +986,6 @@
if (tvp != NULL && tvp != tdvp)
VOP_UNLOCK(tvp);
- checkpath_locked = false;
-
relock:
doingdirectory = newparent = false;
@@ -1108,12 +1106,8 @@
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);
@@ -1276,8 +1270,6 @@
cache_purge(fvp);
unlock:
- if (checkpath_locked)
- lockmgr(&pmp->pm_checkpath_lock, LK_RELEASE, NULL);
vput(fdvp);
vput(fvp);
if (tvp != NULL) {
@@ -1289,7 +1281,6 @@
vput(tdvp);
return (error);
releout:
- MPASS(!checkpath_locked);
vrele(tdvp);
if (tvp != NULL)
vrele(tvp);
diff --git a/sys/fs/msdosfs/msdosfsmount.h b/sys/fs/msdosfs/msdosfsmount.h
--- a/sys/fs/msdosfs/msdosfsmount.h
+++ b/sys/fs/msdosfs/msdosfsmount.h
@@ -116,7 +116,6 @@
void *pm_d2u; /* DOS->Local iconv handle */
#ifndef MAKEFS
struct lock pm_fatlock; /* lockmgr protecting allocations */
- struct lock pm_checkpath_lock; /* protects doscheckpath result */
struct task pm_rw2ro_task; /* context for emergency remount ro */
#endif
};
diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c
--- a/sys/kern/vfs_lookup.c
+++ b/sys/kern/vfs_lookup.c
@@ -164,6 +164,7 @@
struct nameicap_tracker {
struct vnode *dp;
TAILQ_ENTRY(nameicap_tracker) nm_link;
+ struct mount *mp;
};
/* Zone for cap mode tracker elements used for dotdot capability checks. */
@@ -192,20 +193,41 @@
"enables \"..\" components in path lookup in capability mode "
"on non-local mount");
-static void
+static int
nameicap_tracker_add(struct nameidata *ndp, struct vnode *dp)
{
struct nameicap_tracker *nt;
+ int error;
if ((ndp->ni_lcf & NI_LCF_CAP_DOTDOT) == 0 || dp->v_type != VDIR)
- return;
+ return (0);
nt = TAILQ_LAST(&ndp->ni_cap_tracker, nameicap_tracker_head);
if (nt != NULL && nt->dp == dp)
- return;
+ return (0);
nt = malloc(sizeof(*nt), M_NAMEITRACKER, M_WAITOK);
- vhold(dp);
nt->dp = dp;
- TAILQ_INSERT_TAIL(&ndp->ni_cap_tracker, nt, nm_link);
+
+ /*
+ * This is somewhat excessive, the previous tracker entry
+ * might already hold the right renamelock. But since we must
+ * traverse the list in the direct order for cleanup, it is
+ * much simple to lock everything instead of trying to detect
+ * the v_mount change.
+ *
+ * Memoize dp->v_mount since dp is unlocked during the lookup.
+ */
+ nt->mp = dp->v_mount;
+ error = lockmgr(&nt->mp->mnt_renamelock, LK_SHARED | LK_NOWAIT,
+ 0);
+ if (error != 0) {
+ ndp->ni_nctrack_mnt = nt->mp;
+ free(nt, M_NAMEITRACKER);
+ error = ERESTART;
+ } else {
+ vhold(dp);
+ TAILQ_INSERT_TAIL(&ndp->ni_cap_tracker, nt, nm_link);
+ }
+ return (error);
}
static void
@@ -215,6 +237,7 @@
nt = first;
TAILQ_FOREACH_FROM_SAFE(nt, &ndp->ni_cap_tracker, nm_link, nt1) {
+ lockmgr(&nt->mp->mnt_renamelock, LK_RELEASE, 0);
TAILQ_REMOVE(&ndp->ni_cap_tracker, nt, nm_link);
vdrop(nt->dp);
free(nt, M_NAMEITRACKER);
@@ -761,6 +784,16 @@
namei_cleanup_cnp(cnp);
nameicap_cleanup(ndp);
pwd_drop(pwd);
+ if (error == ERESTART) {
+ struct mount *mp;
+
+ mp = ndp->ni_nctrack_mnt;
+ if (mp != NULL) {
+ lockmgr(&mp->mnt_renamelock, LK_EXCLUSIVE, 0);
+ lockmgr(&mp->mnt_renamelock, LK_RELEASE, 0);
+ }
+ goto restart;
+ }
return (error);
}
@@ -1185,7 +1218,9 @@
}
}
- nameicap_tracker_add(ndp, dp);
+ error = nameicap_tracker_add(ndp, dp);
+ if (error != 0)
+ goto bad;
/*
* Make sure degenerate names don't get here, their handling was
@@ -1314,7 +1349,9 @@
vn_lock(dp,
enforce_lkflags(dp->v_mount, cnp->cn_lkflags |
LK_RETRY));
- nameicap_tracker_add(ndp, dp);
+ error = nameicap_tracker_add(ndp, dp);
+ if (error != 0)
+ goto bad;
goto unionlookup;
}
@@ -1485,8 +1522,11 @@
}
success_right_lock:
if (ndp->ni_vp != NULL) {
- if ((cnp->cn_flags & ISDOTDOT) == 0)
- nameicap_tracker_add(ndp, ndp->ni_vp);
+ if ((cnp->cn_flags & ISDOTDOT) == 0) {
+ error = nameicap_tracker_add(ndp, ndp->ni_vp);
+ if (error != 0)
+ goto bad2;
+ }
if ((cnp->cn_flags & (FAILIFEXISTS | ISSYMLINK)) == FAILIFEXISTS)
return (vfs_lookup_failifexists(ndp));
}
diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c
--- a/sys/kern/vfs_mount.c
+++ b/sys/kern/vfs_mount.c
@@ -157,6 +157,7 @@
mtx_init(&mp->mnt_mtx, "struct mount mtx", NULL, MTX_DEF);
mtx_init(&mp->mnt_listmtx, "struct mount vlist mtx", NULL, MTX_DEF);
lockinit(&mp->mnt_explock, PVFS, "explock", 0, 0);
+ lockinit(&mp->mnt_renamelock, PVFS, "rename", 0, 0);
mp->mnt_pcpu = uma_zalloc_pcpu(pcpu_zone_16, M_WAITOK | M_ZERO);
mp->mnt_ref = 0;
mp->mnt_vfs_ops = 1;
@@ -171,6 +172,7 @@
mp = (struct mount *)mem;
uma_zfree_pcpu(pcpu_zone_16, mp->mnt_pcpu);
+ lockdestroy(&mp->mnt_renamelock);
lockdestroy(&mp->mnt_explock);
mtx_destroy(&mp->mnt_listmtx);
mtx_destroy(&mp->mnt_mtx);
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -3759,8 +3759,10 @@
uint64_t tondflags;
int error;
short irflag;
+ bool lock_mntrename;
again:
+ lock_mntrename = false;
bwillwrite();
#ifdef MAC
if (mac_vnode_check_rename_from_enabled()) {
@@ -3796,6 +3798,7 @@
tvp = tond.ni_vp;
error = vn_start_write(fvp, &mp, V_NOWAIT);
if (error != 0) {
+again1:
NDFREE_PNBUF(&fromnd);
NDFREE_PNBUF(&tond);
if (tvp != NULL)
@@ -3809,8 +3812,17 @@
error = vn_start_write(NULL, &mp, V_XSLEEP | V_PCATCH);
if (error != 0)
return (error);
+ if (lock_mntrename) {
+ lockmgr(&mp->mnt_renamelock, LK_EXCLUSIVE, NULL);
+ lockmgr(&mp->mnt_renamelock, LK_RELEASE, NULL);
+ }
goto again;
}
+ error = lockmgr(&mp->mnt_renamelock, LK_EXCLUSIVE | LK_NOWAIT, NULL);
+ if (error != 0) {
+ lock_mntrename = true;
+ goto again1;
+ }
irflag = vn_irflag_read(fvp);
if (((irflag & VIRF_NAMEDATTR) != 0 && tdvp != fromnd.ni_dvp) ||
(irflag & VIRF_NAMEDDIR) != 0) {
@@ -3872,6 +3884,7 @@
vrele(fvp);
}
vn_finished_write(mp);
+ lockmgr(&mp->mnt_renamelock, LK_RELEASE, 0);
out1:
if (error == ERESTART)
return (0);
diff --git a/sys/sys/mount.h b/sys/sys/mount.h
--- a/sys/sys/mount.h
+++ b/sys/sys/mount.h
@@ -263,6 +263,7 @@
int mnt_lazyvnodelistsize; /* (l) # of lazy vnodes */
int mnt_upper_pending; /* (i) # of pending ops on mnt_uppers */
struct lock mnt_explock; /* vfs_export walkers lock */
+ struct lock mnt_renamelock; /* renames and O_RESOLVE_BENEATH */
TAILQ_HEAD(, mount_upper_node) mnt_uppers; /* (i) upper mounts over us */
TAILQ_HEAD(, mount_upper_node) mnt_notify; /* (i) upper mounts for notification */
STAILQ_ENTRY(mount) mnt_taskqueue_link; /* (d) our place in deferred unmount list */
diff --git a/sys/sys/namei.h b/sys/sys/namei.h
--- a/sys/sys/namei.h
+++ b/sys/sys/namei.h
@@ -115,6 +115,8 @@
*/
seqc_t ni_dvp_seqc;
seqc_t ni_vp_seqc;
+
+ struct mount *ni_nctrack_mnt;
};
#ifdef _KERNEL
@@ -258,6 +260,7 @@
_ndp->ni_resflags = 0; \
filecaps_init(&_ndp->ni_filecaps); \
_ndp->ni_rightsneeded = _rightsp; \
+ _ndp->ni_nctrack_mnt = NULL; \
} while (0)
#define NDREINIT(ndp) do { \
diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c
--- a/sys/ufs/ffs/ffs_vfsops.c
+++ b/sys/ufs/ffs/ffs_vfsops.c
@@ -1012,7 +1012,6 @@
else
ump->um_check_blkno = NULL;
mtx_init(UFS_MTX(ump), "FFS", "FFS Lock", MTX_DEF);
- sx_init(&ump->um_checkpath_lock, "uchpth");
fs->fs_ronly = ronly;
fs->fs_active = NULL;
mp->mnt_data = ump;
@@ -1182,7 +1181,6 @@
}
if (ump != NULL) {
mtx_destroy(UFS_MTX(ump));
- sx_destroy(&ump->um_checkpath_lock);
if (mp->mnt_gjprovider != NULL) {
free(mp->mnt_gjprovider, M_UFSMNT);
mp->mnt_gjprovider = NULL;
@@ -1306,7 +1304,6 @@
vrele(ump->um_odevvp);
dev_rel(ump->um_dev);
mtx_destroy(UFS_MTX(ump));
- sx_destroy(&ump->um_checkpath_lock);
if (mp->mnt_gjprovider != NULL) {
free(mp->mnt_gjprovider, M_UFSMNT);
mp->mnt_gjprovider = NULL;
diff --git a/sys/ufs/ufs/ufs_lookup.c b/sys/ufs/ufs/ufs_lookup.c
--- a/sys/ufs/ufs/ufs_lookup.c
+++ b/sys/ufs/ufs/ufs_lookup.c
@@ -1412,7 +1412,6 @@
vp = tvp = ITOV(target);
mp = vp->v_mount;
*wait_ino = 0;
- sx_assert(&VFSTOUFS(mp)->um_checkpath_lock, SA_XLOCKED);
if (target->i_number == source_ino)
return (EEXIST);
diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c
--- a/sys/ufs/ufs/ufs_vnops.c
+++ b/sys/ufs/ufs/ufs_vnops.c
@@ -1273,9 +1273,9 @@
struct mount *mp;
ino_t ino;
seqc_t fdvp_s, fvp_s, tdvp_s, tvp_s;
- bool checkpath_locked, want_seqc_end;
+ bool want_seqc_end;
- checkpath_locked = want_seqc_end = false;
+ want_seqc_end = false;
endoff = 0;
mp = tdvp->v_mount;
@@ -1427,10 +1427,6 @@
}
vfs_ref(mp);
MPASS(!want_seqc_end);
- if (checkpath_locked) {
- sx_xunlock(&VFSTOUFS(mp)->um_checkpath_lock);
- checkpath_locked = false;
- }
VOP_UNLOCK(fdvp);
VOP_UNLOCK(fvp);
vref(tdvp);
@@ -1484,8 +1480,6 @@
if (error)
goto unlockout;
- sx_xlock(&VFSTOUFS(mp)->um_checkpath_lock);
- checkpath_locked = true;
error = ufs_checkpath(ino, fdp->i_number, tdp, tcnp->cn_cred,
&ino);
/*
@@ -1493,8 +1487,6 @@
* everything else and VGET before restarting.
*/
if (ino) {
- sx_xunlock(&VFSTOUFS(mp)->um_checkpath_lock);
- checkpath_locked = false;
VOP_UNLOCK(fdvp);
VOP_UNLOCK(fvp);
VOP_UNLOCK(tdvp);
@@ -1574,9 +1566,6 @@
vn_seqc_write_end(fdvp);
want_seqc_end = false;
vfs_ref(mp);
- MPASS(checkpath_locked);
- sx_xunlock(&VFSTOUFS(mp)->um_checkpath_lock);
- checkpath_locked = false;
VOP_UNLOCK(fdvp);
VOP_UNLOCK(fvp);
vref(tdvp);
@@ -1763,9 +1752,6 @@
vn_seqc_write_end(fdvp);
}
- if (checkpath_locked)
- sx_xunlock(&VFSTOUFS(mp)->um_checkpath_lock);
-
vput(fdvp);
vput(fvp);
diff --git a/sys/ufs/ufs/ufsmount.h b/sys/ufs/ufs/ufsmount.h
--- a/sys/ufs/ufs/ufsmount.h
+++ b/sys/ufs/ufs/ufsmount.h
@@ -97,8 +97,6 @@
uint64_t um_maxsymlinklen; /* (c) max size of short
symlink */
struct mtx um_lock; /* (c) Protects ufsmount & fs */
- struct sx um_checkpath_lock; /* (c) Protects ufs_checkpath()
- result */
struct mount_softdeps *um_softdep; /* (c) softdep mgmt structure */
struct vnode *um_quotas[MAXQUOTAS]; /* (q) pointer to quota files */
struct ucred *um_cred[MAXQUOTAS]; /* (q) quota file access cred */

File Metadata

Mime Type
text/plain
Expires
Wed, Jul 1, 4:29 PM (16 h, 3 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34569635
Default Alt Text
D50648.id156431.diff (12 KB)

Event Timeline