From: Sage Weil Date: Sat, 19 Jul 2014 06:16:09 +0000 (-0700) Subject: os/LFNIndex: only consider alt xattr if nlink > 1 X-Git-Tag: v0.80.6~103^2~2^2^2~2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=b213866eac422a6ac6aeacd3ab4741a6421ce20c;p=ceph.git os/LFNIndex: only consider alt xattr if nlink > 1 If we are doing a lookup, the main xattr fails, we'll check if there is an alt xattr. If it exists, but the nlink on the inode is only 1, we will kill the xattr. This cleans up the mess left over by an incomplete lfn_unlink operation. This resolves the problem with an lfn_link to a second long name that hashes to the same short_name: we will ignore the old name the moment the old link goes away. Fixes: #8701 Signed-off-by: Sage Weil (cherry picked from commit 6fb3260d59faab1e20ebf1e44f850f85f6b8342a) --- diff --git a/src/os/LFNIndex.cc b/src/os/LFNIndex.cc index 11f78d1c4ba1..faeb243b6532 100644 --- a/src/os/LFNIndex.cc +++ b/src/os/LFNIndex.cc @@ -799,6 +799,23 @@ int LFNIndex::lfn_get_name(const vector &path, r = chain_getxattr(candidate_path.c_str(), get_alt_lfn_attr().c_str(), buf, sizeof(buf)); if (r > 0) { + // only consider alt name if nlink > 1 + struct stat st; + int rc = ::stat(candidate_path.c_str(), &st); + if (rc < 0) + return -errno; + if (st.st_nlink <= 1) { + // left over from incomplete unlink, remove + maybe_inject_failure(); + dout(20) << __func__ << " found extra alt attr for " << candidate_path + << ", long name " << string(buf, r) << dendl; + rc = chain_removexattr(candidate_path.c_str(), + get_alt_lfn_attr().c_str()); + maybe_inject_failure(); + if (rc < 0) + return rc; + continue; + } buf[MIN((int)sizeof(buf) - 1, r)] = '\0'; if (!strcmp(buf, full_name.c_str())) { dout(20) << __func__ << " used alt attr for " << full_name << dendl;