]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
Merge remote branch 'origin/syslog' into unstable
authorSage Weil <sage@newdream.net>
Sat, 11 Dec 2010 16:09:17 +0000 (08:09 -0800)
committerSage Weil <sage@newdream.net>
Sat, 11 Dec 2010 16:09:17 +0000 (08:09 -0800)
Conflicts:
src/mon/Paxos.cc
src/osd/PG.cc

24 files changed:
1  2 
src/Makefile.am
src/auth/Crypto.cc
src/client/Client.cc
src/common/DoutStreambuf.cc
src/config.cc
src/config.h
src/librados.cc
src/mds/CDir.cc
src/mds/CInode.cc
src/mds/Locker.cc
src/mds/MDCache.cc
src/mds/Migrator.cc
src/mds/Server.cc
src/mon/OSDMonitor.cc
src/mon/Paxos.cc
src/msg/SimpleMessenger.cc
src/os/FileJournal.cc
src/os/FileStore.cc
src/os/JournalingObjectStore.cc
src/osd/OSD.cc
src/osd/PG.cc
src/osd/ReplicatedPG.cc
src/tools/ceph.cc
src/tools/cmd.cc

diff --cc src/Makefile.am
Simple merge
index 467e086b3c9d40bafdd9e229f8422774d6580a0f,0a732e6bd0de3c5c1f6c3da4908796ad00209f18..a561e7dbc33b8b3d9849d512c89a011a9ce5efeb
@@@ -134,30 -132,41 +134,30 @@@ int CryptoAES::validate_secret(bufferpt
  int CryptoAES::encrypt(bufferptr& secret, const bufferlist& in, bufferlist& out)
  {
    const unsigned char *key = (const unsigned char *)secret.c_str();
 -  int in_len = in.length();
    const unsigned char *in_buf;
 -  int max_out = (in_len + AES_BLOCK_SIZE) & ~(AES_BLOCK_SIZE -1);
 -  int total_out = 0;
 -  int outlen;
 -#define OUT_BUF_EXTRA 128
 -  unsigned char outbuf[max_out + OUT_BUF_EXTRA];
  
    if (secret.length() < AES_KEY_LEN) {
-     derr(0) << "key is too short" << dendl;
+     dout(0) << "key is too short" << dendl;
      return false;
    }
 +  string ciphertext;
 +  CryptoPP::AES::Encryption aesEncryption(key, CryptoPP::AES::DEFAULT_KEYLENGTH);
 +  CryptoPP::CBC_Mode_ExternalCipher::Encryption cbcEncryption( aesEncryption, aes_iv );
 +  CryptoPP::StringSink *sink = new CryptoPP::StringSink(ciphertext);
 +  if (!sink)
 +    return false;
 +  CryptoPP::StreamTransformationFilter stfEncryptor(cbcEncryption, sink);
  
 -  EVP_CIPHER_CTX ctx;
 -  EVP_CIPHER_CTX_init(&ctx);
 -  EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key, aes_iv);
 -
 -  bool ret = false;
    for (std::list<bufferptr>::const_iterator it = in.buffers().begin(); 
         it != in.buffers().end(); it++) {
 -    outlen = max_out - total_out;
      in_buf = (const unsigned char *)it->c_str();
 -    if (!EVP_EncryptUpdate(&ctx, &outbuf[total_out], &outlen, in_buf, it->length()))
 -      goto out;
 -    total_out += outlen;
 +
 +    stfEncryptor.Put(in_buf, it->length());
    }
 -  if (!EVP_EncryptFinal_ex(&ctx, outbuf + total_out, &outlen))
 -    goto out;
 -  total_out += outlen;
 -
 -  out.append((const char *)outbuf, total_out);
 -  ret = true;
 - out:
 -  EVP_CIPHER_CTX_cleanup(&ctx);
 -  return ret;
 +  stfEncryptor.MessageEnd();
 +  out.append((const char *)ciphertext.c_str(), ciphertext.length());
 +
 +  return true;
  }
  
  int CryptoAES::decrypt(bufferptr& secret, const bufferlist& in, bufferlist& out)
