29 Jan, 2010

3 commits

  • If you have a disk failure in RAID1 and then add a new disk to the
    array, and then try to remove the missing volume, it will fail. The
    reason is the sanity check only looks at the total number of rw devices,
    which is just 2 because we have 2 good disks and 1 bad one. Instead
    check the total number of devices in the array to make sure we can
    actually remove the device. Tested this with a failed disk setup and
    with this test we can now run

    btrfs-vol -r missing /mount/point

    and it works fine.

    Signed-off-by: Josef Bacik
    Signed-off-by: Chris Mason

    Josef Bacik
     
  • Hit this problem while testing RAID1 failure stuff. open_bdev_exclusive
    returns ERR_PTR(), not NULL. So change the return value properly. This
    is important if you accidently specify a device that doesn't exist when
    trying to add a new device to an array, you will panic the box
    dereferencing bdev.

    Signed-off-by: Josef Bacik
    Signed-off-by: Chris Mason

    Josef Bacik
     
  • If a RAID setup has chunks that span multiple disks, and one of those
    disks has failed, btrfs_chunk_readonly will return 1 since one of the
    disks in that chunk's stripes is dead and therefore not writeable. So
    instead if we are in degraded mode, return 0 so we can go ahead and
    allocate stuff. Without this patch all of the block groups in a RAID1
    setup will end up read-only, which will mean we can't add new disks to
    the array since we won't be able to make allocations.

    Signed-off-by: Josef Bacik
    Signed-off-by: Chris Mason

    Josef Bacik
     

18 Jan, 2010

1 commit


18 Dec, 2009

1 commit

  • This patch makes us a bit less zealous about making sure we have enough free
    metadata space by pearing down the size of new metadata chunks to 256mb instead
    of 1gb. Also, we used to try an allocate metadata chunks when allocating data,
    but that sort of thing is done elsewhere now so we can just remove it. With my
    -ENOSPC test I used to have 3gb reserved for metadata out of 75gb, now I have
    1.7gb. Thanks,

    Signed-off-by: Josef Bacik
    Signed-off-by: Chris Mason

    Josef Bacik
     

02 Oct, 2009

1 commit


30 Sep, 2009

1 commit

  • Error handling code following a kzalloc should free the allocated data.

    The semantic match that finds the problem is as follows:
    (http://www.emn.fr/x-info/coccinelle/)

    //
    @r exists@
    local idexpression x;
    statement S;
    expression E;
    identifier f,f1,l;
    position p1,p2;
    expression *ptr != NULL;
    @@

    x@p1 = \(kmalloc\|kzalloc\|kcalloc\)(...);
    ...
    if (x == NULL) S
    }
    (
    x->f1 = E
    |
    (x->f1 == NULL || ...)
    |
    f(...,x->f1,...)
    )
    ...>
    (
    return \(0\|\|ptr\);
    |
    return@p2 ...;
    )

    @script:python@
    p1 << r.p1;
    p2 << r.p2;
    @@

    print "* file: %s kmalloc %s return %s" % (p1[0].file,p1[0].line,p2[0].line)
    //

    Signed-off-by: Julia Lawall
    Signed-off-by: Chris Mason

    Julia Lawall
     

24 Sep, 2009

1 commit


22 Sep, 2009

1 commit

  • Currently, we can panic the box if the first block group we go to move is of a
    type where there is no space left to move those extents. For example, if we
    fill the disk up with data, and then we try to balance and we have no room to
    move the data nor room to allocate new chunks, we will panic. Change this by
    checking to see if we have room to move this chunk around, and if not, return
    -ENOSPC and move on to the next chunk. This will make sure we remove block
    groups that are moveable, like if we have alot of empty metadata block groups,
    and then that way we make room to be able to balance our data chunks as well.
    Tested this with an fs that would panic on btrfs-vol -b normally, but no longer
    panics with this patch.

    V1->V2:
    -actually search for a free extent on the device to make sure we can allocate a
    chunk if need be.

    -fix btrfs_shrink_device to make sure we actually try to relocate all the
    chunks, and then if we can't return -ENOSPC so if we are doing a btrfs-vol -r
    we don't remove the device with data still on it.

    -check to make sure the block group we are going to relocate isn't the last one
    in that particular space

    -fix a bug in btrfs_shrink_device where we would change the device's size and
    not fix it if we fail to do our relocate

    Signed-off-by: Josef Bacik
    Signed-off-by: Chris Mason

    Josef Bacik
     

