From: John Spray Date: Fri, 17 Jul 2015 13:19:57 +0000 (+0100) Subject: cls_cephfs: add PGLSCephFSFilter X-Git-Tag: v10.0.2~134^2~2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=786d111a972471a85032c05bdbfb9b85dcdc1cb2;p=ceph.git cls_cephfs: add PGLSCephFSFilter Special purpose filter for use with CephFS disaster recovery. Fixes: #12145 Signed-off-by: John Spray --- diff --git a/src/cls/cephfs/cls_cephfs.cc b/src/cls/cephfs/cls_cephfs.cc index f58f0de39af..8f54e3a6973 100644 --- a/src/cls/cephfs/cls_cephfs.cc +++ b/src/cls/cephfs/cls_cephfs.cc @@ -123,6 +123,72 @@ static int accumulate_inode_metadata(cls_method_context_t hctx, return 0; } +// I want to select objects that have a name ending 00000000 +// and an xattr (scrub_tag) not equal to a specific value. +// This is so special case that we can't really pretend it's +// generic, so just fess up and call this the cephfs filter. +class PGLSCephFSFilter : public PGLSFilter { +protected: + std::string scrub_tag; +public: + int init(bufferlist::iterator& params) { + try { + InodeTagFilterArgs args; + args.decode(params); + scrub_tag = args.scrub_tag; + } catch (buffer::error &e) { + return -EINVAL; + } + + if (scrub_tag.empty()) { + xattr = ""; + } else { + xattr = "_scrub_tag"; + } + + return 0; + } + + virtual ~PGLSCephFSFilter() {} + virtual bool reject_empty_xattr() { return false; } + virtual bool filter(const hobject_t &obj, bufferlist& xattr_data, + bufferlist& outdata); +}; + +bool PGLSCephFSFilter::filter(const hobject_t &obj, + bufferlist& xattr_data, bufferlist& outdata) +{ + const std::string need_ending = ".00000000"; + const std::string &obj_name = obj.oid.name; + + if (obj_name.length() < need_ending.length()) { + return false; + } + + const bool match = obj_name.compare (obj_name.length() - need_ending.length(), need_ending.length(), need_ending) == 0; + if (!match) { + return false; + } + + if (!scrub_tag.empty() && xattr_data.length() > 0) { + std::string tag_ondisk; + bufferlist::iterator q = xattr_data.begin(); + try { + ::decode(tag_ondisk, q); + if (tag_ondisk == scrub_tag) + return false; + } catch (const buffer::error &err) { + } + } + + return true; +} + +PGLSFilter *inode_tag_filter() +{ + return new PGLSCephFSFilter(); +} + /** * initialize class * @@ -139,5 +205,8 @@ void __cls_init() cls_register_cxx_method(h_class, "accumulate_inode_metadata", CLS_METHOD_WR | CLS_METHOD_RD, accumulate_inode_metadata, &h_accumulate_inode_metadata); + + // A PGLS filter + cls_register_cxx_filter(h_class, "inode_tag", inode_tag_filter); } diff --git a/src/cls/cephfs/cls_cephfs.h b/src/cls/cephfs/cls_cephfs.h index d4a5f23811d..ca631c66d90 100644 --- a/src/cls/cephfs/cls_cephfs.h +++ b/src/cls/cephfs/cls_cephfs.h @@ -108,6 +108,26 @@ public: } }; +class InodeTagFilterArgs +{ + public: + std::string scrub_tag; + + void encode(bufferlist &bl) const + { + ENCODE_START(1, 1, bl); + ::encode(scrub_tag, bl); + ENCODE_FINISH(bl); + } + + void decode(bufferlist::iterator &bl) + { + DECODE_START(1, bl); + ::decode(scrub_tag, bl); + DECODE_FINISH(bl); + } +}; + class AccumulateResult { public: diff --git a/src/cls/cephfs/cls_cephfs_client.cc b/src/cls/cephfs/cls_cephfs_client.cc index c471fdeb70a..dc945282b90 100644 --- a/src/cls/cephfs/cls_cephfs_client.cc +++ b/src/cls/cephfs/cls_cephfs_client.cc @@ -144,3 +144,18 @@ int ClsCephFSClient::fetch_inode_accumulate_result( return 0; } +void ClsCephFSClient::build_tag_filter( + const std::string &scrub_tag, + bufferlist *out_bl) +{ + assert(out_bl != NULL); + + // Leading part of bl is un-versioned string naming the filter + ::encode(std::string("cephfs.inode_tag"), *out_bl); + + // Filter-specific part of the bl: in our case this is a versioned structure + InodeTagFilterArgs args; + args.scrub_tag = scrub_tag; + args.encode(*out_bl); +} + diff --git a/src/cls/cephfs/cls_cephfs_client.h b/src/cls/cephfs/cls_cephfs_client.h index 45d3c4bb699..ddd84566d06 100644 --- a/src/cls/cephfs/cls_cephfs_client.h +++ b/src/cls/cephfs/cls_cephfs_client.h @@ -22,5 +22,9 @@ class ClsCephFSClient inode_backtrace_t *backtrace, ceph_file_layout *layout, AccumulateResult *result); + + static void build_tag_filter( + const std::string &scrub_tag, + bufferlist *out_bl); };