Commit Graph
2307 Commits
Author SHA1 Message Date
Zach Brown d91dc45368 scoutfs: add interval tree
Add an interval tree that lets us efficiently discover intervals that
overlap a given search region.  We're going to need this now to sanely
implementing merging and in the future to implement granting access
ranges.

It's easy to implement an interval tree by using the kernel's augmented
rbtree to track the max end value of the subtree of intervals.  The
tricky bit is that the augmented interface assumes that it can directly
compare the augmented value.

If we were developing against mainline we'd just patch the interface.
But we're developing against distro kernels that development partners
deploy so the kernel is frozen in amber.

We deploy a giant stinky hack to import a private tweaked version of the
interface.  It's isolated so we can trivially drop it once we merge with
the fixed upstream interface.  We also add some build time checks to
make sure that we don't accidentally combine rb structures between the
private import and the main kernel interface.

Signed-off-by: Zach Brown <zab@versity.com>
2016-04-01 14:53:06 -07:00
Zach Brown 544fd1ba9a Add ctrstat command
Like vmstat and iostat, this prints out our counters over time.

Signed-off-by: Zach Brown <zab@versity.com>
2016-04-01 00:04:26 -04:00
Zach Brown 7a565a69df scoutfs: add percpu coutners with sysfs files
Add percpu counters that will let us track all manner of things.

To report them we add a sysfs directory full of attribute files in a
sysfs dir for each mount:

    # (cd /sys/fs/scoutfs/loop0/counters && grep . *)
    skip_delete:0
    skip_insert:3218
    skip_lookup:8439
    skip_next:1190
    skip_search:156

The implementation is careful to define each counter in only one place.
We don't have to make sure that a bunch of defintions and arrays are in
sync.

This builds off of Ben's initial patches that added sysfs dirs.

Signed-off-by: Zach Brown <zab@versity.com>
Signed-off-by: Ben McClelland <ben.mcclelland@versity.com>
2016-03-31 16:44:37 -07:00
Zach Brown 6e20913661 scoutfs: insert new manifests at highest level
Manifests for newly written segments can be inserted at the highest
level that doesn't have segments they intersect.  This avoids ring and
merging churn.

The change cleans up the code a little bit, which is nice, and adds
tracepoints for manifests entering and leaving the in memory structures.

Signed-off-by: Zach Brown <zab@versity.com>
2016-03-29 16:15:09 -07:00
Zach Brown 52c315942f scoutfs: update item block and manifest item range
The manifests for level 0 blocks always claimed that they could contain
all keys.  That causes a lot of extra bloom filter lookups when in fact
the blocks contain a very small range of keys.

It's true that we don't know what items a dirty segment is going to
contain, don't want to update the manfiest at every insertion, and have
to find the items in the segments in regular searching.

But when they're finalized we know the items they'll contain and can
update the manifest.  We do that by initializing the item block range to
nonsense and extending it as items are added.  When it's finalized we
update the manifest in memory and in the ring.

Signed-off-by: Zach Brown <zab@versity.com>
2016-03-29 11:27:27 -07:00
Zach Brown 97e6c1e605 scoutfs: fix final overlapping item/val
Item headers are written from the front of the block to the tail.
Item values are written from the tail of the block towards the head.

The math to detect their overlapping in the center forgot to take the
length of the item header into account.  We could have final item
headers and values overriding each other which causes file data to
appear as an item header.

Signed-off-by: Zach Brown <zab@versity.com>
2016-03-29 11:25:36 -07:00
Zach Brown af2975111a Update format for smaller bloom
Update our format for the smaller bloom sizes.

Signed-off-by: Zach Brown <zab@versity.com>
2016-03-29 13:10:45 -04:00
Zach Brown c7c8969704 scoutfs: adjust bloom size for segment item max
The bloom filter was much too large for the current typical limit on the
number of items that fit in a segment.  Having them too large decreases
storage efficiency, has us read more data from a cold cache, and bloom
tests pin too much data.

We can cut it down to 25% for our current segment and item sizes.