12 Sep, 2009

2 commits

  • There are two main users of the extent_map tree. The
    first is regular file inodes, where it is evenly spread
    between readers and writers.

    The second is the chunk allocation tree, which maps blocks from
    logical addresses to phyiscal ones, and it is 99.99% reads.

    The mapping tree is a point of lock contention during heavy IO
    workloads, so this commit switches things to a rw lock.

    Signed-off-by: Chris Mason

    Chris Mason
     
  • The btrfs io submission thread tries to back off congested devices in
    favor of rotating off to another disk.

    But, it tries to make sure it submits at least some IO before rotating
    on (the others may be congested too), and so it has a magic number of
    requests it tries to write before it hops.

    This makes the magic number smaller. Testing shows that we're spending
    too much time on congested devices and leaving the other devices idle.

    Signed-off-by: Chris Mason

    Chris Mason
     

11 Sep, 2009

1 commit


25 Jul, 2009

1 commit

  • Allocating new block group is easy when the disk has plenty of space.
    But things get difficult as the disk fills up, especially if
    the FS has been run through btrfs-vol -b. The balance operation
    is likely to make the total bytes available on the device greater
    than the largest extent we'll actually be able to allocate.

    But the device extent allocation code incorrectly assumes that a device
    with 5G free will be able to allocate a 5G extent. It isn't normally a
    problem because device extents don't get freed unless btrfs-vol -b
    is run.

    This fixes the device extent allocator to remember the largest free
    extent it can find, and then uses that value as a fallback.

    Signed-off-by: Chris Mason

    Chris Mason
     

24 Jul, 2009

1 commit


23 Jul, 2009

1 commit

  • It was never actually doing anything anyway (see the loop condition),
    and it would be difficult to make it work for RAID[56].

    Even if it was actually working, it's checking for the wrong thing
    anyway. Instead of checking whether we list a block which _doesn't_ land
    at the relevant physical location, it should be checking that we _have_
    listed all the logical blocks which refer to the required physical
    location on all devices.

    This function is only called from remove_sb_from_cache() to ensure that
    we reserve the logical blocks which would reside at the same physical
    location as the superblock copies. So listing more blocks than we need
    is actually OK.

    With RAID[56] we're going to throw away an entire stripe for each block
    we have to ignore, so we _are_ going to list blocks other than the
    ones which actually contain the superblock.

    Signed-off-by: David Woodhouse
    Signed-off-by: Chris Mason

    David Woodhouse
     

22 Jul, 2009

1 commit


11 Jun, 2009

1 commit

  • On multi-device filesystems, btrfs writes supers to all of the devices
    before considering a sync complete. There wasn't any additional
    locking between super writeout and the device list management code
    because device management was done inside a transaction and
    super writeout only happened with no transation writers running.

    With the btrfs fsync log and other async transaction updates, this
    has been racey for some time. This adds a mutex to protect
    the device list. The existing volume mutex could not be reused due to
    transaction lock ordering requirements.

    Signed-off-by: Chris Mason

    Chris Mason
     

10 Jun, 2009

