]> git.apps.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)
committerSage Weil <sage@redhat.com>
Wed, 23 Jul 2014 21:48:14 +0000 (14:48 -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>
src/os/LFNIndex.cc

index f6c56d489539eefadca6c9b03bdf0a3711a48b22..c021668f15921dab7e317107601079c0acebd409 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;