From: Sage Weil Date: Thu, 7 Aug 2014 00:04:02 +0000 (-0700) Subject: os/FileStore: force any new xattr into omap on E2BIG X-Git-Tag: v0.67.10~11 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=0a1cea58641c4584b85165755145d8d0288f4f22;p=ceph.git os/FileStore: force any new xattr into omap on E2BIG If we have a huge xattr (or many little ones), the _fgetattrs() for the inline_set will fail with E2BIG. The conditions later where we decide whether to clean up the old xattr will then also fail. Will *will* put the xattr in omap, but the non-omap version isn't cleaned up. Fix this by setting a flag if we get E2BIG that the inline_set is known to be incomplete. In that case, take the conservative step of assuming the xattr might be present and chain_fremovexattr(). Ignore any error because it might not be there. This is clearly harmless in the general case because it won't be there. If it is, we will hopefully remove enough xattrs that the E2BIG condition will go away (usually by removing some really big chained xattr). See bug #7779. This is a backport of 26750fcfe8d766874513e57981565adde2e6d8c7. Reviewed-by: Yehuda Sadeh Reviewed-by: Samuel Just Signed-off-by: Sage Weil --- diff --git a/src/os/FileStore.cc b/src/os/FileStore.cc index 58b23f204af3..247a80b196dd 100644 --- a/src/os/FileStore.cc +++ b/src/os/FileStore.cc @@ -4065,14 +4065,18 @@ int FileStore::_setattrs(coll_t cid, const hobject_t& oid, map set omap_remove; map inline_set; map inline_to_set; + bool incomplete_inline = false; FDRef fd; int r = lfn_open(cid, oid, false, &fd); if (r < 0) { goto out; } r = _fgetattrs(**fd, inline_set, false); + incomplete_inline = (r == -E2BIG); assert(!m_filestore_fail_eio || r != -EIO); - dout(15) << "setattrs " << cid << "/" << oid << dendl; + dout(15) << "setattrs " << cid << "/" << oid + << (incomplete_inline ? " (incomplete_inline, forcing omap)" : "") + << dendl; r = 0; for (map::iterator p = aset.begin(); p != aset.end(); @@ -4080,6 +4084,12 @@ int FileStore::_setattrs(coll_t cid, const hobject_t& oid, map char n[CHAIN_XATTR_MAX_NAME_LEN]; get_attrname(p->first.c_str(), n, CHAIN_XATTR_MAX_NAME_LEN); + if (incomplete_inline) { + chain_fremovexattr(**fd, n); // ignore any error + omap_set[p->first].push_back(p->second); + continue; + } + if (p->second.length() > g_conf->filestore_max_inline_xattr_size) { if (inline_set.count(p->first)) { inline_set.erase(p->first);