~ubuntu-branches/ubuntu/precise/ceph/precise-proposed

« back to all changes in this revision

Viewing changes to src/mon/PGMonitor.cc

  • Committer: Bazaar Package Importer
  • Author(s): Laszlo Boszormenyi (GCS)
  • Date: 2011-04-25 10:09:05 UTC
  • mfrom: (1.1.3 upstream) (0.1.5 sid)
  • Revision ID: james.westby@ubuntu.com-20110425100905-exm7dfvi2v5ick02
Tags: 0.27-1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
35
35
#include "osd/osd_types.h"
36
36
#include "osd/PG.h"  // yuck
37
37
 
38
 
#include "config.h"
 
38
#include "common/config.h"
39
39
#include <sstream>
40
40
 
41
41
#define DOUT_SUBSYS mon
42
42
#undef dout_prefix
43
43
#define dout_prefix _prefix(mon, pg_map)
44
44
static ostream& _prefix(Monitor *mon, PGMap& pg_map) {
45
 
  return *_dout << dbeginl
46
 
                << "mon." << mon->name << "@" << mon->rank
 
45
  return *_dout << "mon." << mon->name << "@" << mon->rank
47
46
                << (mon->is_starting() ? (const char*)"(starting)":(mon->is_leader() ? (const char*)"(leader)":(mon->is_peon() ? (const char*)"(peon)":(const char*)"(?\?)")))
48
47
                << ".pg v" << pg_map.version << " ";
49
48
}
50
49
 
51
 
 
52
50
/*
53
51
 Tick function to update the map based on performance every N seconds
54
52
*/
55
53
 
 
54
void PGMonitor::on_election_start()
 
55
{
 
56
  // clear leader state
 
57
  last_sent_pg_create.clear();
 
58
  last_osd_report.clear();
 
59
}
 
60
 
56
61
void PGMonitor::tick() 
57
62
{
58
63
  if (!paxos->is_active()) return;
59
64
 
60
65
  update_from_paxos();
 
66
  handle_osd_timeouts();
61
67
  dout(10) << pg_map << dendl;
62
68
}
63
69
 
93
99
  } 
94
100
 
95
101
  // walk through incrementals
 
102
  utime_t now(g_clock.now());
96
103
  while (paxosv > pg_map.version) {
97
104
    bufferlist bl;
98
105
    bool success = paxos->read(pg_map.version+1, bl);
144
151
  return true;
145
152
}
146
153
 
 
154
void PGMonitor::handle_osd_timeouts()
 
155
{
 
156
  if (!mon->is_leader())
 
157
    return;
 
158
  utime_t now(g_clock.now());
 
159
  utime_t timeo(g_conf.mon_osd_report_timeout, 0);
 
160
  if (now - mon->get_leader_since() < timeo) {
 
161
    // We haven't been the leader for long enough to consider OSD timeouts
 
162
    return;
 
163
  }
 
164
 
 
165
  mon->osdmon()->handle_osd_timeouts(now, last_osd_report);
 
166
}
 
167
 
