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
);