Merge branch 'for-linus-4.7' of git://git.kernel.org/pub/scm/linux/kernel/git/mason...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 27 May 2016 23:37:36 +0000 (16:37 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 27 May 2016 23:37:36 +0000 (16:37 -0700)
Pull btrfs cleanups and fixes from Chris Mason:
 "We have another round of fixes and a few cleanups.

  I have a fix for short returns from btrfs_copy_from_user, which
  finally nails down a very hard to find regression we added in v4.6.

  Dave is pushing around gfp parameters, mostly to cleanup internal apis
  and make it a little more consistent.

  The rest are smaller fixes, and one speelling fixup patch"

* 'for-linus-4.7' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs: (22 commits)
  Btrfs: fix handling of faults from btrfs_copy_from_user
  btrfs: fix string and comment grammatical issues and typos
  btrfs: scrub: Set bbio to NULL before calling btrfs_map_block
  Btrfs: fix unexpected return value of fiemap
  Btrfs: free sys_array eb as soon as possible
  btrfs: sink gfp parameter to convert_extent_bit
  btrfs: make state preallocation more speculative in __set_extent_bit
  btrfs: untangle gotos a bit in convert_extent_bit
  btrfs: untangle gotos a bit in __clear_extent_bit
  btrfs: untangle gotos a bit in __set_extent_bit
  btrfs: sink gfp parameter to set_record_extent_bits
  btrfs: sink gfp parameter to set_extent_new
  btrfs: sink gfp parameter to set_extent_defrag
  btrfs: sink gfp parameter to set_extent_delalloc
  btrfs: sink gfp parameter to clear_extent_dirty
  btrfs: sink gfp parameter to clear_record_extent_bits
  btrfs: sink gfp parameter to clear_extent_bits
  btrfs: sink gfp parameter to set_extent_bits
  btrfs: make find_workspace warn if there are no workspaces
  btrfs: make find_workspace always succeed
  ...

1  2 
fs/btrfs/file.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/tree-log.c
fs/btrfs/volumes.c

diff --combined fs/btrfs/file.c
@@@ -1596,6 -1596,13 +1596,13 @@@ again
  
                copied = btrfs_copy_from_user(pos, write_bytes, pages, i);
  
+               num_sectors = BTRFS_BYTES_TO_BLKS(root->fs_info,
+                                               reserve_bytes);
+               dirty_sectors = round_up(copied + sector_offset,
+                                       root->sectorsize);
+               dirty_sectors = BTRFS_BYTES_TO_BLKS(root->fs_info,
+                                               dirty_sectors);
                /*
                 * if we have trouble faulting in the pages, fall
                 * back to one page at a time
  
                if (copied == 0) {
                        force_page_uptodate = true;
+                       dirty_sectors = 0;
                        dirty_pages = 0;
                } else {
                        force_page_uptodate = false;
                /*
                 * If we had a short copy we need to release the excess delaloc
                 * bytes we reserved.  We need to increment outstanding_extents
-                * because btrfs_delalloc_release_space will decrement it, but
+                * because btrfs_delalloc_release_space and
+                * btrfs_delalloc_release_metadata will decrement it, but
                 * we still have an outstanding extent for the chunk we actually
                 * managed to copy.
                 */