Simple merge
index 0000000000000000000000000000000000000000,9fc489002a5b1981dcb95547397d68ff567ecd65..4279e4fbebdfe738a066d44f161186d6a1257cfc
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,627 +1,628 @@@
+ // -*- 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) 2010 Dreamhost
+  *
+  * 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 "config.h"
+ #include "common/DoutStreambuf.h"
+ #include "common/errno.h"
+ #include "common/Mutex.h"
++#include <values.h>
+ #include <assert.h>
+ #include <errno.h>
+ #include <fstream>
+ #include <iostream>
+ #include <memory>
+ #include <sstream>
+ #include <streambuf>
+ #include <string.h>
+ #include <syslog.h>
+ ///////////////////////////// Globals /////////////////////////////
+ // TODO: get rid of this lock using thread-local storage
+ extern Mutex _dout_lock;
+ //////////////////////// Helper functions //////////////////////////
+ // Try a 0-byte write to a file descriptor to see if it open.
+ static bool fd_is_open(int fd)
+ {
+   char buf;
+   ssize_t res = TEMP_FAILURE_RETRY(write(fd, &buf, 0));
+   return (res == 0);
+ }
+ static bool empty(const char *str)
+ {
+   if (!str)
+     return true;
+   if (!str[0])
+     return true;
+   return false;
+ }
+ static string cpp_str(const char *str)
+ {
+   if (!str)
+     return "(NULL)";
+   if (str[0] == '\0')
+     return "(empty)";
+   return str;
+ }
+ static std::string normalize_relative(const char *from)
+ {
+   if (from[0] == '/')
+     return string(from);
+   char c[512];
+   char *cwd = getcwd(c, sizeof(c));
+   ostringstream oss;
+   oss << cwd << "/" << from;
+   return oss.str();
+ }
+ /* Complain about errors even without a logfile */
+ static void primitive_log(const std::string &str)
+ {
+   std::cerr << str;
+   std::cerr.flush();
+   syslog(LOG_USER | LOG_NOTICE, "%s", str.c_str());
+ }
+ static inline bool prio_is_visible_on_stderr(int prio)
+ {
+   return prio <= 5;
+ }
+ static inline int dout_prio_to_syslog_prio(int prio)
+ {
+   if (prio <= 3)
+     return LOG_CRIT;
+   if (prio <= 5)
+     return LOG_ERR;
+   if (prio <= 15)
+     return LOG_WARNING;
+   if (prio <= 30)
+     return LOG_NOTICE;
+   if (prio <= 40)
+     return LOG_INFO;
+   return LOG_DEBUG;
+ }
+ static int safe_write(int fd, const char *buf, signed int len)
+ {
+   int res;
+   assert(len != 0);
+   while (1) {
+     res = write(fd, buf, len);
+     if (res < 0) {
+       int err = errno;
+       if (err != EINTR) {
+       ostringstream oss;
+       oss << __func__ << ": failed to write to fd " << fd << ": "
+           << cpp_strerror(err) << "\n";
+       primitive_log(oss.str());
+       return err;
+       }
+     }
+     len -= res;
+     buf += res;
+     if (len <= 0)
+       return 0;
+   }
+ }
+ static std::string get_basename(const std::string &filename)
+ {
+   size_t last_slash = filename.find_last_of("/");
+   if (last_slash == std::string::npos)
+     return filename;
+   return filename.substr(last_slash + 1);
+ }
+ static std::string get_dirname(const std::string &filename)
+ {
+   size_t last_slash = filename.find_last_of("/");
+   if (last_slash == std::string::npos)
+     return ".";
+   if (last_slash == 0)
+     return filename;
+   return filename.substr(0, last_slash);
+ }
+ static int create_symlink(string oldpath, const string &newpath)
+ {
+   // Create relative symlink if the files are in the same directory
+   if (get_dirname(oldpath) == get_dirname(newpath)) {
+     oldpath = string("./") + get_basename(oldpath);
+   }
+   while (1) {
+     if (::symlink(oldpath.c_str(), newpath.c_str()) == 0)
+       return 0;
+     int err = errno;
+     if (err == EEXIST) {
+       // Handle EEXIST
+       if (::unlink(newpath.c_str())) {
+       err = errno;
+       ostringstream oss;
+       oss << __func__ << ": failed to remove '" << newpath << "': "
+           << cpp_strerror(err) << "\n";
+       primitive_log(oss.str());
+       return err;
+       }
+     }
+     else {
+       // Other errors
+       ostringstream oss;
+       oss << __func__ << ": failed to symlink(oldpath='" << oldpath
+         << "', newpath='" << newpath << "'): " << cpp_strerror(err) << "\n";
+       primitive_log(oss.str());
+       return err;
+     }
+   }
+ }
+ ///////////////////////////// DoutStreambuf /////////////////////////////
+ template <typename charT, typename traits>
+ DoutStreambuf<charT, traits>::DoutStreambuf()
+   : flags(0), ofd(-1)
+ {
+   // Initialize get pointer to zero so that underflow is called on the first read.
+   this->setg(0, 0, 0);
+   // Initialize output_buffer
+   _clear_output_buffer();
+ }
+ // This function is called when the output buffer is filled.
+ // In this function, the buffer should be written to wherever it should
+ // be written to (in this case, the streambuf object that this is controlling).
+ template <typename charT, typename traits>
+ typename DoutStreambuf<charT, traits>::int_type
+ DoutStreambuf<charT, traits>::overflow(DoutStreambuf<charT, traits>::int_type c)
+ {
+   {
+     // zero-terminate the buffer
+     charT* end_ptr = this->pptr();
+     *end_ptr++ = '\0';
+     *end_ptr++ = '\0';
+ //    char buf[1000];
+ //    hex2str(obuf, end_ptr - obuf, buf, sizeof(buf));
+ //    printf("overflow buffer: '%s'\n", buf);
+   }
+   // Loop over all lines in the buffer.
+   int prio = 100;
+   charT* start = obuf;
+   while (true) {
+     char* end = strchrnul(start, '\n');
+     if (start == end) {
+       if (*start == '\0')
+       break;
+       // skip zero-length lines
+       ++start;
+       continue;
+     }
+     if (*start == '\1') {
+       // Decode some control characters
+       ++start;
+       unsigned char tmp = *((unsigned char*)start);
+       prio = tmp - 11;
+       ++start;
+     }
+     *end = '\n';
+     char next = *(end+1);
+     *(end+1) = '\0';
+     // Now 'start' points to a NULL-terminated string, which we want to
+     // output with priority 'prio'
+     int len = strlen(start);
+     if (flags & DOUTSB_FLAG_SYSLOG) {
+       //printf("syslogging: '%s' len=%d\n", start, len);
+       syslog(LOG_USER | dout_prio_to_syslog_prio(prio), "%s", start);
+     }
+     if (flags & DOUTSB_FLAG_STDOUT) {
+       // Just write directly out to the stdout fileno. There's no point in
+       // using something like fputs to write to a temporary buffer,
+       // because we would just have to flush that temporary buffer
+       // immediately.
+       if (safe_write(STDOUT_FILENO, start, len))
+       flags &= ~DOUTSB_FLAG_STDOUT;
+     }
+     if (flags & DOUTSB_FLAG_STDERR) {
+       // Only write to stderr if the message is important enough.
+       if (prio_is_visible_on_stderr(prio)) {
+       if (safe_write(STDERR_FILENO, start, len))
+         flags &= ~DOUTSB_FLAG_STDERR;
+       }
+     }
+     if (flags & DOUTSB_FLAG_OFILE) {
+       if (safe_write(ofd, start, len))
+       flags &= ~DOUTSB_FLAG_OFILE;
+     }
+     *(end+1) = next;
+     start = end + 1;
+   }
+   _clear_output_buffer();
+   // A value different than EOF (or traits::eof() for other traits) signals success.
+   // If the function fails, either EOF (or traits::eof() for other traits) is returned or an
+   // exception is thrown.
+   return traits_ty::not_eof(c);
+ }
+ template <typename charT, typename traits>
+ void DoutStreambuf<charT, traits>::handle_stderr_closed()
+ {
+   assert(_dout_lock.is_locked());
+   flags &= ~DOUTSB_FLAG_STDERR;
+ }
+ template <typename charT, typename traits>
+ void DoutStreambuf<charT, traits>::handle_stdout_closed()
+ {
+   assert(_dout_lock.is_locked());
+   flags &= ~DOUTSB_FLAG_STDOUT;
+ }
+ template <typename charT, typename traits>
+ void DoutStreambuf<charT, traits>::read_global_config()
+ {
+   assert(_dout_lock.is_locked());
+   flags = 0;
+   if (g_conf.log_to_syslog) {
+     flags |= DOUTSB_FLAG_SYSLOG;
+   }
+   if (g_conf.log_to_stdout) {
+     if (fd_is_open(STDOUT_FILENO)) {
+       flags |= DOUTSB_FLAG_STDOUT;
+     }
+   }
+   if (fd_is_open(STDERR_FILENO)) {
+     flags |= DOUTSB_FLAG_STDERR;
+   }
+   if (g_conf.log_to_file) {
+     if (_read_ofile_config()) {
+       flags |= DOUTSB_FLAG_OFILE;
+     }
+   }
+ }
+ template <typename charT, typename traits>
+ void DoutStreambuf<charT, traits>::
+ set_flags(int flags_)
+ {
+   assert(_dout_lock.is_locked());
+   flags = flags_;
+ }
+ template <typename charT, typename traits>
+ void DoutStreambuf<charT, traits>::
+ set_prio(int prio)
+ {
+   charT* p = this->pptr();
+   *p++ = '\1';
+   unsigned char val = (prio + 11);
+   *p++ = val;
+   this->pbump(2);
+ }
+ template <typename charT, typename traits>
+ int DoutStreambuf<charT, traits>::handle_pid_change()
+ {
+   assert(_dout_lock.is_locked());
+   if (!(flags & DOUTSB_FLAG_OFILE))
+     return 0;
+   string new_opath(_calculate_opath());
+   if (opath == new_opath)
+     return 0;
+   if (!isym_path.empty()) {
+     // Re-create the instance symlink
+     int ret = create_symlink(new_opath, isym_path);
+     if (ret) {
+       ostringstream oss;
+       oss << __func__ << ": failed to (re)create instance symlink";
+       primitive_log(oss.str());
+       return ret;
+     }
+   }
+   if (!rsym_path.empty()) {
+     // Re-create the rank symlink
+     int ret = create_symlink(new_opath, rsym_path);
+     if (ret) {
+       ostringstream oss;
+       oss << __func__ << ": failed to (re)create rank symlink";
+       primitive_log(oss.str());
+       return ret;
+     }
+   }
+   int ret = ::rename(opath.c_str(), new_opath.c_str());
+   if (ret) {
+     int err = errno;
+     ostringstream oss;
+     oss << __func__ << ": failed to rename '" << opath << "' to "
+         << "'" << new_opath << "': " << cpp_strerror(err) << "\n";
+     primitive_log(oss.str());
+     return err;
+   }
+   opath = new_opath;
+   return 0;
+ }
+ template <typename charT, typename traits>
+ int DoutStreambuf<charT, traits>::create_rank_symlink(int n)
+ {
+   Mutex::Locker l(_dout_lock);
+   if (!(flags & DOUTSB_FLAG_OFILE))
+     return 0;
+   ostringstream rss;
+   std::string symlink_dir(_get_symlink_dir());
+   rss << symlink_dir << "/" << g_conf.type << "." << n;
+   string rsym_path_(rss.str());
+   int ret = create_symlink(opath, rsym_path_);
+   if (ret) {
+     ostringstream oss;
+     oss << __func__ << ": failed to create rank symlink with n = "
+       << n << "\n";
+     primitive_log(oss.str());
+     return ret;
+   }
+   rsym_path = rsym_path_;
+   return 0;
+ }
+ template <typename charT, typename traits>
+ std::string DoutStreambuf<charT, traits>::config_to_str() const
+ {
+   assert(_dout_lock.is_locked());
+   ostringstream oss;
+   oss << "g_conf.log_to_syslog = " << g_conf.log_to_syslog << "\n";
+   oss << "g_conf.log_to_stdout = " << g_conf.log_to_stdout << "\n";
+   oss << "g_conf.log_to_file = " << g_conf.log_to_file << "\n";
+   oss << "g_conf.log_file = '" << cpp_str(g_conf.log_file) << "'\n";
+   oss << "g_conf.log_dir = '" << cpp_str(g_conf.log_dir) << "'\n";
+   oss << "g_conf.g_conf.log_per_instance = '"
+       << g_conf.log_per_instance << "'\n";
+   oss << "flags = 0x" << std::hex << flags << std::dec << "\n";
+   oss << "ofd = " << ofd << "\n";
+   oss << "opath = '" << opath << "'\n";
+   oss << "isym_path = '" << isym_path << "'\n";
+   oss << "rsym_path = '" << rsym_path << "'\n";
+   oss << "log_sym_history = " << g_conf.log_sym_history  << "\n";
+   return oss.str();
+ }
+ // This is called to flush the buffer.
+ // This is called when we're done with the file stream (or when .flush() is called).
+ template <typename charT, typename traits>
+ typename DoutStreambuf<charT, traits>::int_type
+ DoutStreambuf<charT, traits>::sync()
+ {
+   //std::cout << "flush!" << std::endl;
+   typename DoutStreambuf<charT, traits>::int_type
+     ret(this->overflow(traits_ty::eof()));
+   if (ret == traits_ty::eof())
+     return -1;
+   return 0;
+ }
+ template <typename charT, typename traits>
+ typename DoutStreambuf<charT, traits>::int_type
+ DoutStreambuf<charT, traits>::underflow()
+ {
+   // We can't read from this
+   // TODO: some more elegant way of preventing callers from trying to get input from this stream
+   assert(0);
+ }
+ template <typename charT, typename traits>
+ void DoutStreambuf<charT, traits>::_clear_output_buffer()
+ {
+   // Set up the put pointer.
+   // Overflow is called when this buffer is filled
+   this->setp(obuf, obuf + OBUF_SZ - 5);
+ }
+ template <typename charT, typename traits>
+ std::string DoutStreambuf<charT, traits>::_calculate_opath() const
+ {
+   assert(_dout_lock.is_locked());
+   // If g_conf.log_file was specified, that takes the highest priority
+   if (!empty(g_conf.log_file)) {
+     return normalize_relative(g_conf.log_file);
+   }
+   string log_dir;
+   if (empty(g_conf.log_dir))
+     log_dir = normalize_relative(".");
+   else
+     log_dir = normalize_relative(g_conf.log_dir);
+   if (g_conf.log_per_instance) {
+     char hostname[255];
+     memset(hostname, 0, sizeof(hostname));
+     int ret = gethostname(hostname, sizeof(hostname));
+     if (ret) {
+       int err = errno;
+       ostringstream oss;
+       oss << __func__ << ": error calling gethostname: " << cpp_strerror(err) << "\n";
+       primitive_log(oss.str());
+       return "";
+     }
+     ostringstream oss;
+     oss << log_dir << "/" << hostname << "." << getpid();
+     return oss.str();
+   }
+   else {
+     ostringstream oss;
+     oss << log_dir << "/" << g_conf.type << "." << g_conf.id << ".log";
+     return oss.str();
+   }
+ }
+ template <typename charT, typename traits>
+ std::string DoutStreambuf<charT, traits>::_get_symlink_dir() const
+ {
+   if (!empty(g_conf.log_sym_dir))
+     return normalize_relative(g_conf.log_sym_dir);
+   else
+     return get_dirname(opath);
+ }
+ template <typename charT, typename traits>
+ bool DoutStreambuf<charT, traits>::_read_ofile_config()
+ {
+   int ret;
+   isym_path = "";
+   rsym_path = "";
+   opath = _calculate_opath();
+   if (opath.empty()) {
+     ostringstream oss;
+     oss << __func__ << ": _calculate_opath failed.\n";
+     primitive_log(oss.str());
+     return false;
+   }
+   if (empty(g_conf.log_file) && g_conf.log_per_instance) {
+     // Calculate instance symlink path (isym_path)
+     ostringstream iss;
+     std::string symlink_dir(_get_symlink_dir());
+     iss << symlink_dir << "/" << g_conf.type << "." << g_conf.id;
+     isym_path = iss.str();
+     // Rotate isym_path
+     ret = _rotate_files(isym_path);
+     if (ret) {
+       ostringstream oss;
+       oss << __func__ << ": failed to rotate instance symlinks";
+       primitive_log(oss.str());
+       return ret;
+     }
+     // Create isym_path
+     ret = create_symlink(opath, isym_path);
+     if (ret) {
+       ostringstream oss;
+       oss << __func__ << ": failed to create instance symlink";
+       primitive_log(oss.str());
+       return ret;
+     }
+   }
+   assert(ofd == -1);
+   ofd = open(opath.c_str(),
+           O_CREAT | O_WRONLY | O_APPEND, S_IWUSR | S_IRUSR);
+   if (ofd < 0) {
+     int err = errno;
+     ostringstream oss;
+     oss << "failed to open log file '" << opath << "': "
+       << cpp_strerror(err) << "\n";
+     primitive_log(oss.str());
+     return false;
+   }
+   return true;
+ }
+ template <typename charT, typename traits>
+ int DoutStreambuf<charT, traits>::_rotate_files(const std::string &base)
+ {
+   // Given a file name base, and a directory like this:
+   // base
+   // base.1
+   // base.2
+   // base.3
+   // base.4
+   // unrelated_blah
+   // unrelated_blah.1
+   //
+   // We'll take the following actions:
+   // base               rename to base.1
+   // base.1             rename to base.2
+   // base.2             rename to base.3
+   // base.3             (unlink)
+   // base.4             (unlink)
+   // unrelated_blah     (do nothing)
+   // unrelated_blah.1   (do nothing)
+   signed int i;
+   for (i = -1; i < INT_MAX; ++i) {
+     ostringstream oss;
+     oss << base;
+     if (i != -1)
+       oss << "." << i;
+     string path(oss.str());
+     if (::access(path.c_str(), R_OK | W_OK))
+       break;
+   }
+   signed int max_symlink = i - 1;
+   for (signed int j = max_symlink; j >= -1; --j) {
+     ostringstream oss;
+     oss << base;
+     if (j != -1)
+       oss << "." << j;
+     string path(oss.str());
+     signed int k = j + 1;
+     if (k >= g_conf.log_sym_history) {
+       if (::unlink(path.c_str())) {
+       int err = errno;
+       ostringstream ess;
+       ess << __func__ << ": failed to unlink '" << path << "': "
+           << cpp_strerror(err) << "\n";
+       primitive_log(ess.str());
+       return err;
+       }
+       //*_dout << "---- " << getpid() << " removed " << path << " ----"
+       //       << std::endl;
+     }
+     else {
+       ostringstream pss;
+       pss << base << "." << k;
+       string new_path(pss.str());
+       if (::rename(path.c_str(), new_path.c_str())) {
+       int err = errno;
+       ostringstream ess;
+       ess << __func__ << ": failed to rename '" << path << "' to "
+           << "'" << new_path << "': " << cpp_strerror(err) << "\n";
+       primitive_log(ess.str());
+       return err;
+       }
+ //      *_dout << "---- " << getpid() << " renamed " << path << " -> "
+ //      << newpath << " ----" << std::endl;
+     }
+   }
+   return 0;
+ }
+ // Explicit template instantiation
+ template class DoutStreambuf <char>;
diff --cc src/config.cc
Simple merge
diff --cc src/config.h
Simple merge
diff --cc src/librados.cc
Simple merge
diff --cc src/mds/CDir.cc
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 342f737153eda534fa20bb580e6efdf3b530ed8a,fb5c039fd4465b24d22792f0fb30278083485d6e..f0a253b5aed36a846c93fbaae3a1d49ae77948c5
@@@ -560,26 -559,6 +559,24 @@@ void Paxos::extend_lease(
    mon->timer.add_event_at(at, lease_renew_event);
  }
  
-       stringstream ss;
-       ss << "message from " << from << " was stamped " << diff
-          << "s in the future, clocks not synchronized";
-       mon->get_logclient()->log(LOG_WARN, ss);
 +void Paxos::warn_on_future_time(utime_t t, entity_name_t from)
 +{
 +  utime_t now = g_clock.now();
 +  if (t > now) {
 +    utime_t diff = t - now;
 +    if (diff > g_conf.mon_clock_drift_allowed) {
 +      utime_t warn_diff = now - last_clock_drift_warn;
 +      if (warn_diff >
 +        pow(g_conf.mon_clock_drift_warn_backoff, clock_drift_warned)) {
++      mon->clog.warn() << "message from " << from << " was stamped " << diff
++                       << "s in the future, clocks not synchronized";
 +      last_clock_drift_warn = g_clock.now();
 +      ++clock_drift_warned;
 +      }
 +    }
 +  }
 +
 +}
  
  // peon
  void Paxos::handle_lease(MMonPaxos *lease)
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc src/osd/OSD.cc
Simple merge
diff --cc src/osd/PG.cc
index 22a095476595b17a6779569c057c706bb912fcfb,955a75b1b612edfedec4eab037123e75cd926691..67f80a75654ae62da83e6d815578283cfca31209
@@@ -3194,9 -3197,9 +3192,8 @@@ void PG::scrub(
        }
        if (anymissing) {
        for (unsigned i=0; i<acting.size(); i++) {
 -        if (p[i] == m[i]->objects.end() || po->poid != p[i]->second.poid) {
 -          osd->clog.error() << info.pgid << " " << mode << " osd"
 -            << acting[i] << " missing " << po->poid << "\n";
 +        if (p[i] == m[i]->objects.end() || *psoid != p[i]->first) {
-           ss << info.pgid << " " << mode << " osd" << acting[i] << " missing " << *psoid;
-           osd->get_logclient()->log(LOG_ERROR, ss);
++          osd->clog.error() << info.pgid << " " << mode << " osd" << acting[i] << " missing " << *psoid;
            num_missing++;
            
            if (repair)
        for (unsigned i=1; i<acting.size(); i++) {
        bool peerok = true;
        if (po->size != p[i]->second.size) {
 -        dout(0) << "scrub osd" << acting[i] << " " << po->poid
 +        dout(0) << "scrub osd" << acting[i] << " " << *psoid
                  << " size " << p[i]->second.size << " != " << po->size << dendl;
-         ss << info.pgid << " " << mode << " osd" << acting[i] << " " << *psoid
 -        osd->clog.error() << info.pgid << " " << mode << " osd"
 -            << acting[i] << " " << po->poid << " size " << p[i]->second.size
 -            << " != " << po->size << "\n";
++        osd->clog.error() << info.pgid << " " << mode << " osd" << acting[i] << " " << *psoid
 +           << " size " << p[i]->second.size << " != " << po->size;
-         osd->get_logclient()->log(LOG_ERROR, ss);
          peerok = ok = false;
          num_bad++;
        }
        if (po->attrs.size() != p[i]->second.attrs.size()) {
 -        dout(0) << "scrub osd" << acting[i] << " " << po->poid
 -                << " attr count " << p[i]->second.attrs.size() << " != " 
 -                << po->attrs.size() << dendl;
 -        osd->clog.error() << info.pgid << " " << mode << " osd"
 -            << acting[i] << " " << po->poid
 -            << " attr count " << p[i]->second.attrs.size()
 -            << " != " << po->attrs.size() << "\n";
 +        dout(0) << "scrub osd" << acting[i] << " " << *psoid
 +                << " attr count " << p[i]->second.attrs.size() << " != " << po->attrs.size() << dendl;
-         ss << info.pgid << " " << mode << " osd" << acting[i] << " " << *psoid
-            << " attr count " << p[i]->second.attrs.size() << " != " << po->attrs.size();
-         osd->get_logclient()->log(LOG_ERROR, ss);
++        osd->clog.error() << info.pgid << " " << mode << " osd" << acting[i] << " " << *psoid
++                          << " attr count " << p[i]->second.attrs.size() << " != " << po->attrs.size();
          peerok = ok = false;
          num_bad++;
        }
        for (map<string,bufferptr>::iterator q = po->attrs.begin(); q != po->attrs.end(); q++) {
          if (p[i]->second.attrs.count(q->first)) {
            if (q->second.cmp(p[i]->second.attrs[q->first])) {
 -            dout(0) << "scrub osd" << acting[i] << " " << po->poid
 +            dout(0) << "scrub osd" << acting[i] << " " << *psoid
                      << " attr " << q->first << " value mismatch" << dendl;
-             ss << info.pgid << " " << mode << " osd" << acting[i] << " " << *psoid
-                << " attr " << q->first << " value mismatch";
-             osd->get_logclient()->log(LOG_ERROR, ss);
 -            osd->clog.error() << info.pgid << " " << mode << " osd"
 -                << acting[i] << " " << po->poid
 -                << " attr " << q->first << " value mismatch\n";
++            osd->clog.error() << info.pgid << " " << mode << " osd" << acting[i] << " " << *psoid
++                              << " attr " << q->first << " value mismatch";
              peerok = ok = false;
              num_bad++;
            }
          } else {
 -          dout(0) << "scrub osd" << acting[i] << " " << po->poid
 +          dout(0) << "scrub osd" << acting[i] << " " << *psoid
                    << " attr " << q->first << " missing" << dendl;
-           ss << info.pgid << " " << mode << " osd" << acting[i] << " " << *psoid
 -          osd->clog.error() << info.pgid << " " << mode << " osd"
 -             << acting[i] << " " << po->poid << " attr " << q->first
 -             << " missing" << "\n";
++          osd->clog.error() << info.pgid << " " << mode << " osd" << acting[i] << " " << *psoid
 +             << " attr " << q->first << " missing";
-           osd->get_logclient()->log(LOG_ERROR, ss);
            peerok = ok = false;
            num_bad++;
          }
Simple merge
Simple merge
index ef40e4456f0b18ea1963a70eeea17630a016c7dd,0000000000000000000000000000000000000000..a380e6e09648aa75b2f715477d3b93568679ec5e
mode 100644,000000..100644
--- /dev/null
@@@ -1,199 -1,0 +1,200 @@@
 +// -*- 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) 2004-2010 Sage Weil <sage@newdream.net>
 + * Copyright (C) 2010 Dreamhost
 + *
 + * 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 "ceph.h"
 +#include "common/common_init.h"
 +#include "common/errno.h"
 +#include "config.h"
 +
++#include <limits.h>
 +#include <errno.h>
 +#include <fcntl.h>
 +#include <iostream>
 +#include <sys/stat.h>
 +#include <sys/types.h>
 +#include <vector>
 +
 +using std::cerr;
 +using std::vector;
 +
 +static void usage()
 +{
 +  cerr << "usage: ceph [options] [commands]" << std::endl;
 +  cerr << "If no commands are specified, enter interactive mode.\n";
 +  cerr << "Commands:" << std::endl;
 +  cerr << "   stop              -- cleanly shut down file system" << std::endl
 +       << "   (osd|pg|mds) stat -- get monitor subsystem status" << std::endl
 +       << "   ..." << std::endl;
 +  cerr << "Options:" << std::endl;
 +  cerr << "   -i infile\n";
 +  cerr << "   -o outfile\n";
 +  cerr << "        specify input or output file (for certain commands)\n";
 +  cerr << "   -s or --status\n";
 +  cerr << "        print current system status\n";
 +  cerr << "   -w or --watch\n";
 +  cerr << "        watch system status changes in real time (push)\n";
 +  generic_client_usage(); // Will exit()
 +}
 +
 +static void parse_cmd_args(const vector<const char*> &args,
 +              const char **in_file, const char ** out_file,
 +              ceph_tool_mode_t *mode, vector<const char*> *nargs)
 +{
 +  DEFINE_CONF_VARS(usage);
 +  FOR_EACH_ARG(args) {
 +    if (CONF_ARG_EQ("in_file", 'i')) {
 +      CONF_SAFE_SET_ARG_VAL(in_file, OPT_STR);
 +    } else if (CONF_ARG_EQ("out_file", 'o')) {
 +      CONF_SAFE_SET_ARG_VAL(out_file, OPT_STR);
 +    } else if (CONF_ARG_EQ("status", 's')) {
 +      *mode = CEPH_TOOL_MODE_ONE_SHOT_OBSERVER;
 +    } else if (CONF_ARG_EQ("watch", 'w')) {
 +      *mode = CEPH_TOOL_MODE_OBSERVER;
 +    } else if (CONF_ARG_EQ("help", 'h')) {
 +      usage();
 +    } else if (args[i][0] == '-' && nargs->empty()) {
 +      cerr << "unrecognized option " << args[i] << std::endl;
 +      usage();
 +    } else {
 +      nargs->push_back(args[i]);
 +    }
 +  }
 +}
 +
 +static int safe_read(int fd, char *buf, size_t count)
 +{
 +  if (count > SSIZE_MAX)
 +    return E2BIG;
 +  while (1) {
 +    int res;
 +    res = read(fd, buf, count);
 +    if (res < 0) {
 +      int err = errno;
 +      if (err == EINVAL)
 +      continue;
 +      return err;
 +    }
 +    count -= res;
 +    buf += res;
 +    if (count <= 0)
 +      return 0;
 +  }
 +}
 +
 +static int get_indata(const char *in_file, bufferlist &indata)
 +{
 +  int fd = TEMP_FAILURE_RETRY(::open(in_file, O_RDONLY));
 +  if (fd < 0) {
 +    int err = errno;
 +    cerr << "error opening in_file '" << in_file << "': "
 +       << cpp_strerror(err);
 +    return 1;
 +  }
 +  struct stat st;
 +  if (::fstat(fd, &st)) {
 +    int err = errno;
 +    cerr << "error getting size of in_file '" << in_file << "': "
 +       << cpp_strerror(err);
 +    return 1;
 +  }
 +
 +  indata.push_back(buffer::create(st.st_size));
 +  indata.zero();
 +  int ret = safe_read(fd, indata.c_str(), st.st_size);
 +  if (ret) {
 +    cerr << "error reading in_file '" << in_file << "': "
 +       << cpp_strerror(ret);
 +    return 1;
 +  }
 +
 +  TEMP_FAILURE_RETRY(::close(fd));
 +  cout << "read " << st.st_size << " bytes from " << in_file << std::endl;
 +  return 0;
 +}
 +
 +int main(int argc, const char **argv)
 +{
 +  vector<const char*> args;
 +  argv_to_vec(argc, argv, args);
 +  env_to_vec(args);
 +
 +  ceph_set_default_id("admin");
 +
 +  common_set_defaults(false);
 +  common_init(args, "ceph", true);
 +
 +  vec_to_argv(args, argc, argv);
 +
 +  const char *in_file = NULL;
 +  const char *out_file = NULL;
 +  enum ceph_tool_mode_t mode = CEPH_TOOL_MODE_CLI_INPUT;
 +  vector<const char*> nargs;
 +
 +  // parse user input
 +  parse_cmd_args(args, &in_file, &out_file, &mode, &nargs);
 +
 +  bufferlist indata;
 +
 +  if (in_file) {
 +    if (get_indata(in_file, indata)) {
 +      cerr << "failed to get data from '" << in_file << "'" << std::endl;
 +      return 1;
 +    }
 +  }
 +
 +  if (ceph_tool_common_init(mode)) {
 +    cerr << "ceph_tool_common_init failed." << std::endl;
 +    return 1;
 +  }
 +
 +  int ret = 0;
 +  switch (mode) {
 +    case CEPH_TOOL_MODE_ONE_SHOT_OBSERVER: // fall through
 +    case CEPH_TOOL_MODE_OBSERVER: {
 +      g.lock.Lock();
 +      send_observe_requests();
 +      g.lock.Unlock();
 +      break;
 +    }
 +
 +    case CEPH_TOOL_MODE_CLI_INPUT: {
 +      vector<string> cmd;
 +      for (unsigned int i = 0; i < nargs.size(); ++i) {
 +      cmd.push_back(string(nargs[i]));
 +      }
 +      if (cmd.empty()) {
 +      if (ceph_tool_do_cli())
 +        ret = 1;
 +      }
 +      else {
 +      if (ceph_tool_cli_input(cmd, out_file, indata))
 +        ret = 1;
 +      }
 +      if (ceph_tool_messenger_shutdown())
 +      ret = 1;
 +      break;
 +    }
 +
 +    default: {
 +      cerr << "logic error: illegal ceph command mode " << mode << std::endl;
 +      ret = 1;
 +      break;
 +    }
 +  }
 +
 +  if (ceph_tool_common_shutdown())
 +    ret = 1;
 +  return ret;
 +}