]> git.karo-electronics.de Git - mv-sheeva.git/commitdiff
Merge git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 13 Mar 2011 23:00:49 +0000 (16:00 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 13 Mar 2011 23:00:49 +0000 (16:00 -0700)
* git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable:
  Btrfs: break out of shrink_delalloc earlier
  btrfs: fix not enough reserved space
  btrfs: fix dip leak
  Btrfs: make sure not to return overlapping extents to fiemap
  Btrfs: deal with short returns from copy_from_user
  Btrfs: fix regressions in copy_from_user handling

1  2 
fs/btrfs/ctree.h
fs/btrfs/extent-tree.c
fs/btrfs/extent_io.c
fs/btrfs/file.c
fs/btrfs/inode.c

diff --combined fs/btrfs/ctree.h
index 6f820fa23df4f362e5d553d06db021d7e20e6065,8b4b9d158a0a4477ff4002083d1e10f6d708fcab..7f78cc78fdd0a3dcc77218be33be516b5f2ac038
@@@ -729,6 -729,15 +729,15 @@@ struct btrfs_space_info 
        u64 disk_total;         /* total bytes on disk, takes mirrors into
                                   account */
  
+       /*
+        * we bump reservation progress every time we decrement
+        * bytes_reserved.  This way people waiting for reservations
+        * know something good has happened and they can check
+        * for progress.  The number here isn't to be trusted, it
+        * just shows reclaim activity
+        */
+       unsigned long reservation_progress;
        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
@@@ -2586,7 -2595,7 +2595,7 @@@ do {                                                            
  
  /* acl.c */
  #ifdef CONFIG_BTRFS_FS_POSIX_ACL
 -int btrfs_check_acl(struct inode *inode, int mask);
 +int btrfs_check_acl(struct inode *inode, int mask, unsigned int flags);
  #else
  #define btrfs_check_acl NULL
  #endif
diff --combined fs/btrfs/extent-tree.c
index 588ff9849873c5dc6690ae5baebd2a1111de00ac,f1db57d4a016e3d060db66ccb25341cc64d8a453..7b3089b5c2df816522e2356d3064f0b2bdb40c4f
@@@ -1743,7 -1743,8 +1743,7 @@@ static int remove_extent_backref(struc
  static void btrfs_issue_discard(struct block_device *bdev,
                                u64 start, u64 len)
  {
 -      blkdev_issue_discard(bdev, start >> 9, len >> 9, GFP_KERNEL,
 -                      BLKDEV_IFL_WAIT | BLKDEV_IFL_BARRIER);
 +      blkdev_issue_discard(bdev, start >> 9, len >> 9, GFP_KERNEL, 0);
  }
  
  static int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr,
@@@ -3342,15 -3343,16 +3342,16 @@@ static int shrink_delalloc(struct btrfs
        u64 max_reclaim;
        u64 reclaimed = 0;
        long time_left;
-       int pause = 1;
        int nr_pages = (2 * 1024 * 1024) >> PAGE_CACHE_SHIFT;
        int loops = 0;
+       unsigned long progress;
  
        block_rsv = &root->fs_info->delalloc_block_rsv;
        space_info = block_rsv->space_info;
  
        smp_mb();
        reserved = space_info->bytes_reserved;
+       progress = space_info->reservation_progress;
  
        if (reserved == 0)
                return 0;
                writeback_inodes_sb_nr_if_idle(root->fs_info->sb, nr_pages);
  
                spin_lock(&space_info->lock);
-               if (reserved > space_info->bytes_reserved) {
-                       loops = 0;
+               if (reserved > space_info->bytes_reserved)
                        reclaimed += reserved - space_info->bytes_reserved;
-               } else {
-                       loops++;
-               }
                reserved = space_info->bytes_reserved;
                spin_unlock(&space_info->lock);
  
+               loops++;
                if (reserved == 0 || reclaimed >= max_reclaim)
                        break;
  
                if (trans && trans->transaction->blocked)
                        return -EAGAIN;
  
-               __set_current_state(TASK_INTERRUPTIBLE);
-               time_left = schedule_timeout(pause);
+               time_left = schedule_timeout_interruptible(1);
  
                /* We were interrupted, exit */
                if (time_left)
                        break;
  
-               pause <<= 1;
-               if (pause > HZ / 10)
-                       pause = HZ / 10;
+               /* we've kicked the IO a few times, if anything has been freed,
+                * exit.  There is no sense in looping here for a long time
+                * when we really need to commit the transaction, or there are
+                * just too many writers without enough free space
+                */
+               if (loops > 3) {
+                       smp_mb();
+                       if (progress != space_info->reservation_progress)
+                               break;
+               }
  
        }
        return reclaimed >= to_reclaim;
@@@ -3612,6 -3619,7 +3618,7 @@@ void block_rsv_release_bytes(struct btr
                if (num_bytes) {
                        spin_lock(&space_info->lock);
                        space_info->bytes_reserved -= num_bytes;
+                       space_info->reservation_progress++;
                        spin_unlock(&space_info->lock);
                }
        }
@@@ -3844,6 -3852,7 +3851,7 @@@ static void update_global_block_rsv(str
        if (block_rsv->reserved >= block_rsv->size) {
                num_bytes = block_rsv->reserved - block_rsv->size;
                sinfo->bytes_reserved -= num_bytes;
+               sinfo->reservation_progress++;
                block_rsv->reserved = block_rsv->size;
                block_rsv->full = 1;
        }
@@@ -4005,7 -4014,6 +4013,6 @@@ int btrfs_delalloc_reserve_metadata(str
                to_reserve = 0;
        }
        spin_unlock(&BTRFS_I(inode)->accounting_lock);
        to_reserve += calc_csum_metadata_size(inode, num_bytes);
        ret = reserve_metadata_bytes(NULL, root, block_rsv, to_reserve, 1);
        if (ret)
@@@ -4133,6 -4141,7 +4140,7 @@@ static int update_block_group(struct bt
                        btrfs_set_block_group_used(&cache->item, old_val);
                        cache->reserved -= num_bytes;
                        cache->space_info->bytes_reserved -= num_bytes;
+                       cache->space_info->reservation_progress++;
                        cache->space_info->bytes_used += num_bytes;
                        cache->space_info->disk_used += num_bytes * factor;
                        spin_unlock(&cache->lock);
@@@ -4184,6 -4193,7 +4192,7 @@@ static int pin_down_extent(struct btrfs
        if (reserved) {
                cache->reserved -= num_bytes;
                cache->space_info->bytes_reserved -= num_bytes;
+               cache->space_info->reservation_progress++;
        }
        spin_unlock(&cache->lock);
        spin_unlock(&cache->space_info->lock);
@@@ -4234,6 -4244,7 +4243,7 @@@ static int update_reserved_bytes(struc
                                space_info->bytes_readonly += num_bytes;
                        cache->reserved -= num_bytes;
                        space_info->bytes_reserved -= num_bytes;
+                       space_info->reservation_progress++;
                }
                spin_unlock(&cache->lock);
                spin_unlock(&space_info->lock);
@@@ -4712,6 -4723,7 +4722,7 @@@ void btrfs_free_tree_block(struct btrfs
                if (ret) {
                        spin_lock(&cache->space_info->lock);
                        cache->space_info->bytes_reserved -= buf->len;
+                       cache->space_info->reservation_progress++;
                        spin_unlock(&cache->space_info->lock);
                }
                goto out;
diff --combined fs/btrfs/extent_io.c
index fd3f172e94e69491d80c3b1be950b5f98a95c41b,9fcb5ede6b722f962a3099f77dde2f643e055ca4..714adc4ac4c24eaae26900bb9e862bc8b874432b
@@@ -3046,17 -3046,38 +3046,38 @@@ int extent_fiemap(struct inode *inode, 
        }
  
        while (!end) {
-               off = extent_map_end(em);
-               if (off >= max)
-                       end = 1;
+               u64 offset_in_extent;
+               /* break if the extent we found is outside the range */
+               if (em->start >= max || extent_map_end(em) < off)
+                       break;
+               /*
+                * get_extent may return an extent that starts before our
+                * requested range.  We have to make sure the ranges
+                * we return to fiemap always move forward and don't
+                * overlap, so adjust the offsets here
+                */
+               em_start = max(em->start, off);
  
-               em_start = em->start;
-               em_len = em->len;
+               /*
+                * record the offset from the start of the extent
+                * for adjusting the disk offset below
+                */
+               offset_in_extent = em_start - em->start;
                em_end = extent_map_end(em);
+               em_len = em_end - em_start;
                emflags = em->flags;
                disko = 0;
                flags = 0;
  
+               /*
+                * bump off for our next call to get_extent
+                */
+               off = extent_map_end(em);
+               if (off >= max)
+                       end = 1;
                if (em->block_start == EXTENT_MAP_LAST_BYTE) {
                        end = 1;
                        flags |= FIEMAP_EXTENT_LAST;
                        flags |= (FIEMAP_EXTENT_DELALLOC |
                                  FIEMAP_EXTENT_UNKNOWN);
                } else {
-                       disko = em->block_start;
+                       disko = em->block_start + offset_in_extent;
                }
                if (test_bit(EXTENT_FLAG_COMPRESSED, &em->flags))
                        flags |= FIEMAP_EXTENT_ENCODED;
@@@ -3152,6 -3173,7 +3173,6 @@@ static struct extent_buffer *__alloc_ex
        eb->len = len;
        spin_lock_init(&eb->lock);
        init_waitqueue_head(&eb->lock_wq);
 -      INIT_RCU_HEAD(&eb->rcu_head);
  
  #if LEAK_DEBUG
        spin_lock_irqsave(&leak_lock, flags);
diff --combined fs/btrfs/file.c
index 7084140d5940e68f653ad8919a0084549d6b8e1b,ab22ca4f237fcaad91aae7b54bbc675a4d639d30..f447b783bb84ce25af44cb2276b3d49684948166
@@@ -24,7 -24,6 +24,7 @@@
  #include <linux/string.h>
  #include <linux/backing-dev.h>
  #include <linux/mpage.h>
 +#include <linux/falloc.h>
  #include <linux/swap.h>
  #include <linux/writeback.h>
  #include <linux/statfs.h>
@@@ -70,6 -69,19 +70,19 @@@ static noinline int btrfs_copy_from_use
  
                /* Flush processor's dcache for this page */
                flush_dcache_page(page);
+               /*
+                * if we get a partial write, we can end up with
+                * partially up to date pages.  These add
+                * a lot of complexity, so make sure they don't
+                * happen by forcing this copy to be retried.
+                *
+                * The rest of the btrfs_file_write code will fall
+                * back to page at a time copies after we return 0.
+                */
+               if (!PageUptodate(page) && copied < count)
+                       copied = 0;
                iov_iter_advance(i, copied);
                write_bytes -= copied;
                total_copied += copied;
@@@ -762,6 -774,27 +775,27 @@@ out
        return 0;
  }
  
+ /*
+  * on error we return an unlocked page and the error value
+  * on success we return a locked page and 0
+  */
+ static int prepare_uptodate_page(struct page *page, u64 pos)
+ {
+       int ret = 0;
+       if ((pos & (PAGE_CACHE_SIZE - 1)) && !PageUptodate(page)) {
+               ret = btrfs_readpage(NULL, page);
+               if (ret)
+                       return ret;
+               lock_page(page);
+               if (!PageUptodate(page)) {
+                       unlock_page(page);
+                       return -EIO;
+               }
+       }
+       return 0;
+ }
  /*
   * this gets pages into the page cache and locks them down, it also properly
   * waits for data=ordered extents to finish before allowing the pages to be
@@@ -777,6 -810,7 +811,7 @@@ static noinline int prepare_pages(struc
        unsigned long index = pos >> PAGE_CACHE_SHIFT;
        struct inode *inode = fdentry(file)->d_inode;
        int err = 0;
+       int faili = 0;
        u64 start_pos;
        u64 last_pos;
  
@@@ -794,15 -828,24 +829,24 @@@ again
        for (i = 0; i < num_pages; i++) {
                pages[i] = grab_cache_page(inode->i_mapping, index + i);
                if (!pages[i]) {
-                       int c;
-                       for (c = i - 1; c >= 0; c--) {
-                               unlock_page(pages[c]);
-                               page_cache_release(pages[c]);
-                       }
-                       return -ENOMEM;
+                       faili = i - 1;
+                       err = -ENOMEM;
+                       goto fail;
+               }
+               if (i == 0)
+                       err = prepare_uptodate_page(pages[i], pos);
+               if (i == num_pages - 1)
+                       err = prepare_uptodate_page(pages[i],
+                                                   pos + write_bytes);
+               if (err) {
+                       page_cache_release(pages[i]);
+                       faili = i - 1;
+                       goto fail;
                }
                wait_on_page_writeback(pages[i]);
        }
+       err = 0;
        if (start_pos < inode->i_size) {
                struct btrfs_ordered_extent *ordered;
                lock_extent_bits(&BTRFS_I(inode)->io_tree,
                WARN_ON(!PageLocked(pages[i]));
        }
        return 0;
+ fail:
+       while (faili >= 0) {
+               unlock_page(pages[faili]);
+               page_cache_release(pages[faili]);
+               faili--;
+       }
+       return err;
  }
  
  static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
        struct file *file = iocb->ki_filp;
        struct inode *inode = fdentry(file)->d_inode;
        struct btrfs_root *root = BTRFS_I(inode)->root;
-       struct page *pinned[2];
        struct page **pages = NULL;
        struct iov_iter i;
        loff_t *ppos = &iocb->ki_pos;
        will_write = ((file->f_flags & O_DSYNC) || IS_SYNC(inode) ||
                      (file->f_flags & O_DIRECT));
  
-       pinned[0] = NULL;
-       pinned[1] = NULL;
        start_pos = pos;
  
        vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE);
        first_index = pos >> PAGE_CACHE_SHIFT;
        last_index = (pos + iov_iter_count(&i)) >> PAGE_CACHE_SHIFT;
  
-       /*
-        * there are lots of better ways to do this, but this code
-        * makes sure the first and last page in the file range are
-        * up to date and ready for cow
-        */
-       if ((pos & (PAGE_CACHE_SIZE - 1))) {
-               pinned[0] = grab_cache_page(inode->i_mapping, first_index);
-               if (!PageUptodate(pinned[0])) {
-                       ret = btrfs_readpage(NULL, pinned[0]);
-                       BUG_ON(ret);
-                       wait_on_page_locked(pinned[0]);
-               } else {
-                       unlock_page(pinned[0]);
-               }
-       }
-       if ((pos + iov_iter_count(&i)) & (PAGE_CACHE_SIZE - 1)) {
-               pinned[1] = grab_cache_page(inode->i_mapping, last_index);
-               if (!PageUptodate(pinned[1])) {
-                       ret = btrfs_readpage(NULL, pinned[1]);
-                       BUG_ON(ret);
-                       wait_on_page_locked(pinned[1]);
-               } else {
-                       unlock_page(pinned[1]);
-               }
-       }
        while (iov_iter_count(&i) > 0) {
                size_t offset = pos & (PAGE_CACHE_SIZE - 1);
                size_t write_bytes = min(iov_iter_count(&i),
  
                copied = btrfs_copy_from_user(pos, num_pages,
                                           write_bytes, pages, &i);
-               dirty_pages = (copied + offset + PAGE_CACHE_SIZE - 1) >>
-                               PAGE_CACHE_SHIFT;
+               /*
+                * if we have trouble faulting in the pages, fall
+                * back to one page at a time
+                */
+               if (copied < write_bytes)
+                       nrptrs = 1;
+               if (copied == 0)
+                       dirty_pages = 0;
+               else
+                       dirty_pages = (copied + offset +
+                                      PAGE_CACHE_SIZE - 1) >>
+                                      PAGE_CACHE_SHIFT;
  
                if (num_pages > dirty_pages) {
                        if (copied > 0)
@@@ -1069,10 -1102,6 +1103,6 @@@ out
                err = ret;
  
        kfree(pages);
-       if (pinned[0])
-               page_cache_release(pinned[0]);
-       if (pinned[1])
-               page_cache_release(pinned[1]);
        *ppos = pos;
  
        /*
@@@ -1260,117 -1289,6 +1290,117 @@@ static int btrfs_file_mmap(struct file      
        return 0;
  }
  
 +static long btrfs_fallocate(struct file *file, int mode,
 +                          loff_t offset, loff_t len)
 +{
 +      struct inode *inode = file->f_path.dentry->d_inode;
 +      struct extent_state *cached_state = NULL;
 +      u64 cur_offset;
 +      u64 last_byte;
 +      u64 alloc_start;
 +      u64 alloc_end;
 +      u64 alloc_hint = 0;
 +      u64 locked_end;
 +      u64 mask = BTRFS_I(inode)->root->sectorsize - 1;
 +      struct extent_map *em;
 +      int ret;
 +
 +      alloc_start = offset & ~mask;
 +      alloc_end =  (offset + len + mask) & ~mask;
 +
 +      /* We only support the FALLOC_FL_KEEP_SIZE mode */
 +      if (mode & ~FALLOC_FL_KEEP_SIZE)
 +              return -EOPNOTSUPP;
 +
 +      /*
 +       * wait for ordered IO before we have any locks.  We'll loop again
 +       * below with the locks held.
 +       */
 +      btrfs_wait_ordered_range(inode, alloc_start, alloc_end - alloc_start);
 +
 +      mutex_lock(&inode->i_mutex);
 +      ret = inode_newsize_ok(inode, alloc_end);
 +      if (ret)
 +              goto out;
 +
 +      if (alloc_start > inode->i_size) {
 +              ret = btrfs_cont_expand(inode, alloc_start);
 +              if (ret)
 +                      goto out;
 +      }
 +
 +      ret = btrfs_check_data_free_space(inode, alloc_end - alloc_start);
 +      if (ret)
 +              goto out;
 +
 +      locked_end = alloc_end - 1;
 +      while (1) {
 +              struct btrfs_ordered_extent *ordered;
 +
 +              /* the extent lock is ordered inside the running
 +               * transaction
 +               */
 +              lock_extent_bits(&BTRFS_I(inode)->io_tree, alloc_start,
 +                               locked_end, 0, &cached_state, GFP_NOFS);
 +              ordered = btrfs_lookup_first_ordered_extent(inode,
 +                                                          alloc_end - 1);
 +              if (ordered &&
 +                  ordered->file_offset + ordered->len > alloc_start &&
 +                  ordered->file_offset < alloc_end) {
 +                      btrfs_put_ordered_extent(ordered);
 +                      unlock_extent_cached(&BTRFS_I(inode)->io_tree,
 +                                           alloc_start, locked_end,
 +                                           &cached_state, GFP_NOFS);
 +                      /*
 +                       * we can't wait on the range with the transaction
 +                       * running or with the extent lock held
 +                       */
 +                      btrfs_wait_ordered_range(inode, alloc_start,
 +                                               alloc_end - alloc_start);
 +              } else {
 +                      if (ordered)
 +                              btrfs_put_ordered_extent(ordered);
 +                      break;
 +              }
 +      }
 +
 +      cur_offset = alloc_start;
 +      while (1) {
 +              em = btrfs_get_extent(inode, NULL, 0, cur_offset,
 +                                    alloc_end - cur_offset, 0);
 +              BUG_ON(IS_ERR(em) || !em);
 +              last_byte = min(extent_map_end(em), alloc_end);
 +              last_byte = (last_byte + mask) & ~mask;
 +              if (em->block_start == EXTENT_MAP_HOLE ||
 +                  (cur_offset >= inode->i_size &&
 +                   !test_bit(EXTENT_FLAG_PREALLOC, &em->flags))) {
 +                      ret = btrfs_prealloc_file_range(inode, mode, cur_offset,
 +                                                      last_byte - cur_offset,
 +                                                      1 << inode->i_blkbits,
 +                                                      offset + len,
 +                                                      &alloc_hint);
 +                      if (ret < 0) {
 +                              free_extent_map(em);
 +                              break;
 +                      }
 +              }
 +              free_extent_map(em);
 +
 +              cur_offset = last_byte;
 +              if (cur_offset >= alloc_end) {
 +                      ret = 0;
 +                      break;
 +              }
 +      }
 +      unlock_extent_cached(&BTRFS_I(inode)->io_tree, alloc_start, locked_end,
 +                           &cached_state, GFP_NOFS);
 +
 +      btrfs_free_reserved_data_space(inode, alloc_end - alloc_start);
 +out:
 +      mutex_unlock(&inode->i_mutex);
 +      return ret;
 +}
 +
  const struct file_operations btrfs_file_operations = {
        .llseek         = generic_file_llseek,
        .read           = do_sync_read,
        .open           = generic_file_open,
        .release        = btrfs_release_file,
        .fsync          = btrfs_sync_file,
 +      .fallocate      = btrfs_fallocate,
        .unlocked_ioctl = btrfs_ioctl,
  #ifdef CONFIG_COMPAT
        .compat_ioctl   = btrfs_ioctl,
diff --combined fs/btrfs/inode.c
index 0efdb65953c577cc27fb7d190dc4f66cd7a933a2,db67821ccac296cf23d1cbe57e581971292320df..9007bbd01dbf69fd53dbd8c9269afe35ee3f79f6
@@@ -3905,7 -3905,7 +3905,7 @@@ again
        p = &root->inode_tree.rb_node;
        parent = NULL;
  
 -      if (hlist_unhashed(&inode->i_hash))
 +      if (inode_unhashed(inode))
                return;
  
        spin_lock(&root->inode_lock);
@@@ -4112,6 -4112,8 +4112,6 @@@ struct inode *btrfs_lookup_dentry(struc
        int index;
        int ret;
  
 -      dentry->d_op = &btrfs_dentry_operations;
 -
        if (dentry->d_name.len > BTRFS_NAME_LEN)
                return ERR_PTR(-ENAMETOOLONG);
  
        return inode;
  }
  
 -static int btrfs_dentry_delete(struct dentry *dentry)
 +static int btrfs_dentry_delete(const struct dentry *dentry)
  {
        struct btrfs_root *root;
  
@@@ -4821,17 -4823,18 +4821,18 @@@ static int btrfs_link(struct dentry *ol
                goto fail;
  
        /*
-        * 1 item for inode ref
+        * 2 items for inode and inode ref
         * 2 items for dir items
+        * 1 item for parent inode
         */
-       trans = btrfs_start_transaction(root, 3);
+       trans = btrfs_start_transaction(root, 5);
        if (IS_ERR(trans)) {
                err = PTR_ERR(trans);
                goto fail;
        }
  
        btrfs_set_trans_block_group(trans, dir);
 -      atomic_inc(&inode->i_count);
 +      ihold(inode);
  
        err = btrfs_add_nondir(trans, dir, dentry, inode, 1, index);
  
@@@ -6056,6 -6059,7 +6057,7 @@@ static void btrfs_submit_direct(int rw
        if (!skip_sum) {
                dip->csums = kmalloc(sizeof(u32) * bio->bi_vcnt, GFP_NOFS);
                if (!dip->csums) {
+                       kfree(dip);
                        ret = -ENOMEM;
                        goto free_ordered;
                }
@@@ -6653,13 -6657,6 +6655,13 @@@ struct inode *btrfs_alloc_inode(struct 
        return inode;
  }
  
 +static void btrfs_i_callback(struct rcu_head *head)
 +{
 +      struct inode *inode = container_of(head, struct inode, i_rcu);
 +      INIT_LIST_HEAD(&inode->i_dentry);
 +      kmem_cache_free(btrfs_inode_cachep, BTRFS_I(inode));
 +}
 +
  void btrfs_destroy_inode(struct inode *inode)
  {
        struct btrfs_ordered_extent *ordered;
        inode_tree_del(inode);
        btrfs_drop_extent_cache(inode, 0, (u64)-1, 0);
  free:
 -      kmem_cache_free(btrfs_inode_cachep, BTRFS_I(inode));
 +      call_rcu(&inode->i_rcu, btrfs_i_callback);
  }
  
  int btrfs_drop_inode(struct inode *inode)
@@@ -7258,12 -7255,118 +7260,12 @@@ int btrfs_prealloc_file_range_trans(str
                                           min_size, actual_len, alloc_hint, trans);
  }
  
 -static long btrfs_fallocate(struct inode *inode, int mode,
 -                          loff_t offset, loff_t len)
 -{
 -      struct extent_state *cached_state = NULL;
 -      u64 cur_offset;
 -      u64 last_byte;
 -      u64 alloc_start;
 -      u64 alloc_end;
 -      u64 alloc_hint = 0;
 -      u64 locked_end;
 -      u64 mask = BTRFS_I(inode)->root->sectorsize - 1;
 -      struct extent_map *em;
 -      int ret;
 -
 -      alloc_start = offset & ~mask;
 -      alloc_end =  (offset + len + mask) & ~mask;
 -
 -      /*
 -       * wait for ordered IO before we have any locks.  We'll loop again
 -       * below with the locks held.
 -       */
 -      btrfs_wait_ordered_range(inode, alloc_start, alloc_end - alloc_start);
 -
 -      mutex_lock(&inode->i_mutex);
 -      ret = inode_newsize_ok(inode, alloc_end);
 -      if (ret)
 -              goto out;
 -
 -      if (alloc_start > inode->i_size) {
 -              ret = btrfs_cont_expand(inode, alloc_start);
 -              if (ret)
 -                      goto out;
 -      }
 -
 -      ret = btrfs_check_data_free_space(inode, alloc_end - alloc_start);
 -      if (ret)
 -              goto out;
 -
 -      locked_end = alloc_end - 1;
 -      while (1) {
 -              struct btrfs_ordered_extent *ordered;
 -
 -              /* the extent lock is ordered inside the running
 -               * transaction
 -               */
 -              lock_extent_bits(&BTRFS_I(inode)->io_tree, alloc_start,
 -                               locked_end, 0, &cached_state, GFP_NOFS);
 -              ordered = btrfs_lookup_first_ordered_extent(inode,
 -                                                          alloc_end - 1);
 -              if (ordered &&
 -                  ordered->file_offset + ordered->len > alloc_start &&
 -                  ordered->file_offset < alloc_end) {
 -                      btrfs_put_ordered_extent(ordered);
 -                      unlock_extent_cached(&BTRFS_I(inode)->io_tree,
 -                                           alloc_start, locked_end,
 -                                           &cached_state, GFP_NOFS);
 -                      /*
 -                       * we can't wait on the range with the transaction
 -                       * running or with the extent lock held
 -                       */
 -                      btrfs_wait_ordered_range(inode, alloc_start,
 -                                               alloc_end - alloc_start);
 -              } else {
 -                      if (ordered)
 -                              btrfs_put_ordered_extent(ordered);
 -                      break;
 -              }
 -      }
 -
 -      cur_offset = alloc_start;
 -      while (1) {
 -              em = btrfs_get_extent(inode, NULL, 0, cur_offset,
 -                                    alloc_end - cur_offset, 0);
 -              BUG_ON(IS_ERR(em) || !em);
 -              last_byte = min(extent_map_end(em), alloc_end);
 -              last_byte = (last_byte + mask) & ~mask;
 -              if (em->block_start == EXTENT_MAP_HOLE ||
 -                  (cur_offset >= inode->i_size &&
 -                   !test_bit(EXTENT_FLAG_PREALLOC, &em->flags))) {
 -                      ret = btrfs_prealloc_file_range(inode, mode, cur_offset,
 -                                                      last_byte - cur_offset,
 -                                                      1 << inode->i_blkbits,
 -                                                      offset + len,
 -                                                      &alloc_hint);
 -                      if (ret < 0) {
 -                              free_extent_map(em);
 -                              break;
 -                      }
 -              }
 -              free_extent_map(em);
 -
 -              cur_offset = last_byte;
 -              if (cur_offset >= alloc_end) {
 -                      ret = 0;
 -                      break;
 -              }
 -      }
 -      unlock_extent_cached(&BTRFS_I(inode)->io_tree, alloc_start, locked_end,
 -                           &cached_state, GFP_NOFS);
 -
 -      btrfs_free_reserved_data_space(inode, alloc_end - alloc_start);
 -out:
 -      mutex_unlock(&inode->i_mutex);
 -      return ret;
 -}
 -
  static int btrfs_set_page_dirty(struct page *page)
  {
        return __set_page_dirty_nobuffers(page);
  }
  
 -static int btrfs_permission(struct inode *inode, int mask)
 +static int btrfs_permission(struct inode *inode, int mask, unsigned int flags)
  {
        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, btrfs_check_acl);
 +      return generic_permission(inode, mask, flags, btrfs_check_acl);
  }
  
  static const struct inode_operations btrfs_dir_inode_operations = {
@@@ -7364,6 -7467,7 +7366,6 @@@ static const struct inode_operations bt
        .listxattr      = btrfs_listxattr,
        .removexattr    = btrfs_removexattr,
        .permission     = btrfs_permission,
 -      .fallocate      = btrfs_fallocate,
        .fiemap         = btrfs_fiemap,
  };
  static const struct inode_operations btrfs_special_inode_operations = {