]> nv-tegra.nvidia Code Review - linux-2.6.git/commitdiff
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 2 Oct 2009 03:23:15 +0000 (20:23 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 2 Oct 2009 03:23:15 +0000 (20:23 -0700)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable:
  Btrfs: fix data space leak fix
  Btrfs: remove duplicates of filemap_ helpers
  Btrfs: take i_mutex before generic_write_checks
  Btrfs: fix arguments to btrfs_wait_on_page_writeback_range
  Btrfs: fix deadlock with free space handling and user transactions
  Btrfs: fix error cases for ioctl transactions
  Btrfs: Use CONFIG_BTRFS_POSIX_ACL to enable ACL code
  Btrfs: introduce missing kfree
  Btrfs: Fix setting umask when POSIX ACLs are not enabled
  Btrfs: proper -ENOSPC handling

1  2 
fs/btrfs/ctree.h
fs/btrfs/file.c
fs/btrfs/inode.c

diff --combined fs/btrfs/ctree.h
index 4484eb3408afb1729814f6d1a7aeb209caad11b1,8184f2feb2f3f5ae8815b070e824c0ebc9330eaa..dd8ced9814c4a5d0bc35e9bd8ef12cd8745382b9
@@@ -675,18 -675,19 +675,19 @@@ struct btrfs_space_info 
                                   current allocations */
        u64 bytes_readonly;     /* total bytes that are read only */
        u64 bytes_super;        /* total bytes reserved for the super blocks */
-       /* delalloc accounting */
-       u64 bytes_delalloc;     /* number of bytes reserved for allocation,
-                                  this space is not necessarily reserved yet
-                                  by the allocator */
+       u64 bytes_root;         /* the number of bytes needed to commit a
+                                  transaction */
        u64 bytes_may_use;      /* number of bytes that may be used for
-                                  delalloc */
+                                  delalloc/allocations */
+       u64 bytes_delalloc;     /* number of bytes currently reserved for
+                                  delayed allocation */
  
        int full;               /* indicates that we cannot allocate any more
                                   chunks for this space */
        int force_alloc;        /* set if we need to force a chunk alloc for
                                   this space */
+       int force_delalloc;     /* make people start doing filemap_flush until
+                                  we're under a threshold */
  
        struct list_head list;
  
        spinlock_t lock;
        struct rw_semaphore groups_sem;
        atomic_t caching_threads;
+       int allocating_chunk;
+       wait_queue_head_t wait;
  };
  
  /*
@@@ -2022,7 -2026,12 +2026,12 @@@ u64 btrfs_reduce_alloc_profile(struct b
  void btrfs_set_inode_space_info(struct btrfs_root *root, struct inode *ionde);
  void btrfs_clear_space_info_full(struct btrfs_fs_info *info);
  
- int btrfs_check_metadata_free_space(struct btrfs_root *root);
+ int btrfs_reserve_metadata_space(struct btrfs_root *root, int num_items);
+ int btrfs_unreserve_metadata_space(struct btrfs_root *root, int num_items);
+ int btrfs_unreserve_metadata_for_delalloc(struct btrfs_root *root,
+                                         struct inode *inode, int num_items);
+ int btrfs_reserve_metadata_for_delalloc(struct btrfs_root *root,
+                                       struct inode *inode, int num_items);
  int btrfs_check_data_free_space(struct btrfs_root *root, struct inode *inode,
                                u64 bytes);
  void btrfs_free_reserved_data_space(struct btrfs_root *root,
@@@ -2326,7 -2335,7 +2335,7 @@@ int btrfs_sync_file(struct file *file, 
  int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
                            int skip_pinned);
  int btrfs_check_file(struct btrfs_root *root, struct inode *inode);
 -extern struct file_operations btrfs_file_operations;
 +extern const struct file_operations btrfs_file_operations;
  int btrfs_drop_extents(struct btrfs_trans_handle *trans,
                       struct btrfs_root *root, struct inode *inode,
                       u64 start, u64 end, u64 locked_end,
@@@ -2357,7 -2366,7 +2366,7 @@@ int btrfs_parse_options(struct btrfs_ro
  int btrfs_sync_fs(struct super_block *sb, int wait);
  
  /* acl.c */
