git: 4eaf9609fe42 - main - nullfs: provide custom null_rename bypass
Konstantin Belousov
kib at FreeBSD.org
Tue Jul 27 16:59:03 UTC 2021
The branch main has been updated by kib:
URL: https://cgit.FreeBSD.org/src/commit/?id=4eaf9609fe42878eccaaf5fe1873f792074a62e4
commit 4eaf9609fe42878eccaaf5fe1873f792074a62e4
Author: Konstantin Belousov <kib at FreeBSD.org>
AuthorDate: 2021-07-24 15:05:58 +0000
Commit: Konstantin Belousov <kib at FreeBSD.org>
CommitDate: 2021-07-27 16:58:48 +0000
nullfs: provide custom null_rename bypass
fdvp and fvp vnodes are not locked, and race with reclaim cannot be handled
by the generic bypass routine.
Reported and tested by: pho
Reviewed by: markj
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
Differential revision: https://reviews.freebsd.org/D31310
---
sys/fs/nullfs/null_vnops.c | 68 ++++++++++++++++++++++++++++++++++++++--------
1 file changed, 57 insertions(+), 11 deletions(-)
diff --git a/sys/fs/nullfs/null_vnops.c b/sys/fs/nullfs/null_vnops.c
index ce67d2760418..e3a320a22bfa 100644
--- a/sys/fs/nullfs/null_vnops.c
+++ b/sys/fs/nullfs/null_vnops.c
@@ -656,32 +656,78 @@ static int
null_rename(struct vop_rename_args *ap)
{
struct vnode *fdvp, *fvp, *tdvp, *tvp;
- struct null_node *tnn;
+ struct vnode *lfdvp, *lfvp, *ltdvp, *ltvp;
+ struct null_node *fdnn, *fnn, *tdnn, *tnn;
+ int error;
tdvp = ap->a_tdvp;
fvp = ap->a_fvp;
fdvp = ap->a_fdvp;
tvp = ap->a_tvp;
+ lfdvp = NULL;
/* Check for cross-device rename. */
if ((fvp->v_mount != tdvp->v_mount) ||
(tvp != NULL && fvp->v_mount != tvp->v_mount)) {
- if (tdvp == tvp)
- vrele(tdvp);
- else
- vput(tdvp);
- if (tvp)
- vput(tvp);
- vrele(fdvp);
- vrele(fvp);
- return (EXDEV);
+ error = EXDEV;
+ goto upper_err;
+ }
+
+ VI_LOCK(fdvp);
+ fdnn = VTONULL(fdvp);
+ if (fdnn == NULL) { /* fdvp is not locked, can be doomed */
+ VI_UNLOCK(fdvp);
+ error = ENOENT;
+ goto upper_err;
}
+ lfdvp = fdnn->null_lowervp;
+ vref(lfdvp);
+ VI_UNLOCK(fdvp);
+
+ VI_LOCK(fvp);
+ fnn = VTONULL(fvp);
+ if (fnn == NULL) {
+ VI_UNLOCK(fvp);
+ error = ENOENT;
+ goto upper_err;
+ }
+ lfvp = fnn->null_lowervp;
+ vref(lfvp);
+ VI_UNLOCK(fvp);
+
+ tdnn = VTONULL(tdvp);
+ ltdvp = tdnn->null_lowervp;
+ vref(ltdvp);
if (tvp != NULL) {
tnn = VTONULL(tvp);
+ ltvp = tnn->null_lowervp;
+ vref(ltvp);
tnn->null_flags |= NULLV_DROP;
+ } else {
+ ltvp = NULL;
}
- return (null_bypass((struct vop_generic_args *)ap));
+
+ error = VOP_RENAME(lfdvp, lfvp, ap->a_fcnp, ltdvp, ltvp, ap->a_tcnp);
+ vrele(fdvp);
+ vrele(fvp);
+ vrele(tdvp);
+ if (tvp != NULL)
+ vrele(tvp);
+ return (error);
+
+upper_err:
+ if (tdvp == tvp)
+ vrele(tdvp);
+ else
+ vput(tdvp);
+ if (tvp)
+ vput(tvp);
+ if (lfdvp != NULL)
+ vrele(lfdvp);
+ vrele(fdvp);
+ vrele(fvp);
+ return (error);
}
static int
More information about the dev-commits-src-all
mailing list