Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 3 Aug 2011 07:14:05 +0000 (21:14 -1000)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 3 Aug 2011 07:14:05 +0000 (21:14 -1000)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable: (31 commits)
  Btrfs: don't call writepages from within write_full_page
  Btrfs: Remove unused variable 'last_index' in file.c
  Btrfs: clean up for find_first_extent_bit()
  Btrfs: clean up for wait_extent_bit()
  Btrfs: clean up for insert_state()
  Btrfs: remove unused members from struct extent_state
  Btrfs: clean up code for merging extent maps
  Btrfs: clean up code for extent_map lookup
  Btrfs: clean up search_extent_mapping()
  Btrfs: remove redundant code for dir item lookup
  Btrfs: make acl functions really no-op if acl is not enabled
  Btrfs: remove remaining ref-cache code
  Btrfs: remove a BUG_ON() in btrfs_commit_transaction()
  Btrfs: use wait_event()
  Btrfs: check the nodatasum flag when writing compressed files
  Btrfs: copy string correctly in INO_LOOKUP ioctl
  Btrfs: don't print the leaf if we had an error
  btrfs: make btrfs_set_root_node void
  Btrfs: fix oops while writing data to SSD partitions
  Btrfs: Protect the readonly flag of block group
  ...

Fix up trivial conflicts (due to acl and writeback cleanups) in
 - fs/btrfs/acl.c
 - fs/btrfs/ctree.h
 - fs/btrfs/extent_io.c

1  2 
fs/btrfs/acl.c
fs/btrfs/ctree.h
fs/btrfs/extent_io.c
fs/btrfs/file.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c

diff --combined fs/btrfs/acl.c
@@@ -28,9 -28,7 +28,7 @@@
  #include "btrfs_inode.h"
  #include "xattr.h"
  
- #ifdef CONFIG_BTRFS_FS_POSIX_ACL
 -static struct posix_acl *btrfs_get_acl(struct inode *inode, int type)
 +struct posix_acl *btrfs_get_acl(struct inode *inode, int type)
  {
        int size;
        const char *name;
@@@ -111,6 -109,7 +109,6 @@@ static int btrfs_set_acl(struct btrfs_t
        int ret, size = 0;
        const char *name;
        char *value = NULL;
 -      mode_t mode;
  
        if (acl) {
                ret = posix_acl_valid(acl);
  
        switch (type) {
        case ACL_TYPE_ACCESS:
 -              mode = inode->i_mode;
                name = POSIX_ACL_XATTR_ACCESS;
                if (acl) {
 -                      ret = posix_acl_equiv_mode(acl, &mode);
 +                      ret = posix_acl_equiv_mode(acl, &inode->i_mode);
                        if (ret < 0)
                                return ret;
 -                      inode->i_mode = mode;
                }
                ret = 0;
                break;
@@@ -192,6 -193,28 +190,6 @@@ out
        return ret;
  }
  
 -int btrfs_check_acl(struct inode *inode, int mask, unsigned int flags)
 -{
 -      int error = -EAGAIN;
 -
 -      if (flags & IPERM_FLAG_RCU) {
 -              if (!negative_cached_acl(inode, ACL_TYPE_ACCESS))
 -                      error = -ECHILD;
 -
 -      } else {
 -              struct posix_acl *acl;
 -              acl = btrfs_get_acl(inode, ACL_TYPE_ACCESS);
 -              if (IS_ERR(acl))
 -                      return PTR_ERR(acl);
 -              if (acl) {
 -                      error = posix_acl_permission(inode, acl, mask);
 -                      posix_acl_release(acl);
 -              }
 -      }
 -
 -      return error;
 -}
 -
  /*
   * btrfs_init_acl is already generally called under fs_mutex, so the locking
   * stuff has been fixed to work with that.  If the locking stuff changes, we
@@@ -219,20 -242,31 +217,20 @@@ int btrfs_init_acl(struct btrfs_trans_h
        }
  
        if (IS_POSIXACL(dir) && acl) {
 -              struct posix_acl *clone;
 -              mode_t mode;
 -
                if (S_ISDIR(inode->i_mode)) {
                        ret = btrfs_set_acl(trans, inode, acl,
                                            ACL_TYPE_DEFAULT);
                        if (ret)
                                goto failed;
                }
 -              clone = posix_acl_clone(acl, GFP_NOFS);
 -              ret = -ENOMEM;
 -              if (!clone)
 -                      goto failed;
 -
 -              mode = inode->i_mode;
 -              ret = posix_acl_create_masq(clone, &mode);
 -              if (ret >= 0) {
 -                      inode->i_mode = mode;
 -                      if (ret > 0) {
 -                              /* we need an acl */
 -                              ret = btrfs_set_acl(trans, inode, clone,
 -                                                  ACL_TYPE_ACCESS);
 -                      }
 +              ret = posix_acl_create(&acl, GFP_NOFS, &inode->i_mode);
 +              if (ret < 0)
 +                      return ret;
 +
 +              if (ret > 0) {
 +                      /* we need an acl */
 +                      ret = btrfs_set_acl(trans, inode, acl, ACL_TYPE_ACCESS);
                }
 -              posix_acl_release(clone);
        }
  failed:
        posix_acl_release(acl);
  
  int btrfs_acl_chmod(struct inode *inode)
  {
 -      struct posix_acl *acl, *clone;
 +      struct posix_acl *acl;
        int ret = 0;
  
        if (S_ISLNK(inode->i_mode))
        if (IS_ERR_OR_NULL(acl))
                return PTR_ERR(acl);
  
 -      clone = posix_acl_clone(acl, GFP_KERNEL);
 +      ret = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
 +      if (ret)
 +              return ret;
 +      ret = btrfs_set_acl(NULL, inode, acl, ACL_TYPE_ACCESS);
        posix_acl_release(acl);
 -      if (!clone)
 -              return -ENOMEM;
 -
 -      ret = posix_acl_chmod_masq(clone, inode->i_mode);
 -      if (!ret)
 -              ret = btrfs_set_acl(NULL, inode, clone, ACL_TYPE_ACCESS);
 -
 -      posix_acl_release(clone);
 -
        return ret;
  }
  
@@@ -276,18 -316,3 +274,3 @@@ const struct xattr_handler btrfs_xattr_
        .get    = btrfs_xattr_acl_get,
        .set    = btrfs_xattr_acl_set,
  };