Signed-off-by: Zach Brown <zab@versity.com>
2016-03-29 10:08:37 -07:00
Zach Brown 7ea78502c8 Read both super blocks and use current
When printing try to read both super blocks and use the most recent one
instead of just using the first one.

Signed-off-by: Zach Brown <zab@versity.com>
2016-03-29 13:07:00 -04:00
Zach Brown f1b5eb8a80 scoutfs: more dirty segment locking
The segment code wasn't always locking around concurrent accesses to the
dirty segment.  This is mostly a problem for updating all the next
elements in skip list modification.  But we also want to serialize dirty
block writing.

Add a little helper function to acquire the dirty mutex when we're
reading from the current dirty segment.

Bring sync in to segment.c so it's clear that it's intimately related to
the dirty segment.

The item deletion hack was totally unlocked.

Signed-off-by: Zach Brown <zab@versity.com>
2016-03-27 19:29:38 -07:00
Zach Brown 9c3918b576 scoutfs: remove accidentally committed notes
Some brainstorming notes in a comment accdentally made their way in to a
commit.

Signed-off-by: Zach Brown <zab@versity.com>
2016-03-27 16:19:19 -07:00
Zach Brown eff3d78cb1 scoutfs: update inode when write changes i_size
Extended file data wasn't persistent because we weren't writing out the
inode with the i_size update that covered the newly written data.

Signed-off-by: Zach Brown <zab@versity.com>
2016-03-26 22:28:45 -07:00
Zach Brown 059212d50e scoutfs: add some basic tracepoints
I added these tracepoints to verify that file data isn't reachable after
mount because we're not writing out the inode with the current i_size.

Signed-off-by: Zach Brown <zab@versity.com>
2016-03-26 22:28:42 -07:00
Zach Brown 402dd2969f scoutfs: add tracepoint support with bloom example
Add the intrastucture for tracepoints.  We include an example user that
traces bloom filter hits and misses.

Signed-off-by: Zach Brown <zab@versity.com>
2016-03-26 20:58:31 -07:00
Zach Brown 10cf83ffc5 Update key type value format change
Adding file data items changed the item key values.

Signed-off-by: Zach Brown <zab@versity.com>
2016-03-26 14:00:19 -04:00
Zach Brown 9cf87ee571 scoutfs: add basic file page cache read and write
Add basic file data support by implementing the address space file and
page read and write methods.  This passis basic read/write tests but is
only the seed of a final implementation.

Signed-off-by: Zach Brown <zab@versity.com>
2016-03-26 10:58:06 -07:00
Zach Brown 867d717d2b scoutfs: item offsets need to skip block headers
The vallue offset allocation knew to skip block headers at the start of
each segment block but, weirdly, the item offset allocation didn't.

We make item offset calculation skip the header and we add some tracing
to help see the problem.

Signed-off-by: Zach Brown <zab@versity.com>
2016-03-25 19:28:21 -07:00
Zach Brown 6834100251 scoutfs: free our dentry info
Stop leaking dentry_info allocations by adding a dentry_op with a
d_release that frees our dentry info allocation.  rmmod tests no longer
fail when dmesg screams that we have slab caches that still have
allocated objects.

Signed-off-by: Zach Brown <zab@versity.com>
s
2016-03-25 11:08:20 -07:00
Zach Brown 434cbb9c78 scoutfs: create dirty items for inode updates
Inode updates weren't persistent because they were being stored in clean
segments in memory.  This was triggered by the new hashed dirent
mechanism returning -ENOENT when the inode still had a 0 max dirent hash
nr.

We make sure that there is a dirty item in the dirty segment at the
start of inode modification so that later updates will store in the
dirty segment.  Nothing ensures that the dirty segment won't be written
out today but that will be added soon.

Signed-off-by: Zach Brown <zab@versity.com>
2016-03-25 10:08:34 -07:00
Zach Brown 3bb00fafdc scoutfs: require sparse builds
Now that we know that it's easy to fix sparse build failures against
RHEL kernel headers we can require sparse builds when developing.

