Page MenuHomeFreeBSD

D30041.id90444.diff
No OneTemporary

D30041.id90444.diff

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
@@ -1328,6 +1328,7 @@
}
if (error != 0)
return (error);
+ NDPREINIT(&nd);
restart:
bwillwrite();
NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1 |
@@ -1436,6 +1437,7 @@
int error;
AUDIT_ARG_MODE(mode);
+ NDPREINIT(&nd);
restart:
bwillwrite();
NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1 |
@@ -1566,6 +1568,7 @@
struct nameidata nd;
int error;
+ NDPREINIT(&nd);
do {
bwillwrite();
NDINIT_ATRIGHTS(&nd, LOOKUP, AUDITVNODE1 | at2cnpflags(flag,
@@ -1714,6 +1717,7 @@
syspath = tmppath;
}
AUDIT_ARG_TEXT(syspath);
+ NDPREINIT(&nd);
restart:
bwillwrite();
NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1 |
@@ -1778,6 +1782,7 @@
struct nameidata nd;
int error;
+ NDPREINIT(&nd);
restart:
bwillwrite();
NDINIT(&nd, DELETE, LOCKPARENT | DOWHITEOUT | AUDITVNODE1,
@@ -1891,6 +1896,7 @@
return (error);
}
+ NDPREINIT(&nd);
restart:
bwillwrite();
NDINIT_ATRIGHTS(&nd, DELETE, LOCKPARENT | LOCKLEAF | AUDITVNODE1 |
@@ -3422,6 +3428,7 @@
if (length < 0)
return (EINVAL);
+ NDPREINIT(&nd);
retry:
NDINIT(&nd, LOOKUP, FOLLOW | AUDITVNODE1, pathseg, path, td);
if ((error = namei(&nd)) != 0)
@@ -3789,6 +3796,7 @@
int error;
AUDIT_ARG_MODE(mode);
+ NDPREINIT(&nd);
restart:
bwillwrite();
NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1 |
@@ -3859,6 +3867,7 @@
return (error);
}
+ NDPREINIT(&nd);
restart:
bwillwrite();
NDINIT_ATRIGHTS(&nd, DELETE, LOCKPARENT | LOCKLEAF | AUDITVNODE1 |
diff --git a/sys/sys/namei.h b/sys/sys/namei.h
--- a/sys/sys/namei.h
+++ b/sys/sys/namei.h
@@ -38,6 +38,7 @@
#include <sys/caprights.h>
#include <sys/filedesc.h>
#include <sys/queue.h>
+#include <sys/_seqc.h>
#include <sys/_uio.h>
enum nameiop { LOOKUP, CREATE, DELETE, RENAME };
@@ -111,6 +112,12 @@
*/
struct componentname ni_cnd;
struct nameicap_tracker_head ni_cap_tracker;
+ /*
+ * Private helper data for UFS, must be at the end. See
+ * NDINIT_PREFILL().
+ */
+ seqc_t ni_dvp_seqc;
+ seqc_t ni_vp_seqc;
};
#ifdef _KERNEL
@@ -224,7 +231,8 @@
* Note the constant pattern may *hide* bugs.
*/
#ifdef INVARIANTS
-#define NDINIT_PREFILL(arg) memset(arg, 0xff, sizeof(*arg))
+#define NDINIT_PREFILL(arg) memset(arg, 0xff, sizeof(struct nameidata) - \
+ offsetof(struct nameidata, ni_dvp_seqc))
#define NDINIT_DBG(arg) { (arg)->ni_debugflags = NAMEI_DBG_INITED; }
#define NDREINIT_DBG(arg) { \
if (((arg)->ni_debugflags & NAMEI_DBG_INITED) == 0) \
@@ -265,6 +273,11 @@
_ndp->ni_startdir = NULL; \
} while (0)
+#define NDPREINIT(ndp) do { \
+ (ndp)->ni_dvp_seqc = SEQC_MOD; \
+ (ndp)->ni_vp_seqc = SEQC_MOD; \
+} while (0)
+
#define NDF_NO_DVP_RELE 0x00000001
#define NDF_NO_DVP_UNLOCK 0x00000002
#define NDF_NO_DVP_PUT 0x00000003
diff --git a/sys/sys/seqc.h b/sys/sys/seqc.h
--- a/sys/sys/seqc.h
+++ b/sys/sys/seqc.h
@@ -45,13 +45,15 @@
#include <machine/cpu.h>
+#define SEQC_MOD 1
+
/*
* Predicts from inline functions are not honored by clang.
*/
#define seqc_in_modify(seqc) ({ \
seqc_t __seqc = (seqc); \
\
- __predict_false(__seqc & 1); \
+ __predict_false(__seqc & SEQC_MOD); \
})
static __inline void
@@ -60,7 +62,7 @@
critical_enter();
MPASS(!seqc_in_modify(*seqcp));
- *seqcp += 1;
+ *seqcp += SEQC_MOD;
atomic_thread_fence_rel();
}
@@ -69,7 +71,7 @@
{
atomic_thread_fence_rel();
- *seqcp += 1;
+ *seqcp += SEQC_MOD;
MPASS(!seqc_in_modify(*seqcp));
critical_exit();
}
@@ -85,7 +87,7 @@
seqc_read_notmodify(const seqc_t *seqcp)
{
- return (atomic_load_acq_int(__DECONST(seqc_t *, seqcp)) & ~1);
+ return (atomic_load_acq_int(__DECONST(seqc_t *, seqcp)) & ~SEQC_MOD);
}
static __inline seqc_t
@@ -126,7 +128,7 @@
{
MPASS(!seqc_in_modify(*seqcp));
- *seqcp += 1;
+ *seqcp += SEQC_MOD;
atomic_thread_fence_rel();
}
@@ -135,7 +137,7 @@
{
atomic_thread_fence_rel();
- *seqcp += 1;
+ *seqcp += SEQC_MOD;
MPASS(!seqc_in_modify(*seqcp));
}
diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c
--- a/sys/ufs/ffs/ffs_alloc.c
+++ b/sys/ufs/ffs/ffs_alloc.c
@@ -517,6 +517,7 @@
} */ *ap;
{
struct ufsmount *ump;
+ int error;
/*
* We used to skip reallocating the blocks of a file into a
@@ -546,9 +547,11 @@
if (DOINGSUJ(ap->a_vp))
if (softdep_prealloc(ap->a_vp, MNT_NOWAIT) != 0)
return (ENOSPC);
- if (ump->um_fstype == UFS1)
- return (ffs_reallocblks_ufs1(ap));
- return (ffs_reallocblks_ufs2(ap));
+ vn_seqc_write_begin(ap->a_vp);
+ error = ump->um_fstype == UFS1 ? ffs_reallocblks_ufs1(ap) :
+ ffs_reallocblks_ufs2(ap);
+ vn_seqc_write_end(ap->a_vp);
+ return (error);
}
static int
diff --git a/sys/ufs/ffs/ffs_balloc.c b/sys/ufs/ffs/ffs_balloc.c
--- a/sys/ufs/ffs/ffs_balloc.c
+++ b/sys/ufs/ffs/ffs_balloc.c
@@ -128,6 +128,8 @@
return (EFBIG);
gbflags = (flags & BA_UNMAPPED) != 0 ? GB_UNMAPPED : 0;
+ vn_seqc_write_begin(vp);
+
/*
* If the next write will extend the file into a new block,
* and the file is currently composed of a fragment
@@ -144,7 +146,7 @@
&dp->di_db[0]), osize, (int)fs->fs_bsize, flags,
cred, &bp);
if (error)
- return (error);
+ goto done;
if (DOINGSOFTDEP(vp))
softdep_setup_allocdirect(ip, nb,
dbtofsb(fs, bp->b_blkno), dp->di_db[nb],
@@ -174,17 +176,20 @@
error = bread(vp, lbn, fs->fs_bsize, NOCRED,
&bp);
if (error != 0)
- return (error);
+ goto done;
} else {
bp = getblk(vp, lbn, fs->fs_bsize, 0, 0,
gbflags);
- if (bp == NULL)
- return (EIO);
+ if (bp == NULL) {
+ error = EIO;
+ goto done;
+ }
vfs_bio_clrbuf(bp);
}
bp->b_blkno = fsbtodb(fs, nb);
*bpp = bp;
- return (0);
+ error = 0;
+ goto done;
}
if (nb != 0) {
/*
@@ -194,9 +199,8 @@
nsize = fragroundup(fs, size);
if (nsize <= osize) {
error = bread(vp, lbn, osize, NOCRED, &bp);
- if (error) {
- return (error);
- }
+ if (error)
+ goto done;
bp->b_blkno = fsbtodb(fs, nb);
} else {
UFS_LOCK(ump);
@@ -205,7 +209,7 @@
&dp->di_db[0]), osize, nsize, flags,
cred, &bp);
if (error)
- return (error);
+ goto done;
if (DOINGSOFTDEP(vp))
softdep_setup_allocdirect(ip, lbn,
dbtofsb(fs, bp->b_blkno), nb,
@@ -221,7 +225,7 @@
ffs_blkpref_ufs1(ip, lbn, (int)lbn, &dp->di_db[0]),
nsize, flags, cred, &newb);
if (error)
- return (error);
+ goto done;
bp = getblk(vp, lbn, nsize, 0, 0, gbflags);
bp->b_blkno = fsbtodb(fs, newb);
if (flags & BA_CLRBUF)
@@ -233,14 +237,15 @@
dp->di_db[lbn] = dbtofsb(fs, bp->b_blkno);
UFS_INODE_SET_FLAG(ip, IN_CHANGE | IN_UPDATE | IN_IBLKDATA);
*bpp = bp;
- return (0);
+ error = 0;
+ goto done;
}
/*
* Determine the number of levels of indirection.
*/
pref = 0;
if ((error = ufs_getlbns(vp, lbn, indirs, &num)) != 0)
- return(error);
+ goto done;
#ifdef INVARIANTS
if (num < 1)
panic ("ffs_balloc_ufs1: ufs_getlbns returned indirect block");
@@ -261,7 +266,7 @@
if ((error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize,
flags, cred, &newb)) != 0) {
curthread_pflags_restore(saved_inbdflush);
- return (error);
+ goto done;
}
pref = newb + fs->fs_frag;
nb = newb;
@@ -387,7 +392,8 @@
if (flags & BA_METAONLY) {
curthread_pflags_restore(saved_inbdflush);
*bpp = bp;
- return (0);
+ error = 0;
+ goto done;
}
/*
* Get the data block, allocating if necessary.
@@ -453,7 +459,8 @@
}
curthread_pflags_restore(saved_inbdflush);
*bpp = nbp;
- return (0);
+ error = 0;
+ goto done;
}
brelse(bp);
if (flags & BA_CLRBUF) {
@@ -478,7 +485,8 @@
}
curthread_pflags_restore(saved_inbdflush);
*bpp = nbp;
- return (0);
+ error = 0;
+ goto done;
fail:
curthread_pflags_restore(saved_inbdflush);
/*
@@ -486,7 +494,7 @@
* This is the usual case and avoids the need to fsync the file.
*/
if (allocblk == allociblk && allocib == NULL && unwindidx == -1)
- return (error);
+ goto done;
/*
* If we have failed part way through block allocation, we
* have to deallocate any indirect blocks that we have allocated.
@@ -574,6 +582,8 @@
ffs_blkfree(ump, fs, ump->um_devvp, *blkp, fs->fs_bsize,
ip->i_number, vp->v_type, NULL, SINGLETON_KEY);
}
+done:
+ vn_seqc_write_end(vp);
return (error);
}
@@ -619,12 +629,17 @@
return (EFBIG);
gbflags = (flags & BA_UNMAPPED) != 0 ? GB_UNMAPPED : 0;
+ vn_seqc_write_begin(vp);
+
/*
* Check for allocating external data.
*/
if (flags & IO_EXT) {
- if (lbn >= UFS_NXADDR)
- return (EFBIG);
+ if (lbn >= UFS_NXADDR) {
+ error = EFBIG;
+ goto done;
+ }
+
/*
* If the next write will extend the data into a new block,
* and the data is currently composed of a fragment
@@ -642,7 +657,7 @@
&dp->di_extb[0]), osize,
(int)fs->fs_bsize, flags, cred, &bp);
if (error)
- return (error);
+ goto done;
if (DOINGSOFTDEP(vp))
softdep_setup_allocext(ip, nb,
dbtofsb(fs, bp->b_blkno),
@@ -668,13 +683,12 @@
if (nb != 0 && dp->di_extsize >= smalllblktosize(fs, lbn + 1)) {
error = bread_gb(vp, -1 - lbn, fs->fs_bsize, NOCRED,
gbflags, &bp);
- if (error) {
- return (error);
- }
+ if (error)
+ goto done;
bp->b_blkno = fsbtodb(fs, nb);
bp->b_xflags |= BX_ALTDATA;
*bpp = bp;
- return (0);
+ goto done;
}
if (nb != 0) {
/*
@@ -685,9 +699,8 @@
if (nsize <= osize) {
error = bread_gb(vp, -1 - lbn, osize, NOCRED,
gbflags, &bp);
- if (error) {
- return (error);
- }
+ if (error)
+ goto done;
bp->b_blkno = fsbtodb(fs, nb);
bp->b_xflags |= BX_ALTDATA;
} else {
@@ -698,7 +711,7 @@
&dp->di_extb[0]), osize, nsize, flags,
cred, &bp);
if (error)
- return (error);
+ goto done;
bp->b_xflags |= BX_ALTDATA;
if (DOINGSOFTDEP(vp))
softdep_setup_allocext(ip, lbn,
@@ -715,7 +728,7 @@
ffs_blkpref_ufs2(ip, lbn, (int)lbn, &dp->di_extb[0]),
nsize, flags, cred, &newb);
if (error)
- return (error);
+ goto done;
bp = getblk(vp, -1 - lbn, nsize, 0, 0, gbflags);
bp->b_blkno = fsbtodb(fs, newb);
bp->b_xflags |= BX_ALTDATA;
@@ -728,7 +741,8 @@
dp->di_extb[lbn] = dbtofsb(fs, bp->b_blkno);
UFS_INODE_SET_FLAG(ip, IN_CHANGE | IN_IBLKDATA);
*bpp = bp;
- return (0);
+ error = 0;
+ goto done;
}
/*
* If the next write will extend the file into a new block,
@@ -746,7 +760,7 @@
&dp->di_db[0]), osize, (int)fs->fs_bsize,
flags, cred, &bp);
if (error)
- return (error);
+ goto done;
if (DOINGSOFTDEP(vp))
softdep_setup_allocdirect(ip, nb,
dbtofsb(fs, bp->b_blkno),
@@ -775,17 +789,20 @@
error = bread_gb(vp, lbn, fs->fs_bsize, NOCRED,
gbflags, &bp);
if (error != 0)
- return (error);
+ goto done;
} else {
bp = getblk(vp, lbn, fs->fs_bsize, 0, 0,
gbflags);
- if (bp == NULL)
- return (EIO);
+ if (bp == NULL) {
+ error = EIO;
+ goto done;
+ }
vfs_bio_clrbuf(bp);
}
bp->b_blkno = fsbtodb(fs, nb);
*bpp = bp;
- return (0);
+ error = 0;
+ goto done;
}
if (nb != 0) {
/*
@@ -796,9 +813,8 @@
if (nsize <= osize) {
error = bread_gb(vp, lbn, osize, NOCRED,
gbflags, &bp);
- if (error) {
- return (error);
- }
+ if (error)
+ goto done;
bp->b_blkno = fsbtodb(fs, nb);
} else {
UFS_LOCK(ump);
@@ -807,7 +823,7 @@
&dp->di_db[0]), osize, nsize, flags,
cred, &bp);
if (error)
- return (error);
+ goto done;
if (DOINGSOFTDEP(vp))
softdep_setup_allocdirect(ip, lbn,
dbtofsb(fs, bp->b_blkno), nb,
@@ -823,7 +839,7 @@
ffs_blkpref_ufs2(ip, lbn, (int)lbn,
&dp->di_db[0]), nsize, flags, cred, &newb);
if (error)
- return (error);
+ goto done;
bp = getblk(vp, lbn, nsize, 0, 0, gbflags);
bp->b_blkno = fsbtodb(fs, newb);
if (flags & BA_CLRBUF)
@@ -835,14 +851,15 @@
dp->di_db[lbn] = dbtofsb(fs, bp->b_blkno);
UFS_INODE_SET_FLAG(ip, IN_CHANGE | IN_UPDATE | IN_IBLKDATA);
*bpp = bp;
- return (0);
+ error = 0;
+ goto done;
}
/*
* Determine the number of levels of indirection.
*/
pref = 0;
if ((error = ufs_getlbns(vp, lbn, indirs, &num)) != 0)
- return(error);
+ goto done;
#ifdef INVARIANTS
if (num < 1)
panic ("ffs_balloc_ufs2: ufs_getlbns returned indirect block");
@@ -863,7 +880,7 @@
if ((error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize,
flags, cred, &newb)) != 0) {
curthread_pflags_restore(saved_inbdflush);
- return (error);
+ goto done;
}
pref = newb + fs->fs_frag;
nb = newb;
@@ -991,7 +1008,8 @@
if (flags & BA_METAONLY) {
curthread_pflags_restore(saved_inbdflush);
*bpp = bp;
- return (0);
+ error = 0;
+ goto done;
}
/*
* Get the data block, allocating if necessary.
@@ -1057,7 +1075,8 @@
}
curthread_pflags_restore(saved_inbdflush);
*bpp = nbp;
- return (0);
+ error = 0;
+ goto done;
}
brelse(bp);
/*
@@ -1088,7 +1107,8 @@
}
curthread_pflags_restore(saved_inbdflush);
*bpp = nbp;
- return (0);
+ error = 0;
+ goto done;
fail:
curthread_pflags_restore(saved_inbdflush);
/*
@@ -1096,7 +1116,7 @@
* This is the usual case and avoids the need to fsync the file.
*/
if (allocblk == allociblk && allocib == NULL && unwindidx == -1)
- return (error);
+ goto done;
/*
* If we have failed part way through block allocation, we
* have to deallocate any indirect blocks that we have allocated.
@@ -1184,5 +1204,7 @@
ffs_blkfree(ump, fs, ump->um_devvp, *blkp, fs->fs_bsize,
ip->i_number, vp->v_type, NULL, SINGLETON_KEY);
}
+done:
+ vn_seqc_write_end(vp);
return (error);
}
diff --git a/sys/ufs/ffs/ffs_extern.h b/sys/ufs/ffs/ffs_extern.h
--- a/sys/ufs/ffs/ffs_extern.h
+++ b/sys/ufs/ffs/ffs_extern.h
@@ -181,7 +181,8 @@
struct ucred *, int);
int softdep_prerename(struct vnode *, struct vnode *, struct vnode *,
struct vnode *);
-int softdep_prelink(struct vnode *, struct vnode *);
+int softdep_prelink(struct vnode *, struct vnode *,
+ struct componentname *);
void softdep_setup_freeblocks(struct inode *, off_t, int);
void softdep_setup_inomapdep(struct buf *, struct inode *, ino_t, int);
void softdep_setup_blkmapdep(struct buf *, struct mount *, ufs2_daddr_t,
diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
--- a/sys/ufs/ffs/ffs_softdep.c
+++ b/sys/ufs/ffs/ffs_softdep.c
@@ -621,9 +621,10 @@
}
int
-softdep_prelink(dvp, vp)
+softdep_prelink(dvp, vp, cnp)
struct vnode *dvp;
struct vnode *vp;
+ struct componentname *cnp;
{
panic("softdep_prelink called");
@@ -3384,11 +3385,13 @@
* syscall must be restarted at top level from the lookup.
*/
int
-softdep_prelink(dvp, vp)
+softdep_prelink(dvp, vp, cnp)
struct vnode *dvp;
struct vnode *vp;
+ struct componentname *cnp;
{
struct ufsmount *ump;
+ struct nameidata *ndp;
ASSERT_VOP_ELOCKED(dvp, "prelink dvp");
if (vp != NULL)
@@ -3404,37 +3407,42 @@
if (journal_space(ump, 0) || (vp != NULL && IS_SNAPSHOT(VTOI(vp))))
return (0);
+ ndp = __containerof(cnp, struct nameidata, ni_cnd);
+ if (!seqc_in_modify(ndp->ni_dvp_seqc) &&
+ vn_seqc_consistent(dvp, ndp->ni_dvp_seqc) &&
+ (vp == NULL || (!seqc_in_modify(ndp->ni_vp_seqc) &&
+ vn_seqc_consistent(vp, ndp->ni_vp_seqc))))
+ return (0);
+
stat_journal_low++;
if (vp != NULL) {
VOP_UNLOCK(dvp);
ffs_syncvnode(vp, MNT_NOWAIT, 0);
vn_lock_pair(dvp, false, vp, true);
if (dvp->v_data == NULL)
- return (ERELOOKUP);
+ goto out;
}
if (vp != NULL)
VOP_UNLOCK(vp);
ffs_syncvnode(dvp, MNT_WAIT, 0);
- VOP_UNLOCK(dvp);
-
/* Process vp before dvp as it may create .. removes. */
if (vp != NULL) {
+ VOP_UNLOCK(dvp);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
if (vp->v_data == NULL) {
vn_lock_pair(dvp, false, vp, true);
- return (ERELOOKUP);
+ goto out;
}
ACQUIRE_LOCK(ump);
process_removes(vp);
process_truncates(vp);
FREE_LOCK(ump);
VOP_UNLOCK(vp);
- }
-
- vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
- if (dvp->v_data == NULL) {
- vn_lock_pair(dvp, true, vp, false);
- return (ERELOOKUP);
+ vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
+ if (dvp->v_data == NULL) {
+ vn_lock_pair(dvp, true, vp, false);
+ goto out;
+ }
}
ACQUIRE_LOCK(ump);
@@ -3452,6 +3460,10 @@
FREE_LOCK(ump);
vn_lock_pair(dvp, false, vp, false);
+out:
+ ndp->ni_dvp_seqc = vn_seqc_read_any(dvp);
+ if (vp != NULL)
+ ndp->ni_vp_seqc = vn_seqc_read_any(vp);
return (ERELOOKUP);
}
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
@@ -105,14 +105,16 @@
static vop_accessx_t ufs_accessx;
static vop_fplookup_vexec_t ufs_fplookup_vexec;
static int ufs_chmod(struct vnode *, int, struct ucred *, struct thread *);
-static int ufs_chown(struct vnode *, uid_t, gid_t, struct ucred *, struct thread *);
+static int ufs_chown(struct vnode *, uid_t, gid_t, struct ucred *,
+ struct thread *);
static vop_close_t ufs_close;
static vop_create_t ufs_create;
static vop_stat_t ufs_stat;
static vop_getattr_t ufs_getattr;
static vop_ioctl_t ufs_ioctl;
static vop_link_t ufs_link;
-static int ufs_makeinode(int mode, struct vnode *, struct vnode **, struct componentname *, const char *);
+static int ufs_makeinode(int mode, struct vnode *, struct vnode **,
+ struct componentname *, const char *);
static vop_mmapped_t ufs_mmapped;
static vop_mkdir_t ufs_mkdir;
static vop_mknod_t ufs_mknod;
@@ -1008,7 +1010,7 @@
(VTOI(dvp)->i_flags & APPEND))
return (EPERM);
if (DOINGSUJ(dvp)) {
- error = softdep_prelink(dvp, vp);
+ error = softdep_prelink(dvp, vp, ap->a_cnp);
if (error != 0) {
MPASS(error == ERELOOKUP);
return (error);
@@ -1073,7 +1075,7 @@
#endif
if (DOINGSUJ(tdvp)) {
- error = softdep_prelink(tdvp, vp);
+ error = softdep_prelink(tdvp, vp, cnp);
if (error != 0) {
MPASS(error == ERELOOKUP);
return (error);
@@ -1145,7 +1147,7 @@
if (DOINGSUJ(dvp) && (ap->a_flags == CREATE ||
ap->a_flags == DELETE)) {
- error = softdep_prelink(dvp, NULL);
+ error = softdep_prelink(dvp, NULL, cnp);
if (error != 0) {
MPASS(error == ERELOOKUP);
return (error);
@@ -1246,6 +1248,7 @@
int error = 0;
struct mount *mp;
ino_t ino;
+ seqc_t fdvp_s, fvp_s, tdvp_s, tvp_s;
bool want_seqc_end;
want_seqc_end = false;
@@ -1269,6 +1272,8 @@
mp = NULL;
goto releout;
}
+
+ fdvp_s = fvp_s = tdvp_s = tvp_s = SEQC_MOD;
relock:
/*
* We need to acquire 2 to 4 locks depending on whether tvp is NULL
@@ -1362,10 +1367,20 @@
}
}
- if (DOINGSOFTDEP(fdvp)) {
+ if (DOINGSUJ(fdvp) &&
+ (seqc_in_modify(fdvp_s) || !vn_seqc_consistent(fdvp, fdvp_s) ||
+ seqc_in_modify(fvp_s) || !vn_seqc_consistent(fvp, fvp_s) ||
+ seqc_in_modify(tdvp_s) || !vn_seqc_consistent(tdvp, tdvp_s) ||
+ (tvp != NULL && (seqc_in_modify(tvp_s) ||
+ !vn_seqc_consistent(tvp, tvp_s))))) {
error = softdep_prerename(fdvp, fvp, tdvp, tvp);
if (error != 0) {
if (error == ERELOOKUP) {
+ fdvp_s = vn_seqc_read_any(fdvp);
+ fvp_s = vn_seqc_read_any(fvp);
+ tdvp_s = vn_seqc_read_any(tdvp);
+ if (tvp != NULL)
+ tvp_s = vn_seqc_read_any(tvp);
atomic_add_int(&rename_restarts, 1);
goto relock;
}
@@ -1947,7 +1962,7 @@
}
if (DOINGSUJ(dvp)) {
- error = softdep_prelink(dvp, NULL);
+ error = softdep_prelink(dvp, NULL, cnp);
if (error != 0) {
MPASS(error == ERELOOKUP);
return (error);
@@ -2211,7 +2226,7 @@
goto out;
}
if (DOINGSUJ(dvp)) {
- error = softdep_prelink(dvp, vp);
+ error = softdep_prelink(dvp, vp, cnp);
if (error != 0) {
MPASS(error == ERELOOKUP);
return (error);
@@ -2736,7 +2751,7 @@
return (EINVAL);
}
if (DOINGSUJ(dvp)) {
- error = softdep_prelink(dvp, NULL);
+ error = softdep_prelink(dvp, NULL, cnp);
if (error != 0) {
MPASS(error == ERELOOKUP);
return (error);

File Metadata

Mime Type
text/plain
Expires
Thu, Sep 3, 12:41 AM (14 h, 20 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
38038501
Default Alt Text
D30041.id90444.diff (19 KB)

Event Timeline