- #ifdef CONFIG_FS_POSIX_ACL
+ #ifdef CONFIG_BTRFS_POSIX_ACL
  int btrfs_check_acl(struct inode *inode, int mask);
  #else
  #define btrfs_check_acl NULL
diff --combined fs/btrfs/file.c
index 9ed17dbe5c6e468725dbc529139ed26264f7269b,ca784a7fbeba1151939fc66a5b9c259c1788c35c..f19e1259a971d52d62a9979ba311d3f136289e05
@@@ -123,7 -123,10 +123,10 @@@ static noinline int dirty_and_release_p
                    root->sectorsize - 1) & ~((u64)root->sectorsize - 1);
  
        end_of_last_block = start_pos + num_bytes - 1;
-       btrfs_set_extent_delalloc(inode, start_pos, end_of_last_block);
+       err = btrfs_set_extent_delalloc(inode, start_pos, end_of_last_block);
+       if (err)
+               return err;
        for (i = 0; i < num_pages; i++) {
                struct page *p = pages[i];
                SetPageUptodate(p);
@@@ -917,21 -920,35 +920,35 @@@ static ssize_t btrfs_file_write(struct 
        start_pos = pos;
  
        vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE);
+       /* do the reserve before the mutex lock in case we have to do some
+        * flushing.  We wouldn't deadlock, but this is more polite.
+        */
+       err = btrfs_reserve_metadata_for_delalloc(root, inode, 1);
+       if (err)
+               goto out_nolock;
+       mutex_lock(&inode->i_mutex);
        current->backing_dev_info = inode->i_mapping->backing_dev_info;
        err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode));
        if (err)
-               goto out_nolock;
+               goto out;
        if (count == 0)
-               goto out_nolock;
+               goto out;
  
        err = file_remove_suid(file);
        if (err)
-               goto out_nolock;
+               goto out;
        file_update_time(file);
  
        pages = kmalloc(nrptrs * sizeof(struct page *), GFP_KERNEL);
  
-       mutex_lock(&inode->i_mutex);
+       /* generic_write_checks can change our pos */
+       start_pos = pos;
        BTRFS_I(inode)->sequence++;
        first_index = pos >> PAGE_CACHE_SHIFT;
        last_index = (pos + count) >> PAGE_CACHE_SHIFT;
                }
  
                if (will_write) {
-                       btrfs_fdatawrite_range(inode->i_mapping, pos,
-                                              pos + write_bytes - 1,
-                                              WB_SYNC_ALL);
+                       filemap_fdatawrite_range(inode->i_mapping, pos,
+                                                pos + write_bytes - 1);
                } else {
                        balance_dirty_pages_ratelimited_nr(inode->i_mapping,
                                                           num_pages);
@@@ -1028,6 -1044,7 +1044,7 @@@ out
        mutex_unlock(&inode->i_mutex);
        if (ret)
                err = ret;
+       btrfs_unreserve_metadata_for_delalloc(root, inode, 1);
  
  out_nolock:
        kfree(pages);
@@@ -1196,7 -1213,7 +1213,7 @@@ static int btrfs_file_mmap(struct file  
        return 0;
  }
  
 -struct file_operations btrfs_file_operations = {
 +const struct file_operations btrfs_file_operations = {
        .llseek         = generic_file_llseek,
        .read           = do_sync_read,
        .aio_read       = generic_file_aio_read,
diff --combined fs/btrfs/inode.c
index b9fe06d751c030545943ff9e55b9c80887500836,f4001112df78ee490c526d8840483ecc45167139..112e5aa85892c35dbaf921ba16bba119d4c2c49e
@@@ -62,7 -62,7 +62,7 @@@ static const struct inode_operations bt
  static const struct inode_operations btrfs_file_inode_operations;
  static const struct address_space_operations btrfs_aops;
  static const struct address_space_operations btrfs_symlink_aops;
 -static struct file_operations btrfs_dir_file_operations;
 +static const struct file_operations btrfs_dir_file_operations;
  static struct extent_io_ops btrfs_extent_io_ops;
  
  static struct kmem_cache *btrfs_inode_cachep;
@@@ -1159,6 -1159,83 +1159,83 @@@ static int run_delalloc_range(struct in
        return ret;
  }
  
+ static int btrfs_split_extent_hook(struct inode *inode,
+                                   struct extent_state *orig, u64 split)
+ {
+       struct btrfs_root *root = BTRFS_I(inode)->root;
+       u64 size;
+       if (!(orig->state & EXTENT_DELALLOC))
+               return 0;
+       size = orig->end - orig->start + 1;
+       if (size > root->fs_info->max_extent) {
+               u64 num_extents;
+               u64 new_size;
+               new_size = orig->end - split + 1;
+               num_extents = div64_u64(size + root->fs_info->max_extent - 1,
+                                       root->fs_info->max_extent);
+               /*
+                * if we break a large extent up then leave delalloc_extents be,
+                * since we've already accounted for the large extent.
+                */
+               if (div64_u64(new_size + root->fs_info->max_extent - 1,
+                             root->fs_info->max_extent) < num_extents)
+                       return 0;
+       }
+       BTRFS_I(inode)->delalloc_extents++;
+       return 0;
+ }
+ /*
+  * extent_io.c merge_extent_hook, used to track merged delayed allocation
+  * extents so we can keep track of new extents that are just merged onto old
+  * 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)
+ {
+       struct btrfs_root *root = BTRFS_I(inode)->root;
+       u64 new_size, old_size;
+       u64 num_extents;
+       /* not delalloc, ignore it */
+       if (!(other->state & EXTENT_DELALLOC))
+               return 0;
+       old_size = other->end - other->start + 1;
+       if (new->start < other->start)
+               new_size = other->end - new->start + 1;
+       else
+               new_size = new->end - other->start + 1;
+       /* we're not bigger than the max, unreserve the space and go */
+       if (new_size <= root->fs_info->max_extent) {
+               BTRFS_I(inode)->delalloc_extents--;
+               return 0;
+       }
+       /*
+        * If we grew by another max_extent, just return, we want to keep that
+        * reserved amount.
+        */
+       num_extents = div64_u64(old_size + root->fs_info->max_extent - 1,
+                               root->fs_info->max_extent);
+       if (div64_u64(new_size + root->fs_info->max_extent - 1,
+                     root->fs_info->max_extent) > num_extents)
+               return 0;
+       BTRFS_I(inode)->delalloc_extents--;
+       return 0;
+ }
  /*
   * extent_io.c set_bit_hook, used to track delayed allocation
   * bytes in this file, and to maintain the list of inodes that
  static int btrfs_set_bit_hook(struct inode *inode, u64 start, u64 end,
                       unsigned long old, unsigned long bits)
  {
        /*
         * set_bit and clear bit hooks normally require _irqsave/restore
         * but in this case, we are only testeing for the DELALLOC
         */
        if (!(old & EXTENT_DELALLOC) && (bits & EXTENT_DELALLOC)) {
                struct btrfs_root *root = BTRFS_I(inode)->root;
+               BTRFS_I(inode)->delalloc_extents++;
                btrfs_delalloc_reserve_space(root, inode, end - start + 1);
                spin_lock(&root->fs_info->delalloc_lock);
                BTRFS_I(inode)->delalloc_bytes += end - start + 1;
  /*
   * extent_io.c clear_bit_hook, see set_bit_hook for why
   */
- static int btrfs_clear_bit_hook(struct inode *inode, u64 start, u64 end,
-                        unsigned long old, unsigned long bits)
+ static int btrfs_clear_bit_hook(struct inode *inode,
+                               struct extent_state *state, unsigned long bits)
  {
        /*
         * set_bit and clear bit hooks normally require _irqsave/restore
         * but in this case, we are only testeing for the DELALLOC
         * bit, which is only set or cleared with irqs on
         */
-       if ((old & EXTENT_DELALLOC) && (bits & EXTENT_DELALLOC)) {
+       if ((state->state & EXTENT_DELALLOC) && (bits & EXTENT_DELALLOC)) {
                struct btrfs_root *root = BTRFS_I(inode)->root;
  
+               BTRFS_I(inode)->delalloc_extents--;
+               btrfs_unreserve_metadata_for_delalloc(root, inode, 1);
                spin_lock(&root->fs_info->delalloc_lock);
-               if (end - start + 1 > root->fs_info->delalloc_bytes) {
+               if (state->end - state->start + 1 >
+                   root->fs_info->delalloc_bytes) {
                        printk(KERN_INFO "btrfs warning: delalloc account "
                               "%llu %llu\n",
-                              (unsigned long long)end - start + 1,
+                              (unsigned long long)
+                              state->end - state->start + 1,
                               (unsigned long long)
                               root->fs_info->delalloc_bytes);
                        btrfs_delalloc_free_space(root, inode, (u64)-1);
                        BTRFS_I(inode)->delalloc_bytes = 0;
                } else {
                        btrfs_delalloc_free_space(root, inode,
-                                                 end - start + 1);
-                       root->fs_info->delalloc_bytes -= end - start + 1;
-                       BTRFS_I(inode)->delalloc_bytes -= end - start + 1;
+                                                 state->end -
+                                                 state->start + 1);
+                       root->fs_info->delalloc_bytes -= state->end -
+                               state->start + 1;
+                       BTRFS_I(inode)->delalloc_bytes -= state->end -
+                               state->start + 1;
                }
                if (BTRFS_I(inode)->delalloc_bytes == 0 &&
                    !list_empty(&BTRFS_I(inode)->delalloc_inodes)) {
@@@ -2950,7 -3038,12 +3038,12 @@@ again
                goto again;
        }
  
-       btrfs_set_extent_delalloc(inode, page_start, page_end);
+       ret = btrfs_set_extent_delalloc(inode, page_start, page_end);
+       if (ret) {
+               unlock_extent(io_tree, page_start, page_end, GFP_NOFS);
+               goto out_unlock;
+       }
        ret = 0;
        if (offset != PAGE_CACHE_SIZE) {
                kaddr = kmap(page);
@@@ -2981,15 -3074,11 +3074,11 @@@ int btrfs_cont_expand(struct inode *ino
        u64 last_byte;
        u64 cur_offset;
        u64 hole_size;
-       int err;
+       int err = 0;
  
        if (size <= hole_start)
                return 0;
  
-       err = btrfs_check_metadata_free_space(root);
-       if (err)
-               return err;
        btrfs_truncate_page(inode->i_mapping, inode->i_size);
  
        while (1) {
                                                 cur_offset, &hint_byte, 1);
                        if (err)
                                break;
+                       err = btrfs_reserve_metadata_space(root, 1);
+                       if (err)
+                               break;
                        err = btrfs_insert_file_extent(trans, root,
                                        inode->i_ino, cur_offset, 0,
                                        0, hole_size, 0, hole_size,
                                        0, 0, 0);
                        btrfs_drop_extent_cache(inode, hole_start,
                                        last_byte - 1, 0);
+                       btrfs_unreserve_metadata_space(root, 1);
                }
                free_extent_map(em);
                cur_offset = last_byte;
@@@ -3990,11 -4085,18 +4085,18 @@@ static int btrfs_mknod(struct inode *di
        if (!new_valid_dev(rdev))
                return -EINVAL;
  
-       err = btrfs_check_metadata_free_space(root);
+       /*
+        * 2 for inode item and ref
+        * 2 for dir items
+        * 1 for xattr if selinux is on
+        */
+       err = btrfs_reserve_metadata_space(root, 5);
        if (err)
-               goto fail;
+               return err;
  
        trans = btrfs_start_transaction(root, 1);
+       if (!trans)
+               goto fail;
        btrfs_set_trans_block_group(trans, dir);
  
        err = btrfs_find_free_objectid(trans, root, dir->i_ino, &objectid);
@@@ -4032,6 -4134,7 +4134,7 @@@ out_unlock
        nr = trans->blocks_used;
        btrfs_end_transaction_throttle(trans, root);
  fail:
+       btrfs_unreserve_metadata_space(root, 5);
        if (drop_inode) {
                inode_dec_link_count(inode);
                iput(inode);
@@@ -4052,10 -4155,18 +4155,18 @@@ static int btrfs_create(struct inode *d
        u64 objectid;
        u64 index = 0;
  
-       err = btrfs_check_metadata_free_space(root);
+       /*
+        * 2 for inode item and ref
+        * 2 for dir items
+        * 1 for xattr if selinux is on
+        */
+       err = btrfs_reserve_metadata_space(root, 5);
        if (err)
-               goto fail;
+               return err;
        trans = btrfs_start_transaction(root, 1);
+       if (!trans)
+               goto fail;
        btrfs_set_trans_block_group(trans, dir);
  
        err = btrfs_find_free_objectid(trans, root, dir->i_ino, &objectid);
@@@ -4096,6 -4207,7 +4207,7 @@@ out_unlock
        nr = trans->blocks_used;
        btrfs_end_transaction_throttle(trans, root);
  fail:
+       btrfs_unreserve_metadata_space(root, 5);
        if (drop_inode) {
                inode_dec_link_count(inode);
                iput(inode);
@@@ -4118,10 -4230,16 +4230,16 @@@ static int btrfs_link(struct dentry *ol
        if (inode->i_nlink == 0)
                return -ENOENT;
  
-       btrfs_inc_nlink(inode);
-       err = btrfs_check_metadata_free_space(root);
+       /*
+        * 1 item for inode ref
+        * 2 items for dir items
+        */
+       err = btrfs_reserve_metadata_space(root, 3);
        if (err)
-               goto fail;
+               return err;
+       btrfs_inc_nlink(inode);
        err = btrfs_set_inode_index(dir, &index);
        if (err)
                goto fail;
        nr = trans->blocks_used;
        btrfs_end_transaction_throttle(trans, root);
  fail:
+       btrfs_unreserve_metadata_space(root, 3);
        if (drop_inode) {
                inode_dec_link_count(inode);
                iput(inode);
@@@ -4164,17 -4283,21 +4283,21 @@@ static int btrfs_mkdir(struct inode *di
        u64 index = 0;
        unsigned long nr = 1;
  
-       err = btrfs_check_metadata_free_space(root);
+       /*
+        * 2 items for inode and ref
+        * 2 items for dir items
+        * 1 for xattr if selinux is on
+        */
+       err = btrfs_reserve_metadata_space(root, 5);
        if (err)
-               goto out_unlock;
+               return err;
  
        trans = btrfs_start_transaction(root, 1);
-       btrfs_set_trans_block_group(trans, dir);
-       if (IS_ERR(trans)) {
-               err = PTR_ERR(trans);
+       if (!trans) {
+               err = -ENOMEM;
                goto out_unlock;
        }
+       btrfs_set_trans_block_group(trans, dir);
  
        err = btrfs_find_free_objectid(trans, root, dir->i_ino, &objectid);
        if (err) {
@@@ -4223,6 -4346,7 +4346,7 @@@ out_fail
        btrfs_end_transaction_throttle(trans, root);
  
  out_unlock:
+       btrfs_unreserve_metadata_space(root, 5);
        if (drop_on_err)
                iput(inode);
        btrfs_btree_balance_dirty(root, nr);
@@@ -4747,6 -4871,13 +4871,13 @@@ int btrfs_page_mkwrite(struct vm_area_s
                goto out;
        }
  
+       ret = btrfs_reserve_metadata_for_delalloc(root, inode, 1);
+       if (ret) {
+               btrfs_free_reserved_data_space(root, inode, PAGE_CACHE_SIZE);
+               ret = VM_FAULT_SIGBUS;
+               goto out;
+       }
        ret = VM_FAULT_NOPAGE; /* make the VM retry the fault */
  again:
        lock_page(page);
                goto again;
        }
  
-       btrfs_set_extent_delalloc(inode, page_start, page_end);
+       /*
+        * XXX - page_mkwrite gets called every time the page is dirtied, even
+        * if it was already dirty, so for space accounting reasons we need to
+        * clear any delalloc bits for the range we are fixing to save.  There
+        * is probably a better way to do this, but for now keep consistent with
+        * prepare_pages in the normal write path.
+        */
+       clear_extent_bits(&BTRFS_I(inode)->io_tree, page_start, page_end,
+                         EXTENT_DIRTY | EXTENT_DELALLOC, GFP_NOFS);
+       ret = btrfs_set_extent_delalloc(inode, page_start, page_end);
+       if (ret) {
+               unlock_extent(io_tree, page_start, page_end, GFP_NOFS);
+               ret = VM_FAULT_SIGBUS;
+               btrfs_free_reserved_data_space(root, inode, PAGE_CACHE_SIZE);
+               goto out_unlock;
+       }
        ret = 0;
  
        /* page is wholly or partially inside EOF */
        unlock_extent(io_tree, page_start, page_end, GFP_NOFS);
  
  out_unlock:
+       btrfs_unreserve_metadata_for_delalloc(root, inode, 1);
        if (!ret)
                return VM_FAULT_LOCKED;
        unlock_page(page);
@@@ -4917,6 -5065,8 +5065,8 @@@ struct inode *btrfs_alloc_inode(struct 
                return NULL;
        ei->last_trans = 0;
        ei->logged_trans = 0;
+       ei->delalloc_extents = 0;
+       ei->delalloc_reserved_extents = 0;
        btrfs_ordered_inode_tree_init(&ei->ordered_tree);
        INIT_LIST_HEAD(&ei->i_orphan);
        INIT_LIST_HEAD(&ei->ordered_operations);
@@@ -5070,7 -5220,12 +5220,12 @@@ static int btrfs_rename(struct inode *o
            new_inode->i_size > BTRFS_EMPTY_DIR_SIZE)
                return -ENOTEMPTY;
  
-       ret = btrfs_check_metadata_free_space(root);
+       /*
+        * 2 items for dir items
+        * 1 item for orphan entry
+        * 1 item for ref
+        */
+       ret = btrfs_reserve_metadata_space(root, 4);
        if (ret)
                return ret;
  
@@@ -5185,6 -5340,8 +5340,8 @@@ out_fail
  
        if (old_inode->i_ino == BTRFS_FIRST_FREE_OBJECTID)
                up_read(&root->fs_info->subvol_sem);
+       btrfs_unreserve_metadata_space(root, 4);
        return ret;
  }
  
@@@ -5256,11 -5413,18 +5413,18 @@@ static int btrfs_symlink(struct inode *
        if (name_len > BTRFS_MAX_INLINE_DATA_SIZE(root))
                return -ENAMETOOLONG;
  
-       err = btrfs_check_metadata_free_space(root);
+       /*
+        * 2 items for inode item and ref
+        * 2 items for dir items
+        * 1 item for xattr if selinux is on
+        */
+       err = btrfs_reserve_metadata_space(root, 5);
        if (err)
-               goto out_fail;
+               return err;
  
        trans = btrfs_start_transaction(root, 1);
+       if (!trans)
+               goto out_fail;
        btrfs_set_trans_block_group(trans, dir);
  
        err = btrfs_find_free_objectid(trans, root, dir->i_ino, &objectid);
@@@ -5341,6 -5505,7 +5505,7 @@@ out_unlock
        nr = trans->blocks_used;
        btrfs_end_transaction_throttle(trans, root);
  out_fail:
+       btrfs_unreserve_metadata_space(root, 5);
        if (drop_inode) {
                inode_dec_link_count(inode);
                iput(inode);
@@@ -5362,6 -5527,11 +5527,11 @@@ static int prealloc_file_range(struct b
  
        while (num_bytes > 0) {
                alloc_size = min(num_bytes, root->fs_info->max_extent);
+               ret = btrfs_reserve_metadata_space(root, 1);
+               if (ret)
+                       goto out;
                ret = btrfs_reserve_extent(trans, root, alloc_size,
                                           root->sectorsize, 0, alloc_hint,
                                           (u64)-1, &ins, 1);
                num_bytes -= ins.offset;
                cur_offset += ins.offset;
                alloc_hint = ins.objectid + ins.offset;
+               btrfs_unreserve_metadata_space(root, 1);
        }
  out:
        if (cur_offset > start) {
@@@ -5544,7 -5715,7 +5715,7 @@@ static const struct inode_operations bt
        .permission     = btrfs_permission,
  };
  
 -static struct file_operations btrfs_dir_file_operations = {
 +static const struct file_operations btrfs_dir_file_operations = {
        .llseek         = generic_file_llseek,
        .read           = generic_read_dir,
        .readdir        = btrfs_real_readdir,
@@@ -5566,6 -5737,8 +5737,8 @@@ static struct extent_io_ops btrfs_exten
        .readpage_io_failed_hook = btrfs_io_failed_hook,
        .set_bit_hook = btrfs_set_bit_hook,
        .clear_bit_hook = btrfs_clear_bit_hook,
+       .merge_extent_hook = btrfs_merge_extent_hook,
+       .split_extent_hook = btrfs_split_extent_hook,
  };
  
  /*