Signed-off-by: Zach Brown <zab@versity.com>
2016-03-24 21:45:08 -07:00
Zach Brown fbbfac1b27 scoutfs: fix sparse errors
I was building against a RHEL tree that broke sparse builds.  With that
fixed I can now see and fix sparse errors.

Signed-off-by: Zach Brown <zab@versity.com>
2016-03-24 21:44:42 -07:00
Zach Brown 339c719e4e Print dirents in print command
Add support for printing dirent items to scoutfs print.  We're careful
to change non-printable characters to ".".

Signed-off-by: Zach Brown <zab@versity.com>
2016-03-25 00:24:48 -04:00
Zach Brown e1c1c50ead Update to multiple dirent hash format
Update print to show the inode fields in the newer dirent hashing
scheme.  mkfs doesn't create directory entries.

Signed-off-by: Zach Brown <zab@versity.com>
2016-03-24 21:09:51 -07:00
Zach Brown 3755adddd5 scoutfs: store dirents at multiple hash values
Previously we dealt with colliding dirent hash values by storing all the
dirents that share a hash value in a big item with multiple dirents.

This complicated the code and strongly encouraged resizing items as
dirents come and go.  Resizing items isn't very easy with our simple log
segment item creation mechanism.

Instead let's deal with collisions by allowing a dirent to be stored at
multiple hash values.  The code is much simpler.

Lookup has to iterate over all possible hash values.  We can track the
greatest hash iteration stored in the directory inode to limit the
overhead of negative lookups in small directories.

Signed-off-by: Zach Brown <zab@versity.com>
2016-03-24 20:11:58 -07:00
Zach Brown 1270553f1f scoutfs: mega item access omnibus commit 9000
Initially items were stored in memory with an rbtree.  That let us build
up the API above items without worrying about their storage.  That gave
us dirty items in memory and we could start working on writing them to
and reading them from the log segment blocks.

Now that we have the code on either side we can get rid of the item
cache in between.  It had some nice properties but it's fundamentally
duplicating the item storage in cached log segment blocks.  We'd also
have to teach it to differentiate between negative cache entries and
missing entries that need to be filled from blocks.  And the giant item
index becomes a bottleneck.

We have to index items in log segments anyway so we rewrite the item
APIs to read and write the items in the log segments directly.  Creation
writes to dirty blocks in memory and reading and iteration walk through
the cached blocks in the buffer cache.

I've tried to comment the files and functions appropriately so most of
the commentary for the new methods is in the body of the commit.

The overall theme is making it relatively efficient to operate on
individual items in log segments.  Previously we could only walk all the
items in an existing segment or write all the dirty items to a new
segment.  Now we have bloom filters and sorted item headers to let us
test for the presence of an item's key with progressively more expensive
methods.   We hold on to a dirty segment and fill it as we create new
items.

This needs more fleshing out and testing but this is a solid first pass
and it passes our existing tests.

Signed-off-by: Zach Brown <zab@versity.com>
2016-03-24 17:40:14 -07:00
Zach Brown e0e6179156 Fix bloom filter bugs
The bloom filter had two bad bugs.

First the calculation was adding the bit width of newly hashed data to
the hash value instead of the record of the hashed bits available.

And the block offset calculation for each bit wasn't truncated to the
number of bloom blocks.  While fixing this we can clean up the code and
make it faster by recording the bits in terms of their block and bit
offset instead of their large bit value.

Signed-off-by: Zach Brown <zab@versity.com>
2016-03-23 22:23:21 -04:00
Zach Brown ddf5ef1017 Fix set_bit_le() type width problems
The swizzle value was defined in terms of longs but the code used u64s.
And the bare shifted value was an int so it'd get truncated.  Switch it
all to using longs.

The ratio of bugs to lines of code in that first attempt was through the
roof!

Signed-off-by: Zach Brown <zab@versity.com>
2016-03-23 22:21:11 -04:00
Zach Brown 502783e1bc Update to segment format with skiplists and bloom
Update to the format rev which has large log segments that start with
bloom filter blocks, have items linked in a skip list, and item values
stored at offsets in the block.