- #else /* CONFIG_BTRFS_FS_POSIX_ACL */
- int btrfs_acl_chmod(struct inode *inode)
- {
-       return 0;
- }
- int btrfs_init_acl(struct btrfs_trans_handle *trans,
-                  struct inode *inode, struct inode *dir)
- {
-       return 0;
- }
- #endif /* CONFIG_BTRFS_FS_POSIX_ACL */
diff --combined fs/btrfs/ctree.h
@@@ -1224,7 -1224,7 +1224,7 @@@ struct btrfs_root 
         * right now this just gets used so that a root has its own devid
         * for stat.  It may be used for more later
         */
 -      struct super_block anon_super;
 +      dev_t anon_dev;
  };
  
  struct btrfs_ioctl_defrag_range_args {
@@@ -2406,8 -2406,8 +2406,8 @@@ int btrfs_find_last_root(struct btrfs_r
                         btrfs_root_item *item, struct btrfs_key *key);
  int btrfs_find_dead_roots(struct btrfs_root *root, u64 objectid);
  int btrfs_find_orphan_roots(struct btrfs_root *tree_root);
int btrfs_set_root_node(struct btrfs_root_item *item,
-                       struct extent_buffer *node);
void btrfs_set_root_node(struct btrfs_root_item *item,
+                        struct extent_buffer *node);
  void btrfs_check_and_init_root_item(struct btrfs_root_item *item);
  
  /* dir-item.c */
@@@ -2512,9 -2512,6 +2512,9 @@@ int btrfs_csum_truncate(struct btrfs_tr
  int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end,
                             struct list_head *list, int search_commit);
  /* inode.c */
 +struct extent_map *btrfs_get_extent_fiemap(struct inode *inode, struct page *page,
 +                                         size_t pg_offset, u64 start, u64 len,
 +                                         int create);
  
  /* RHEL and EL kernels have a patch that renames PG_checked to FsMisc */
  #if defined(ClearPageFsMisc) && !defined(ClearPageChecked)
  #define PageChecked PageFsMisc
  #endif
  
+ /* This forces readahead on a given range of bytes in an inode */
+ static inline void btrfs_force_ra(struct address_space *mapping,
+                                 struct file_ra_state *ra, struct file *file,
+                                 pgoff_t offset, unsigned long req_size)
+ {
+       page_cache_sync_readahead(mapping, ra, file, offset, req_size);
+ }
  struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry);
  int btrfs_set_inode_index(struct inode *dir, u64 *index);
  int btrfs_unlink_inode(struct btrfs_trans_handle *trans,
@@@ -2551,9 -2556,6 +2559,6 @@@ int btrfs_create_subvol_root(struct btr
  int btrfs_merge_bio_hook(struct page *page, unsigned long offset,
                         size_t size, struct bio *bio, unsigned long bio_flags);
  
- unsigned long btrfs_force_ra(struct address_space *mapping,
-                             struct file_ra_state *ra, struct file *file,
-                             pgoff_t offset, pgoff_t last_index);
  int btrfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf);
  int btrfs_readpage(struct file *file, struct page *page);
  void btrfs_evict_inode(struct inode *inode);
@@@ -2607,7 -2609,7 +2612,7 @@@ int btrfs_defrag_file(struct inode *ino
  int btrfs_add_inode_defrag(struct btrfs_trans_handle *trans,
                           struct inode *inode);
  int btrfs_run_defrag_inodes(struct btrfs_fs_info *fs_info);
 -int btrfs_sync_file(struct file *file, int datasync);
 +int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync);
  int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
                            int skip_pinned);
  extern const struct file_operations btrfs_file_operations;
