]> git.proxmox.com Git - ceph.git/blob - ceph/src/tools/rados/PoolDump.cc
9bfafa107dc652f7da25ce44e8123bc8ed2e2b4b
[ceph.git] / ceph / src / tools / rados / PoolDump.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2015 Red Hat
7 *
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.
12 *
13 */
14
15 #include "include/rados/librados.hpp"
16 #include "common/errno.h"
17
18 #include "PoolDump.h"
19
20 using namespace librados;
21
22 #define dout_context g_ceph_context
23 #define dout_subsys ceph_subsys_rados
24
25 /**
26 * Export RADOS objects from a live cluster
27 * to a serialized format via a file descriptor.
28 *
29 * @returns 0 on success, else error code
30 */
31 int PoolDump::dump(IoCtx *io_ctx)
32 {
33 ceph_assert(io_ctx != NULL);
34
35 int r = 0;
36 write_super();
37
38 r = write_simple(TYPE_POOL_BEGIN, file_fd);
39 if (r != 0) {
40 return r;
41 }
42
43 io_ctx->set_namespace(all_nspaces);
44 librados::NObjectIterator i = io_ctx->nobjects_begin();
45
46 librados::NObjectIterator i_end = io_ctx->nobjects_end();
47 for (; i != i_end; ++i) {
48 const std::string oid = i->get_oid();
49 dout(10) << "OID '" << oid << "'" << dendl;
50
51 // Compose OBJECT_BEGIN
52 // ====================
53 object_begin obj_begin;
54 obj_begin.hoid.hobj.oid = i->get_oid();
55 obj_begin.hoid.hobj.nspace = i->get_nspace();
56 obj_begin.hoid.hobj.set_key(i->get_locator());
57
58 // Only output head, RadosImport only wants that
59 obj_begin.hoid.hobj.snap = CEPH_NOSNAP;
60
61 // Skip setting object_begin.oi, RadosImport doesn't care
62
63 r = write_section(TYPE_OBJECT_BEGIN, obj_begin, file_fd);
64 if (r != 0) {
65 return r;
66 }
67
68 // Compose TYPE_DATA chunks
69 // ========================
70 const uint32_t op_size = 4096 * 1024;
71 uint64_t offset = 0;
72 io_ctx->set_namespace(i->get_nspace());
73 io_ctx->locator_set_key(i->get_locator());
74 while (true) {
75 bufferlist outdata;
76 r = io_ctx->read(oid, outdata, op_size, offset);
77 if (r <= 0) {
78 // Error or no data
79 break;
80 }
81
82 r = write_section(TYPE_DATA,
83 data_section(offset, outdata.length(), outdata), file_fd);
84 if (r != 0) {
85 // Output stream error
86 return r;
87 }
88
89 if (outdata.length() < op_size) {
90 // No more data
91 break;
92 }
93 offset += outdata.length();
94 }
95
96 // Compose TYPE_ATTRS chunk
97 // ========================
98 std::map<std::string, bufferlist> raw_xattrs;
99 std::map<std::string, bufferlist> xattrs;
100 r = io_ctx->getxattrs(oid, raw_xattrs);
101 if (r < 0) {
102 cerr << "error getting xattr set " << oid << ": " << cpp_strerror(r)
103 << std::endl;
104 return r;
105 }
106 // Prepend "_" to mimic how user keys are represented in a pg export
107 for (std::map<std::string, bufferlist>::iterator i = raw_xattrs.begin();
108 i != raw_xattrs.end(); ++i) {
109 std::pair< std::string, bufferlist> item(std::string("_") + std::string(i->first.c_str()), i->second);
110 xattrs.insert(item);
111 }
112 r = write_section(TYPE_ATTRS, attr_section(xattrs), file_fd);
113 if (r != 0) {
114 return r;
115 }
116
117 // Compose TYPE_OMAP_HDR section
118 // =============================
119 bufferlist omap_header;
120 r = io_ctx->omap_get_header(oid, &omap_header);
121 if (r < 0) {
122 cerr << "error getting omap header " << oid
123 << ": " << cpp_strerror(r) << std::endl;
124 return r;
125 }
126 r = write_section(TYPE_OMAP_HDR, omap_hdr_section(omap_header), file_fd);
127 if (r != 0) {
128 return r;
129 }
130
131 // Compose TYPE_OMAP
132 int MAX_READ = 512;
133 string last_read = "";
134 do {
135 map<string, bufferlist> values;
136 r = io_ctx->omap_get_vals(oid, last_read, MAX_READ, &values);
137 if (r < 0) {
138 cerr << "error getting omap keys " << oid << ": "
139 << cpp_strerror(r) << std::endl;
140 return r;
141 }
142 if (values.size()) {
143 last_read = values.rbegin()->first;
144 } else {
145 break;
146 }
147
148 r = write_section(TYPE_OMAP, omap_section(values), file_fd);
149 if (r != 0) {
150 return r;
151 }
152 r = values.size();
153 } while (r == MAX_READ);
154
155 // Close object
156 // =============
157 r = write_simple(TYPE_OBJECT_END, file_fd);
158 if (r != 0) {
159 return r;
160 }
161 }
162
163 r = write_simple(TYPE_POOL_END, file_fd);
164 #if defined(__linux__)
165 if (file_fd != STDOUT_FILENO)
166 posix_fadvise(file_fd, 0, 0, POSIX_FADV_DONTNEED);
167 #endif
168 return r;
169 }