Linux Btrfs filesystem development
 help / color / mirror / Atom feed
From: Alexandre Oliva <oliva@gnu.org>
To: Chris Mason <clmason@fusionio.com>
Cc: Samuel Just <sam.just@inktank.com>,
	"linux-btrfs\@vger.kernel.org" <linux-btrfs@vger.kernel.org>,
	"ceph-devel\@vger.kernel.org" <ceph-devel@vger.kernel.org>
Subject: Re: corruption of active mmapped files in btrfs snapshots
Date: Sat, 23 Mar 2013 06:47:26 -0300	[thread overview]
Message-ID: <or620ia1n5.fsf@livre.home> (raw)
In-Reply-To: <20130322171214.27874.48118@localhost.localdomain> (Chris Mason's message of "Fri, 22 Mar 2013 13:12:14 -0400")

[-- Attachment #1: Type: text/plain, Size: 652 bytes --]

On Mar 22, 2013, Chris Mason <clmason@fusionio.com> wrote:

> Quoting Samuel Just (2013-03-22 13:06:41)
>> Incomplete writes for leveldb should just result in lost updates, not
>> corruption.

> In this case, I think Alexandre is scanning for zeros in the file.

Yup, the symptom is zeros at the end of a page, with nonzeros on the
subsequent page, which indicates that the writes to the previous page
were dropped.

What I actually do is to iterate over the entire database, which will
error out when the block header is found to be corrupted.  I use this
program I wrote (also hereby provided under GNU GPLv3+) to check the
database for corruption.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: dbck.cc --]
[-- Type: text/x-c++src, Size: 3237 bytes --]

#include <assert.h>
#include <iostream>
#include "leveldb/db.h"

int main(int argc, char *argv[]) {
  bool paranoid = false;
  bool dump = false;
  bool repair = false;
  bool quiet = false;
  int i = 0;
  int errors = 0;

  if (argc == 1) {
  usage:
    std::cout << "usage: [flags] dbname [flags] ..." << std::endl
	      << "-d --dump     dump database contents" << std::endl
	      << "-r --repair   repair database" << std::endl
	      << "-p --paranoid enable paranoid mode" << std::endl
	      << "-l --lax      disable paranoid mode (default)" << std::endl
	      << "-q --quiet    enable quiet mode" << std::endl
	      << "-v --verbose  disable quiet mode (default)" << std::endl
	      << "-h --help     show this message and exit" << std::endl
	      << "dbname        check, dump and repair" << std::endl
	      << std::endl
	      << "exit status is the number of errors" << std::endl;
    return errors;
  }

  for (i++; i < argc; i++) {
    if (argv[i][0] == '-') {
      if (strcmp (argv[i], "--dump") == 0
	  || strcmp (argv[i], "-d") == 0)
	dump = true;
      else if (strcmp (argv[i], "--repair") == 0
	       || strcmp (argv[i], "-r") == 0)
	repair = true;
      else if (strcmp (argv[i], "--paranoid") == 0
	       || strcmp (argv[i], "-p") == 0)
	paranoid = true;
      else if (strcmp (argv[i], "--lax") == 0
	       || strcmp (argv[i], "-l") == 0)
	paranoid = false;
      else if (strcmp (argv[i], "--quiet") == 0
	       || strcmp (argv[i], "-q") == 0)
	quiet = true;
      else if (strcmp (argv[i], "--verbose") == 0
	       || strcmp (argv[i], "-v") == 0)
	quiet = false;
      else if (strcmp (argv[i], "--help") == 0
	       || strcmp (argv[i], "-h") == 0)
	goto usage;
      else {
	std::cerr << "unrecognized option: " << argv[i] << std::endl;
	goto usage;
      }
    } else {
      if (!quiet)
	std::cout << argv[i] << std::endl;

      leveldb::DB* db;
      leveldb::Options options;
      options.paranoid_checks = paranoid;
      leveldb::Status status = leveldb::DB::Open(options, argv[i], &db);
      bool bad = false;

      if (!status.ok()) {
	std::cerr << status.ToString() << std::endl;
	bad = true;
      } else {
	leveldb::ReadOptions rdopt;
	rdopt.verify_checksums = paranoid;
	rdopt.fill_cache = false;
	leveldb::Iterator* it = db->NewIterator(rdopt);
	int count = 0;
	try {
	  for (it->SeekToFirst(); it->Valid(); it->Next()) {
	    count++;
	    if (dump)
	      std::cout << it->key().ToString() << ": "
			<< it->value().ToString() << std::endl;
	    else if (!quiet && count % 1000 == 0)
	      std::cout << count << " entries\r" << std::flush;
	  }
	  if (!it->status().ok()) {
	    std::cerr << it->status().ToString() << std::endl;
	    bad = true;
	  }
	} catch (...) {
	  std::cerr << "caught an exception" << std::endl;
	}
	delete it;
	if (!quiet)
	  std::cout << count << " entries" << std::endl;
      }

      delete db;

      if (bad) {
	errors++;
	if (repair) {
	  if (!quiet)
	    std::cout << "repairing..." << std::endl;
	  status = RepairDB(argv[i], options);
	  if (!status.ok()) {
	    std::cerr << status.ToString() << std::endl;
	    errors++;
	  }
	} else if (!quiet)
	  std::cout << "use --repair to repair" << std::endl;
      }
    }
  }

  return errors;
}

[-- Attachment #3: Type: text/plain, Size: 258 bytes --]



-- 
Alexandre Oliva, freedom fighter    http://FSFLA.org/~lxoliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/   FSF Latin America board member
Free Software Evangelist      Red Hat Brazil Compiler Engineer

  reply	other threads:[~2013-03-23  9:48 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-03-18 21:14 corruption of active mmapped files in btrfs snapshots Alexandre Oliva
2013-03-18 22:43 ` Alexandre Oliva
2013-03-18 22:52 ` Chris Mason
2013-03-19  5:20   ` Alexandre Oliva
2013-03-19 12:09     ` Chris Mason
2013-03-19 17:29       ` Sage Weil
2013-03-19 19:26         ` Alexandre Oliva
2013-03-19 19:26       ` Alexandre Oliva
2013-03-20  1:58         ` Alexandre Oliva
2013-03-21  7:14           ` Alexandre Oliva
2013-03-21 18:06             ` Chris Mason
2013-03-21 23:06               ` Chris Mason
2013-03-22  5:27                 ` Alexandre Oliva
2013-03-22 12:07                   ` Chris Mason
2013-03-22 14:17                     ` Alexandre Oliva
2013-03-22 14:26                       ` Chris Mason
2013-03-22 17:06                         ` Samuel Just
2013-03-22 17:12                           ` Chris Mason
2013-03-23  9:47                             ` Alexandre Oliva [this message]
2013-03-22 17:08                         ` David Sterba
2013-03-23  9:48                           ` Alexandre Oliva
2013-03-25 15:33                             ` David Sterba
2013-03-22 17:18                         ` Sage Weil
2013-03-22 18:07 ` Chris Mason
2013-03-22 20:31   ` Chris Mason
2013-03-26  0:08     ` Chris Mason
2013-03-29  9:56       ` Alexandre Oliva
2013-03-29 11:35         ` Chris Mason

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=or620ia1n5.fsf@livre.home \
    --to=oliva@gnu.org \
    --cc=ceph-devel@vger.kernel.org \
    --cc=clmason@fusionio.com \
    --cc=linux-btrfs@vger.kernel.org \
    --cc=sam.just@inktank.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox