btrfs: improve error handling of btrfs_add_link
[sfrench/cifs-2.6.git] / fs / btrfs / inode.c
index e1451a69432b3ae1d855d6dd1e42cfadc540ee50..3d29505971fe23059b1cbb8adc814d2638a463d9 100644 (file)
@@ -240,7 +240,7 @@ static int insert_inline_extent(struct btrfs_trans_handle *trans,
                                     start >> PAGE_SHIFT);
                btrfs_set_file_extent_compression(leaf, ei, 0);
                kaddr = kmap_atomic(page);
-               offset = start & (PAGE_SIZE - 1);
+               offset = offset_in_page(start);
                write_extent_buffer(leaf, kaddr + offset, ptr, size);
                kunmap_atomic(kaddr);
                put_page(page);
@@ -549,8 +549,7 @@ again:
                                           &total_compressed);
 
                if (!ret) {
-                       unsigned long offset = total_compressed &
-                               (PAGE_SIZE - 1);
+                       unsigned long offset = offset_in_page(total_compressed);
                        struct page *page = pages[nr_pages - 1];
                        char *kaddr;
 
@@ -2040,7 +2039,7 @@ int btrfs_set_extent_delalloc(struct inode *inode, u64 start, u64 end,
                              unsigned int extra_bits,
                              struct extent_state **cached_state, int dedupe)
 {
-       WARN_ON((end & (PAGE_SIZE - 1)) == 0);
+       WARN_ON(PAGE_ALIGNED(end));
        return set_extent_delalloc(&BTRFS_I(inode)->io_tree, start, end,
                                   extra_bits, cached_state);
 }
@@ -4443,31 +4442,6 @@ out:
        return err;
 }
 
-static int truncate_space_check(struct btrfs_trans_handle *trans,
-                               struct btrfs_root *root,
-                               u64 bytes_deleted)
-{
-       struct btrfs_fs_info *fs_info = root->fs_info;
-       int ret;
-
-       /*
-        * This is only used to apply pressure to the enospc system, we don't
-        * intend to use this reservation at all.
-        */
-       bytes_deleted = btrfs_csum_bytes_to_leaves(fs_info, bytes_deleted);
-       bytes_deleted *= fs_info->nodesize;
-       ret = btrfs_block_rsv_add(root, &fs_info->trans_block_rsv,
-                                 bytes_deleted, BTRFS_RESERVE_NO_FLUSH);
-       if (!ret) {
-               trace_btrfs_space_reservation(fs_info, "transaction",
-                                             trans->transid,
-                                             bytes_deleted, 1);
-               trans->bytes_reserved += bytes_deleted;
-       }
-       return ret;
-
-}
-
 /*
  * Return this if we need to call truncate_block for the last bit of the
  * truncate.
@@ -4512,7 +4486,6 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
        u64 bytes_deleted = 0;
        bool be_nice = false;
        bool should_throttle = false;
-       bool should_end = false;
 
        BUG_ON(new_size > 0 && min_type != BTRFS_EXTENT_DATA_KEY);
 
@@ -4725,15 +4698,7 @@ delete:
                                btrfs_abort_transaction(trans, ret);
                                break;
                        }
-                       if (btrfs_should_throttle_delayed_refs(trans))
-                               btrfs_async_run_delayed_refs(fs_info,
-                                       trans->delayed_ref_updates * 2,
-                                       trans->transid, 0);
                        if (be_nice) {
-                               if (truncate_space_check(trans, root,
-                                                        extent_num_bytes)) {
-                                       should_end = true;
-                               }
                                if (btrfs_should_throttle_delayed_refs(trans))
                                        should_throttle = true;
                        }
@@ -4744,7 +4709,7 @@ delete:
 
                if (path->slots[0] == 0 ||
                    path->slots[0] != pending_del_slot ||
-                   should_throttle || should_end) {
+                   should_throttle) {
                        if (pending_del_nr) {
                                ret = btrfs_del_items(trans, root, path,
                                                pending_del_slot,
@@ -4756,23 +4721,24 @@ delete:
                                pending_del_nr = 0;
                        }
                        btrfs_release_path(path);
-                       if (should_throttle) {
-                               unsigned long updates = trans->delayed_ref_updates;
-                               if (updates) {
-                                       trans->delayed_ref_updates = 0;
-                                       ret = btrfs_run_delayed_refs(trans,
-                                                                  updates * 2);
-                                       if (ret)
-                                               break;
-                               }
-                       }
+
                        /*
-                        * if we failed to refill our space rsv, bail out
-                        * and let the transaction restart
+                        * We can generate a lot of delayed refs, so we need to
+                        * throttle every once and a while and make sure we're
+                        * adding enough space to keep up with the work we are
+                        * generating.  Since we hold a transaction here we
+                        * can't flush, and we don't want to FLUSH_LIMIT because
+                        * we could have generated too many delayed refs to
+                        * actually allocate, so just bail if we're short and
+                        * let the normal reservation dance happen higher up.
                         */
-                       if (should_end) {
-                               ret = -EAGAIN;
-                               break;
+                       if (should_throttle) {
+                               ret = btrfs_delayed_refs_rsv_refill(fs_info,
+                                                       BTRFS_RESERVE_NO_FLUSH);
+                               if (ret) {
+                                       ret = -EAGAIN;
+                                       break;
+                               }
                        }
                        goto search_again;
                } else {
@@ -4798,18 +4764,6 @@ out:
        }
 
        btrfs_free_path(path);
-
-       if (be_nice && bytes_deleted > SZ_32M && (ret >= 0 || ret == -EAGAIN)) {
-               unsigned long updates = trans->delayed_ref_updates;
-               int err;
-
-               if (updates) {
-                       trans->delayed_ref_updates = 0;
-                       err = btrfs_run_delayed_refs(trans, updates * 2);
-                       if (err)
-                               ret = err;
-               }
-       }
        return ret;
 }
 
@@ -5332,8 +5286,8 @@ static struct btrfs_trans_handle *evict_refill_and_join(struct btrfs_root *root,
                 * Try to steal from the global reserve if there is space for
                 * it.
                 */
-               if (!btrfs_check_space_for_delayed_refs(trans) &&
-                   !btrfs_block_rsv_migrate(global_rsv, rsv, rsv->size, false))
+               if (!btrfs_check_space_for_delayed_refs(fs_info) &&
+                   !btrfs_block_rsv_migrate(global_rsv, rsv, rsv->size, 0))
                        return trans;
 
                /* If not, commit and try again. */
@@ -6405,14 +6359,19 @@ fail_dir_item:
                err = btrfs_del_root_ref(trans, key.objectid,
                                         root->root_key.objectid, parent_ino,
                                         &local_index, name, name_len);
-
+               if (err)
+                       btrfs_abort_transaction(trans, err);
        } else if (add_backref) {
                u64 local_index;
                int err;
 
                err = btrfs_del_inode_ref(trans, root, name, name_len,
                                          ino, parent_ino, &local_index);
+               if (err)
+                       btrfs_abort_transaction(trans, err);
        }
+
+       /* Return the original error code */
        return ret;
 }
 
@@ -8906,7 +8865,7 @@ again:
 
        /* page is wholly or partially inside EOF */
        if (page_start + PAGE_SIZE > size)
-               zero_start = size & ~PAGE_MASK;
+               zero_start = offset_in_page(size);
        else
                zero_start = PAGE_SIZE;