@@@ -2647,13 -2649,22 +2652,22 @@@ do {                                                         
  
  /* acl.c */
  #ifdef CONFIG_BTRFS_FS_POSIX_ACL
 -int btrfs_check_acl(struct inode *inode, int mask, unsigned int flags);
 +struct posix_acl *btrfs_get_acl(struct inode *inode, int type);
- #else
- #define btrfs_get_acl NULL
- #endif
  int btrfs_init_acl(struct btrfs_trans_handle *trans,
                   struct inode *inode, struct inode *dir);
  int btrfs_acl_chmod(struct inode *inode);
 -#define btrfs_check_acl NULL
+ #else
++#define btrfs_get_acl NULL
+ static inline int btrfs_init_acl(struct btrfs_trans_handle *trans,
+                                struct inode *inode, struct inode *dir)
+ {
+       return 0;
+ }
+ static inline int btrfs_acl_chmod(struct inode *inode)
+ {
+       return 0;
+ }
+ #endif
  
  /* relocation.c */
  int btrfs_relocate_block_group(struct btrfs_root *root, u64 group_start);
diff --combined fs/btrfs/extent_io.c
@@@ -254,14 -254,14 +254,14 @@@ static void merge_cb(struct extent_io_t
   *
   * This should be called with the tree lock held.
   */
- static int merge_state(struct extent_io_tree *tree,
-                      struct extent_state *state)
+ static void merge_state(struct extent_io_tree *tree,
+                       struct extent_state *state)
  {
        struct extent_state *other;
        struct rb_node *other_node;
  
        if (state->state & (EXTENT_IOBITS | EXTENT_BOUNDARY))
-               return 0;
+               return;
  
        other_node = rb_prev(&state->rb_node);
        if (other_node) {
                        free_extent_state(other);
                }
        }
-       return 0;
  }
  
- static int set_state_cb(struct extent_io_tree *tree,
+ static void set_state_cb(struct extent_io_tree *tree,
                         struct extent_state *state, int *bits)
  {
-       if (tree->ops && tree->ops->set_bit_hook) {
-               return tree->ops->set_bit_hook(tree->mapping->host,
-                                              state, bits);
-       }
-       return 0;
+       if (tree->ops && tree->ops->set_bit_hook)
+               tree->ops->set_bit_hook(tree->mapping->host, state, bits);
  }
  
  static void clear_state_cb(struct extent_io_tree *tree,
                tree->ops->clear_bit_hook(tree->mapping->host, state, bits);
  }
  
+ static void set_state_bits(struct extent_io_tree *tree,
+                          struct extent_state *state, int *bits);
  /*
   * insert an extent_state struct into the tree.  'bits' are set on the
   * struct before it is inserted.
@@@ -324,8 -321,6 +321,6 @@@ static int insert_state(struct extent_i
                        int *bits)
  {
        struct rb_node *node;
-       int bits_to_set = *bits & ~EXTENT_CTLBITS;
-       int ret;
  
        if (end < start) {
                printk(KERN_ERR "btrfs end < start %llu %llu\n",
        }
        state->start = start;
        state->end = end;
-       ret = set_state_cb(tree, state, bits);
-       if (ret)
-               return ret;
  
-       if (bits_to_set & EXTENT_DIRTY)
-               tree->dirty_bytes += end - start + 1;
-       state->state |= bits_to_set;
+       set_state_bits(tree, state, bits);
        node = tree_insert(&tree->state, end, &state->rb_node);
        if (node) {
                struct extent_state *found;
        return 0;
  }
  
- static int split_cb(struct extent_io_tree *tree, struct extent_state *orig,
+ static void split_cb(struct extent_io_tree *tree, struct extent_state *orig,
                     u64 split)
  {
        if (tree->ops && tree->ops->split_extent_hook)
-               return tree->ops->split_extent_hook(tree->mapping->host,
-                                                   orig, split);
-       return 0;
+               tree->ops->split_extent_hook(tree->mapping->host, orig, split);
  }
  
  /*
@@@ -659,34 -648,25 +648,25 @@@ again
                if (start > end)
                        break;
  
-               if (need_resched()) {
-                       spin_unlock(&tree->lock);
-                       cond_resched();
-                       spin_lock(&tree->lock);
-               }
+               cond_resched_lock(&tree->lock);
        }
  out:
        spin_unlock(&tree->lock);
        return 0;
  }
  
- static int set_state_bits(struct extent_io_tree *tree,
+ static void set_state_bits(struct extent_io_tree *tree,
                           struct extent_state *state,
                           int *bits)
  {
-       int ret;
        int bits_to_set = *bits & ~EXTENT_CTLBITS;
  
-       ret = set_state_cb(tree, state, bits);
-       if (ret)
-               return ret;
+       set_state_cb(tree, state, bits);
        if ((bits_to_set & EXTENT_DIRTY) && !(state->state & EXTENT_DIRTY)) {
                u64 range = state->end - state->start + 1;
                tree->dirty_bytes += range;
        }
        state->state |= bits_to_set;
-       return 0;
  }
  
  static void cache_state(struct extent_state *state,
@@@ -779,9 -759,7 +759,7 @@@ hit_next
                        goto out;
                }
  
-               err = set_state_bits(tree, state, &bits);
-               if (err)
-                       goto out;
+               set_state_bits(tree, state, &bits);
  
                cache_state(state, cached_state);
                merge_state(tree, state);
                if (err)
                        goto out;
                if (state->end <= end) {
-                       err = set_state_bits(tree, state, &bits);
-                       if (err)
-                               goto out;
+                       set_state_bits(tree, state, &bits);
                        cache_state(state, cached_state);
                        merge_state(tree, state);
                        if (last_end == (u64)-1)
                err = split_state(tree, state, prealloc, end + 1);
                BUG_ON(err == -EEXIST);
  
-               err = set_state_bits(tree, prealloc, &bits);
-               if (err) {
-                       prealloc = NULL;
-                       goto out;
-               }
+               set_state_bits(tree, prealloc, &bits);
                cache_state(prealloc, cached_state);
                merge_state(tree, prealloc);
                prealloc = NULL;
@@@ -1059,46 -1031,6 +1031,6 @@@ static int set_range_writeback(struct e
        return 0;
  }
  
- /*
-  * find the first offset in the io tree with 'bits' set. zero is
-  * returned if we find something, and *start_ret and *end_ret are
-  * set to reflect the state struct that was found.
-  *
-  * If nothing was found, 1 is returned, < 0 on error
-  */
- int find_first_extent_bit(struct extent_io_tree *tree, u64 start,
-                         u64 *start_ret, u64 *end_ret, int bits)
- {
-       struct rb_node *node;
-       struct extent_state *state;
-       int ret = 1;
-       spin_lock(&tree->lock);
-       /*
-        * this search will find all the extents that end after
-        * our range starts.
-        */
-       node = tree_search(tree, start);
-       if (!node)
-               goto out;
-       while (1) {
-               state = rb_entry(node, struct extent_state, rb_node);
-               if (state->end >= start && (state->state & bits)) {
-                       *start_ret = state->start;
-                       *end_ret = state->end;
-                       ret = 0;
-                       break;
-               }
-               node = rb_next(node);
-               if (!node)
-                       break;
-       }
- out:
-       spin_unlock(&tree->lock);
-       return ret;
- }
  /* find the first state struct with 'bits' set after 'start', and
   * return it.  tree->lock must be held.  NULL will returned if
   * nothing was found after 'start'
        return NULL;
  }
  
+ /*
+  * find the first offset in the io tree with 'bits' set. zero is
+  * returned if we find something, and *start_ret and *end_ret are
+  * set to reflect the state struct that was found.
+  *
+  * If nothing was found, 1 is returned, < 0 on error
+  */
+ int find_first_extent_bit(struct extent_io_tree *tree, u64 start,
+                         u64 *start_ret, u64 *end_ret, int bits)
+ {
+       struct extent_state *state;
+       int ret = 1;
+       spin_lock(&tree->lock);
+       state = find_first_extent_bit_state(tree, start, bits);
+       if (state) {
+               *start_ret = state->start;
+               *end_ret = state->end;
+               ret = 0;
+       }
+       spin_unlock(&tree->lock);
+       return ret;
+ }
  /*
   * find a contiguous range of bytes in the file marked as delalloc, not
   * more than 'max_bytes'.  start and end are used to return the range,
@@@ -2546,7 -2502,6 +2502,6 @@@ int extent_write_full_page(struct exten
                          struct writeback_control *wbc)
  {
        int ret;
-       struct address_space *mapping = page->mapping;
        struct extent_page_data epd = {
                .bio = NULL,
                .tree = tree,
                .extent_locked = 0,
                .sync_io = wbc->sync_mode == WB_SYNC_ALL,
        };
-       struct writeback_control wbc_writepages = {
-               .sync_mode      = wbc->sync_mode,
-               .nr_to_write    = 64,
-               .range_start    = page_offset(page) + PAGE_CACHE_SIZE,
-               .range_end      = (loff_t)-1,
-       };
  
        ret = __extent_writepage(page, wbc, &epd);
  
-       extent_write_cache_pages(tree, mapping, &wbc_writepages,
-                                __extent_writepage, &epd, flush_write_bio);
        flush_epd_write_bio(&epd);
        return ret;
  }
@@@ -2588,6 -2535,7 +2535,6 @@@ int extent_write_locked_range(struct ex
        };
        struct writeback_control wbc_writepages = {
                .sync_mode      = mode,
 -              .older_than_this = NULL,
                .nr_to_write    = nr_pages * 2,
                .range_start    = start,
                .range_end      = end + 1,
diff --combined fs/btrfs/file.c
@@@ -74,7 -74,7 +74,7 @@@ struct inode_defrag 
   * If an existing record is found the defrag item you
   * pass in is freed
   */
- static int __btrfs_add_inode_defrag(struct inode *inode,
+ static void __btrfs_add_inode_defrag(struct inode *inode,
                                    struct inode_defrag *defrag)
  {
        struct btrfs_root *root = BTRFS_I(inode)->root;
        BTRFS_I(inode)->in_defrag = 1;
        rb_link_node(&defrag->rb_node, parent, p);
        rb_insert_color(&defrag->rb_node, &root->fs_info->defrag_inodes);
-       return 0;
+       return;
  
  exists:
        kfree(defrag);
-       return 0;
+       return;
  
  }
  
@@@ -123,7 -123,6 +123,6 @@@ int btrfs_add_inode_defrag(struct btrfs
  {
        struct btrfs_root *root = BTRFS_I(inode)->root;
        struct inode_defrag *defrag;
-       int ret = 0;
        u64 transid;
  
        if (!btrfs_test_opt(root, AUTO_DEFRAG))
  
        spin_lock(&root->fs_info->defrag_inodes_lock);
        if (!BTRFS_I(inode)->in_defrag)
-               ret = __btrfs_add_inode_defrag(inode, defrag);
+               __btrfs_add_inode_defrag(inode, defrag);
        spin_unlock(&root->fs_info->defrag_inodes_lock);
-       return ret;
+       return 0;
  }
  
  /*
@@@ -855,7 -854,8 +854,8 @@@ int btrfs_mark_extent_written(struct bt
        btrfs_drop_extent_cache(inode, start, end - 1, 0);
  
        path = btrfs_alloc_path();
-       BUG_ON(!path);
+       if (!path)
+               return -ENOMEM;
  again:
        recow = 0;
        split = start;
@@@ -1059,7 -1059,7 +1059,7 @@@ static int prepare_uptodate_page(struc
  static noinline int prepare_pages(struct btrfs_root *root, struct file *file,
                         struct page **pages, size_t num_pages,
                         loff_t pos, unsigned long first_index,
-                        unsigned long last_index, size_t write_bytes)
+                        size_t write_bytes)
  {
        struct extent_state *cached_state = NULL;
        int i;
@@@ -1159,7 -1159,6 +1159,6 @@@ static noinline ssize_t __btrfs_buffere
        struct btrfs_root *root = BTRFS_I(inode)->root;
        struct page **pages = NULL;
        unsigned long first_index;
-       unsigned long last_index;
        size_t num_written = 0;
        int nrptrs;
        int ret = 0;
                return -ENOMEM;
  
        first_index = pos >> PAGE_CACHE_SHIFT;
-       last_index = (pos + iov_iter_count(i)) >> PAGE_CACHE_SHIFT;
  
        while (iov_iter_count(i) > 0) {
                size_t offset = pos & (PAGE_CACHE_SIZE - 1);
                 * contents of pages from loop to loop
                 */
                ret = prepare_pages(root, file, pages, num_pages,
-                                   pos, first_index, last_index,
-                                   write_bytes);
+                                   pos, first_index, write_bytes);
                if (ret) {
                        btrfs_delalloc_release_space(inode,
                                        num_pages << PAGE_CACHE_SHIFT);
@@@ -1455,7 -1452,7 +1452,7 @@@ int btrfs_release_file(struct inode *in
   * important optimization for directories because holding the mutex prevents
   * new operations on the dir while we write to disk.
   */
 -int btrfs_sync_file(struct file *file, int datasync)
 +int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
  {
        struct dentry *dentry = file->f_path.dentry;
        struct inode *inode = dentry->d_inode;
  
        trace_btrfs_sync_file(file, datasync);
  
 +      ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
 +      if (ret)
 +              return ret;
 +      mutex_lock(&inode->i_mutex);
 +
        /* we wait first, since the writeback may change the inode */
        root->log_batch++;
 -      /* the VFS called filemap_fdatawrite for us */
        btrfs_wait_ordered_range(inode, 0, (u64)-1);
        root->log_batch++;
  
         * check the transaction that last modified this inode
         * and see if its already been committed
         */
 -      if (!BTRFS_I(inode)->last_trans)
 +      if (!BTRFS_I(inode)->last_trans) {
 +              mutex_unlock(&inode->i_mutex);
                goto out;
 +      }
  
        /*
         * if the last transaction that changed this file was before
        if (BTRFS_I(inode)->last_trans <=
            root->fs_info->last_trans_committed) {
                BTRFS_I(inode)->last_trans = 0;
 +              mutex_unlock(&inode->i_mutex);
                goto out;
        }
  
        trans = btrfs_start_transaction(root, 0);
        if (IS_ERR(trans)) {
                ret = PTR_ERR(trans);
 +              mutex_unlock(&inode->i_mutex);
                goto out;
        }
  
        ret = btrfs_log_dentry_safe(trans, root, dentry);
 -      if (ret < 0)
 +      if (ret < 0) {
 +              mutex_unlock(&inode->i_mutex);
                goto out;
 +      }
  
        /* we've logged all the items and now have a consistent
         * version of the file in the log.  It is possible that
         * file again, but that will end up using the synchronization
         * inside btrfs_sync_log to keep things safe.
         */
 -      mutex_unlock(&dentry->d_inode->i_mutex);
 +      mutex_unlock(&inode->i_mutex);
  
        if (ret != BTRFS_NO_LOG_SYNC) {
                if (ret > 0) {
        } else {
                ret = btrfs_end_transaction(trans, root);
        }
 -      mutex_lock(&dentry->d_inode->i_mutex);
  out:
        return ret > 0 ? -EIO : ret;
  }
        return ret;
  }
  
 +static int find_desired_extent(struct inode *inode, loff_t *offset, int origin)
 +{
 +      struct btrfs_root *root = BTRFS_I(inode)->root;
 +      struct extent_map *em;
 +      struct extent_state *cached_state = NULL;
 +      u64 lockstart = *offset;
 +      u64 lockend = i_size_read(inode);
 +      u64 start = *offset;
 +      u64 orig_start = *offset;
 +      u64 len = i_size_read(inode);
 +      u64 last_end = 0;
 +      int ret = 0;
 +
 +      lockend = max_t(u64, root->sectorsize, lockend);
 +      if (lockend <= lockstart)
 +              lockend = lockstart + root->sectorsize;
 +
 +      len = lockend - lockstart + 1;
 +
 +      len = max_t(u64, len, root->sectorsize);
 +      if (inode->i_size == 0)
 +              return -ENXIO;
 +
 +      lock_extent_bits(&BTRFS_I(inode)->io_tree, lockstart, lockend, 0,
 +                       &cached_state, GFP_NOFS);
 +
 +      /*
 +       * Delalloc is such a pain.  If we have a hole and we have pending
 +       * delalloc for a portion of the hole we will get back a hole that
 +       * exists for the entire range since it hasn't been actually written
 +       * yet.  So to take care of this case we need to look for an extent just
 +       * before the position we want in case there is outstanding delalloc
 +       * going on here.
 +       */
 +      if (origin == SEEK_HOLE && start != 0) {
 +              if (start <= root->sectorsize)
 +                      em = btrfs_get_extent_fiemap(inode, NULL, 0, 0,
 +                                                   root->sectorsize, 0);
 +              else
 +                      em = btrfs_get_extent_fiemap(inode, NULL, 0,
 +                                                   start - root->sectorsize,
 +                                                   root->sectorsize, 0);
 +              if (IS_ERR(em)) {
 +                      ret = -ENXIO;
 +                      goto out;
 +              }
 +              last_end = em->start + em->len;
 +              if (em->block_start == EXTENT_MAP_DELALLOC)
 +                      last_end = min_t(u64, last_end, inode->i_size);
 +              free_extent_map(em);
 +      }
 +
 +      while (1) {
 +              em = btrfs_get_extent_fiemap(inode, NULL, 0, start, len, 0);
 +              if (IS_ERR(em)) {
 +                      ret = -ENXIO;
 +                      break;
 +              }
 +
 +              if (em->block_start == EXTENT_MAP_HOLE) {
 +                      if (test_bit(EXTENT_FLAG_VACANCY, &em->flags)) {
 +                              if (last_end <= orig_start) {
 +                                      free_extent_map(em);
 +                                      ret = -ENXIO;
 +                                      break;
 +                              }
 +                      }
 +
 +                      if (origin == SEEK_HOLE) {
 +                              *offset = start;
 +                              free_extent_map(em);
 +                              break;
 +                      }
 +              } else {
 +                      if (origin == SEEK_DATA) {
 +                              if (em->block_start == EXTENT_MAP_DELALLOC) {
 +                                      if (start >= inode->i_size) {
 +                                              free_extent_map(em);
 +                                              ret = -ENXIO;
 +                                              break;
 +                                      }
 +                              }
 +
 +                              *offset = start;
 +                              free_extent_map(em);
 +                              break;
 +                      }
 +              }
 +
 +              start = em->start + em->len;
 +              last_end = em->start + em->len;
 +
 +              if (em->block_start == EXTENT_MAP_DELALLOC)
 +                      last_end = min_t(u64, last_end, inode->i_size);
 +
 +              if (test_bit(EXTENT_FLAG_VACANCY, &em->flags)) {
 +                      free_extent_map(em);
 +                      ret = -ENXIO;
 +                      break;
 +              }
 +              free_extent_map(em);
 +              cond_resched();
 +      }
 +      if (!ret)
 +              *offset = min(*offset, inode->i_size);
 +out:
 +      unlock_extent_cached(&BTRFS_I(inode)->io_tree, lockstart, lockend,
 +                           &cached_state, GFP_NOFS);
 +      return ret;
 +}
 +
 +static loff_t btrfs_file_llseek(struct file *file, loff_t offset, int origin)
 +{
 +      struct inode *inode = file->f_mapping->host;
 +      int ret;
 +
 +      mutex_lock(&inode->i_mutex);
 +      switch (origin) {
 +      case SEEK_END:
 +      case SEEK_CUR:
 +              offset = generic_file_llseek_unlocked(file, offset, origin);
 +              goto out;
 +      case SEEK_DATA:
 +      case SEEK_HOLE:
 +              ret = find_desired_extent(inode, &offset, origin);
 +              if (ret) {
 +                      mutex_unlock(&inode->i_mutex);
 +                      return ret;
 +              }
 +      }
 +
 +      if (offset < 0 && !(file->f_mode & FMODE_UNSIGNED_OFFSET))
 +              return -EINVAL;
 +      if (offset > inode->i_sb->s_maxbytes)
 +              return -EINVAL;
 +
 +      /* Special lock needed here? */
 +      if (offset != file->f_pos) {
 +              file->f_pos = offset;
 +              file->f_version = 0;
 +      }
 +out:
 +      mutex_unlock(&inode->i_mutex);
 +      return offset;
 +}
 +
  const struct file_operations btrfs_file_operations = {
 -      .llseek         = generic_file_llseek,
 +      .llseek         = btrfs_file_llseek,
        .read           = do_sync_read,
        .write          = do_sync_write,
        .aio_read       = generic_file_aio_read,
diff --combined fs/btrfs/inode.c
@@@ -1061,7 -1061,8 +1061,8 @@@ static noinline int run_delalloc_nocow(
        u64 ino = btrfs_ino(inode);
  
        path = btrfs_alloc_path();
-       BUG_ON(!path);
+       if (!path)
+               return -ENOMEM;
  
        nolock = btrfs_is_free_space_inode(root, inode);
  
@@@ -1282,17 -1283,16 +1283,16 @@@ static int run_delalloc_range(struct in
        return ret;
  }
  
- static int btrfs_split_extent_hook(struct inode *inode,
-                                  struct extent_state *orig, u64 split)
+ static void btrfs_split_extent_hook(struct inode *inode,
+                                   struct extent_state *orig, u64 split)
  {
        /* not delalloc, ignore it */
        if (!(orig->state & EXTENT_DELALLOC))
-               return 0;
+               return;
  
        spin_lock(&BTRFS_I(inode)->lock);
        BTRFS_I(inode)->outstanding_extents++;
        spin_unlock(&BTRFS_I(inode)->lock);
-       return 0;
  }
  
  /*
   * extents, such as when we are doing sequential writes, so we can properly
   * account for the metadata space we'll need.
   */
- static int btrfs_merge_extent_hook(struct inode *inode,
-                                  struct extent_state *new,
-                                  struct extent_state *other)
+ static void btrfs_merge_extent_hook(struct inode *inode,
+                                   struct extent_state *new,
+                                   struct extent_state *other)
  {
        /* not delalloc, ignore it */
        if (!(other->state & EXTENT_DELALLOC))
-               return 0;
+               return;
  
        spin_lock(&BTRFS_I(inode)->lock);
        BTRFS_I(inode)->outstanding_extents--;
        spin_unlock(&BTRFS_I(inode)->lock);
-       return 0;
  }
  
  /*
   * bytes in this file, and to maintain the list of inodes that
   * have pending delalloc work to be done.
   */
- static int btrfs_set_bit_hook(struct inode *inode,
-                             struct extent_state *state, int *bits)
+ static void btrfs_set_bit_hook(struct inode *inode,
+                              struct extent_state *state, int *bits)
  {
  
        /*
                }
                spin_unlock(&root->fs_info->delalloc_lock);
        }
-       return 0;
  }
  
  /*
   * extent_io.c clear_bit_hook, see set_bit_hook for why
   */
- static int btrfs_clear_bit_hook(struct inode *inode,
-                               struct extent_state *state, int *bits)
+ static void btrfs_clear_bit_hook(struct inode *inode,
+                                struct extent_state *state, int *bits)
  {
        /*
         * set_bit and clear bit hooks normally require _irqsave/restore
                }
                spin_unlock(&root->fs_info->delalloc_lock);
        }
-       return 0;
  }
  
  /*
@@@ -1645,7 -1642,8 +1642,8 @@@ static int insert_reserved_file_extent(
        int ret;
  
        path = btrfs_alloc_path();
-       BUG_ON(!path);
+       if (!path)
+               return -ENOMEM;
  
        path->leave_spinning = 1;
  
@@@ -2215,7 -2213,8 +2213,8 @@@ int btrfs_orphan_add(struct btrfs_trans
  
        if (!root->orphan_block_rsv) {
                block_rsv = btrfs_alloc_block_rsv(root);
-               BUG_ON(!block_rsv);
+               if (!block_rsv)
+                       return -ENOMEM;
        }
  
        spin_lock(&root->orphan_lock);
@@@ -2517,7 -2516,9 +2516,9 @@@ static void btrfs_read_locked_inode(str
                filled = true;
  
        path = btrfs_alloc_path();
-       BUG_ON(!path);
+       if (!path)
+               goto make_bad;
        path->leave_spinning = 1;
        memcpy(&location, &BTRFS_I(inode)->location, sizeof(location));
  
@@@ -2998,13 -2999,16 +2999,16 @@@ static int btrfs_unlink(struct inode *d
  
        ret = btrfs_unlink_inode(trans, root, dir, dentry->d_inode,
                                 dentry->d_name.name, dentry->d_name.len);
-       BUG_ON(ret);
+       if (ret)
+               goto out;
  
        if (inode->i_nlink == 0) {
                ret = btrfs_orphan_add(trans, inode);
-               BUG_ON(ret);
+               if (ret)
+                       goto out;
        }
  
+ out:
        nr = trans->blocks_used;
        __unlink_end_trans(trans, root);
        btrfs_btree_balance_dirty(root, nr);
@@@ -3147,6 -3151,11 +3151,11 @@@ int btrfs_truncate_inode_items(struct b
  
        BUG_ON(new_size > 0 && min_type != BTRFS_EXTENT_DATA_KEY);
  
+       path = btrfs_alloc_path();
+       if (!path)
+               return -ENOMEM;
+       path->reada = -1;
        if (root->ref_cows || root == root->fs_info->tree_root)
                btrfs_drop_extent_cache(inode, new_size & (~mask), (u64)-1, 0);
  
        if (min_type == 0 && root == BTRFS_I(inode)->root)
                btrfs_kill_delayed_inode_items(inode);
  
-       path = btrfs_alloc_path();
-       BUG_ON(!path);
-       path->reada = -1;
        key.objectid = ino;
        key.offset = (u64)-1;
        key.type = (u8)-1;
@@@ -3690,7 -3695,8 +3695,8 @@@ static int btrfs_inode_by_name(struct i
        int ret = 0;
  
        path = btrfs_alloc_path();
-       BUG_ON(!path);
+       if (!path)
+               return -ENOMEM;
  
        di = btrfs_lookup_dir_item(NULL, root, path, btrfs_ino(dir), name,
                                    namelen, 0);
@@@ -3946,6 -3952,7 +3952,7 @@@ struct inode *btrfs_iget(struct super_b
                         struct btrfs_root *root, int *new)
  {
        struct inode *inode;
+       int bad_inode = 0;
  
        inode = btrfs_iget_locked(s, location->objectid, root);
        if (!inode)
                BTRFS_I(inode)->root = root;
                memcpy(&BTRFS_I(inode)->location, location, sizeof(*location));
                btrfs_read_locked_inode(inode);
-               inode_tree_add(inode);
-               unlock_new_inode(inode);
-               if (new)
-                       *new = 1;
+               if (!is_bad_inode(inode)) {
+                       inode_tree_add(inode);
+                       unlock_new_inode(inode);
+                       if (new)
+                               *new = 1;
+               } else {
+                       bad_inode = 1;
+               }
+       }
+       if (bad_inode) {
+               iput(inode);
+               inode = ERR_PTR(-ESTALE);
        }
  
        return inode;
@@@ -3993,19 -4009,12 +4009,19 @@@ struct inode *btrfs_lookup_dentry(struc
        struct btrfs_root *sub_root = root;
        struct btrfs_key location;
        int index;
 -      int ret;
 +      int ret = 0;
  
        if (dentry->d_name.len > BTRFS_NAME_LEN)
                return ERR_PTR(-ENAMETOOLONG);
  
 -      ret = btrfs_inode_by_name(dir, dentry, &location);
 +      if (unlikely(d_need_lookup(dentry))) {
 +              memcpy(&location, dentry->d_fsdata, sizeof(struct btrfs_key));
 +              kfree(dentry->d_fsdata);
 +              dentry->d_fsdata = NULL;
 +              d_clear_need_lookup(dentry);
 +      } else {
 +              ret = btrfs_inode_by_name(dir, dentry, &location);
 +      }
  
        if (ret < 0)
                return ERR_PTR(ret);
@@@ -4060,16 -4069,16 +4076,16 @@@ static int btrfs_dentry_delete(const st
        return 0;
  }
  
 +static void btrfs_dentry_release(struct dentry *dentry)
 +{
 +      if (dentry->d_fsdata)
 +              kfree(dentry->d_fsdata);
 +}
 +
  static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry,
                                   struct nameidata *nd)
  {
 -      struct inode *inode;
 -
 -      inode = btrfs_lookup_dentry(dir, dentry);
 -      if (IS_ERR(inode))
 -              return ERR_CAST(inode);
 -
 -      return d_splice_alias(inode, dentry);
 +      return d_splice_alias(btrfs_lookup_dentry(dir, dentry), dentry);
  }
  
  unsigned char btrfs_filetype_table[] = {
@@@ -4088,7 -4097,6 +4104,7 @@@ static int btrfs_real_readdir(struct fi
        struct btrfs_path *path;
        struct list_head ins_list;
        struct list_head del_list;
 +      struct qstr q;
        int ret;
        struct extent_buffer *leaf;
        int slot;
  
                while (di_cur < di_total) {
                        struct btrfs_key location;
 +                      struct dentry *tmp;
  
                        if (verify_dir_item(root, leaf, di))
                                break;
                        d_type = btrfs_filetype_table[btrfs_dir_type(leaf, di)];
                        btrfs_dir_item_key_to_cpu(leaf, di, &location);
  
 +                      q.name = name_ptr;
 +                      q.len = name_len;
 +                      q.hash = full_name_hash(q.name, q.len);
 +                      tmp = d_lookup(filp->f_dentry, &q);
 +                      if (!tmp) {
 +                              struct btrfs_key *newkey;
 +
 +                              newkey = kzalloc(sizeof(struct btrfs_key),
 +                                               GFP_NOFS);
 +                              if (!newkey)
 +                                      goto no_dentry;
 +                              tmp = d_alloc(filp->f_dentry, &q);
 +                              if (!tmp) {
 +                                      kfree(newkey);
 +                                      dput(tmp);
 +                                      goto no_dentry;
 +                              }
 +                              memcpy(newkey, &location,
 +                                     sizeof(struct btrfs_key));
 +                              tmp->d_fsdata = newkey;
 +                              tmp->d_flags |= DCACHE_NEED_LOOKUP;
 +                              d_rehash(tmp);
 +                              dput(tmp);
 +                      } else {
 +                              dput(tmp);
 +                      }
 +no_dentry:
                        /* is this a reference to our own snapshot? If so
                         * skip it
                         */
@@@ -4451,7 -4431,8 +4467,8 @@@ static struct inode *btrfs_new_inode(st
        int owner;
  
        path = btrfs_alloc_path();
-       BUG_ON(!path);
+       if (!path)
+               return ERR_PTR(-ENOMEM);
  
        inode = new_inode(root->fs_info->sb);
        if (!inode) {
        inode->i_generation = BTRFS_I(inode)->generation;
        btrfs_set_inode_space_info(root, inode);
  
 -      if (mode & S_IFDIR)
 +      if (S_ISDIR(mode))
                owner = 0;
        else
                owner = 1;
  
        btrfs_inherit_iflags(inode, dir);
  
 -      if ((mode & S_IFREG)) {
 +      if (S_ISREG(mode)) {
                if (btrfs_test_opt(root, NODATASUM))
                        BTRFS_I(inode)->flags |= BTRFS_INODE_NODATASUM;
                if (btrfs_test_opt(root, NODATACOW) ||
@@@ -4785,10 -4766,11 +4802,10 @@@ static int btrfs_link(struct dentry *ol
        if (err) {
                drop_inode = 1;
        } else {
 -              struct dentry *parent = dget_parent(dentry);
 +              struct dentry *parent = dentry->d_parent;
                err = btrfs_update_inode(trans, root, inode);
                BUG_ON(err);
                btrfs_log_new_name(trans, inode, NULL, parent);
 -              dput(parent);
        }
  
        nr = trans->blocks_used;
@@@ -6711,19 -6693,6 +6728,6 @@@ int btrfs_create_subvol_root(struct btr
        return 0;
  }
  
- /* helper function for file defrag and space balancing.  This
-  * forces readahead on a given range of bytes in an inode
-  */
- unsigned long btrfs_force_ra(struct address_space *mapping,
-                             struct file_ra_state *ra, struct file *file,
-                             pgoff_t offset, pgoff_t last_index)
- {
-       pgoff_t req_size = last_index - offset + 1;
-       page_cache_sync_readahead(mapping, ra, file, offset, req_size);
-       return offset + req_size;
- }
  struct inode *btrfs_alloc_inode(struct super_block *sb)
  {
        struct btrfs_inode *ei;
@@@ -6913,7 -6882,7 +6917,7 @@@ static int btrfs_getattr(struct vfsmoun
  {
        struct inode *inode = dentry->d_inode;
        generic_fillattr(inode, stat);
 -      stat->dev = BTRFS_I(inode)->root->anon_super.s_dev;
 +      stat->dev = BTRFS_I(inode)->root->anon_dev;
        stat->blksize = PAGE_CACHE_SIZE;
        stat->blocks = (inode_get_bytes(inode) +
                        BTRFS_I(inode)->delalloc_bytes) >> 9;
@@@ -7081,8 -7050,9 +7085,8 @@@ static int btrfs_rename(struct inode *o
        BUG_ON(ret);
  
        if (old_ino != BTRFS_FIRST_FREE_OBJECTID) {
 -              struct dentry *parent = dget_parent(new_dentry);
 +              struct dentry *parent = new_dentry->d_parent;
                btrfs_log_new_name(trans, old_inode, old_dir, parent);
 -              dput(parent);
                btrfs_end_log_trans(root);
        }
  out_fail:
@@@ -7206,7 -7176,11 +7210,11 @@@ static int btrfs_symlink(struct inode *
                goto out_unlock;
  
        path = btrfs_alloc_path();
-       BUG_ON(!path);
+       if (!path) {
+               err = -ENOMEM;
+               drop_inode = 1;
+               goto out_unlock;
+       }
        key.objectid = btrfs_ino(inode);
        key.offset = 0;
        btrfs_set_key_type(&key, BTRFS_EXTENT_DATA_KEY);
@@@ -7343,7 -7317,7 +7351,7 @@@ static int btrfs_set_page_dirty(struct 
        return __set_page_dirty_nobuffers(page);
  }
  
 -static int btrfs_permission(struct inode *inode, int mask, unsigned int flags)
 +static int btrfs_permission(struct inode *inode, int mask)
  {
        struct btrfs_root *root = BTRFS_I(inode)->root;
  
                return -EROFS;
        if ((BTRFS_I(inode)->flags & BTRFS_INODE_READONLY) && (mask & MAY_WRITE))
                return -EACCES;
 -      return generic_permission(inode, mask, flags, btrfs_check_acl);
 +      return generic_permission(inode, mask);
  }
  
  static const struct inode_operations btrfs_dir_inode_operations = {
        .listxattr      = btrfs_listxattr,
        .removexattr    = btrfs_removexattr,
        .permission     = btrfs_permission,
 +      .get_acl        = btrfs_get_acl,
  };
  static const struct inode_operations btrfs_dir_ro_inode_operations = {
        .lookup         = btrfs_lookup,
        .permission     = btrfs_permission,
 +      .get_acl        = btrfs_get_acl,
  };
  
  static const struct file_operations btrfs_dir_file_operations = {
@@@ -7445,7 -7417,6 +7453,7 @@@ static const struct inode_operations bt
        .removexattr    = btrfs_removexattr,
        .permission     = btrfs_permission,
        .fiemap         = btrfs_fiemap,
 +      .get_acl        = btrfs_get_acl,
  };
  static const struct inode_operations btrfs_special_inode_operations = {
        .getattr        = btrfs_getattr,
        .getxattr       = btrfs_getxattr,
        .listxattr      = btrfs_listxattr,
        .removexattr    = btrfs_removexattr,
 +      .get_acl        = btrfs_get_acl,
  };
  static const struct inode_operations btrfs_symlink_inode_operations = {
        .readlink       = generic_readlink,
        .getxattr       = btrfs_getxattr,
        .listxattr      = btrfs_listxattr,
        .removexattr    = btrfs_removexattr,
 +      .get_acl        = btrfs_get_acl,
  };
  
  const struct dentry_operations btrfs_dentry_operations = {
        .d_delete       = btrfs_dentry_delete,
 +      .d_release      = btrfs_dentry_release,
  };
diff --combined fs/btrfs/ioctl.c
@@@ -323,7 -323,7 +323,7 @@@ static noinline int create_subvol(struc
        struct btrfs_inode_item *inode_item;
        struct extent_buffer *leaf;
        struct btrfs_root *new_root;
 -      struct dentry *parent = dget_parent(dentry);
 +      struct dentry *parent = dentry->d_parent;
        struct inode *dir;
        int ret;
        int err;
        u64 index = 0;
  
        ret = btrfs_find_free_objectid(root->fs_info->tree_root, &objectid);
 -      if (ret) {
 -              dput(parent);
 +      if (ret)
                return ret;
 -      }
  
        dir = parent->d_inode;
  
         * 2 - dir items
         */
        trans = btrfs_start_transaction(root, 6);
 -      if (IS_ERR(trans)) {
 -              dput(parent);
 +      if (IS_ERR(trans))
                return PTR_ERR(trans);
 -      }
  
        leaf = btrfs_alloc_free_block(trans, root, root->leafsize,
                                      0, objectid, NULL, 0, 0, 0);
  
        d_instantiate(dentry, btrfs_lookup_dentry(dir, dentry));
  fail:
 -      dput(parent);
        if (async_transid) {
                *async_transid = trans->transid;
                err = btrfs_commit_transaction_async(trans, root, 1);
@@@ -451,6 -456,7 +451,6 @@@ static int create_snapshot(struct btrfs
                           bool readonly)
  {
        struct inode *inode;
 -      struct dentry *parent;
        struct btrfs_pending_snapshot *pending_snapshot;
        struct btrfs_trans_handle *trans;
        int ret;
        if (ret)
                goto fail;
  
 -      parent = dget_parent(dentry);
 -      inode = btrfs_lookup_dentry(parent->d_inode, dentry);
 -      dput(parent);
 +      inode = btrfs_lookup_dentry(dentry->d_parent->d_inode, dentry);
        if (IS_ERR(inode)) {
                ret = PTR_ERR(inode);
                goto fail;
@@@ -1749,11 -1757,10 +1749,10 @@@ static noinline int btrfs_search_path_i
                key.objectid = key.offset;
                key.offset = (u64)-1;
                dirid = key.objectid;
        }
        if (ptr < name)
                goto out;
-       memcpy(name, ptr, total_len);
+       memmove(name, ptr, total_len);
        name[total_len]='\0';
        ret = 0;
  out: