@@ -1013,6 +1013,9 @@ zfs_lookup(vnode_t *dvp, const char *nm, vnode_t **vpp,
1013
1013
znode_t * zdp = VTOZ (dvp );
1014
1014
znode_t * zp ;
1015
1015
zfsvfs_t * zfsvfs = zdp -> z_zfsvfs ;
1016
+ #if __FreeBSD_version > 1300124
1017
+ seqc_t dvp_seqc ;
1018
+ #endif
1016
1019
int error = 0 ;
1017
1020
1018
1021
/*
@@ -1038,6 +1041,10 @@ zfs_lookup(vnode_t *dvp, const char *nm, vnode_t **vpp,
1038
1041
ZFS_ENTER (zfsvfs );
1039
1042
ZFS_VERIFY_ZP (zdp );
1040
1043
1044
+ #if __FreeBSD_version > 1300124
1045
+ dvp_seqc = vn_seqc_read_notmodify (dvp );
1046
+ #endif
1047
+
1041
1048
* vpp = NULL ;
1042
1049
1043
1050
if (flags & LOOKUP_XATTR ) {
@@ -1207,6 +1214,26 @@ zfs_lookup(vnode_t *dvp, const char *nm, vnode_t **vpp,
1207
1214
}
1208
1215
}
1209
1216
1217
+ #if __FreeBSD_version > 1300124
1218
+ if ((cnp -> cn_flags & ISDOTDOT ) != 0 ) {
1219
+ /*
1220
+ * FIXME: zfs_lookup_lock relocks vnodes and does nothing to
1221
+ * handle races. In particular different callers may end up
1222
+ * with different vnodes and will try to add conflicting
1223
+ * entries to the namecache.
1224
+ *
1225
+ * While finding different result may be acceptable in face
1226
+ * of concurrent modification, adding conflicting entries
1227
+ * trips over an assert in the namecache.
1228
+ *
1229
+ * Ultimately let an entry through once everything settles.
1230
+ */
1231
+ if (!vn_seqc_consistent (dvp , dvp_seqc )) {
1232
+ cnp -> cn_flags &= ~MAKEENTRY ;
1233
+ }
1234
+ }
1235
+ #endif
1236
+
1210
1237
/* Insert name into cache (as non-existent) if appropriate. */
1211
1238
if (zfsvfs -> z_use_namecache && !zfsvfs -> z_replay &&
1212
1239
error == ENOENT && (cnp -> cn_flags & MAKEENTRY ) != 0 )
0 commit comments