]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
os/LFNIndex: only consider alt xattr if nlink > 1
authorSage Weil <sage@redhat.com>
Sat, 19 Jul 2014 06:16:09 +0000 (23:16 -0700)
committerSamuel Just <sam.just@inktank.com>
Sun, 3 Aug 2014 19:47:10 +0000 (12:47 -0700)
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 <sage@redhat.com>
(cherry picked from commit 6fb3260d59faab1e20ebf1e44f850f85f6b8342a)

src/os/LFNIndex.cc

index 11f78d1c4ba11bf9c7da545c56164699e37861fe..faeb243b6532e5dd157180135ab46b8a99ee80dc 100644 (file)
@@ -799,6 +799,23 @@ int LFNIndex::lfn_get_name(const vector<string> &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;