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.
20 #include "objclass/objclass.h"
22 #include "cls_cephfs.h"
28 std::ostream
&operator<<(std::ostream
&out
, const ObjCeiling
&in
)
30 out
<< "id: " << in
.id
<< " size: " << in
.size
;
36 * Set a named xattr to a given value, if and only if the xattr
37 * is not already set to a greater value.
39 * If the xattr is missing, then it is set to the input integer.
41 * @param xattr_name: name of xattr to compare against and set
42 * @param input_val: candidate new value, of ::encode()'able type
43 * @returns 0 on success (irrespective of whether our new value
44 * was used) else an error code
47 static int set_if_greater(cls_method_context_t hctx
,
48 const std::string
&xattr_name
, const A input_val
)
50 bufferlist existing_val_bl
;
53 int r
= cls_cxx_getxattr(hctx
, xattr_name
.c_str(), &existing_val_bl
);
54 if (r
== -ENOENT
|| existing_val_bl
.length() == 0) {
57 bufferlist::iterator existing_p
= existing_val_bl
.begin();
60 ::decode(existing_val
, existing_p
);
61 if (!existing_p
.end()) {
62 // Trailing junk? Consider it invalid and overwrite
65 // Valid existing value, do comparison
66 set_val
= input_val
> existing_val
;
68 } catch (const buffer::error
&err
) {
69 // Corrupt or empty existing value, overwrite it
76 // Conditionally set the new xattr
79 ::encode(input_val
, set_bl
);
80 return cls_cxx_setxattr(hctx
, xattr_name
.c_str(), &set_bl
);
86 static int accumulate_inode_metadata(cls_method_context_t hctx
,
87 bufferlist
*in
, bufferlist
*out
)
95 bufferlist::iterator q
= in
->begin();
99 } catch (const buffer::error
&err
) {
103 ObjCeiling
ceiling(args
.obj_index
, args
.obj_size
);
104 r
= set_if_greater(hctx
, args
.obj_xattr_name
, ceiling
);
109 r
= set_if_greater(hctx
, args
.mtime_xattr_name
, args
.mtime
);
114 r
= set_if_greater(hctx
, args
.obj_size_xattr_name
, args
.obj_size
);
122 // I want to select objects that have a name ending 00000000
123 // and an xattr (scrub_tag) not equal to a specific value.
124 // This is so special case that we can't really pretend it's
125 // generic, so just fess up and call this the cephfs filter.
126 class PGLSCephFSFilter
: public PGLSFilter
{
128 std::string scrub_tag
;
130 int init(bufferlist::iterator
& params
) override
{
132 InodeTagFilterArgs args
;
134 scrub_tag
= args
.scrub_tag
;
135 } catch (buffer::error
&e
) {
139 if (scrub_tag
.empty()) {
142 xattr
= "_scrub_tag";
148 ~PGLSCephFSFilter() override
{}
149 bool reject_empty_xattr() override
{ return false; }
150 bool filter(const hobject_t
&obj
, bufferlist
& xattr_data
,
151 bufferlist
& outdata
) override
;
154 bool PGLSCephFSFilter::filter(const hobject_t
&obj
,
155 bufferlist
& xattr_data
, bufferlist
& outdata
)
157 const std::string need_ending
= ".00000000";
158 const std::string
&obj_name
= obj
.oid
.name
;
160 if (obj_name
.length() < need_ending
.length()) {
164 const bool match
= obj_name
.compare (obj_name
.length() - need_ending
.length(), need_ending
.length(), need_ending
) == 0;
169 if (!scrub_tag
.empty() && xattr_data
.length() > 0) {
170 std::string tag_ondisk
;
171 bufferlist::iterator q
= xattr_data
.begin();
173 ::decode(tag_ondisk
, q
);
174 if (tag_ondisk
== scrub_tag
)
176 } catch (const buffer::error
&err
) {
183 PGLSFilter
*inode_tag_filter()
185 return new PGLSCephFSFilter();
191 * We do two things here: we register the new class, and then register
192 * all of the class's methods.
196 // this log message, at level 0, will always appear in the ceph-osd
198 CLS_LOG(0, "loading cephfs");
200 cls_handle_t h_class
;
201 cls_method_handle_t h_accumulate_inode_metadata
;
203 cls_register("cephfs", &h_class
);
204 cls_register_cxx_method(h_class
, "accumulate_inode_metadata",
205 CLS_METHOD_WR
| CLS_METHOD_RD
,
206 accumulate_inode_metadata
, &h_accumulate_inode_metadata
);
209 cls_register_cxx_filter(h_class
, "inode_tag", inode_tag_filter
);