+ /*
+ * Update the vnode if the name/and or the parent has
+ * changed. We need to do this so that if getattrlist is
+ * called asking for ATTR_CMN_NAME, that the "most"
+ * correct name is being returned if we're not making an
+ * entry. In addition for monitored vnodes we need to
+ * kick the vnode out of the name cache. We do this so
+ * that if there are hard links in the same directory
+ * the link will not be found and a lookup will get us
+ * here to return the name of the current link. In
+ * addition by removing the name from the name cache the
+ * old name will not be found after a rename done on
+ * another client or the server. The principle reason
+ * to do this is because Finder is asking for
+ * notifications on a directory. The directory changes,
+ * Finder gets notified, reads the directory (which we
+ * have purged) and for each entry returned calls
+ * getattrlist with the name returned from
+ * readdir. gettattrlist has to call namei/lookup to
+ * resolve the name, because its not in the cache we end
+ * up here. We need to update the name so Finder will
+ * get the name it called us with.
+ *
+ * We had an imperfect solution with respect to case
+ * sensitivity. There is a test that is run in
+ * FileBuster that does renames from some name to
+ * another name differing only in case. It then reads
+ * the directory looking for the new name, after it
+ * finds that new name, it ask gettattrlist to verify
+ * that the name is the new name. Usually that works,
+ * but renames generate fsevents and fseventsd will do a
+ * lookup on the name via lstat. Since that test renames
+ * old name to new name back and forth there is a race
+ * that an fsevent will be behind and will access the
+ * file by the old name, on a case insensitive file
+ * system that will work. Problem is if we do a case
+ * sensitive compare, we're going to change the name,
+ * which the test's getattrlist verification step is
+ * going to fail. So we will check the case sensitivity
+ * of the file system and do the appropriate compare. In
+ * a rare instance for non homogeneous file systems
+ * w.r.t. pathconf we will use case sensitive compares.
+ * That could break if the file system is actually case
+ * insensitive.
+ *
+ * Note that V2 does not know the case, so we just
+ * assume case sensitivity.
+ *
+ * This is clearly not perfect due to races, but this is
+ * as good as its going to get. You can defeat the
+ * handling of hard links simply by doing:
+ *
+ * while :; do ls -l > /dev/null; done
+ *
+ * in a terminal window. Even a single ls -l can cause a
+ * race.
+ *
+ * <rant>What we really need is for the caller, that
+ * knows the name being used is valid since it got it
+ * from a readdir to use that name and not ask for the
+ * ATTR_CMN_NAME</rant>
+ */
+ if (dnp && cnp && (vp != NFSTOV(dnp))) {
+ int update_flags = vnode_ismonitored((NFSTOV(dnp))) ? VNODE_UPDATE_CACHE : 0;
+ int (*cmp)(const char *s1, const char *s2, size_t n);
+
+ cmp = nfs_case_insensitive(mp) ? strncasecmp : strncmp;
+
+ if (vp->v_name && cnp->cn_namelen && (*cmp)(cnp->cn_nameptr, vp->v_name, cnp->cn_namelen))
+ update_flags |= VNODE_UPDATE_NAME;
+ if ((vp->v_name == NULL && cnp->cn_namelen != 0) || (vp->v_name != NULL && cnp->cn_namelen == 0))
+ update_flags |= VNODE_UPDATE_NAME;
+ if (vnode_parent(vp) != NFSTOV(dnp))
+ update_flags |= VNODE_UPDATE_PARENT;
+ if (update_flags)
+ vnode_update_identity(vp, NFSTOV(dnp), cnp->cn_nameptr, cnp->cn_namelen, 0, update_flags);
+ }
+