1. 12 Nov, 2008 1 commit
    • Yan Zheng's avatar
      Btrfs: Fix race in btrfs_mark_extent_written · c36047d7
      Yan Zheng authored
      When extent needs to be split, btrfs_mark_extent_written truncates the extent
      first, then inserts a new extent and increases the reference count.
      
      The race happens if someone else deletes the old extent before the new extent
      is inserted. The fix here is increase the reference count in advance. This race
      is similar to the race in btrfs_drop_extents that was recently fixed.
      Signed-off-by: default avatarYan Zheng <zheng.yan@oracle.com>
      c36047d7
  2. 18 Nov, 2008 1 commit
    • Yan Zheng's avatar
      Btrfs: Seed device support · 2b82032c
      Yan Zheng authored
      Seed device is a special btrfs with SEEDING super flag
      set and can only be mounted in read-only mode. Seed
      devices allow people to create new btrfs on top of it.
      
      The new FS contains the same contents as the seed device,
      but it can be mounted in read-write mode.
      
      This patch does the following:
      
      1) split code in btrfs_alloc_chunk into two parts. The first part does makes
      the newly allocated chunk usable, but does not do any operation that modifies
      the chunk tree. The second part does the the chunk tree modifications. This
      division is for the bootstrap step of adding storage to the seed device.
      
      2) Update device management code to handle seed device.
      The basic idea is: For an FS grown from seed devices, its
      seed devices are put into a list. Seed devices are
      opened on demand at mounting time. If any seed device is
      missing or has been changed, btrfs kernel module will
      refuse to mount the FS.
      
      3) make btrfs_find_block_group not return NULL when all
      block groups are read-only.
      Signed-off-by: default avatarYan Zheng <zheng.yan@oracle.com>
      2b82032c
  3. 12 Nov, 2008 3 commits
    • Yan Zheng's avatar
      Btrfs: mount ro and remount support · c146afad
      Yan Zheng authored
      This patch adds mount ro and remount support. The main
      changes in patch are: adding btrfs_remount and related
      helper function; splitting the transaction related code
      out of close_ctree into btrfs_commit_super; updating
      allocator to properly handle read only block group.
      Signed-off-by: default avatarYan Zheng <zheng.yan@oracle.com>
      c146afad
    • Josef Bacik's avatar
      Btrfs: batch extent inserts/updates/deletions on the extent root · f3465ca4
      Josef Bacik authored
      While profiling the allocator I noticed a good amount of time was being spent in
      finish_current_insert and del_pending_extents, and as the filesystem filled up
      more and more time was being spent in those functions.  This patch aims to try
      and reduce that problem.  This happens two ways
      
      1) track if we tried to delete an extent that we are going to update or insert.
      Once we get into finish_current_insert we discard any of the extents that were
      marked for deletion.  This saves us from doing unnecessary work almost every
      time finish_current_insert runs.
      
      2) Batch insertion/updates/deletions.  Instead of doing a btrfs_search_slot for
      each individual extent and doing the needed operation, we instead keep the leaf
      around and see if there is anything else we can do on that leaf.  On the insert
      case I introduced a btrfs_insert_some_items, which will take an array of keys
      with an array of data_sizes and try and squeeze in as many of those keys as
      possible, and then return how many keys it was able to insert.  In the update
      case we search for an extent ref, update the ref and then loop through the leaf
      to see if any of the other refs we are looking to update are on that leaf, and
      then once we are done we release the path and search for the next ref we need to
      update.  And finally for the deletion we try and delete the extent+ref in pairs,
      so we will try to find extent+ref pairs next to the extent we are trying to free
      and free them in bulk if possible.
      
      This along with the other cluster fix that Chris pushed out a bit ago helps make
      the allocator preform more uniformly as it fills up the disk.  There is still a
      slight drop as we fill up the disk since we start having to stick new blocks in
      odd places which results in more COW's than on a empty fs, but the drop is not
      nearly as severe as it was before.
      Signed-off-by: default avatarJosef Bacik <jbacik@redhat.com>
      f3465ca4
    • Sage Weil's avatar
      Btrfs: allow clone of an arbitrary file range · c5c9cd4d
      Sage Weil authored
      This patch adds an additional CLONE_RANGE ioctl to clone an arbitrary 
      (block-aligned) file range to another file.  The original CLONE ioctl 
      becomes a special case of cloning the entire file range.  The logic is a 
      bit more complex now since ranges may be cloned to different offsets, and 
      because we may only be cloning the beginning or end of a particular extent 
      or checksum item.
      
      An additional sanity check ensures the source and destination files aren't 
      the same (which would previously deadlock), although eventually this could 
      be extended to allow the duplication of file data at a different offset 
      within the same file.
      
      Any extents within the destination range in the target file are dropped.
      
      We currently do not cope with the case where a compressed inline extent 
      needs to be split.  This will probably require decompressing the extent 
      into a temporary address_space, and inserting just the cloned portion as a 
      new compressed inline extent.  For now, just return -EINVAL in this case.  
      Note that this never comes up in the more common case of cloning an entire 
      file.
      Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
      c5c9cd4d
  4. 13 Nov, 2008 2 commits
    • Chris Mason's avatar
      Btrfs: Fix handling of space info full during allocations · 2ed6d664
      Chris Mason authored
      When we fail to allocate a new block group, we should still do the
      checks to make sure allocations try again with the minimum requested
      allocation size.
      
      This also fixes a deadlock that come from a missed down_read in
      the chunk allocation failure handling.
      Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
      2ed6d664
    • Chris Mason's avatar
      Btrfs: Improve metadata read latencies · 6f3577bd
      Chris Mason authored
      This fixes latency problems on metadata reads by making sure they
      don't go through the async submit queue, and by tuning down the amount
      of readahead done during btree searches.
      
      Also, the btrfs bdi congestion function is tuned to ignore the
      number of pending async bios and checksums pending.  There is additional
      code that throttles new async bios now and the congestion function
      doesn't need to worry about it anymore.
      Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
      6f3577bd
  5. 11 Nov, 2008 2 commits
  6. 10 Nov, 2008 10 commits
  7. 07 Nov, 2008 7 commits
    • Chris Mason's avatar
      Btrfs: Avoid unplug storms during commit · 5f2cc086
      Chris Mason authored
      While doing a commit, btrfs makes sure all the metadata blocks
      were properly written to disk, calling wait_on_page_writeback for
      each page.  This writeback happens after allowing another transaction
      to start, so it competes for the disk with other processes in the FS.
      
      If the page writeback bit is still set, each wait_on_page_writeback might
      trigger an unplug, even though the page might be waiting for checksumming
      to finish or might be waiting for the async work queue to submit the
      bio.
      
      This trades wait_on_page_writeback for waiting on the extent writeback
      bits.  It won't trigger any unplugs and substantially improves performance
      in a number of workloads.
      
      This also changes the async bio submission to avoid requeueing if there
      is only one device.  The requeue just wastes CPU time because there are
      no other devices to service.
      Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
      5f2cc086
    • Chris Mason's avatar
      Btrfs: Fix more false enospc errors and an oops from empty clustering · 42e70e7a
      Chris Mason authored
      In comes cases the empty cluster was added twice to the total number of
      bytes the allocator was trying to find.
      
      With empty clustering on, the hint byte was sometimes outside of the
      block group.  Add an extra goto to find the correct block group.
      Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
      42e70e7a
    • Chris Mason's avatar
      Btrfs: make sure compressed bios don't complete too soon · af09abfe
      Chris Mason authored
      When writing a compressed extent, a number of bios are created that
      point to a single struct compressed_bio.  At end_io time an atomic counter in
      the compressed_bio struct makes sure that all of the bios have finished
      before final end_io processing is done.
      
      But when multiple bios are needed to write a compressed extent, the
      counter was being incremented after the first bio was sent to submit_bio.
      It is possible the bio will complete before the counter is incremented,
      making the end_io handler free the compressed_bio struct before
      processing is finished.
      
      The fix is to increment the atomic counter before bio submission,
      both for compressed reads and writes.
      Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
      af09abfe
    • Chris Mason's avatar
      Btfs: More metadata allocator optimizations · 4366211c
      Chris Mason authored
      This lowers the empty cluster target for metadata allocations.  The lower
      target makes it easier to do allocations and still seems to perform well.
      
      It also fixes the allocator loop to drop the empty cluster when things
      start getting difficult, avoiding false enospc warnings.
      Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
      4366211c
    • Chris Mason's avatar
      Btrfs: enforce metadata allocation clustering · 3b7885bf
      Chris Mason authored
      The allocator uses the last allocation as a starting point for metadata
      allocations, and tries to allocate in clusters of at least 256k.
      
      If the search for a free block fails to find the expected block, this patch
      forces a new cluster to be found in the free list.
      Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
      3b7885bf
    • Chris Mason's avatar
      Btrfs: Optimize compressed writeback and reads · 771ed689
      Chris Mason authored
      When reading compressed extents, try to put pages into the page cache
      for any pages covered by the compressed extent that readpages didn't already
      preload.
      
      Add an async work queue to handle transformations at delayed allocation processing
      time.  Right now this is just compression.  The workflow is:
      
      1) Find offsets in the file marked for delayed allocation
      2) Lock the pages
      3) Lock the state bits
      4) Call the async delalloc code
      
      The async delalloc code clears the state lock bits and delalloc bits.  It is
      important this happens before the range goes into the work queue because
      otherwise it might deadlock with other work queue items that try to lock
      those extent bits.
      
      The file pages are compressed, and if the compression doesn't work the
      pages are written back directly.
      
      An ordered work queue is used to make sure the inodes are written in the same
      order that pdflush or writepages sent them down.
      
      This changes extent_write_cache_pages to let the writepage function
      update the wbc nr_written count.
      Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
      771ed689
    • Chris Mason's avatar
      Btrfs: Add ordered async work queues · 4a69a410
      Chris Mason authored
      Btrfs uses kernel threads to create async work queues for cpu intensive
      operations such as checksumming and decompression.  These work well,
      but they make it difficult to keep IO order intact.
      
      A single writepages call from pdflush or fsync will turn into a number
      of bios, and each bio is checksummed in parallel.  Once the checksum is
      computed, the bio is sent down to the disk, and since we don't control
      the order in which the parallel operations happen, they might go down to
      the disk in almost any order.
      
      The code deals with this somewhat by having deep work queues for a single
      kernel thread, making it very likely that a single thread will process all
      the bios for a single inode.
      
      This patch introduces an explicitly ordered work queue.  As work structs
      are placed into the queue they are put onto the tail of a list.  They have
      three callbacks:
      
      ->func (cpu intensive processing here)
      ->ordered_func (order sensitive processing here)
      ->ordered_free (free the work struct, all processing is done)
      
      The work struct has three callbacks.  The func callback does the cpu intensive
      work, and when it completes the work struct is marked as done.
      
      Every time a work struct completes, the list is checked to see if the head
      is marked as done.  If so the ordered_func callback is used to do the
      order sensitive processing and the ordered_free callback is used to do
      any cleanup.  Then we loop back and check the head of the list again.
      
      This patch also changes the checksumming code to use the ordered workqueues.
      One a 4 drive array, it increases streaming writes from 280MB/s to 350MB/s.
      Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
      4a69a410
  8. 31 Oct, 2008 2 commits
    • Chris Mason's avatar
      Btrfs: rev the disk format for fallocate · 537fb067
      Chris Mason authored
      Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
      537fb067
    • Chris Mason's avatar
      Btrfs: Compression corner fixes · 70b99e69
      Chris Mason authored
      Make sure we keep page->mapping NULL on the pages we're getting
      via alloc_page.  It gets set so a few of the callbacks can do the right
      thing, but in general these pages don't have a mapping.
      
      Don't try to truncate compressed inline items in btrfs_drop_extents.
      The whole compressed item must be preserved.
      
      Don't try to create multipage inline compressed items.  When we try to
      overwrite just the first page of the file, we would have to read in and recow
      all the pages after it in the same compressed inline items.  For now, only
      create single page inline items.
      
      Make sure we lock pages in the correct order during delalloc.  The
      search into the state tree for delalloc bytes can return bytes before
      the page we already have locked.
      Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
      70b99e69
  9. 30 Oct, 2008 7 commits
  10. 29 Oct, 2008 5 commits
    • Chris Mason's avatar
    • Yan Zheng's avatar
      Btrfs: Add root tree pointer transaction ids · 84234f3a
      Yan Zheng authored
      This patch adds transaction IDs to root tree pointers.
      Transaction IDs in tree pointers are compared with the
      generation numbers in block headers when reading root
      blocks of trees. This can detect some types of IO errors.
      Signed-off-by: default avatarYan Zheng <zheng.yan@oracle.com>
      
      84234f3a
    • Josef Bacik's avatar
      Btrfs: nuke fs wide allocation mutex V2 · 25179201
      Josef Bacik authored
      This patch removes the giant fs_info->alloc_mutex and replaces it with a bunch
      of little locks.
      
      There is now a pinned_mutex, which is used when messing with the pinned_extents
      extent io tree, and the extent_ins_mutex which is used with the pending_del and
      extent_ins extent io trees.
      
      The locking for the extent tree stuff was inspired by a patch that Yan Zheng
      wrote to fix a race condition, I cleaned it up some and changed the locking
      around a little bit, but the idea remains the same.  Basically instead of
      holding the extent_ins_mutex throughout the processing of an extent on the
      extent_ins or pending_del trees, we just hold it while we're searching and when
      we clear the bits on those trees, and lock the extent for the duration of the
      operations on the extent.
      
      Also to keep from getting hung up waiting to lock an extent, I've added a
      try_lock_extent so if we cannot lock the extent, move on to the next one in the
      tree and we'll come back to that one.  I have tested this heavily and it does
      not appear to break anything.  This has to be applied on top of my
      find_free_extent redo patch.
      
      I tested this patch on top of Yan's space reblancing code and it worked fine.
      The only thing that has changed since the last version is I pulled out all my
      debugging stuff, apparently I forgot to run guilt refresh before I sent the
      last patch out.  Thank you,
      Signed-off-by: default avatarJosef Bacik <jbacik@redhat.com>
      
      25179201
    • Josef Bacik's avatar
      Btrfs: fix enospc when there is plenty of space · 80eb234a
      Josef Bacik authored
      So there is an odd case where we can possibly return -ENOSPC when there is in
      fact space to be had.  It only happens with Metadata writes, and happens _very_
      infrequently.  What has to happen is we have to allocate have allocated out of
      the first logical byte on the disk, which would set last_alloc to
      first_logical_byte(root, 0), so search_start == orig_search_start.  We then
      need to allocate for normal metadata, so BTRFS_BLOCK_GROUP_METADATA |
      BTRFS_BLOCK_GROUP_DUP.  We will do a block lookup for the given search_start,
      block_group_bits() won't match and we'll go to choose another block group.
      However because search_start matches orig_search_start we go to see if we can
      allocate a chunk.
      
      If we are in the situation that we cannot allocate a chunk, we fail and ENOSPC.
      This is kind of a big flaw of the way find_free_extent works, as it along with
      find_free_space loop through _all_ of the block groups, not just the ones that
      we want to allocate out of.  This patch completely kills find_free_space and
      rolls it into find_free_extent.  I've introduced a sort of state machine into
      this, which will make it easier to get cache miss information out of the
      allocator, and will work well with my locking changes.
      
      The basic flow is this:  We have the variable loop which is 0, meaning we are
      in the hint phase.  We lookup the block group for the hint, and lookup the
      space_info for what we want to allocate out of.  If the block group we were
      pointed at by the hint either isn't of the correct type, or just doesn't have
      the space we need, we set head to space_info->block_groups, so we start at the
      beginning of the block groups for this particular space info, and loop through.
      
      This is also where we add the empty_cluster to total_needed.  At this point
      loop is set to 1 and we just loop through all of the block groups for this
      particular space_info looking for the space we need, just as find_free_space
      would have done, except we only hit the block groups we want and not _all_ of
      the block groups.  If we come full circle we see if we can allocate a chunk.
      If we cannot of course we exit with -ENOSPC and we are good.  If not we start
      over at space_info->block_groups and loop through again, with loop == 2.  If we
      come full circle and haven't found what we need then we exit with -ENOSPC.
      I've been running this for a couple of days now and it seems stable, and I
      haven't yet hit a -ENOSPC when there was plenty of space left.
      
      Also I've made a groups_sem to handle the group list for the space_info.  This
      is part of my locking changes, but is relatively safe and seems better than
      holding the space_info spinlock over that entire search time.  Thanks,
      Signed-off-by: default avatarJosef Bacik <jbacik@redhat.com>
       
      80eb234a
    • Yan Zheng's avatar
      Btrfs: Improve space balancing code · f82d02d9
      Yan Zheng authored
      This patch improves the space balancing code to keep more sharing
      of tree blocks. The only case that breaks sharing of tree blocks is
      data extents get fragmented during balancing. The main changes in
      this patch are:
      
      Add a 'drop sub-tree' function. This solves the problem in old code
      that BTRFS_HEADER_FLAG_WRITTEN check breaks sharing of tree block.
      
      Remove relocation mapping tree. Relocation mappings are stored in
      struct btrfs_ref_path and updated dynamically during walking up/down
      the reference path. This reduces CPU usage and simplifies code.
      
      This patch also fixes a bug. Root items for reloc trees should be
      updated in btrfs_free_reloc_root.
      Signed-off-by: default avatarYan Zheng <zheng.yan@oracle.com>
      
      f82d02d9