1. 21 5月, 2011 1 次提交
    • M
      btrfs: implement delayed inode items operation · 16cdcec7
      Miao Xie 提交于
      Changelog V5 -> V6:
      - Fix oom when the memory load is high, by storing the delayed nodes into the
        root's radix tree, and letting btrfs inodes go.
      
      Changelog V4 -> V5:
      - Fix the race on adding the delayed node to the inode, which is spotted by
        Chris Mason.
      - Merge Chris Mason's incremental patch into this patch.
      - Fix deadlock between readdir() and memory fault, which is reported by
        Itaru Kitayama.
      
      Changelog V3 -> V4:
      - Fix nested lock, which is reported by Itaru Kitayama, by updating space cache
        inode in time.
      
      Changelog V2 -> V3:
      - Fix the race between the delayed worker and the task which does delayed items
        balance, which is reported by Tsutomu Itoh.
      - Modify the patch address David Sterba's comment.
      - Fix the bug of the cpu recursion spinlock, reported by Chris Mason
      
      Changelog V1 -> V2:
      - break up the global rb-tree, use a list to manage the delayed nodes,
        which is created for every directory and file, and used to manage the
        delayed directory name index items and the delayed inode item.
      - introduce a worker to deal with the delayed nodes.
      
      Compare with Ext3/4, the performance of file creation and deletion on btrfs
      is very poor. the reason is that btrfs must do a lot of b+ tree insertions,
      such as inode item, directory name item, directory name index and so on.
      
      If we can do some delayed b+ tree insertion or deletion, we can improve the
      performance, so we made this patch which implemented delayed directory name
      index insertion/deletion and delayed inode update.
      
      Implementation:
      - introduce a delayed root object into the filesystem, that use two lists to
        manage the delayed nodes which are created for every file/directory.
        One is used to manage all the delayed nodes that have delayed items. And the
        other is used to manage the delayed nodes which is waiting to be dealt with
        by the work thread.
      - Every delayed node has two rb-tree, one is used to manage the directory name
        index which is going to be inserted into b+ tree, and the other is used to
        manage the directory name index which is going to be deleted from b+ tree.
      - introduce a worker to deal with the delayed operation. This worker is used
        to deal with the works of the delayed directory name index items insertion
        and deletion and the delayed inode update.
        When the delayed items is beyond the lower limit, we create works for some
        delayed nodes and insert them into the work queue of the worker, and then
        go back.
        When the delayed items is beyond the upper bound, we create works for all
        the delayed nodes that haven't been dealt with, and insert them into the work
        queue of the worker, and then wait for that the untreated items is below some
        threshold value.
      - When we want to insert a directory name index into b+ tree, we just add the
        information into the delayed inserting rb-tree.
        And then we check the number of the delayed items and do delayed items
        balance. (The balance policy is above.)
      - When we want to delete a directory name index from the b+ tree, we search it
        in the inserting rb-tree at first. If we look it up, just drop it. If not,
        add the key of it into the delayed deleting rb-tree.
        Similar to the delayed inserting rb-tree, we also check the number of the
        delayed items and do delayed items balance.
        (The same to inserting manipulation)
      - When we want to update the metadata of some inode, we cached the data of the
        inode into the delayed node. the worker will flush it into the b+ tree after
        dealing with the delayed insertion and deletion.
      - We will move the delayed node to the tail of the list after we access the
        delayed node, By this way, we can cache more delayed items and merge more
        inode updates.
      - If we want to commit transaction, we will deal with all the delayed node.
      - the delayed node will be freed when we free the btrfs inode.
      - Before we log the inode items, we commit all the directory name index items
        and the delayed inode update.
      
      I did a quick test by the benchmark tool[1] and found we can improve the
      performance of file creation by ~15%, and file deletion by ~20%.
      
      Before applying this patch:
      Create files:
              Total files: 50000
              Total time: 1.096108
              Average time: 0.000022
      Delete files:
              Total files: 50000
              Total time: 1.510403
              Average time: 0.000030
      
      After applying this patch:
      Create files:
              Total files: 50000
              Total time: 0.932899
              Average time: 0.000019
      Delete files:
              Total files: 50000
              Total time: 1.215732
              Average time: 0.000024
      
      [1] http://marc.info/?l=linux-btrfs&m=128212635122920&q=p3
      
      Many thanks for Kitayama-san's help!
      Signed-off-by: NMiao Xie <miaox@cn.fujitsu.com>
      Reviewed-by: NDavid Sterba <dave@jikos.cz>
      Tested-by: NTsutomu Itoh <t-itoh@jp.fujitsu.com>
      Tested-by: NItaru Kitayama <kitayama@cl.bb4u.ne.jp>
      Signed-off-by: NChris Mason <chris.mason@oracle.com>
      16cdcec7
  2. 26 4月, 2011 3 次提交
  3. 25 4月, 2011 3 次提交
    • L
      Btrfs: Support reading/writing on disk free ino cache · 82d5902d
      Li Zefan 提交于
      This is similar to block group caching.
      
      We dedicate a special inode in fs tree to save free ino cache.
      
      At the very first time we create/delete a file after mount, the free ino
      cache will be loaded from disk into memory. When the fs tree is commited,
      the cache will be written back to disk.
      
      To keep compatibility, we check the root generation against the generation
      of the special inode when loading the cache, so the loading will fail
      if the btrfs filesystem was mounted in an older kernel before.
      Signed-off-by: NLi Zefan <lizf@cn.fujitsu.com>
      82d5902d
    • L
      Btrfs: Always use 64bit inode number · 33345d01
      Li Zefan 提交于
      There's a potential problem in 32bit system when we exhaust 32bit inode
      numbers and start to allocate big inode numbers, because btrfs uses
      inode->i_ino in many places.
      
      So here we always use BTRFS_I(inode)->location.objectid, which is an
      u64 variable.
      
      There are 2 exceptions that BTRFS_I(inode)->location.objectid !=
      inode->i_ino: the btree inode (0 vs 1) and empty subvol dirs (256 vs 2),
      and inode->i_ino will be used in those cases.
      
      Another reason to make this change is I'm going to use a special inode
      to save free ino cache, and the inode number must be > (u64)-256.
      Signed-off-by: NLi Zefan <lizf@cn.fujitsu.com>
      33345d01
    • L
      Btrfs: Cache free inode numbers in memory · 581bb050
      Li Zefan 提交于
      Currently btrfs stores the highest objectid of the fs tree, and it always
      returns (highest+1) inode number when we create a file, so inode numbers
      won't be reclaimed when we delete files, so we'll run out of inode numbers
      as we keep create/delete files in 32bits machines.
      
      This fixes it, and it works similarly to how we cache free space in block
      cgroups.
      
      We start a kernel thread to read the file tree. By scanning inode items,
      we know which chunks of inode numbers are free, and we cache them in
      an rb-tree.
      
      Because we are searching the commit root, we have to carefully handle the
      cross-transaction case.
      
      The rb-tree is a hybrid extent+bitmap tree, so if we have too many small
      chunks of inode numbers, we'll use bitmaps. Initially we allow 16K ram
      of extents, and a bitmap will be used if we exceed this threshold. The
      extents threshold is adjusted in runtime.
      Signed-off-by: NLi Zefan <lizf@cn.fujitsu.com>
      581bb050
  4. 13 4月, 2011 2 次提交
  5. 12 4月, 2011 3 次提交
  6. 09 4月, 2011 6 次提交
    • J
      Btrfs: check for duplicate iov_base's when doing dio reads · 93a54bc4
      Josef Bacik 提交于
      Apparently it is ok to submit a read to an IDE device with the same target page
      for different offsets.  This is what Windows does under qemu.  The problem is
      under DIO we expect them to be different buffers for checksumming reasons, and
      so this sort of thing will result in checksum errors, when in reality the file
      is fine.  So when reading, check to make sure that all iov bases are different,
      and if they aren't fall back to buffered mode, since that will work out right.
      Thanks,
      Signed-off-by: NJosef Bacik <josef@redhat.com>
      93a54bc4
    • J
      Btrfs: reuse the extent_map we found when calling btrfs_get_extent · 16d299ac
      Josef Bacik 提交于
      In btrfs_get_block_direct we call btrfs_get_extent to lookup the extent for the
      range that we are looking for.  If we don't find an extent, btrfs_get_extent
      will insert a extent_map for that area and mark it as a hole.  So it does the
      job of allocating a new extent map and inserting it into the io tree.  But if
      we're creating a new extent we free it up and redo all of that work.  So instead
      pass the em to btrfs_new_extent_direct(), and if it will work just allocate the
      disk space and set it up properly and bypass the freeing/allocating of a new
      extent map and the expensive operation of inserting the thing into the io_tree.
      Thanks,
      Signed-off-by: NJosef Bacik <josef@redhat.com>
      16d299ac
    • J
      Btrfs: do not use async submit for small DIO io's · 1ae39938
      Josef Bacik 提交于
      When looking at our DIO performance Chris said that for small IO's doing the
      async submit stuff tends to be more overhead than it's worth.  With this on top
      of my other fixes I get about a 17-20% speedup doing a sequential dd with 4k
      IO's.  Basically if we don't have to split the bio for the map length it's small
      enough to be directly submitted, otherwise go back to the async submit.  Thanks,
      Signed-off-by: NJosef Bacik <josef@redhat.com>
      1ae39938
    • J
      Btrfs: don't split dio bios if we don't have to · 02f57c7a
      Josef Bacik 提交于
      We have been unconditionally allocating a new bio and re-adding all pages from
      our original bio to the new bio.  This is needed if our original bio is larger
      than our stripe size, but if it is smaller than the stripe size then there is no
      need to do this.  So check the map length and if we are under that then go ahead
      and submit the original bio.  Thanks,
      Signed-off-by: NJosef Bacik <josef@redhat.com>
      02f57c7a
    • J
      Btrfs: do not call btrfs_update_inode in endio if nothing changed · 1ef30be1
      Josef Bacik 提交于
      In the DIO code we often don't update the i_disk_size because the i_size isn't
      updated until after the DIO is completed, so basically we are allocating a path,
      doing a search, and updating the inode item for no reason since nothing changed.
      btrfs_ordered_update_i_size will return 1 if it didn't update i_disk_size, so
      only run btrfs_update_inode if btrfs_ordered_update_i_size returns 0.  Thanks,
      Signed-off-by: NJosef Bacik <josef@redhat.com>
      1ef30be1
    • J
      Btrfs: map the inode item when doing fill_inode_item · 12ddb96c
      Josef Bacik 提交于
      Instead of calling kmap_atomic for every thing we set in the inode item, map the
      entire inode item at the start and unmap it at the end.  This makes a sequential
      dd of 400mb O_DIRECT something like 1% faster.  Thanks,
      Signed-off-by: NJosef Bacik <josef@redhat.com>
      12ddb96c
  7. 05 4月, 2011 4 次提交
  8. 31 3月, 2011 1 次提交
  9. 28 3月, 2011 8 次提交
    • M
      btrfs: fix possible deadlock by clearing __GFP_FS flag · 1561deda
      Miao Xie 提交于
      Using the GFP_HIGHUSER_MOVABLE flag to allocate the metadata's page may cause
      deadlock.
        Task1
        open()
          ...
          btrfs_search_slot()
            ...
            btrfs_cow_block()
      	...
      	alloc_page()
      	  wait for reclaiming
      					shrink_slab()
      					  ...
      					  shrink_icache_memory()
      					    ...
      					    btrfs_evict_inode()
      					      ...
      					      btrfs_search_slot()
      
      If the path is locked by task1, the deadlock happens.
      
      So the btree's page cache is different with the file's page cache, it can not
      allocate pages by GFP_HIGHUSER_MOVABLE flag, we must clear __GFP_FS flag in
      GFP_HIGHUSER_MOVABLE flag.
      Reported-by: NItaru Kitayama <kitayama@cl.bb4u.ne.jp>
      Signed-off-by: NMiao Xie <miaox@cn.fujitsu.com>
      Signed-off-by: NChris Mason <chris.mason@oracle.com>
      1561deda
    • A
      btrfs: check link counter overflow in link(2) · c055e99e
      Al Viro 提交于
      Signed-off-by: NAl Viro <viro@zeniv.linux.org.uk>
      Signed-off-by: NChris Mason <chris.mason@oracle.com>
      c055e99e
    • A
      btrfs: don't mess with i_nlink of unlocked inode in rename() · 92986796
      Al Viro 提交于
      old_inode is not locked; it's not safe to play with its link
      count.  Instead of bumping it and calling btrfs_unlink_inode(),
      add a variant of the latter that does not do btrfs_drop_nlink()/
      btrfs_update_inode(), call it instead of btrfs_inc_nlink()/
      btrfs_unlink_inode() and do btrfs_update_inode() ourselves.
      Signed-off-by: NAl Viro <viro@zeniv.linux.org.uk>
      Signed-off-by: NChris Mason <chris.mason@oracle.com>
      92986796
    • T
      Btrfs: check return value of btrfs_alloc_path() · c2db1073
      Tsutomu Itoh 提交于
      Adding the check on the return value of btrfs_alloc_path() to several places.
      And, some of callers are modified by this change.
      Signed-off-by: NTsutomu Itoh <t-itoh@jp.fujitsu.com>
      Signed-off-by: NChris Mason <chris.mason@oracle.com>
      c2db1073
    • Y
      Btrfs: fix uncheck memory allocations · dac97e51
      Yoshinori Sano 提交于
      To make Btrfs code more robust, several return value checks where memory
      allocation can fail are introduced. I use BUG_ON where I don't know how
      to handle the error properly, which increases the number of using the
      notorious BUG_ON, though.
      Signed-off-by: NYoshinori Sano <yoshinori.sano@gmail.com>
      Signed-off-by: NChris Mason <chris.mason@oracle.com>
      dac97e51
    • M
      btrfs: return EXDEV when linking from different subvolumes · 3ab3564f
      Mark Fasheh 提交于
      btrfs_link returns EPERM if a cross-subvolume link is attempted.
      
      However, in this case I believe EXDEV to be the more appropriate value.
      >From the link(2) man page:
      
      EXDEV  oldpath and newpath are not on the same mounted file system.  (Linux
             permits a file system to be mounted at multiple points, but link()
             does not work across different mount points, even if the same file
             system is mounted on both.)
      
      This matters because an application may have different behaviors based on
      return codes.
      Signed-off-by: NMark Fasheh <mfasheh@suse.com>
      Signed-off-by: NChris Mason <chris.mason@oracle.com>
      3ab3564f
    • L
      Btrfs: Per file/directory controls for COW and compression · 75e7cb7f
      Liu Bo 提交于
      Data compression and data cow are controlled across the entire FS by mount
      options right now.  ioctls are needed to set this on a per file or per
      directory basis.  This has been proposed previously, but VFS developers
      wanted us to use generic ioctls rather than btrfs-specific ones.
      
      According to Chris's comment, there should be just one true compression
      method(probably LZO) stored in the super.  However, before this, we would
      wait for that one method is stable enough to be adopted into the super.
      So I list it as a long term goal, and just store it in ram today.
      
      After applying this patch, we can use the generic "FS_IOC_SETFLAGS" ioctl to
      control file and directory's datacow and compression attribute.
      
      NOTE:
       - The compression type is selected by such rules:
         If we mount btrfs with compress options, ie, zlib/lzo, the type is it.
         Otherwise, we'll use the default compress type (zlib today).
      
      v1->v2:
      - rebase to the latest btrfs.
      v2->v3:
      - fix a problem, i.e. when a file is set NOCOW via mount option, then this NOCOW
        will be screwed by inheritance from parent directory.
      Signed-off-by: NLiu Bo <liubo2009@cn.fujitsu.com>
      Signed-off-by: NChris Mason <chris.mason@oracle.com>
      75e7cb7f
    • L
      Btrfs: add initial tracepoint support for btrfs · 1abe9b8a
      liubo 提交于
      Tracepoints can provide insight into why btrfs hits bugs and be greatly
      helpful for debugging, e.g
                    dd-7822  [000]  2121.641088: btrfs_inode_request: root = 5(FS_TREE), gen = 4, ino = 256, blocks = 8, disk_i_size = 0, last_trans = 8, logged_trans = 0
                    dd-7822  [000]  2121.641100: btrfs_inode_new: root = 5(FS_TREE), gen = 8, ino = 257, blocks = 0, disk_i_size = 0, last_trans = 0, logged_trans = 0
       btrfs-transacti-7804  [001]  2146.935420: btrfs_cow_block: root = 2(EXTENT_TREE), refs = 2, orig_buf = 29368320 (orig_level = 0), cow_buf = 29388800 (cow_level = 0)
       btrfs-transacti-7804  [001]  2146.935473: btrfs_cow_block: root = 1(ROOT_TREE), refs = 2, orig_buf = 29364224 (orig_level = 0), cow_buf = 29392896 (cow_level = 0)
       btrfs-transacti-7804  [001]  2146.972221: btrfs_transaction_commit: root = 1(ROOT_TREE), gen = 8
         flush-btrfs-2-7821  [001]  2155.824210: btrfs_chunk_alloc: root = 3(CHUNK_TREE), offset = 1103101952, size = 1073741824, num_stripes = 1, sub_stripes = 0, type = DATA
         flush-btrfs-2-7821  [001]  2155.824241: btrfs_cow_block: root = 2(EXTENT_TREE), refs = 2, orig_buf = 29388800 (orig_level = 0), cow_buf = 29396992 (cow_level = 0)
         flush-btrfs-2-7821  [001]  2155.824255: btrfs_cow_block: root = 4(DEV_TREE), refs = 2, orig_buf = 29372416 (orig_level = 0), cow_buf = 29401088 (cow_level = 0)
         flush-btrfs-2-7821  [000]  2155.824329: btrfs_cow_block: root = 3(CHUNK_TREE), refs = 2, orig_buf = 20971520 (orig_level = 0), cow_buf = 20975616 (cow_level = 0)
       btrfs-endio-wri-7800  [001]  2155.898019: btrfs_cow_block: root = 5(FS_TREE), refs = 2, orig_buf = 29384704 (orig_level = 0), cow_buf = 29405184 (cow_level = 0)
       btrfs-endio-wri-7800  [001]  2155.898043: btrfs_cow_block: root = 7(CSUM_TREE), refs = 2, orig_buf = 29376512 (orig_level = 0), cow_buf = 29409280 (cow_level = 0)
      
      Here is what I have added:
      
      1) ordere_extent:
              btrfs_ordered_extent_add
              btrfs_ordered_extent_remove
              btrfs_ordered_extent_start
              btrfs_ordered_extent_put
      
      These provide critical information to understand how ordered_extents are
      updated.
      
      2) extent_map:
              btrfs_get_extent
      
      extent_map is used in both read and write cases, and it is useful for tracking
      how btrfs specific IO is running.
      
      3) writepage:
              __extent_writepage
              btrfs_writepage_end_io_hook
      
      Pages are cirtical resourses and produce a lot of corner cases during writeback,
      so it is valuable to know how page is written to disk.
      
      4) inode:
              btrfs_inode_new
              btrfs_inode_request
              btrfs_inode_evict
      
      These can show where and when a inode is created, when a inode is evicted.
      
      5) sync:
              btrfs_sync_file
              btrfs_sync_fs
      
      These show sync arguments.
      
      6) transaction:
              btrfs_transaction_commit
      
      In transaction based filesystem, it will be useful to know the generation and
      who does commit.
      
      7) back reference and cow:
      	btrfs_delayed_tree_ref
      	btrfs_delayed_data_ref
      	btrfs_delayed_ref_head
      	btrfs_cow_block
      
      Btrfs natively supports back references, these tracepoints are helpful on
      understanding btrfs's COW mechanism.
      
      8) chunk:
      	btrfs_chunk_alloc
      	btrfs_chunk_free
      
      Chunk is a link between physical offset and logical offset, and stands for space
      infomation in btrfs, and these are helpful on tracing space things.
      
      9) reserved_extent:
      	btrfs_reserved_extent_alloc
      	btrfs_reserved_extent_free
      
      These can show how btrfs uses its space.
      Signed-off-by: NLiu Bo <liubo2009@cn.fujitsu.com>
      Signed-off-by: NChris Mason <chris.mason@oracle.com>
      1abe9b8a
  10. 26 3月, 2011 2 次提交
    • J
      Btrfs: mark the bio with an error if we have a failure in dio · c0da7aa1
      Josef Bacik 提交于
      I noticed that dio_end_io calls the appropriate endio function with an error,
      but the endio functions don't actually do anything with that error, they assume
      that if there was an error then the bio will not be uptodate.  So if we had
      checksum failures we would never pass back EIO.  So if there is an error in our
      endio functions make sure to clear the uptodate flag on the bio.  Thanks,
      Signed-off-by: NJosef Bacik <josef@redhat.com>
      c0da7aa1
    • J
      Btrfs: don't allocate dip->csums when doing writes · 98bc3149
      Josef Bacik 提交于
      When doing direct writes we store the checksums in the ordered sum stuff in the
      ordered extent for writing them when the write completes, so we don't even use
      the dip->csums array.  So if we're writing, don't bother allocating dip->csums
      since we won't use it anyway.  Thanks,
      Signed-off-by: NJosef Bacik <josef@redhat.com>
      98bc3149
  11. 18 3月, 2011 7 次提交