1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2015 Red Hat
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
19 #include "objclass/objclass.h"
21 #include "cls_cephfs.h"
27 std::ostream &operator<<(std::ostream &out, const ObjCeiling &in)
29 out << "id: " << in.id << " size: " << in.size;
35 * Set a named xattr to a given value, if and only if the xattr
36 * is not already set to a greater value.
38 * If the xattr is missing, then it is set to the input integer.
40 * @param xattr_name: name of xattr to compare against and set
41 * @param input_val: candidate new value, of ::encode()'able type
42 * @returns 0 on success (irrespective of whether our new value
43 * was used) else an error code
46 static int set_if_greater(cls_method_context_t hctx,
47 const std::string &xattr_name, const A input_val)
49 bufferlist existing_val_bl;
52 int r = cls_cxx_getxattr(hctx, xattr_name.c_str(), &existing_val_bl);
53 if (r == -ENOENT || existing_val_bl.length() == 0) {
56 bufferlist::iterator existing_p = existing_val_bl.begin();
59 ::decode(existing_val, existing_p);
60 if (!existing_p.end()) {
61 // Trailing junk? Consider it invalid and overwrite
64 // Valid existing value, do comparison
65 set_val = input_val > existing_val;
67 } catch (const buffer::error &err) {
68 // Corrupt or empty existing value, overwrite it
75 // Conditionally set the new xattr
78 ::encode(input_val, set_bl);
79 return cls_cxx_setxattr(hctx, xattr_name.c_str(), &set_bl);
85 static int accumulate_inode_metadata(cls_method_context_t hctx,
86 bufferlist *in, bufferlist *out)
94 bufferlist::iterator q = in->begin();
98 } catch (const buffer::error &err) {
102 ObjCeiling ceiling(args.obj_index, args.obj_size);
103 r = set_if_greater(hctx, args.obj_xattr_name, ceiling);
108 r = set_if_greater(hctx, args.mtime_xattr_name, args.mtime);
113 r = set_if_greater(hctx, args.obj_size_xattr_name, args.obj_size);
121 // I want to select objects that have a name ending 00000000
122 // and an xattr (scrub_tag) not equal to a specific value.
123 // This is so special case that we can't really pretend it's
124 // generic, so just fess up and call this the cephfs filter.
125 class PGLSCephFSFilter : public PGLSFilter {
127 std::string scrub_tag;
129 int init(bufferlist::iterator& params) override {
131 InodeTagFilterArgs args;
133 scrub_tag = args.scrub_tag;
134 } catch (buffer::error &e) {
138 if (scrub_tag.empty()) {
141 xattr = "_scrub_tag";
147 ~PGLSCephFSFilter() override {}
148 bool reject_empty_xattr() override { return false; }
149 bool filter(const hobject_t &obj, bufferlist& xattr_data,
150 bufferlist& outdata) override;
153 bool PGLSCephFSFilter::filter(const hobject_t &obj,
154 bufferlist& xattr_data, bufferlist& outdata)
156 const std::string need_ending = ".00000000";
157 const std::string &obj_name = obj.oid.name;
159 if (obj_name.length() < need_ending.length()) {
163 const bool match = obj_name.compare (obj_name.length() - need_ending.length(), need_ending.length(), need_ending) == 0;
168 if (!scrub_tag.empty() && xattr_data.length() > 0) {
169 std::string tag_ondisk;
170 bufferlist::iterator q = xattr_data.begin();
172 ::decode(tag_ondisk, q);
173 if (tag_ondisk == scrub_tag)
175 } catch (const buffer::error &err) {
182 PGLSFilter *inode_tag_filter()
184 return new PGLSCephFSFilter();
190 * We do two things here: we register the new class, and then register
191 * all of the class's methods.
195 // this log message, at level 0, will always appear in the ceph-osd
197 CLS_LOG(0, "loading cephfs");
199 cls_handle_t h_class;
200 cls_method_handle_t h_accumulate_inode_metadata;
202 cls_register("cephfs", &h_class);
203 cls_register_cxx_method(h_class, "accumulate_inode_metadata",
204 CLS_METHOD_WR | CLS_METHOD_RD,
205 accumulate_inode_metadata, &h_accumulate_inode_metadata);
208 cls_register_cxx_filter(h_class, "inode_tag", inode_tag_filter);