-               num_sectors = BTRFS_BYTES_TO_BLKS(root->fs_info,
-                                               reserve_bytes);
-               dirty_sectors = round_up(copied + sector_offset,
-                                       root->sectorsize);
-               dirty_sectors = BTRFS_BYTES_TO_BLKS(root->fs_info,
-                                               dirty_sectors);
                if (num_sectors > dirty_sectors) {
-                       release_bytes = (write_bytes - copied)
-                               & ~((u64)root->sectorsize - 1);
+                       /*
+                        * we round down because we don't want to count
+                        * any partial blocks actually sent through the
+                        * IO machines
+                        */
+                       release_bytes = round_down(release_bytes - copied,
+                                     root->sectorsize);
                        if (copied > 0) {
                                spin_lock(&BTRFS_I(inode)->lock);
                                BTRFS_I(inode)->outstanding_extents++;
        return num_written ? num_written : ret;
  }
  
 -static ssize_t __btrfs_direct_write(struct kiocb *iocb,
 -                                  struct iov_iter *from,
 -                                  loff_t pos)
 +static ssize_t __btrfs_direct_write(struct kiocb *iocb, struct iov_iter *from)
  {
        struct file *file = iocb->ki_filp;
        struct inode *inode = file_inode(file);
 +      loff_t pos = iocb->ki_pos;
        ssize_t written;
        ssize_t written_buffered;
        loff_t endbyte;
        int err;
  
 -      written = generic_file_direct_write(iocb, from, pos);
 +      written = generic_file_direct_write(iocb, from);
  
        if (written < 0 || !iov_iter_count(from))
                return written;
@@@ -1833,7 -1841,7 +1840,7 @@@ static ssize_t btrfs_file_write_iter(st
                atomic_inc(&BTRFS_I(inode)->sync_writers);
  
        if (iocb->ki_flags & IOCB_DIRECT) {
 -              num_written = __btrfs_direct_write(iocb, from, pos);
 +              num_written = __btrfs_direct_write(iocb, from);
        } else {
                num_written = __btrfs_buffered_write(file, from, pos);
                if (num_written > 0)
        spin_lock(&BTRFS_I(inode)->lock);
        BTRFS_I(inode)->last_sub_trans = root->log_transid;
        spin_unlock(&BTRFS_I(inode)->lock);
 -      if (num_written > 0) {
 -              err = generic_write_sync(file, pos, num_written);
 -              if (err < 0)
 -                      num_written = err;
 -      }
 +      if (num_written > 0)
 +              num_written = generic_write_sync(iocb, num_written);
  
        if (sync)
                atomic_dec(&BTRFS_I(inode)->sync_writers);
@@@ -2022,7 -2033,7 +2029,7 @@@ int btrfs_sync_file(struct file *file, 
             BTRFS_I(inode)->last_trans
             <= root->fs_info->last_trans_committed)) {
                /*
-                * We'v had everything committed since the last time we were
+                * We've had everything committed since the last time we were
                 * modified so clear this flag in case it was set for whatever
                 * reason, it's no longer relevant.
                 */
@@@ -2370,7 -2381,7 +2377,7 @@@ static int btrfs_punch_hole(struct inod
  
        /* Check the aligned pages after the first unaligned page,
         * if offset != orig_start, which means the first unaligned page
-        * including serveral following pages are already in holes,
+        * including several following pages are already in holes,
         * the extra check can be skipped */
        if (offset == orig_start) {
                /* after truncate page, check hole again */
diff --combined fs/btrfs/inode.c
@@@ -455,7 -455,7 +455,7 @@@ again
  
        /*
         * skip compression for a small file range(<=blocksize) that
-        * isn't an inline extent, since it dosen't save disk space at all.
+        * isn't an inline extent, since it doesn't save disk space at all.
         */
        if (total_compressed <= blocksize &&
           (start > 0 || end + 1 < BTRFS_I(inode)->disk_i_size))
@@@ -1978,7 -1978,7 +1978,7 @@@ int btrfs_set_extent_delalloc(struct in
  {
        WARN_ON((end & (PAGE_SIZE - 1)) == 0);
        return set_extent_delalloc(&BTRFS_I(inode)->io_tree, start, end,
-                                  cached_state, GFP_NOFS);
+                                  cached_state);
  }
  
  /* see btrfs_writepage_start_hook for details on why this is required */
@@@ -3119,8 -3119,7 +3119,7 @@@ static int btrfs_readpage_end_io_hook(s
  
        if (root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID &&
            test_range_bit(io_tree, start, end, EXTENT_NODATASUM, 1, NULL)) {
-               clear_extent_bits(io_tree, start, end, EXTENT_NODATASUM,
-                                 GFP_NOFS);
+               clear_extent_bits(io_tree, start, end, EXTENT_NODATASUM);
                return 0;
        }
  
@@@ -3722,7 -3721,7 +3721,7 @@@ cache_index
         * and doesn't have an inode ref with the name "bar" anymore.
         *
         * Setting last_unlink_trans to last_trans is a pessimistic approach,
-        * but it guarantees correctness at the expense of ocassional full
+        * but it guarantees correctness at the expense of occasional full
         * transaction commits on fsync if our inode is a directory, or if our
         * inode is not a directory, logging its parent unnecessarily.
         */
@@@ -4978,7 -4977,7 +4977,7 @@@ static int btrfs_setsize(struct inode *
                 * be instantly completed which will give us extents that need
                 * to be truncated.  If we fail to get an orphan inode down we
                 * could have left over extents that were never meant to live,
-                * so we need to garuntee from this point on that everything
+                * so we need to guarantee from this point on that everything
                 * will be consistent.
                 */
                ret = btrfs_orphan_add(trans, inode);
@@@ -5248,7 -5247,7 +5247,7 @@@ void btrfs_evict_inode(struct inode *in
                }
  
                /*
-                * We can't just steal from the global reserve, we need tomake
+                * We can't just steal from the global reserve, we need to make
                 * sure there is room to do it, if not we need to commit and try
                 * again.
                 */
@@@ -7433,7 -7432,7 +7432,7 @@@ static int lock_extent_direct(struct in
                                 cached_state);
                /*
                 * We're concerned with the entire range that we're going to be
-                * doing DIO to, so we need to make sure theres no ordered
+                * doing DIO to, so we need to make sure there's no ordered
                 * extents in this range.
                 */
                ordered = btrfs_lookup_ordered_range(inode, lockstart,
@@@ -7595,7 -7594,7 +7594,7 @@@ static int btrfs_get_blocks_direct(stru
        if (current->journal_info) {
                /*
                 * Need to pull our outstanding extents and set journal_info to NULL so
-                * that anything that needs to check if there's a transction doesn't get
+                * that anything that needs to check if there's a transaction doesn't get
                 * confused.
                 */
                dio_data = current->journal_info;
         * decompress it, so there will be buffering required no matter what we
         * do, so go ahead and fallback to buffered.
         *
-        * We return -ENOTBLK because thats what makes DIO go ahead and go back
+        * We return -ENOTBLK because that's what makes DIO go ahead and go back
         * to buffered IO.  Don't blame me, this is the price we pay for using
         * the generic code.
         */
        return retval;
  }
  
 -static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
 -                             loff_t offset)
 +static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
  {
        struct file *file = iocb->ki_filp;
        struct inode *inode = file->f_mapping->host;
        struct btrfs_root *root = BTRFS_I(inode)->root;
        struct btrfs_dio_data dio_data = { 0 };
 +      loff_t offset = iocb->ki_pos;
        size_t count = 0;
        int flags = 0;
        bool wakeup = true;
  
        ret = __blockdev_direct_IO(iocb, inode,
                                   BTRFS_I(inode)->root->fs_info->fs_devices->latest_bdev,
 -                                 iter, offset, btrfs_get_blocks_direct, NULL,
 +                                 iter, btrfs_get_blocks_direct, NULL,
                                   btrfs_submit_direct, flags);
        if (iov_iter_rw(iter) == WRITE) {
                current->journal_info = NULL;
@@@ -9041,7 -9040,7 +9040,7 @@@ static int btrfs_truncate(struct inode 
                return ret;
  
        /*
-        * Yes ladies and gentelment, this is indeed ugly.  The fact is we have
+        * Yes ladies and gentlemen, this is indeed ugly.  The fact is we have
         * 3 things going on here
         *
         * 1) We need to reserve space for our orphan item and the space to
         * space reserved in case it uses space during the truncate (thank you
         * very much snapshotting).
         *
-        * And we need these to all be seperate.  The fact is we can use alot of
+        * And we need these to all be separate.  The fact is we can use a lot of
         * space doing the truncate, and we have no earthly idea how much space
-        * we will use, so we need the truncate reservation to be seperate so it
+        * we will use, so we need the truncate reservation to be separate so it
         * doesn't end up using space reserved for updating the inode or
         * removing the orphan item.  We also need to be able to stop the
         * transaction and start a new one, which means we need to be able to
         * update the inode several times, and we have no idea of knowing how
         * many times that will be, so we can't just reserve 1 item for the
-        * entirety of the opration, so that has to be done seperately as well.
+        * entirety of the operation, so that has to be done separately as well.
         * Then there is the orphan item, which does indeed need to be held on
         * to for the whole operation, and we need nobody to touch this reserved
         * space except the orphan code.
@@@ -10494,10 -10493,10 +10493,10 @@@ static const struct inode_operations bt
        .symlink        = btrfs_symlink,
        .setattr        = btrfs_setattr,
        .mknod          = btrfs_mknod,
 -      .setxattr       = btrfs_setxattr,
 +      .setxattr       = generic_setxattr,
        .getxattr       = generic_getxattr,
        .listxattr      = btrfs_listxattr,
 -      .removexattr    = btrfs_removexattr,
 +      .removexattr    = generic_removexattr,
        .permission     = btrfs_permission,
        .get_acl        = btrfs_get_acl,
        .set_acl        = btrfs_set_acl,
@@@ -10571,10 -10570,10 +10570,10 @@@ static const struct address_space_opera
  static const struct inode_operations btrfs_file_inode_operations = {
        .getattr        = btrfs_getattr,
        .setattr        = btrfs_setattr,
 -      .setxattr       = btrfs_setxattr,
 +      .setxattr       = generic_setxattr,
        .getxattr       = generic_getxattr,
        .listxattr      = btrfs_listxattr,
 -      .removexattr    = btrfs_removexattr,
 +      .removexattr    = generic_removexattr,
        .permission     = btrfs_permission,
        .fiemap         = btrfs_fiemap,
        .get_acl        = btrfs_get_acl,
@@@ -10585,10 -10584,10 +10584,10 @@@ static const struct inode_operations bt
        .getattr        = btrfs_getattr,
        .setattr        = btrfs_setattr,
        .permission     = btrfs_permission,
 -      .setxattr       = btrfs_setxattr,
 +      .setxattr       = generic_setxattr,
        .getxattr       = generic_getxattr,
        .listxattr      = btrfs_listxattr,
 -      .removexattr    = btrfs_removexattr,
 +      .removexattr    = generic_removexattr,
        .get_acl        = btrfs_get_acl,
        .set_acl        = btrfs_set_acl,
        .update_time    = btrfs_update_time,
@@@ -10599,10 -10598,10 +10598,10 @@@ static const struct inode_operations bt
        .getattr        = btrfs_getattr,
        .setattr        = btrfs_setattr,
        .permission     = btrfs_permission,
 -      .setxattr       = btrfs_setxattr,
 +      .setxattr       = generic_setxattr,
        .getxattr       = generic_getxattr,
        .listxattr      = btrfs_listxattr,
 -      .removexattr    = btrfs_removexattr,
 +      .removexattr    = generic_removexattr,
        .update_time    = btrfs_update_time,
  };
  
diff --combined fs/btrfs/ioctl.c
@@@ -296,7 -296,7 +296,7 @@@ static int btrfs_ioctl_setflags(struct 
                }
        } else {
                /*
-                * Revert back under same assuptions as above
+                * Revert back under same assumptions as above
                 */
                if (S_ISREG(mode)) {
                        if (inode->i_size == 0)
@@@ -465,7 -465,7 +465,7 @@@ static noinline int create_subvol(struc
  
        /*
         * Don't create subvolume whose level is not zero. Or qgroup will be
-        * screwed up since it assume subvolme qgroup's level to be 0.
+        * screwed up since it assumes subvolume qgroup's level to be 0.
         */
        if (btrfs_qgroup_level(objectid)) {
                ret = -ENOSPC;
@@@ -780,7 -780,7 +780,7 @@@ free_pending
   *    a. be owner of dir, or
   *    b. be owner of victim, or
   *    c. have CAP_FOWNER capability
-  *  6. If the victim is append-only or immutable we can't do antyhing with
+  *  6. If the victim is append-only or immutable we can't do anything with
   *     links pointing to it.
   *  7. If we were asked to remove a directory and victim isn't one - ENOTDIR.
   *  8. If we were asked to remove a non-directory and victim isn't one - EISDIR.
@@@ -846,11 -846,9 +846,11 @@@ static noinline int btrfs_mksubvol(stru
        struct dentry *dentry;
        int error;
  
 -      error = mutex_lock_killable_nested(&dir->i_mutex, I_MUTEX_PARENT);
 -      if (error == -EINTR)
 -              return error;
 +      inode_lock_nested(dir, I_MUTEX_PARENT);
 +      // XXX: should've been
 +      // mutex_lock_killable_nested(&dir->i_mutex, I_MUTEX_PARENT);
 +      // if (error == -EINTR)
 +      //      return error;
  
        dentry = lookup_one_len(name, parent->dentry, namelen);
        error = PTR_ERR(dentry);
@@@ -1239,7 -1237,7 +1239,7 @@@ again
  
  
        set_extent_defrag(&BTRFS_I(inode)->io_tree, page_start, page_end - 1,
-                         &cached_state, GFP_NOFS);
+                         &cached_state);
  
        unlock_extent_cached(&BTRFS_I(inode)->io_tree,
                             page_start, page_end - 1, &cached_state,
@@@ -2377,11 -2375,9 +2377,11 @@@ static noinline int btrfs_ioctl_snap_de
                goto out;
  
  
 -      err = mutex_lock_killable_nested(&dir->i_mutex, I_MUTEX_PARENT);
 -      if (err == -EINTR)
 -              goto out_drop_write;
 +      inode_lock_nested(dir, I_MUTEX_PARENT);
 +      // XXX: should've been
 +      // err = mutex_lock_killable_nested(&dir->i_mutex, I_MUTEX_PARENT);
 +      // if (err == -EINTR)
 +      //      goto out_drop_write;
        dentry = lookup_one_len(vol_args->name, parent, namelen);
        if (IS_ERR(dentry)) {
                err = PTR_ERR(dentry);
@@@ -2571,7 -2567,7 +2571,7 @@@ out_dput
        dput(dentry);
  out_unlock_dir:
        inode_unlock(dir);
 -out_drop_write:
 +//out_drop_write:
        mnt_drop_write_file(file);
  out:
        kfree(vol_args);
@@@ -4654,7 -4650,7 +4654,7 @@@ again
        }
  
        /*
-        * mut. excl. ops lock is locked.  Three possibilites:
+        * mut. excl. ops lock is locked.  Three possibilities:
         *   (1) some other op is running
         *   (2) balance is running
         *   (3) balance is paused -- special case (think resume)
@@@ -5571,7 -5567,7 +5571,7 @@@ long btrfs_ioctl(struct file *file, uns
                ret = btrfs_sync_fs(file_inode(file)->i_sb, 1);
                /*
                 * The transaction thread may want to do more work,
-                * namely it pokes the cleaner ktread that will start
+                * namely it pokes the cleaner kthread that will start
                 * processing uncleaned subvols.
                 */
                wake_up_process(root->fs_info->transaction_kthread);
diff --combined fs/btrfs/tree-log.c
@@@ -2330,7 -2330,7 +2330,7 @@@ static int replay_one_buffer(struct btr
                                break;
  
                        /* for regular files, make sure corresponding
-                        * orhpan item exist. extents past the new EOF
+                        * orphan item exist. extents past the new EOF
                         * will be truncated later by orphan cleanup.
                         */
                        if (S_ISREG(mode)) {
@@@ -3001,7 -3001,7 +3001,7 @@@ static void free_log_tree(struct btrfs_
                        break;
  
                clear_extent_bits(&log->dirty_log_pages, start, end,
-                                 EXTENT_DIRTY | EXTENT_NEW, GFP_NOFS);
+                                 EXTENT_DIRTY | EXTENT_NEW);
        }
  
        /*
@@@ -4914,7 -4914,7 +4914,7 @@@ out_unlock
   * the actual unlink operation, so if we do this check before a concurrent task
   * sets last_unlink_trans it means we've logged a consistent version/state of
   * all the inode items, otherwise we are not sure and must do a transaction
-  * commit (the concurrent task migth have only updated last_unlink_trans before
+  * commit (the concurrent task might have only updated last_unlink_trans before
   * we logged the inode or it might have also done the unlink).
   */
  static bool btrfs_must_commit_transaction(struct btrfs_trans_handle *trans,
@@@ -4965,7 -4965,7 +4965,7 @@@ static noinline int check_parent_dirs_f
                        goto out;
  
        if (!S_ISDIR(inode->i_mode)) {
 -              if (!parent || d_really_is_negative(parent) || sb != d_inode(parent)->i_sb)
 +              if (!parent || d_really_is_negative(parent) || sb != parent->d_sb)
                        goto out;
                inode = d_inode(parent);
        }
        while (1) {
                /*
                 * If we are logging a directory then we start with our inode,
-                * not our parents inode, so we need to skipp setting the
+                * not our parent's inode, so we need to skip setting the
                 * logged_trans so that further down in the log code we don't
                 * think this inode has already been logged.
                 */
                        break;
                }
  
 -              if (!parent || d_really_is_negative(parent) || sb != d_inode(parent)->i_sb)
 +              if (!parent || d_really_is_negative(parent) || sb != parent->d_sb)
                        break;
  
                if (IS_ROOT(parent))
@@@ -5357,7 -5357,7 +5357,7 @@@ static int btrfs_log_inode_parent(struc
                log_dentries = true;
  
        /*
-        * On unlink we must make sure all our current and old parent directores
+        * On unlink we must make sure all our current and old parent directory
         * inodes are fully logged. This is to prevent leaving dangling
         * directory index entries in directories that were our parents but are
         * not anymore. Not doing this results in old parent directory being
        }
  
        while (1) {
 -              if (!parent || d_really_is_negative(parent) || sb != d_inode(parent)->i_sb)
 +              if (!parent || d_really_is_negative(parent) || sb != parent->d_sb)
                        break;
  
                inode = d_inode(parent);
diff --combined fs/btrfs/volumes.c
  #include <linux/slab.h>
  #include <linux/buffer_head.h>
  #include <linux/blkdev.h>
 -#include <linux/random.h>
  #include <linux/iocontext.h>
  #include <linux/capability.h>
  #include <linux/ratelimit.h>
  #include <linux/kthread.h>
  #include <linux/raid/pq.h>
  #include <linux/semaphore.h>
 +#include <linux/uuid.h>
  #include <asm/div64.h>
  #include "ctree.h"
  #include "extent_map.h"
@@@ -2190,7 -2190,7 +2190,7 @@@ static int btrfs_prepare_sprout(struct 
  }
  
  /*
-  * strore the expected generation for seed devices in device items.
+  * Store the expected generation for seed devices in device items.
   */
  static int btrfs_finish_sprout(struct btrfs_trans_handle *trans,
                               struct btrfs_root *root)
@@@ -3387,7 -3387,7 +3387,7 @@@ static int should_balance_chunk(struct 
        } else if ((bargs->flags & BTRFS_BALANCE_ARGS_LIMIT_RANGE)) {
                /*
                 * Same logic as the 'limit' filter; the minimum cannot be
-                * determined here because we do not have the global informatoin
+                * determined here because we do not have the global information
                 * about the count of all chunks that satisfy the filters.
                 */
                if (bargs->limit_max == 0)
@@@ -6076,7 -6076,7 +6076,7 @@@ static void bbio_error(struct btrfs_bi
  {
        atomic_inc(&bbio->error);
        if (atomic_dec_and_test(&bbio->stripes_pending)) {
-               /* Shoud be the original bio. */
+               /* Should be the original bio. */
                WARN_ON(bio != bbio->orig_bio);
  
                btrfs_io_bio(bio)->mirror_num = bbio->mirror_num;
@@@ -6560,7 -6560,7 +6560,7 @@@ int btrfs_read_sys_array(struct btrfs_r
        set_extent_buffer_uptodate(sb);
        btrfs_set_buffer_lockdep_class(root->root_key.objectid, sb, 0);
        /*
-        * The sb extent buffer is artifical and just used to read the system array.
+        * The sb extent buffer is artificial and just used to read the system array.
         * set_extent_buffer_uptodate() call does not properly mark all it's
         * pages up-to-date when the page is larger: extent does not cover the
         * whole page and consequently check_page_uptodate does not find all
                sb_array_offset += len;
                cur_offset += len;
        }
-       free_extent_buffer(sb);
+       free_extent_buffer_stale(sb);
        return ret;
  
  out_short_read:
        printk(KERN_ERR "BTRFS: sys_array too short to read %u bytes at offset %u\n",
                        len, cur_offset);
-       free_extent_buffer(sb);
+       free_extent_buffer_stale(sb);
        return -EIO;
  }