147
168
void PGMonitor::create_pending()
148
169
{
149
170
  pending_inc = PGMap::Incremental();
280
301
 
281
302
bool PGMonitor::preprocess_pg_stats(MPGStats *stats)
282
303
{
283
 
  int from = stats->get_orig_source().num();
284
 
  MPGStatsAck *ack;
285
 
 
286
304
  // check caps
287
305
  MonSession *session = stats->get_session();
288
 
  if (!session)
289
 
    goto out;
 
306
  if (!session) {
 
307
    derr << "PGMonitor::preprocess_pg_stats: no monitor session!" << dendl;
 
308
    stats->put();
 
309
    return true;
 
310
  }
290
311
  if (!session->caps.check_privileges(PAXOS_PGMAP, MON_CAP_R)) {
291
 
    dout(0) << "MPGStats received from entity with insufficient privileges "
292
 
            << session->caps << dendl;
293
 
    goto out;
 
312
    derr << "PGMonitor::preprocess_pg_stats: MPGStats received from entity "
 
313
         << "with insufficient privileges " << session->caps << dendl;
 
314
    stats->put();
 
315
    return true;
294
316
  }
295
317
 
296
 
  // first, just see if they need a new osdmap.  but 
 
318
  // First, just see if they need a new osdmap. But
297
319
  // only if they've had the map for a while.
298
320
  if (stats->had_map_for > 30.0 && 
299
321
      mon->osdmon()->paxos->is_readable() &&
300
322
      stats->epoch < mon->osdmon()->osdmap.get_epoch())
301
323
    mon->osdmon()->send_latest_now_nodelete(stats, stats->epoch+1);
302
324
 
303
 
  // any new osd or pg info?
304
 
  if (!pg_map.osd_stat.count(from) ||
305
 
      pg_map.osd_stat[from] != stats->osd_stat)
306
 
    return false;  // new osd stat
307
 
 
308
 
  for (map<pg_t,pg_stat_t>::iterator p = stats->pg_stat.begin();
309
 
       p != stats->pg_stat.end();
310
 
       p++) {
311
 
    if (pg_map.pg_stat.count(p->first) == 0 ||
312
 
        pg_map.pg_stat[p->first].reported != p->second.reported)
313
 
      return false; // new pg stat(s)
 
325
  // Always forward the PGStats to the leader, even if they are the same as
 
326
  // the old PGStats. The leader will mark as down osds that haven't sent
 
327
  // PGStats for a few minutes.
 
328
  return false;
 
329
}
 
330
 
 
331
bool PGMonitor::pg_stats_have_changed(int from, const MPGStats *stats) const
 
332
{
 
333
  // any new osd info?
 
334
  hash_map<int,osd_stat_t>::const_iterator s = pg_map.osd_stat.find(from);
 
335
  if (s == pg_map.osd_stat.end())
 
336
    return true;
 
337
  if (s->second != stats->osd_stat)
 
338
    return true;
 
339
 
 
340
  // any new pg info?
 
341
  for (map<pg_t,pg_stat_t>::const_iterator p = stats->pg_stat.begin();
 
342
       p != stats->pg_stat.end(); ++p) {
 
343
    hash_map<pg_t,pg_stat_t>::const_iterator t = pg_map.pg_stat.find(p->first);
 
344
    if (t == pg_map.pg_stat.end())
 
345
      return true;
 
346
    if (t->second.reported != p->second.reported)
 
347
      return true;
314
348
  }
315
 
  
316
 
  dout(10) << " message contains no new osd|pg stats" << dendl;
317
 
  ack = new MPGStatsAck;
318
 
  for (map<pg_t,pg_stat_t>::iterator p = stats->pg_stat.begin();
319
 
       p != stats->pg_stat.end();
320
 
       p++)
321
 
    ack->pg_stat[p->first] = p->second.reported;
322
 
  mon->send_reply(stats, ack);
323
 
 out:
324
 
  stats->put();
325
 
  return true;
 
349
 
 
350
  return false;
326
351
}
327
352
 
328
353
bool PGMonitor::prepare_pg_stats(MPGStats *stats) 
335
360
    stats->put();
336
361
    return false;
337
362
  }
 
363
 
 
364
  last_osd_report[from] = g_clock.now();
 
365
 
338
366
  if (!stats->get_orig_source().is_osd() ||
339
367
      !mon->osdmon()->osdmap.is_up(from) ||
340
368
      stats->get_orig_source_inst() != mon->osdmon()->osdmap.get_inst(from)) {
343
371
    return false;
344
372
  }
345
373
      
 
374
  if (!pg_stats_have_changed(from, stats)) {
 
375
    dout(10) << " message contains no new osd|pg stats" << dendl;
 
376
    MPGStatsAck *ack = new MPGStatsAck;
 
377
    for (map<pg_t,pg_stat_t>::const_iterator p = stats->pg_stat.begin();
 
378
         p != stats->pg_stat.end();
 
379
         ++p) {
 
380
      ack->pg_stat[p->first] = p->second.reported;
 
381
    }
 
382
    mon->send_reply(stats, ack);
 
383
    stats->put();
 
384
    return false;
 
385
  }
 
386
 
346
387
  // osd stat
347
388
  pending_inc.osd_stat_updates[from] = stats->osd_stat;
348
389
  
388
429
               << " state " << pg_state_string(p->second.state)
389
430
               << " but DNE in pg_map!!"
390
431
               << dendl;
391
 
      stringstream ss;
392
 
      ss << "got " << pgid << " pg_stat from osd" << from << " but dne in pg_map";
393
 
      mon->logclient.log(LOG_ERROR, ss);
 
432
      mon->clog.error() << "got " << pgid << " pg_stat from osd" << from
 
433
            << " but dne in pg_map\n";
394
434
      continue;
395
435
    }