Signed-off-by: Zach Brown <zab@versity.com>
2016-03-23 15:23:54 -07:00
Zach Brown 463f5e5a07 Correctly store last random word
pseudo_random_bytes() was accidentally copying the last partial long to
the beggining of the buffer instead of the end.  The final partial long
bytes weren't being filled.

Signed-off-by: Zach Brown <zab@versity.com>
2016-03-23 15:16:58 -07:00
Zach Brown d0429e1c88 Add minimal bloom filter helpers
mkfs just needs to initialize bloom filter blocks with the bits for the
single root inode key.  We can get away with these skeletal functions
for now.

Signed-off-by: Zach Brown <zab@versity.com>
2016-03-23 14:01:16 -07:00
Zach Brown 8471134328 Add trivial set_bit_le in bitops.h
We're going to need to start setting bloom filters bits in mkfs so we'll
add this trivial inline.  It might grow later.

Signed-off-by: Zach Brown <zab@versity.com>
2016-03-23 14:00:07 -07:00
Zach Brown f3de3b1817 Add DIV_ROUND_UP() to util.h
We're going to need this in some upcoming format.h changes.

Signed-off-by: Zach Brown <zab@versity.com>
2016-03-23 13:58:59 -07:00
Zach Brown 12d5d3d216 scoutfs: add next item reading
Add code to walk all the block segments that intersect a key range to
find the next item after that key value.

It is easier to just return failure from the next item reader and have
the caller retry the searches so we change the specific item reading
path to use the same convention to keep the caller consistent.

This still warns as it falls off the last block but that's fine for now.
We're going to be changing all this in the next few commits.

Signed-off-by: Zach Brown <zab@versity.com>
2016-03-18 17:30:39 -07:00
Zach Brown af492a9f27 scoutfs: add scoutfs_inc_key()
Add a quick inline function for incrementing a key value across the
inode>type>offset sorted key space.

Signed-off-by: Zach Brown <zab@versity.com>
2016-03-18 17:24:12 -07:00
Zach Brown 96b8a6da46 scoutfs: update created inode times in mknod
In mknod the newly created inode's times are set down in the new inode
creation path instead of up in the mknod path to match the parent dir's
ctime and mtime.

This is strictly legal but it's easier to test that all the times have
been set in the mknod by having them equal.  This stops mkdir-interface
test failures when enough time passes between inode creation and parent
dir timestamp updates to have them differ.

Signed-off-by: Zach Brown <zab@versity.com>
2016-03-18 17:21:12 -07:00
Zach Brown 0c0f2b19d5 scoutfs: update dirty inode items
Wire up the code to update dirty inode items as inodes are modified in
memory.  We had a bit of the code but it wasn't being called.

Signed-off-by: Zach Brown <zab@versity.com>
2016-03-17 19:12:49 -07:00
Zach Brown edf3c8a5d4 scoutfs: add initial item block writing
Add a sync_fs method that writes dirty items into level 0 item blocks.

Add chunk allocator code to allocate new item blocks in free chunks.  As
the allocator bitmap is modified it adds bitmap entries to the ring.

As new item blocks are allocated we create manifest entries that
describe their block location and keys.  The entry is added to the
in-memory manifest and to entries in the ring.

This isn't complete and there's still bugs but this is enough to start
building on.

Signed-off-by: Zach Brown <zab@versity.com>
2016-03-17 17:47:32 -07:00
Zach Brown a0a3ef9675 Mark all mkfs chunks allocated in bitmap
The initial bitmap entry written in the ring by mkfs was off by one.
Three chunks were written but the 0th chunk is also free for the supers.
It has to mark the first four chunks as allocated.

Signed-off-by: Zach Brown <zab@versity.com>
2016-03-17 17:05:24 -07:00
Zach Brown e59d0af199 Print full map and ring blocks
In the first pass we'd only printed the first map and ring blocks.

This reads the number of used map blocks into an allocation large enough
for the maximum number of map blocks.