4 commits

  • During mount, btrfs will check the queue nonrot flag
    for all the devices found in the FS. If they are all
    non-rotating, SSD mode is enabled by default.

    If the FS was mounted with -o nossd, the non-rotating
    flag is ignored.

    Signed-off-by: Chris Mason

    Chris Mason
     
  • The btrfs IO submission threads try to service a bunch of devices with a small
    number of threads. They do a congestion check to try and avoid waiting
    on requests for a busy device.

    The checks make sure we've sent a few requests down to a given device just so
    that we aren't bouncing between busy devices without actually sending down
    any IO. The counter used to decide if we can switch to the next device
    is somewhat overloaded. It is also being used to decide if we've done
    a good batch of requests between the WRITE_SYNC or regular priority lists.
    It may get reset to zero often, leaving us hammering on a busy device
    instead of moving on to another disk.

    This commit adds a new counter for the number of bios sent while
    servicing a device. It doesn't get reset or fiddled with. On
    multi-device filesystems, this fixes IO stalls in streaming
    write workloads.

    Signed-off-by: Chris Mason

    Chris Mason
     
  • Btrfs uses dedicated threads to submit bios when checksumming is on,
    which allows us to make sure the threads dedicated to checksumming don't get
    stuck waiting for requests. For each btrfs device, there are
    two lists of bios. One list is for WRITE_SYNC bios and the other
    is for regular priority bios.

    The IO submission threads used to process all of the WRITE_SYNC bios first and
    then switch to the regular bios. This commit makes sure we don't completely
    starve the regular bios by rotating between the two lists.

    WRITE_SYNC bios are still favored 2:1 over the regular bios, and this tries
    to run in batches to avoid seeking. Benchmarking shows this eliminates
    stalls during streaming buffered writes on both multi-device and
    single device filesystems.

    If the regular bios starve, the system can end up with a large amount of ram
    pinned down in writeback pages. If we are a little more fair between the two
    classes, we're able to keep throughput up and make progress on the bulk of
    our dirty ram.

    Signed-off-by: Chris Mason

    Chris Mason
     
  • This commit introduces a new kind of back reference for btrfs metadata.
    Once a filesystem has been mounted with this commit, IT WILL NO LONGER
    BE MOUNTABLE BY OLDER KERNELS.

    When a tree block in subvolume tree is cow'd, the reference counts of all
    extents it points to are increased by one. At transaction commit time,
    the old root of the subvolume is recorded in a "dead root" data structure,
    and the btree it points to is later walked, dropping reference counts
    and freeing any blocks where the reference count goes to 0.

    The increments done during cow and decrements done after commit cancel out,
    and the walk is a very expensive way to go about freeing the blocks that
    are no longer referenced by the new btree root. This commit reduces the
    transaction overhead by avoiding the need for dead root records.

    When a non-shared tree block is cow'd, we free the old block at once, and the
    new block inherits old block's references. When a tree block with reference
    count > 1 is cow'd, we increase the reference counts of all extents
    the new block points to by one, and decrease the old block's reference count by
    one.

    This dead tree avoidance code removes the need to modify the reference
    counts of lower level extents when a non-shared tree block is cow'd.
    But we still need to update back ref for all pointers in the block.
    This is because the location of the block is recorded in the back ref
    item.

    We can solve this by introducing a new type of back ref. The new
    back ref provides information about pointer's key, level and in which
    tree the pointer lives. This information allow us to find the pointer
    by searching the tree. The shortcoming of the new back ref is that it
    only works for pointers in tree blocks referenced by their owner trees.

    This is mostly a problem for snapshots, where resolving one of these
    fuzzy back references would be O(number_of_snapshots) and quite slow.
    The solution used here is to use the fuzzy back references in the common
    case where a given tree block is only referenced by one root,
    and use the full back references when multiple roots have a reference
    on a given block.

    This commit adds per subvolume red-black tree to keep trace of cached
    inodes. The red-black tree helps the balancing code to find cached
    inodes whose inode numbers within a given range.

    This commit improves the balancing code by introducing several data
    structures to keep the state of balancing. The most important one
    is the back ref cache. It caches how the upper level tree blocks are
    referenced. This greatly reduce the overhead of checking back ref.

    The improved balancing code scales significantly better with a large
    number of snapshots.

    This is a very large commit and was written in a number of
    pieces. But, they depend heavily on the disk format change and were
    squashed together to make sure git bisect didn't end up in a
    bad state wrt space balancing or the format change.

    Signed-off-by: Yan Zheng
    Signed-off-by: Chris Mason

    Yan Zheng
     

