-------- Original Message --------
Subject: Re: Crazy idea of cleanup the inode_record btrfsck things with SQL?
From: Robert White <rwh...@pobox.com>
To: Qu Wenruo <quwen...@cn.fujitsu.com>, linux-btrfs <linux-btrfs@vger.kernel.org>
Date: 2014年12月04日 03:18
On 12/01/2014 05:17 PM, Qu Wenruo wrote:
But I am also somewhat tired of bringing new structure new searching
functions or even bring larger change on
the btrfsck record infrastructure when I found that can't provide the
function when new recovery function is going
to be implemented.

DISCLAIMER: My actual thing is modeling, so coming from the idea that btrfsck is basically building a model of the filesystem and comparing the theoretically correct model to the actual filesystem as found... and having spent nearly zero time inside of the btrfsck code base itself...

I've looked at what I _think_ you are trying to do with the lookup/correlate phase finding peer/parent/child references and I'd think other things would make sense far more sense than SQL.

C++ Standard Template Library at a minimum, life is too short to reinvent data lookups in memory. But its also too short to re-factor SQL queries or wait for degenerate full-table scans.
C++ doesn't comes to me in my first thought, since I haven't use it for a long long time... :-(

The boost "multi-index container", if you are going to bring in an external library, would do you far better for dealing with future structural changes. It would directly index the fields of your (parent,child,name) relation and let you switch iteration on-the-fly (e.g. you can be walking parents and use the same iterator to start walking names etc). (there's even a cookbook item for adding an LRU cache as a natural index for space-constrained items.) Again you'd have to switch over to C++, but it implements exactly what I think you are looking for. the multi-index container declaration syntax gets a little thick but once declared the usage model is really simple. (you pay most-or-all the cost during "update" which is really a remove-then-readd but you won't be updating as often as adding so...)
Yeah, C++ seems much easier to switch, but as the preparation, it is better to cleanup the inode_record codes from
cmds-check.c and put them into a single file.
After the cleanup, I think we can even have different backend to test with.
(Only to test, multi-backend support also seems to be overkilled)

My "crazy-ist idea" would be to maybe mmap all the metadata from the filesystem into the process space and build a page-table-like index over that. The virtual memory demand paging will become your caching buddy. mapped_block+offest gets you directly to the whole native structure. You might have to juggle mappings (map and unmap them) on systems with arger filesystems but smaller virtual tables (e.g. classic pentium 32 bit). Even then, you'd be juggling mappings and the kernel would be doing all the real caching. The more data you can leave in the mmapped ranges the less storage management takes place in the local code.

IMHO, finding a USB stick to make a swap space on is probably just as good, if not better than, doing it with a whole other filesystem and the "put my temp files there" option during emergency maintenance.
Sadly, there is already user complaining about the memory usage:
http://comments.gmane.org/gmane.comp.file-systems.btrfs/34573

The 13T fs may contain several hundreds GB of metadata, already takes over 8G memory. It may takes up 10+ of GB memory, so a memory stick may help but when it happens on a remote server?
Or can you tolerate the snail like slow IO speed?
So better store them on disk when things go really huge.

Map and unmap will be good,but it may not resolve the problem at all.
The main memory usage in btrfsck is extent record, which
we can't free them until we read them all in and checked, so even we mmap/unmap, it can only help with
the extent_buffer(which is already freed if not used according to refs).

Now, I miss the page cache in kernel so much...

Anyway, btrfsck should really consider about the memory usage now.



If the mailing list engine honors attachments, you will find FileEntries.h from one of my projects, offered as a simplified example of a directory entry cache implemented in a boost multi-index container.

(Note that this is fully working code from an upcoming addition to my soruceforge project, so it's not just theoretical implementation ideas.)

struct FileEntry {
  struct NameIndex {};
  struct DirectoryIndex {};
  struct INodeIndex {};
  struct TypedIndex {};
  dev_t         Device;
  long          ParentINode;
  long          INode;
  std::string   Name;
  enum FileType Type;
};

The empty structs inside the struct act as index identifiers/names (Because C++ templates only disambiguate on types so FileEntry::NameIndex is the type-name of the index of file names (etc).

Any other data could be added to FileEntry without disrupting any existing code for indexing or iterating.

The container itself is a little grusome textually ::

typedef multi_index_container<
  FileEntry,
  indexed_by<
    ordered_non_unique<
      tag<FileEntry::NameIndex>,
      member<
        FileEntry,
        std::string,
        &FileEntry::Name
      >
    >,
    ordered_non_unique<
      tag<FileEntry::DirectoryIndex>,
      composite_key<
        FileEntry,
        member<
          FileEntry,
          dev_t,
          &FileEntry::Device
        >,
        member<
          FileEntry,
          long,
          &FileEntry::ParentINode
        >
      >
    >,
    ordered_non_unique<
      tag<FileEntry::INodeIndex>,
      composite_key<
        FileEntry,
        member<
          FileEntry,
          dev_t,
          &FileEntry::Device
        >,
        member<
          FileEntry,
          long,
          &FileEntry::INode
        >
      >
    >,
    ordered_non_unique<
      tag<FileEntry::TypedIndex>,
      composite_key<
        FileEntry,
        member<
          FileEntry,
          enum FileType,
          &FileEntry::Type
        >,
        member<
          FileEntry,
          std::string,
          &FileEntry::Name
        >
      >
    >
  >
> FileSet;


But after that it's super easy to use, uh, if you know STL iterator speak anyway. 8-)

Having a file set is easy and typesafe in any type-able context (such as a member of another structure, or a global):
FileSet result;

Picking yoru index/view has to be done by (admittedly ugly looking) type
FileSet::index<FileEntry::NameIndex>::type

But then when you make one and plumb it ("result" being the working set
FileSet::index<FileEntry::NameIndex>::type & by_name = result.get<FileEntry::NameIndex>();

by_name is now a fully functional view of the set as an iteraterable container with elements like by_name.erase(some_name) and such.

It gets you what you say you want from SQL but without all the indirection or duplication of SQL.

(Note that the attached example will fill a FileSet object into memory with the entire (sub) tree of a file system if you call Fill() with the deep selector; or just fill the set with the contents of a single directory when the shallow selector is used.

etc.

So anyway. I've been in this modeling space for a while. I looked at other means of modeling such as SQL and I decided this one was "the best" for what I was doing.

The results are fast, deterministic, and type-safe with no internal typecasts or full table scan results.
Great implement! Almost fits all the needs, except the ability to save it on disk...

In fact, I have already an idea to implement it in pure C, although not so generic than C++ template, but should
work anyway.

So the remaining problem will be the ability to cache things on disk for case like the 13T array.

For C/C++, saving recording to disk will be a simplified version of page cache, but will still be a huge chanllenge. For SQL, it will be much easier but I am consider it as the last try now, since the C++ implement seems quite good.

Anyway, the memory usage problem is still a problem to resolve.

Thanks,
Qu
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to