Then we use the block numbers from the map blocks to print the active
ring blocks which are described by the super.

Signed-off-by: Zach Brown <zab@versity.com>
2016-03-17 17:05:19 -07:00
Zach Brown d2ead58ce4 scoutfs: translate d_type in readdir
I had forgotten to translate from the scoutfs types in items to the vfs
types for filldir() so userspace was seeing garbage d_type values.

Signed-off-by: Zach Brown <zab@versity.com>
2016-03-16 14:04:20 -07:00
Zach Brown c46fb0be78 scoutfs: fix sense of filldir return in readdir
The migration from the new iterator interface in upstream to the old
readdir interface in rhel7 got the sense of the filldir return code
wrong.  Any readdir would deadlock livelock as the dot entry was
returned at offset 0 without advancing f_pos.

Signed-off-by: Zach Brown <zab@versity.com>
2016-03-14 19:26:47 -07:00
Zach Brown 4b182c7759 scoutfs: insert manifest nodes into blkno radix
We had forgotten to actually insert manifest nodes in to the blkno
radix.  This hasn't mattered yet because there's only been one manifest
in the level 0 list.

Signed-off-by: Zach Brown <zab@versity.com>
2016-02-29 18:21:54 -08:00
Zach Brown 16abddb46a scoutfs: add basic segment reading
Add the most basic ability to read items from log segment blocks.  If
an item isn't in the cache then we walk segments in the manifest and
check for the item in each one.

This is just the core fundamental code.  There's still a lot to do:
basic corruption validation, multi-block segments, bloom filters and
arrays to optimize segment misses, and some day the ability to read file
data items directly into page cache pages.  The manifest locking is also
super broken.

But this is enough to let us mount and stat the root inode!

Signed-off-by: Zach Brown <zab@versity.com>
2016-02-28 17:45:44 -08:00
Zach Brown 8604c85486 scoutfs: add basic reing replay on mount
Read the ring described by the super block and replay its entries to
rebuild the in-memory state of the chunk allocator and log segment
manifest.

We add just enough of the chunk allocator to set the free bits to the
contents of the ring bitmap entries.

We start to build out the basic manifest data structure.  It'll
certainly evolve when we later add code to actually query it.

Signed-off-by: Zach Brown <zab@versity.com>
2016-02-26 17:00:19 -08:00
Zach Brown d8f76cb893 Minor ring manifest format updates
Update to the format changes that were made while implementing ring
replay in the kernel.
2016-02-25 22:45:06 -08:00
Zach Brown 906c0186bc Get path size with stat or ioctl
If we're making a file system in a real device then we need to get
the device size with an ioctl.
2016-02-25 22:40:48 -08:00
Zach Brown 28521e8c45 scoutfs: add block read helper
Add a trivial helper function which verifies the block header in
metadata blocks.

Signed-off-by: Zach Brown <zab@versity.com>
2016-02-23 21:13:56 -08:00
Zach Brown 71df879f07 scoutfs: update format.h to remove bricks
Update to the format.h from the recent -utils changes that moved from
the clumsy 'brick' terminology to the more reasonable
'block/chunk/segment' terminology.

Signed-off-by: Zach Brown <zab@versity.com>
2016-02-23 19:39:02 -08:00
Zach Brown 6686ca191a scoutfs: remove the prototype log writing
The sync implementation was a quick demonstration of packing items in to
large log blocks.  We'll be doing things very differently in the actual
system.  So tear this code out so we can build up more functional
structures.  It'll still be in revision control so we'll be able
to reuse the parts that make sense in the new code.

Signed-off-by: Zach Brown <zab@versity.com>
2016-02-23 19:33:56 -08:00
Zach Brown e9baa4559b Introduce chunk and segment terminology
The use of 'log' for all the large sizes was pretty confusing.  Let's
use 'chunk' to describe the large alloc size.  Other things live in them
as well as logs.  Then use 'log segment' to describe the larger log
structure stored in a chunk that's made up of all the little blocks.
2016-02-23 17:04:28 -08:00