04 Jun, 2009

1 commit


27 Apr, 2009

1 commit

  • Previously, we updated a device's size prior to attempting a shrink
    operation. This patch moves the device resizing logic to only happen if
    the shrink completes successfully. In the process, it introduces a new
    field to btrfs_device -- disk_total_bytes -- to track the on-disk size.

    Signed-off-by: Chris Ball
    Signed-off-by: Chris Mason

    Chris Ball
     

21 Apr, 2009

1 commit

  • Part of reducing fsync/O_SYNC/O_DIRECT latencies is using WRITE_SYNC for
    writes we plan on waiting on in the near future. This patch
    mirrors recent changes in other filesystems and the generic code to
    use WRITE_SYNC when WB_SYNC_ALL is passed and to use WRITE_SYNC for
    other latency critical writes.

    Btrfs uses async worker threads for checksumming before the write is done,
    and then again to actually submit the bios. The bio submission code just
    runs a per-device list of bios that need to be sent down the pipe.

    This list is split into low priority and high priority lists so the
    WRITE_SYNC IO happens first.

    Signed-off-by: Chris Mason

    Chris Mason
     

03 Apr, 2009

2 commits

  • Btrfs pages being written get set to writeback, and then may go through
    a number of steps before they hit the block layer. This includes compression,
    checksumming and async bio submission.

    The end result is that someone who writes a page and then does
    wait_on_page_writeback is likely to unplug the queue before the bio they
    cared about got there.

    We could fix this by marking bios sync, or by doing more frequent unplugs,
    but this commit just changes the async bio submission code to unplug
    after it has processed all the bios for a device. The async bio submission
    does a fair job of collection bios, so this shouldn't be a huge problem
    for reducing merging at the elevator.

    For streaming O_DIRECT writes on a 5 drive array, it boosts performance
    from 386MB/s to 460MB/s.

    Thanks to Hisashi Hifumi for helping with this work.

    Signed-off-by: Chris Mason

    Chris Mason
     
  • Btrfs uses async helper threads to submit write bios so the checksumming
    helper threads don't block on the disk.

    The submit bio threads may process bios for more than one block device,
    so when they find one device congested they try to move on to other
    devices instead of blocking in get_request_wait for one device.

    This does a pretty good job of keeping multiple devices busy, but the
    congested flag has a number of problems. A congested device may still
    give you a request, and other procs that aren't backing off the congested
    device may starve you out.

    This commit uses the io_context stored in current to decide if our process
    has been made a batching process by the block layer. If so, it keeps
    sending IO down for at least one batch. This helps make sure we do
    a good amount of work each time we visit a bdev, and avoids large IO
    stalls in multi-device workloads.

    It's also very ugly. A better solution is in the works with Jens Axboe.

    Signed-off-by: Chris Mason

    Chris Mason
     

11 Mar, 2009

2 commits

  • The full flag on the space info structs tells the allocator not to try
    and allocate more chunks because the devices in the FS are fully allocated.

    When more devices are added, we need to clear the full flag so the allocator
    knows it has more space available.

    Signed-off-by: Chris Mason

    Chris Mason
     
  • Storage allocated to different raid levels in btrfs is tracked by
    a btrfs_space_info structure, and all of the current space_infos are
    collected into a list_head.

    Most filesystems have 3 or 4 of these structs total, and the list is
    only changed when new raid levels are added or at unmount time.

    This commit adds rcu locking on the list head, and properly frees
    things at unmount time. It also clears the space_info->full flag
    whenever new space is added to the FS.

    The locking for the space info list goes like this:

    reads: protected by rcu_read_lock()
    writes: protected by the chunk_mutex

    At unmount time we don't need special locking because all the readers
    are gone.

    Signed-off-by: Chris Mason

    Chris Mason
     

13 Feb, 2009

