~ubuntu-branches/ubuntu/quantal/ceph/quantal

« back to all changes in this revision

Viewing changes to src/osd/OSD.cc

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2012-08-27 08:23:21 UTC
  • mto: This revision was merged to the branch mainline in revision 21.
  • Revision ID: package-import@ubuntu.com-20120827082321-2cfej6ddvk63vsqq
Tags: upstream-0.48.1
ImportĀ upstreamĀ versionĀ 0.48.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
1327
1327
    int role = osdmap->calc_pg_role(whoami, pg->acting);
1328
1328
    pg->set_role(role);
1329
1329
 
 
1330
    if (role != 0)
 
1331
      pg->state_set(PG_STATE_STRAY);
 
1332
 
1330
1333
    PG::RecoveryCtx rctx(0, 0, 0, 0, 0);
1331
1334
    pg->handle_loaded(&rctx);
1332
1335
 
1334
1337
    pg->unlock();
1335
1338
  }
1336
1339
  dout(10) << "load_pgs done" << dendl;
1337
 
}
1338
 
 
 
1340
 
 
1341
  build_past_intervals_parallel();
 
1342
}
 
1343
 
 
1344
 
 
1345
/*
 
1346
 * build past_intervals efficiently on old, degraded, and buried
 
1347
 * clusters.  this is important for efficiently catching up osds that
 
1348
 * are way behind on maps to the current cluster state.
 
1349
 *
 
1350
 * this is a parallel version of PG::generate_past_intervals().
 
1351
 * follow the same logic, but do all pgs at the same time so that we
 
1352
 * can make a single pass across the osdmap history.
 
1353
 */
 
1354
struct pistate {
 
1355
  epoch_t start, end;
 
1356
  vector<int> old_acting, old_up;
 
1357
  epoch_t same_interval_since;
 
1358
};
 
1359
 
 
1360
void OSD::build_past_intervals_parallel()
 
1361
{
 
1362
  map<PG*,pistate> pis;
 
1363
 
 
1364
  // calculate untion of map range
 
1365
  epoch_t end_epoch = superblock.oldest_map;
 
1366
  epoch_t cur_epoch = superblock.newest_map;
 
1367
  for (hash_map<pg_t, PG*>::iterator i = pg_map.begin();
 
1368
       i != pg_map.end();
 
1369
       i++) {
 
1370
    PG *pg = i->second;
 
1371
 
 
1372
    epoch_t start, end;
 
1373
    if (!pg->_calc_past_interval_range(&start, &end))
 
1374
      continue;
 
1375
 
 
1376
    dout(10) << pg->info.pgid << " needs " << start << "-" << end << dendl;
 
1377
    pistate& p = pis[pg];
 
1378
    p.start = start;
 
1379
    p.end = end;
 
1380
    p.same_interval_since = 0;
 
1381
 
 
1382
    if (start < cur_epoch)
 
1383
      cur_epoch = start;
 
1384
    if (end > end_epoch)
 
1385
      end_epoch = end;
 
1386
  }
 
1387
  if (pis.empty()) {
 
1388
    dout(10) << __func__ << " nothing to build" << dendl;
 
1389
    return;
 
1390
  }
 
1391
 
 
1392
  dout(1) << __func__ << " over " << cur_epoch << "-" << end_epoch << dendl;
 
1393
  assert(cur_epoch <= end_epoch);
 
1394
 
 
1395
  OSDMapRef cur_map, last_map;
 
1396
  for ( ; cur_epoch <= end_epoch; cur_epoch++) {
 
1397
    dout(10) << __func__ << " epoch " << cur_epoch << dendl;
 
1398
    last_map = cur_map;
 
1399
    cur_map = get_map(cur_epoch);
 
1400
 
 
1401
    for (map<PG*,pistate>::iterator i = pis.begin(); i != pis.end(); ++i) {
 
1402
      PG *pg = i->first;
 
1403
      pistate& p = i->second;
 
1404
 
 
1405
      if (cur_epoch < p.start || cur_epoch > p.end)
 
1406
        continue;
 
1407
 
 
1408
      vector<int> acting, up;
 
1409
      cur_map->pg_to_up_acting_osds(pg->info.pgid, up, acting);
 
1410
 
 
1411
      if (p.same_interval_since == 0) {
 
1412
        dout(10) << __func__ << " epoch " << cur_epoch << " pg " << pg->info.pgid
 
1413
                 << " first map, acting " << acting
 
1414
                 << " up " << up << ", same_interval_since = " << cur_epoch << dendl;
 
1415
        p.same_interval_since = cur_epoch;
 
1416
        p.old_up = up;
 
1417
        p.old_acting = acting;
 
1418
        continue;
 
1419
      }
 
1420
      assert(last_map);
 
1421
 
 
1422
      std::stringstream debug;
 
1423
      bool new_interval = pg_interval_t::check_new_interval(p.old_acting, acting,
 
1424
                                                            p.old_up, up,
 
1425
                                                            p.same_interval_since,
 
1426
                                                            pg->info.history.last_epoch_clean,
 
1427
                                                            cur_map, last_map,
 
1428
                                                            &pg->past_intervals,
 
1429
                                                            &debug);
 
1430
      if (new_interval) {
 
1431
        dout(10) << __func__ << " epoch " << cur_epoch << " pg " << pg->info.pgid
 
1432
                 << " " << debug.str() << dendl;
 
1433
        p.old_up = up;
 
1434
        p.old_acting = acting;
 
1435
        p.same_interval_since = cur_epoch;
 
1436
      }
 
1437
    }
 
1438
  }
 
1439
 
 
1440
  // write info only at the end.  this is necessary because we check
 
1441
  // whether the past_intervals go far enough back or forward in time,
 
1442
  // but we don't check for holes.  we could avoid it by discarding
 
1443
  // the previous past_intervals and rebuilding from scratch, or we
 
1444
  // can just do this and commit all our work at the end.
 
1445
  ObjectStore::Transaction t;
 
1446
  int num = 0;
 
1447
  for (map<PG*,pistate>::iterator i = pis.begin(); i != pis.end(); ++i) {
 
1448
    PG *pg = i->first;
 
1449
    pg->write_info(t);
 
1450
 
 
1451
    // don't let the transaction get too big
 
1452
    if (++num >= g_conf->osd_target_transaction_size) {
 
1453
      store->apply_transaction(t);
 
1454
      t = ObjectStore::Transaction();
 
1455
      num = 0;
 
1456
    }
 
1457
  }
 
1458
  if (!t.empty())
 
1459
    store->apply_transaction(t);
 
1460
}
 
1461
 
1339
1462
 
1340
1463
/*
1341
1464
 * look up a pg.  if we have it, great.  if not, consider creating it IF the pg mapping
1821
1944
  logger->set(l_osd_buf, buffer::get_total_alloc());
1822
1945
 
1823
1946
  // periodically kick recovery work queue
1824
 
  recovery_tp.kick();
 
1947
  recovery_tp.wake();
1825
1948
  
1826
1949
  if (scrub_should_schedule()) {
1827
1950
    sched_scrub();
2093
2216
  if (osdmap->test_flag(CEPH_OSDMAP_NOUP)) {
2094
2217
    dout(5) << "osdmap NOUP flag is set, waiting for it to clear" << dendl;
2095
2218
  } else if (osdmap->get_epoch() >= oldest - 1 &&
2096
 
             osdmap->get_epoch() < newest + g_conf->osd_map_message_max) {
 
2219
             osdmap->get_epoch() + g_conf->osd_map_message_max > newest) {
2097
2220
    send_boot();
2098
2221
    return;
2099
2222
  }
2511
2634
         << "to " << g_conf->osd_recovery_delay_start;
2512
2635
      defer_recovery_until = ceph_clock_now(g_ceph_context);
2513
2636
      defer_recovery_until += g_conf->osd_recovery_delay_start;
2514
 
      recovery_wq.kick();
 
2637
      recovery_wq.wake();
2515
2638
    }
2516
2639
  }
2517
2640
 
5189
5312
    recovery_queue.push_front(&pg->recovery_item);  // requeue
5190
5313
  }
5191
5314
 
5192
 
  recovery_wq.kick();
 
5315
  recovery_wq._wake();
5193
5316
  recovery_wq.unlock();
5194
5317
}
5195
5318
 
5201
5324
  recovery_wq.lock();
5202
5325
  pg->get();
5203
5326
  recovery_queue.push_back(&pg->recovery_item);
5204
 
  recovery_wq.kick();
 
5327
  recovery_wq._wake();
5205
5328
  recovery_wq.unlock();
5206
5329
}
5207
5330
 
5331
5454
  if (!pg) {
5332
5455
    dout(7) << "hit non-existent pg " << pgid << dendl;
5333
5456
 
5334
 
    if (osdmap->get_pg_role(pgid, whoami) >= 0) {
 
5457
    if (osdmap->get_pg_acting_role(pgid, whoami) >= 0) {
5335
5458
      dout(7) << "we are valid target for op, waiting" << dendl;
5336
5459
      waiting_for_pg[pgid].push_back(op);
5337
5460
      op->mark_delayed();
5351
5474
        send_map->have_pg_pool(pgid.pool()))
5352
5475
      pgid = send_map->raw_pg_to_pg(pgid);
5353
5476
    
5354
 
    if (send_map->get_pg_role(m->get_pg(), whoami) >= 0) {
 
5477
    if (send_map->get_pg_acting_role(m->get_pg(), whoami) >= 0) {
5355
5478
      dout(7) << "dropping request; client will resend when they get new map" << dendl;
5356
5479
    } else {
5357
5480
      dout(7) << "we are invalid target" << dendl;