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) 2004-2006 Sage Weil <sage@newdream.net>
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.
18 #include "common/ceph_argparse.h"
19 #include "common/errno.h"
20 #include "common/safe_io.h"
21 #include "mon/health_check.h"
25 #include "global/global_init.h"
26 #include "osd/OSDMap.h"
31 cout
<< " usage: [--print] <mapfilename>" << std::endl
;
32 cout
<< " --create-from-conf creates an osd map with default configurations" << std::endl
;
33 cout
<< " --createsimple <numosd> [--clobber] [--pg-bits <bitsperosd>] [--pgp-bits <bits>] creates a relatively generic OSD map with <numosd> devices" << std::endl
;
34 cout
<< " --pgp-bits <bits> pgp_num map attribute will be shifted by <bits>" << std::endl
;
35 cout
<< " --pg-bits <bits> pg_num map attribute will be shifted by <bits>" << std::endl
;
36 cout
<< " --clobber allows osdmaptool to overwrite <mapfilename> if it already exists" << std::endl
;
37 cout
<< " --export-crush <file> write osdmap's crush map to <file>" << std::endl
;
38 cout
<< " --import-crush <file> replace osdmap's crush map with <file>" << std::endl
;
39 cout
<< " --health dump health checks" << std::endl
;
40 cout
<< " --test-map-pgs [--pool <poolid>] [--pg_num <pg_num>] [--range-first <first> --range-last <last>] map all pgs" << std::endl
;
41 cout
<< " --test-map-pgs-dump [--pool <poolid>] [--range-first <first> --range-last <last>] map all pgs" << std::endl
;
42 cout
<< " --test-map-pgs-dump-all [--pool <poolid>] [--range-first <first> --range-last <last>] map all pgs to osds" << std::endl
;
43 cout
<< " --mark-up-in mark osds up and in (but do not persist)" << std::endl
;
44 cout
<< " --mark-out <osdid> mark an osd as out (but do not persist)" << std::endl
;
45 cout
<< " --with-default-pool include default pool when creating map" << std::endl
;
46 cout
<< " --clear-temp clear pg_temp and primary_temp" << std::endl
;
47 cout
<< " --test-random do random placements" << std::endl
;
48 cout
<< " --test-map-pg <pgid> map a pgid to osds" << std::endl
;
49 cout
<< " --test-map-object <objectname> [--pool <poolid>] map an object to osds"
51 cout
<< " --upmap-cleanup <file> clean up pg_upmap[_items] entries, writing" << std::endl
;
52 cout
<< " commands to <file> [default: - for stdout]" << std::endl
;
53 cout
<< " --upmap <file> calculate pg upmap entries to balance pg layout" << std::endl
;
54 cout
<< " writing commands to <file> [default: - for stdout]" << std::endl
;
55 cout
<< " --upmap-max <max-count> set max upmap entries to calculate [default: 10]" << std::endl
;
56 cout
<< " --upmap-deviation <max-deviation>" << std::endl
;
57 cout
<< " max deviation from target [default: 5]" << std::endl
;
58 cout
<< " --upmap-pool <poolname> restrict upmap balancing to 1 or more pools" << std::endl
;
59 cout
<< " --upmap-save write modified OSDMap with upmap changes" << std::endl
;
60 cout
<< " --upmap-active Act like an active balancer, keep applying changes until balanced" << std::endl
;
61 cout
<< " --dump <format> displays the map in plain text when <format> is 'plain', 'json' if specified format is not supported" << std::endl
;
62 cout
<< " --tree displays a tree of the map" << std::endl
;
63 cout
<< " --test-crush [--range-first <first> --range-last <last>] map pgs to acting osds" << std::endl
;
67 void print_inc_upmaps(const OSDMap::Incremental
& pending_inc
, int fd
)
70 for (auto& i
: pending_inc
.old_pg_upmap
) {
71 ss
<< "ceph osd rm-pg-upmap " << i
<< std::endl
;
73 for (auto& i
: pending_inc
.new_pg_upmap
) {
74 ss
<< "ceph osd pg-upmap " << i
.first
;
75 for (auto osd
: i
.second
) {
80 for (auto& i
: pending_inc
.old_pg_upmap_items
) {
81 ss
<< "ceph osd rm-pg-upmap-items " << i
<< std::endl
;
83 for (auto& i
: pending_inc
.new_pg_upmap_items
) {
84 ss
<< "ceph osd pg-upmap-items " << i
.first
;
85 for (auto p
: i
.second
) {
86 ss
<< " " << p
.first
<< " " << p
.second
;
91 int r
= safe_write(fd
, s
.c_str(), s
.size());
93 cerr
<< "error writing output: " << cpp_strerror(r
) << std::endl
;
98 int main(int argc
, const char **argv
)
100 vector
<const char*> args
;
101 argv_to_vec(argc
, argv
, args
);
103 cerr
<< argv
[0] << ": -h or --help for usage" << std::endl
;
106 if (ceph_argparse_need_usage(args
)) {
111 auto cct
= global_init(NULL
, args
, CEPH_ENTITY_TYPE_CLIENT
,
112 CODE_ENVIRONMENT_UTILITY
,
113 CINIT_FLAG_NO_DEFAULT_CONFIG_FILE
);
114 common_init_finish(g_ceph_context
);
116 const char *me
= argv
[0];
120 boost::scoped_ptr
<Formatter
> print_formatter
;
122 boost::scoped_ptr
<Formatter
> tree_formatter
;
123 bool createsimple
= false;
124 bool createpool
= false;
125 bool create_from_conf
= false;
129 bool clobber
= false;
130 bool modified
= false;
131 std::string export_crush
, import_crush
, test_map_pg
, test_map_object
;
132 bool test_crush
= false;
133 int range_first
= -1;
136 bool mark_up_in
= false;
138 bool clear_temp
= false;
139 bool test_map_pgs
= false;
140 bool test_map_pgs_dump
= false;
141 bool test_random
= false;
142 bool upmap_cleanup
= false;
144 bool upmap_save
= false;
146 std::string upmap_file
= "-";
148 int upmap_deviation
= 5;
149 bool upmap_active
= false;
150 std::set
<std::string
> upmap_pools
;
152 bool test_map_pgs_dump_all
= false;
155 std::ostringstream err
;
156 for (std::vector
<const char*>::iterator i
= args
.begin(); i
!= args
.end(); ) {
157 if (ceph_argparse_double_dash(args
, i
)) {
159 } else if (ceph_argparse_flag(args
, i
, "-p", "--print", (char*)NULL
)) {
161 } else if (ceph_argparse_witharg(args
, i
, &val
, err
, "--dump", (char*)NULL
)) {
163 if (!val
.empty() && val
!= "plain") {
164 print_formatter
.reset(Formatter::create(val
, "", "json"));
166 } else if (ceph_argparse_witharg(args
, i
, &val
, err
, "--tree", (char*)NULL
)) {
168 if (!val
.empty() && val
!= "plain") {
169 tree_formatter
.reset(Formatter::create(val
, "", "json"));
171 } else if (ceph_argparse_witharg(args
, i
, &pg_bits
, err
, "--osd-pg-bits", (char*)NULL
)) {
172 } else if (ceph_argparse_witharg(args
, i
, &pgp_bits
, err
, "--osd-pgp-bits", (char*)NULL
)) {
173 } else if (ceph_argparse_witharg(args
, i
, &upmap_file
, "--upmap-cleanup", (char*)NULL
)) {
174 upmap_cleanup
= true;
175 } else if (ceph_argparse_witharg(args
, i
, &upmap_file
, "--upmap-save", (char*)NULL
)) {
177 } else if (ceph_argparse_witharg(args
, i
, &upmap_file
, "--upmap", (char*)NULL
)) {
178 upmap_cleanup
= true;
180 } else if (ceph_argparse_witharg(args
, i
, &upmap_max
, err
, "--upmap-max", (char*)NULL
)) {
181 } else if (ceph_argparse_witharg(args
, i
, &upmap_deviation
, err
, "--upmap-deviation", (char*)NULL
)) {
182 } else if (ceph_argparse_witharg(args
, i
, &val
, "--upmap-pool", (char*)NULL
)) {
183 upmap_pools
.insert(val
);
184 } else if (ceph_argparse_witharg(args
, i
, &num_osd
, err
, "--createsimple", (char*)NULL
)) {
185 if (!err
.str().empty()) {
186 cerr
<< err
.str() << std::endl
;
190 } else if (ceph_argparse_flag(args
, i
, "--upmap-active", (char*)NULL
)) {
192 } else if (ceph_argparse_flag(args
, i
, "--health", (char*)NULL
)) {
194 } else if (ceph_argparse_flag(args
, i
, "--with-default-pool", (char*)NULL
)) {
196 } else if (ceph_argparse_flag(args
, i
, "--create-from-conf", (char*)NULL
)) {
197 create_from_conf
= true;
198 } else if (ceph_argparse_flag(args
, i
, "--mark-up-in", (char*)NULL
)) {
200 } else if (ceph_argparse_witharg(args
, i
, &val
, "--mark-out", (char*)NULL
)) {
201 marked_out
= std::stoi(val
);
202 } else if (ceph_argparse_flag(args
, i
, "--clear-temp", (char*)NULL
)) {
204 } else if (ceph_argparse_flag(args
, i
, "--test-map-pgs", (char*)NULL
)) {
206 } else if (ceph_argparse_flag(args
, i
, "--test-map-pgs-dump", (char*)NULL
)) {
207 test_map_pgs_dump
= true;
208 } else if (ceph_argparse_flag(args
, i
, "--test-map-pgs-dump-all", (char*)NULL
)) {
209 test_map_pgs_dump_all
= true;
210 } else if (ceph_argparse_flag(args
, i
, "--test-random", (char*)NULL
)) {
212 } else if (ceph_argparse_flag(args
, i
, "--clobber", (char*)NULL
)) {
214 } else if (ceph_argparse_witharg(args
, i
, &pg_bits
, err
, "--pg_bits", (char*)NULL
)) {
215 if (!err
.str().empty()) {
216 cerr
<< err
.str() << std::endl
;
219 } else if (ceph_argparse_witharg(args
, i
, &pgp_bits
, err
, "--pgp_bits", (char*)NULL
)) {
220 if (!err
.str().empty()) {
221 cerr
<< err
.str() << std::endl
;
224 } else if (ceph_argparse_witharg(args
, i
, &val
, "--export_crush", (char*)NULL
)) {
226 } else if (ceph_argparse_witharg(args
, i
, &val
, "--import_crush", (char*)NULL
)) {
228 } else if (ceph_argparse_witharg(args
, i
, &val
, "--test_map_pg", (char*)NULL
)) {
230 } else if (ceph_argparse_witharg(args
, i
, &val
, "--test_map_object", (char*)NULL
)) {
231 test_map_object
= val
;
232 } else if (ceph_argparse_flag(args
, i
, "--test_crush", (char*)NULL
)) {
234 } else if (ceph_argparse_witharg(args
, i
, &val
, err
, "--pg_num", (char*)NULL
)) {
236 pg_num
= strict_strtoll(val
.c_str(), 10, &interr
);
237 if (interr
.length() > 0) {
238 cerr
<< "error parsing integer value " << interr
<< std::endl
;
241 } else if (ceph_argparse_witharg(args
, i
, &range_first
, err
, "--range_first", (char*)NULL
)) {
242 } else if (ceph_argparse_witharg(args
, i
, &range_last
, err
, "--range_last", (char*)NULL
)) {
243 } else if (ceph_argparse_witharg(args
, i
, &pool
, err
, "--pool", (char*)NULL
)) {
244 if (!err
.str().empty()) {
245 cerr
<< err
.str() << std::endl
;
253 cerr
<< me
<< ": must specify osdmap filename" << std::endl
;
256 else if (args
.size() > 1) {
257 cerr
<< me
<< ": too many arguments" << std::endl
;
260 if (upmap_deviation
< 1) {
261 cerr
<< me
<< ": upmap-deviation must be >= 1" << std::endl
;
266 if (range_first
>= 0 && range_last
>= 0) {
269 for (int i
=range_first
; i
<= range_last
; i
++) {
273 string error
, s
= f
.str();
274 int r
= bl
.read_file(s
.c_str(), &error
);
276 cerr
<< "unable to read " << s
<< ": " << cpp_strerror(r
) << std::endl
;
279 cout
<< s
<< " got " << bl
.length() << " bytes" << std::endl
;
280 OSDMap
*o
= new OSDMap
;
284 OSDMap::dedup(prev
, o
);
293 cerr
<< me
<< ": osdmap file '" << fn
<< "'" << std::endl
;
297 if (!createsimple
&& !create_from_conf
&& !clobber
) {
299 r
= bl
.read_file(fn
.c_str(), &error
);
304 catch (const buffer::error
&e
) {
305 cerr
<< me
<< ": error decoding osdmap '" << fn
<< "'" << std::endl
;
310 cerr
<< me
<< ": couldn't open " << fn
<< ": " << error
<< std::endl
;
314 else if ((createsimple
|| create_from_conf
) && !clobber
&& ::stat(fn
.c_str(), &st
) == 0) {
315 cerr
<< me
<< ": " << fn
<< " exists, --clobber to overwrite" << std::endl
;
319 if (createsimple
|| create_from_conf
) {
322 cerr
<< me
<< ": osd count must be > 0" << std::endl
;
330 osdmap
.build_simple_with_pool(
331 g_ceph_context
, 0, fsid
, num_osd
, pg_bits
, pgp_bits
);
333 osdmap
.build_simple(g_ceph_context
, 0, fsid
, num_osd
);
339 cout
<< "marking all OSDs up and in" << std::endl
;
340 int n
= osdmap
.get_max_osd();
341 for (int i
=0; i
<n
; i
++) {
342 osdmap
.set_state(i
, osdmap
.get_state(i
) | CEPH_OSD_UP
);
343 osdmap
.set_weight(i
, CEPH_OSD_IN
);
344 osdmap
.crush
->adjust_item_weightf(g_ceph_context
, i
, 1.0);
348 if (marked_out
>=0 && marked_out
< osdmap
.get_max_osd()) {
349 cout
<< "marking OSD@" << marked_out
<< " as out" << std::endl
;
351 osdmap
.set_state(id
, osdmap
.get_state(id
) | CEPH_OSD_UP
);
352 osdmap
.set_weight(id
, CEPH_OSD_OUT
);
353 osdmap
.crush
->adjust_item_weightf(g_ceph_context
, id
, 1.0);
357 cout
<< "clearing pg/primary temp" << std::endl
;
360 int upmap_fd
= STDOUT_FILENO
;
361 if (upmap
|| upmap_cleanup
) {
362 if (upmap_file
!= "-") {
363 upmap_fd
= ::open(upmap_file
.c_str(), O_CREAT
|O_WRONLY
|O_TRUNC
, 0644);
365 cerr
<< "error opening " << upmap_file
<< ": " << cpp_strerror(errno
)
369 cout
<< "writing upmap command output to: " << upmap_file
<< std::endl
;
373 cout
<< "checking for upmap cleanups" << std::endl
;
374 OSDMap::Incremental
pending_inc(osdmap
.get_epoch()+1);
375 pending_inc
.fsid
= osdmap
.get_fsid();
376 int r
= osdmap
.clean_pg_upmaps(g_ceph_context
, &pending_inc
);
378 print_inc_upmaps(pending_inc
, upmap_fd
);
379 r
= osdmap
.apply_incremental(pending_inc
);
384 cout
<< "upmap, max-count " << upmap_max
385 << ", max deviation " << upmap_deviation
387 vector
<int64_t> pools
;
388 set
<int64_t> upmap_pool_nums
;
389 for (auto& s
: upmap_pools
) {
390 int64_t p
= osdmap
.lookup_pg_pool_name(s
);
392 cerr
<< " pool " << s
<< " does not exist" << std::endl
;
396 upmap_pool_nums
.insert(p
);
398 if (!pools
.empty()) {
399 cout
<< " limiting to pools " << upmap_pools
<< " (" << pools
<< ")"
402 mempool::osdmap::map
<int64_t,pg_pool_t
> opools
= osdmap
.get_pools();
403 for (auto& i
: opools
) {
404 pools
.push_back(i
.first
);
408 cout
<< "No pools available" << std::endl
;
412 struct timespec round_start
;
413 int r
= clock_gettime(CLOCK_MONOTONIC
, &round_start
);
416 std::random_device rd
;
417 std::shuffle(pools
.begin(), pools
.end(), std::mt19937
{rd()});
420 cout
<< osdmap
.get_pool_name(i
) << " ";
422 OSDMap::Incremental
pending_inc(osdmap
.get_epoch()+1);
423 pending_inc
.fsid
= osdmap
.get_fsid();
425 int left
= upmap_max
;
426 struct timespec begin
, end
;
427 r
= clock_gettime(CLOCK_MONOTONIC
, &begin
);
429 for (auto& i
: pools
) {
430 set
<int64_t> one_pool
;
432 int did
= osdmap
.calc_pg_upmaps(
433 g_ceph_context
, upmap_deviation
,
441 r
= clock_gettime(CLOCK_MONOTONIC
, &end
);
443 cout
<< "prepared " << total_did
<< "/" << upmap_max
<< " changes" << std::endl
;
444 float elapsed_time
= (end
.tv_sec
- begin
.tv_sec
) + 1.0e-9*(end
.tv_nsec
- begin
.tv_nsec
);
446 cout
<< "Time elapsed " << elapsed_time
<< " secs" << std::endl
;
448 print_inc_upmaps(pending_inc
, upmap_fd
);
449 if (upmap_save
|| upmap_active
) {
450 int r
= osdmap
.apply_incremental(pending_inc
);
456 cout
<< "Unable to find further optimization, "
457 << "or distribution is already perfect"
460 map
<int,set
<pg_t
>> pgs_by_osd
;
461 for (auto& i
: osdmap
.get_pools()) {
462 if (!upmap_pool_nums
.empty() && !upmap_pool_nums
.count(i
.first
))
464 for (unsigned ps
= 0; ps
< i
.second
.get_pg_num(); ++ps
) {
465 pg_t
pg(ps
, i
.first
);
467 osdmap
.pg_to_up_acting_osds(pg
, &up
, nullptr, nullptr, nullptr);
468 //ldout(cct, 20) << __func__ << " " << pg << " up " << up << dendl;
469 for (auto osd
: up
) {
470 if (osd
!= CRUSH_ITEM_NONE
)
471 pgs_by_osd
[osd
].insert(pg
);
475 for (auto& i
: pgs_by_osd
)
476 cout
<< "osd." << i
.first
<< " pgs " << i
.second
.size() << std::endl
;
477 float elapsed_time
= (end
.tv_sec
- round_start
.tv_sec
) + 1.0e-9*(end
.tv_nsec
- round_start
.tv_nsec
);
478 cout
<< "Total time elapsed " << elapsed_time
<< " secs, " << rounds
<< " rounds" << std::endl
;
483 } while(upmap_active
);
486 if (upmap_file
!= "-") {
490 if (!import_crush
.empty()) {
493 r
= cbl
.read_file(import_crush
.c_str(), &error
);
495 cerr
<< me
<< ": error reading crush map from " << import_crush
496 << ": " << error
<< std::endl
;
502 auto p
= cbl
.cbegin();
505 if (cw
.get_max_devices() > osdmap
.get_max_osd()) {
506 cerr
<< me
<< ": crushmap max_devices " << cw
.get_max_devices()
507 << " > osdmap max_osd " << osdmap
.get_max_osd() << std::endl
;
512 OSDMap::Incremental inc
;
513 inc
.fsid
= osdmap
.get_fsid();
514 inc
.epoch
= osdmap
.get_epoch()+1;
516 osdmap
.apply_incremental(inc
);
517 cout
<< me
<< ": imported " << cbl
.length() << " byte crush map from " << import_crush
<< std::endl
;
521 if (!export_crush
.empty()) {
523 osdmap
.crush
->encode(cbl
, CEPH_FEATURES_SUPPORTED_DEFAULT
);
524 r
= cbl
.write_file(export_crush
.c_str());
526 cerr
<< me
<< ": error writing crush map to " << import_crush
<< std::endl
;
529 cout
<< me
<< ": exported crush map to " << export_crush
<< std::endl
;
532 if (!test_map_object
.empty()) {
533 object_t
oid(test_map_object
);
535 cout
<< me
<< ": assuming pool 1 (use --pool to override)" << std::endl
;
538 if (!osdmap
.have_pg_pool(pool
)) {
539 cerr
<< "There is no pool " << pool
<< std::endl
;
542 object_locator_t
loc(pool
);
543 pg_t raw_pgid
= osdmap
.object_locator_to_pg(oid
, loc
);
544 pg_t pgid
= osdmap
.raw_pg_to_pg(raw_pgid
);
547 osdmap
.pg_to_acting_osds(pgid
, acting
);
548 cout
<< " object '" << oid
553 if (!test_map_pg
.empty()) {
555 if (!pgid
.parse(test_map_pg
.c_str())) {
556 cerr
<< me
<< ": failed to parse pg '" << test_map_pg
<< std::endl
;
559 cout
<< " parsed '" << test_map_pg
<< "' -> " << pgid
<< std::endl
;
561 vector
<int> raw
, up
, acting
;
562 int raw_primary
, up_primary
, acting_primary
;
563 osdmap
.pg_to_raw_osds(pgid
, &raw
, &raw_primary
);
564 osdmap
.pg_to_up_acting_osds(pgid
, &up
, &up_primary
,
565 &acting
, &acting_primary
);
566 cout
<< pgid
<< " raw (" << raw
<< ", p" << raw_primary
567 << ") up (" << up
<< ", p" << up_primary
568 << ") acting (" << acting
<< ", p" << acting_primary
<< ")"
571 if (test_map_pgs
|| test_map_pgs_dump
|| test_map_pgs_dump_all
) {
572 if (pool
!= -1 && !osdmap
.have_pg_pool(pool
)) {
573 cerr
<< "There is no pool " << pool
<< std::endl
;
576 int n
= osdmap
.get_max_osd();
577 vector
<int> count(n
, 0);
578 vector
<int> first_count(n
, 0);
579 vector
<int> primary_count(n
, 0);
580 vector
<int> size(30, 0);
584 auto& pools
= osdmap
.get_pools();
585 for (auto p
= pools
.begin(); p
!= pools
.end(); ++p
) {
586 if (pool
!= -1 && p
->first
!= pool
)
589 p
->second
.set_pg_num(pg_num
);
591 cout
<< "pool " << p
->first
592 << " pg_num " << p
->second
.get_pg_num() << std::endl
;
593 for (unsigned i
= 0; i
< p
->second
.get_pg_num(); ++i
) {
594 pg_t pgid
= pg_t(i
, p
->first
);
596 vector
<int> osds
, raw
, up
, acting
;
597 int primary
, calced_primary
, up_primary
, acting_primary
;
599 osds
.resize(p
->second
.size
);
600 for (unsigned i
=0; i
<osds
.size(); ++i
) {
601 osds
[i
] = rand() % osdmap
.get_max_osd();
604 } else if (test_map_pgs_dump_all
) {
605 osdmap
.pg_to_raw_osds(pgid
, &raw
, &calced_primary
);
606 osdmap
.pg_to_up_acting_osds(pgid
, &up
, &up_primary
,
607 &acting
, &acting_primary
);
609 primary
= acting_primary
;
611 osdmap
.pg_to_acting_osds(pgid
, &osds
, &primary
);
614 if ((unsigned)max_size
< osds
.size())
615 max_size
= osds
.size();
617 if (test_map_pgs_dump
) {
618 cout
<< pgid
<< "\t" << osds
<< "\t" << primary
<< std::endl
;
619 } else if (test_map_pgs_dump_all
) {
620 cout
<< pgid
<< " raw (" << raw
<< ", p" << calced_primary
621 << ") up (" << up
<< ", p" << up_primary
622 << ") acting (" << acting
<< ", p" << acting_primary
<< ")"
626 for (unsigned i
=0; i
<osds
.size(); i
++) {
627 //cout << " rep " << i << " on " << osds[i] << std::endl;
631 first_count
[osds
[0]]++;
633 primary_count
[primary
]++;
641 cout
<< "#osd\tcount\tfirst\tprimary\tc wt\twt\n";
642 for (int i
=0; i
<n
; i
++) {
643 if (!osdmap
.is_in(i
))
645 if (osdmap
.crush
->get_item_weight(i
) <= 0)
650 << "\t" << first_count
[i
]
651 << "\t" << primary_count
[i
]
652 << "\t" << osdmap
.crush
->get_item_weightf(i
)
653 << "\t" << osdmap
.get_weightf(i
)
658 count
[i
] < count
[min_osd
]))
662 count
[i
] > count
[max_osd
]))
666 uint64_t avg
= in
? (total
/ in
) : 0;
668 for (int i
=0; i
<n
; i
++) {
669 if (!osdmap
.is_in(i
))
671 if (osdmap
.crush
->get_item_weight(i
) <= 0)
673 dev
+= (avg
- count
[i
]) * (avg
- count
[i
]);
678 //double edev = sqrt(pgavg) * (double)avg / pgavg;
679 double edev
= sqrt((double)total
/ (double)in
* (1.0 - (1.0 / (double)in
)));
680 cout
<< " in " << in
<< std::endl
;
681 cout
<< " avg " << avg
683 << " (" << (dev
/avg
) << "x)"
684 << " (expected " << edev
<< " " << (edev
/avg
) << "x))"
688 cout
<< " min osd." << min_osd
<< " " << count
[min_osd
] << std::endl
;
690 cout
<< " max osd." << max_osd
<< " " << count
[max_osd
] << std::endl
;
692 for (int i
=0; i
<=max_size
; i
++) {
694 cout
<< "size " << i
<< "\t" << size
[i
] << std::endl
;
700 cout
<< "pass " << ++pass
<< std::endl
;
702 ceph::unordered_map
<pg_t
,vector
<int> > m
;
703 for (map
<int64_t,pg_pool_t
>::const_iterator p
= osdmap
.get_pools().begin();
704 p
!= osdmap
.get_pools().end();
706 const pg_pool_t
*pool
= osdmap
.get_pg_pool(p
->first
);
707 for (ps_t ps
= 0; ps
< pool
->get_pg_num(); ps
++) {
708 pg_t
pgid(ps
, p
->first
);
709 for (int i
=0; i
<100; i
++) {
710 cout
<< pgid
<< " attempt " << i
<< std::endl
;
713 osdmap
.pg_to_acting_osds(pgid
, r
);
714 //cout << pgid << " " << r << std::endl;
717 cout
<< pgid
<< " had " << m
[pgid
] << " now " << r
<< std::endl
;
728 if (!print
&& !health
&& !tree
&& !modified
&&
729 export_crush
.empty() && import_crush
.empty() &&
730 test_map_pg
.empty() && test_map_object
.empty() &&
731 !test_map_pgs
&& !test_map_pgs_dump
&& !test_map_pgs_dump_all
&&
732 !upmap
&& !upmap_cleanup
) {
733 cerr
<< me
<< ": no action specified?" << std::endl
;
741 health_check_map_t checks
;
742 osdmap
.check_health(cct
.get(), &checks
);
743 JSONFormatter
jf(true);
744 jf
.dump_object("checks", checks
);
748 if (print_formatter
) {
749 print_formatter
->open_object_section("osdmap");
750 osdmap
.dump(print_formatter
.get());
751 print_formatter
->close_section();
752 print_formatter
->flush(cout
);
759 if (tree_formatter
) {
760 tree_formatter
->open_object_section("tree");
761 osdmap
.print_tree(tree_formatter
.get(), NULL
);
762 tree_formatter
->close_section();
763 tree_formatter
->flush(cout
);
766 osdmap
.print_tree(NULL
, &cout
);
771 osdmap
.encode(bl
, CEPH_FEATURES_SUPPORTED_DEFAULT
| CEPH_FEATURE_RESERVED
);
774 cout
<< me
<< ": writing epoch " << osdmap
.get_epoch()
777 int r
= bl
.write_file(fn
.c_str());
779 cerr
<< "osdmaptool: error writing to '" << fn
<< "': "
780 << cpp_strerror(r
) << std::endl
;