396
436
      
600
640
  }
601
641
 
602
642
  // deleted pools?
603
 
  for (set<pg_t>::iterator p = pg_map.pg_set.begin();
604
 
       p != pg_map.pg_set.end();
605
 
       p++) {
606
 
    if (!osdmap->have_pg_pool(p->pool())) {
607
 
      dout(20) << " removing creating_pg " << *p << " because containing pool deleted" << dendl;
608
 
      pending_inc.pg_remove.insert(*p);
 
643
  for (hash_map<pg_t,pg_stat_t>::const_iterator p = pg_map.pg_stat.begin();
 
644
       p != pg_map.pg_stat.end(); ++p) {
 
645
    if (!osdmap->have_pg_pool(p->first.pool())) {
 
646
      dout(20) << " removing creating_pg " << p->first << " because "
 
647
               << "containing pool deleted" << dendl;
 
648
      pending_inc.pg_remove.insert(p->first);
609
649
      ++removed;
610
650
    }
611
651
  }
705
745
      r = -EINVAL;
706
746
      if (pgid.parse(m->cmd[2].c_str())) {
707
747
        vector<int> up, acting;
 
748
        pg_t mpgid = mon->osdmon()->osdmap.raw_pg_to_pg(pgid);
708
749
        mon->osdmon()->osdmap.pg_to_up_acting_osds(pgid, up, acting);
709
 
        ss << "osdmap e" << mon->osdmon()->osdmap.get_epoch() << " pg " << pgid
 
750
        ss << "osdmap e" << mon->osdmon()->osdmap.get_epoch()
 
751
           << " pg " << pgid << " (" << mpgid << ")"
710
752
           << " -> up " << up << " acting " << acting;
711
753
        r = 0;
712
754
      } else
799
841
  mon->reply_command(m, err, rs, paxos->get_version());
800
842
  return false;
801
843
}
 
844
 
 
845
enum health_status_t PGMonitor::get_health(std::ostream &ss) const
 
846
{
 
847
  enum health_status_t ret(HEALTH_OK);
 
848
 
 
849
  const hash_map<pg_t,pg_stat_t> &pg_stat = pg_map.pg_stat;
 
850
 
 
851
  hash_map<pg_t,pg_stat_t>::const_iterator p = pg_stat.begin();
 
852
  hash_map<pg_t,pg_stat_t>::const_iterator p_end = pg_stat.end();
 
853
  int seen = 0;
 
854
  for (; p != p_end; ++p) {
 
855
    seen |= p->second.state;
 
856
  }
 
857
 
 
858
  string prequel(" Some PGs are: ");
 
859
  if (seen & PG_STATE_CRASHED) {
 
860
    ss << prequel << "crashed";
 
861
    prequel = ",";
 
862
  }
 
863
  if (seen & PG_STATE_DOWN) {
 
864
    ss << prequel << "down";
 
865
    prequel = ",";
 
866
  }
 
867
  if (seen & PG_STATE_REPLAY) {
 
868
    ss << prequel << "replaying";
 
869
    prequel = ",";
 
870
  }
 
871
  if (seen & PG_STATE_SPLITTING) {
 
872
    ss << prequel << "splitting";
 
873
    prequel = ",";
 
874
  }
 
875
  if (seen & PG_STATE_DEGRADED) {
 
876
    ss << prequel << "degraded";
 
877
    prequel = ",";
 
878
  }
 
879
  if (seen & PG_STATE_INCONSISTENT) {
 
880
    ss << prequel << "inconsistent";
 
881
    prequel = ",";
 
882
  }
 
883
  if (seen & PG_STATE_PEERING) {
 
884
    ss << prequel << "peering";
 
885
    prequel = ",";
 
886
  }
 
887
  if (seen & PG_STATE_REPAIR) {
 
888
    ss << prequel << "repairing";
 
889
    prequel = ",";
 
890
  }
 
891
  if (prequel == ",") {
 
892
    if (ret > HEALTH_WARN)
 
893
      ret = HEALTH_WARN;
 
894
  }
 
895
  return ret;
 
896
}