summaryrefslogtreecommitdiffstats
path: root/src/cls/cephfs/cls_cephfs_client.cc
blob: d776443fe996205b4a7dd6eea2c7a5d86a1214da (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
/*
 * Ceph - scalable distributed file system
 *
 * Copyright (C) 2015 Red Hat
 *
 * This is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1, as published by the Free Software
 * Foundation.  See file COPYING.
 *
 */



#include "include/rados/librados.hpp"
#include "mds/CInode.h"

#include "cls_cephfs_client.h"

using ceph::bufferlist;
using ceph::decode;

#define XATTR_CEILING "scan_ceiling"
#define XATTR_MAX_MTIME "scan_max_mtime"
#define XATTR_MAX_SIZE "scan_max_size"

int ClsCephFSClient::accumulate_inode_metadata(
  librados::IoCtx &ctx,
  inodeno_t inode_no,
  const uint64_t obj_index,
  const uint64_t obj_size,
  const time_t mtime)
{
  AccumulateArgs args(
      obj_index,
      obj_size,
      mtime,
      XATTR_CEILING,
      XATTR_MAX_MTIME,
      XATTR_MAX_SIZE);

  // Generate 0th object name, where we will accumulate sizes/mtimes
  object_t zeroth_object = InodeStore::get_object_name(inode_no, frag_t(), "");

  // Construct a librados operation invoking our class method
  librados::ObjectReadOperation op;
  bufferlist inbl;
  args.encode(inbl);
  op.exec("cephfs", "accumulate_inode_metadata", inbl);

  // Execute op
  bufferlist outbl;
  return ctx.operate(zeroth_object.name, &op, &outbl);
}

int ClsCephFSClient::delete_inode_accumulate_result(
    librados::IoCtx &ctx,
    const std::string &oid)
{
  librados::ObjectWriteOperation op;

  // Remove xattrs from object
  //
  op.rmxattr(XATTR_CEILING);
  op.rmxattr(XATTR_MAX_SIZE);
  op.rmxattr(XATTR_MAX_MTIME);

  return (ctx.operate(oid, &op));
}

int ClsCephFSClient::fetch_inode_accumulate_result(
  librados::IoCtx &ctx,
  const std::string &oid,
  inode_backtrace_t *backtrace,
  file_layout_t *layout,
  AccumulateResult *result)
{
  ceph_assert(backtrace != NULL);
  ceph_assert(result != NULL);

  librados::ObjectReadOperation op;

  int scan_ceiling_r = 0;
  bufferlist scan_ceiling_bl;
  op.getxattr(XATTR_CEILING, &scan_ceiling_bl, &scan_ceiling_r);

  int scan_max_size_r = 0;
  bufferlist scan_max_size_bl;
  op.getxattr(XATTR_MAX_SIZE, &scan_max_size_bl, &scan_max_size_r);

  int scan_max_mtime_r = 0;
  bufferlist scan_max_mtime_bl;
  op.getxattr(XATTR_MAX_MTIME, &scan_max_mtime_bl, &scan_max_mtime_r);

  int parent_r = 0;
  bufferlist parent_bl;
  op.getxattr("parent", &parent_bl, &parent_r);
  op.set_op_flags2(librados::OP_FAILOK);

  int layout_r = 0;
  bufferlist layout_bl;
  op.getxattr("layout", &layout_bl, &layout_r);
  op.set_op_flags2(librados::OP_FAILOK);

  bufferlist op_bl;
  int r = ctx.operate(oid, &op, &op_bl);
  if (r < 0) {
    return r;
  }

  // Load scan_ceiling
  try {
    auto scan_ceiling_bl_iter = scan_ceiling_bl.cbegin();
    ObjCeiling ceiling;
    ceiling.decode(scan_ceiling_bl_iter);
    result->ceiling_obj_index = ceiling.id;
    result->ceiling_obj_size = ceiling.size;
  } catch (const ceph::buffer::error &err) {
    //dout(4) << "Invalid size attr on '" << oid << "'" << dendl;
    return -EINVAL;
  }

  // Load scan_max_size
  try {
    auto scan_max_size_bl_iter = scan_max_size_bl.cbegin();
    decode(result->max_obj_size, scan_max_size_bl_iter);
  } catch (const ceph::buffer::error &err) {
    //dout(4) << "Invalid size attr on '" << oid << "'" << dendl;
    return -EINVAL;
  }

  // Load scan_max_mtime
  try {
    auto scan_max_mtime_bl_iter = scan_max_mtime_bl.cbegin();
    decode(result->max_mtime, scan_max_mtime_bl_iter);
  } catch (const ceph::buffer::error &err) {
    //dout(4) << "Invalid size attr on '" << oid << "'" << dendl;
    return -EINVAL;
  }

  // Deserialize backtrace
  if (parent_bl.length()) {
    try {
      auto q = parent_bl.cbegin();
      backtrace->decode(q);
    } catch (ceph::buffer::error &e) {
      //dout(4) << "Corrupt backtrace on '" << oid << "': " << e << dendl;
      return -EINVAL;
    }
  }

  // Deserialize layout
  if (layout_bl.length()) {
    try {
      auto q = layout_bl.cbegin();
      decode(*layout, q);
    } catch (ceph::buffer::error &e) {
      return -EINVAL;
    }
  }

  return 0;
}

void ClsCephFSClient::build_tag_filter(
          const std::string &scrub_tag,
          bufferlist *out_bl)
{
  ceph_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);
}