1 commit

  • Btrfs is currently using spin_lock_nested with a nested value based
    on the tree depth of the block. But, this doesn't quite work because
    the max tree depth is bigger than what spin_lock_nested can deal with,
    and because locks are sometimes taken before the level field is filled in.

    The solution here is to use lockdep_set_class_and_name instead, and to
    set the class before unlocking the pages when the block is read from the
    disk and just after init of a freshly allocated tree block.

    btrfs_clear_path_blocking is also changed to take the locks in the proper
    order, and it also makes sure all the locks currently held are properly
    set to blocking before it tries to retake the spinlocks. Otherwise, lockdep
    gets upset about bad lock orderin.

    The lockdep magic cam from Peter Zijlstra

    Signed-off-by: Chris Mason

    Chris Mason
     

12 Feb, 2009

1 commit

  • The call to kzalloc is followed by a kmalloc whose result is stored in the
    same variable.

    The semantic match that finds the problem is as follows:
    (http://www.emn.fr/x-info/coccinelle/)

    //
    @r exists@
    local idexpression x;
    statement S;
    expression E;
    identifier f,l;
    position p1,p2;
    expression *ptr != NULL;
    @@

    (
    if ((x@p1 = \(kmalloc\|kzalloc\|kcalloc\)(...)) == NULL) S
    |
    x@p1 = \(kmalloc\|kzalloc\|kcalloc\)(...);
    ...
    if (x == NULL) S
    )
    }
    x->f = E
    ...>
    (
    return \(0\|\|ptr\);
    |
    return@p2 ...;
    )

    @script:python@
    p1 << r.p1;
    p2 << r.p2;
    @@

    print "* file: %s kmalloc %s return %s" % (p1[0].file,p1[0].line,p2[0].line)
    //

    Signed-off-by: Julia Lawall
    Signed-off-by: Chris Mason

    Julia Lawall
     

04 Feb, 2009

1 commit


21 Jan, 2009

3 commits


17 Jan, 2009

1 commit

  • Btrfs maintains a queue of async bio submissions so the checksumming
    threads don't have to wait on get_request_wait. In order to avoid
    extra wakeups, this code has a running_pending flag that is used
    to tell new submissions they don't need to wake the thread.

    When the threads notice congestion on a single device, they
    may decide to requeue the job and move on to other devices. This
    makes sure the running_pending flag is cleared before the
    job is requeued.

    It should help avoid IO stalls by making sure the task is woken up
    when new submissions come in.

    Signed-off-by: Chris Mason

    Chris Mason
     

06 Jan, 2009

1 commit


12 Dec, 2008

1 commit

  • This patch makes seed device possible to be shared by
    multiple mounted file systems. The sharing is achieved
    by cloning seed device's btrfs_fs_devices structure.
    Thanks you,

    Signed-off-by: Yan Zheng

    Yan Zheng
     

09 Dec, 2008

3 commits

  • This adds a sequence number to the btrfs inode that is increased on
    every update. NFS will be able to use that to detect when an inode has
    changed, without relying on inaccurate time fields.

    While we're here, this also:

    Puts reserved space into the super block and inode

    Adds a log root transid to the super so we can pick the newest super
    based on the fsync log as well as the main transaction ID. For now
    the log root transid is always zero, but that'll get fixed.

    Adds a starting offset to the dev_item. This will let us do better
    alignment calculations if we know the start of a partition on the disk.

    Signed-off-by: Chris Mason

    Chris Mason
     
  • It is possible that generic_bin_search will be called on a tree block
    that has not been locked. This happens because cache_block_block skips
    locking on the tree blocks.

    Since the tree block isn't locked, we aren't allowed to change
    the extent_buffer->map_token field. Using map_private_extent_buffer
    avoids any changes to the internal extent buffer fields.

    Signed-off-by: Chris Mason

    Chris Mason
     
  • This patch implements superblock duplication. Superblocks
    are stored at offset 16K, 64M and 256G on every devices.
    Spaces used by superblocks are preserved by the allocator,
    which uses a reverse mapping function to find the logical
    addresses that correspond to superblocks. Thank you,

    Signed-off-by: Yan Zheng

    Yan Zheng