btrfs: Handle btrfs_set_extent_delalloc failure in fixup worker
[sfrench/cifs-2.6.git] / fs / btrfs / inode.c
index e1a7f3cb5be940561af3ec855b6657c3fce7c850..9ad8c9321c8f6eb2f2f26692676d187148f09597 100644 (file)
@@ -536,9 +536,14 @@ again:
                 *
                 * If the compression fails for any reason, we set the pages
                 * dirty again later on.
+                *
+                * Note that the remaining part is redirtied, the start pointer
+                * has moved, the end is the original one.
                 */
-               extent_range_clear_dirty_for_io(inode, start, end);
-               redirty = 1;
+               if (!redirty) {
+                       extent_range_clear_dirty_for_io(inode, start, end);
+                       redirty = 1;
+               }
 
                /* Compression level is applied here and only here */
                ret = btrfs_compress_pages(
@@ -769,7 +774,6 @@ retry:
                                                  inode, async_extent->start,
                                                  async_extent->start +
                                                  async_extent->ram_size - 1,
-                                                 btrfs_get_extent,
                                                  WB_SYNC_ALL);
                        else if (ret)
                                unlock_page(async_cow->locked_page);
@@ -1203,7 +1207,7 @@ static int cow_file_range_async(struct inode *inode, struct page *locked_page,
        u64 cur_end;
 
        clear_extent_bit(&BTRFS_I(inode)->io_tree, start, end, EXTENT_LOCKED,
-                        1, 0, NULL, GFP_NOFS);
+                        1, 0, NULL);
        while (start < end) {
                async_cow = kmalloc(sizeof(*async_cow), GFP_NOFS);
                BUG_ON(!async_cow); /* -ENOMEM */
@@ -1951,7 +1955,21 @@ static blk_status_t __btrfs_submit_bio_done(void *private_data, struct bio *bio,
 
 /*
  * extent_io.c submission hook. This does the right thing for csum calculation
- * on write, or reading the csums from the tree before a read
+ * on write, or reading the csums from the tree before a read.
+ *
+ * Rules about async/sync submit,
+ * a) read:                            sync submit
+ *
+ * b) write without checksum:          sync submit
+ *
+ * c) write with checksum:
+ *    c-1) if bio is issued by fsync:  sync submit
+ *         (sync_writers != 0)
+ *
+ *    c-2) if root is reloc root:      sync submit
+ *         (only in case of buffered IO)
+ *
+ *    c-3) otherwise:                  async submit
  */
 static blk_status_t btrfs_submit_bio_hook(void *private_data, struct bio *bio,
                                 int mirror_num, unsigned long bio_flags,
@@ -2023,10 +2041,10 @@ static noinline int add_pending_csums(struct btrfs_trans_handle *trans,
        struct btrfs_ordered_sum *sum;
 
        list_for_each_entry(sum, list, list) {
-               trans->adding_csums = 1;
+               trans->adding_csums = true;
                btrfs_csum_file_blocks(trans,
                       BTRFS_I(inode)->root->fs_info->csum_root, sum);
-               trans->adding_csums = 0;
+               trans->adding_csums = false;
        }
        return 0;
 }
@@ -2098,8 +2116,15 @@ again:
                goto out;
         }
 
-       btrfs_set_extent_delalloc(inode, page_start, page_end, 0, &cached_state,
-                                 0);
+       ret = btrfs_set_extent_delalloc(inode, page_start, page_end, 0,
+                                       &cached_state, 0);
+       if (ret) {
+               mapping_set_error(page->mapping, ret);
+               end_extent_writepage(page, ret, page_start, page_end);
+               ClearPageChecked(page);
+               goto out;
+       }
+
        ClearPageChecked(page);
        set_page_dirty(page);
        btrfs_delalloc_release_extents(BTRFS_I(inode), PAGE_SIZE);
@@ -2986,7 +3011,7 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent)
 
                clear_extent_bit(io_tree, ordered_extent->file_offset,
                        ordered_extent->file_offset + ordered_extent->len - 1,
-                       EXTENT_DEFRAG, 0, 0, &cached_state, GFP_NOFS);
+                       EXTENT_DEFRAG, 0, 0, &cached_state);
        }
 
        if (nolock)
@@ -3056,7 +3081,7 @@ out:
                                 ordered_extent->len - 1,
                                 clear_bits,
                                 (clear_bits & EXTENT_LOCKED) ? 1 : 0,
-                                0, &cached_state, GFP_NOFS);
+                                0, &cached_state);
        }
 
        if (trans)
@@ -3070,7 +3095,7 @@ out:
                else
                        start = ordered_extent->file_offset;
                end = ordered_extent->file_offset + ordered_extent->len - 1;
-               clear_extent_uptodate(io_tree, start, end, NULL, GFP_NOFS);
+               clear_extent_uptodate(io_tree, start, end, NULL);
 
                /* Drop the cache for the part of the extent we didn't write. */
                btrfs_drop_extent_cache(BTRFS_I(inode), start, end, 0);
@@ -4798,7 +4823,7 @@ again:
        clear_extent_bit(&BTRFS_I(inode)->io_tree, block_start, block_end,
                          EXTENT_DIRTY | EXTENT_DELALLOC |
                          EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG,
-                         0, 0, &cached_state, GFP_NOFS);
+                         0, 0, &cached_state);
 
        ret = btrfs_set_extent_delalloc(inode, block_start, block_end, 0,
                                        &cached_state, 0);
@@ -5234,8 +5259,7 @@ static void evict_inode_truncate_pages(struct inode *inode)
                clear_extent_bit(io_tree, start, end,
                                 EXTENT_LOCKED | EXTENT_DIRTY |
                                 EXTENT_DELALLOC | EXTENT_DO_ACCOUNTING |
-                                EXTENT_DEFRAG, 1, 1,
-                                &cached_state, GFP_NOFS);
+                                EXTENT_DEFRAG, 1, 1, &cached_state);
 
                cond_resched();
                spin_lock(&io_tree->lock);
@@ -5894,7 +5918,6 @@ static int btrfs_filldir(void *addr, int entries, struct dir_context *ctx)
 static int btrfs_real_readdir(struct file *file, struct dir_context *ctx)
 {
        struct inode *inode = file_inode(file);
-       struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
        struct btrfs_root *root = BTRFS_I(inode)->root;
        struct btrfs_file_private *private = file->private_data;
        struct btrfs_dir_item *di;
@@ -5962,9 +5985,6 @@ again:
                if (btrfs_should_delete_dir_index(&del_list, found_key.offset))
                        goto next;
                di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item);
-               if (verify_dir_item(fs_info, leaf, slot, di))
-                       goto next;
-
                name_len = btrfs_dir_name_len(leaf, di);
                if ((total_len + sizeof(struct dir_entry) + name_len) >=
                    PAGE_SIZE) {
@@ -6560,7 +6580,6 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry,
 
 out_unlock:
        btrfs_end_transaction(trans);
-       btrfs_balance_delayed_items(fs_info);
        btrfs_btree_balance_dirty(fs_info);
        if (drop_inode) {
                inode_dec_link_count(inode);
@@ -6641,7 +6660,6 @@ out_unlock:
                inode_dec_link_count(inode);
                iput(inode);
        }
-       btrfs_balance_delayed_items(fs_info);
        btrfs_btree_balance_dirty(fs_info);
        return err;
 
@@ -6716,7 +6734,6 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
                btrfs_log_new_name(trans, BTRFS_I(inode), NULL, parent);
        }
 
-       btrfs_balance_delayed_items(fs_info);
 fail:
        if (trans)
                btrfs_end_transaction(trans);
@@ -6794,7 +6811,6 @@ out_fail:
                inode_dec_link_count(inode);
                iput(inode);
        }
-       btrfs_balance_delayed_items(fs_info);
        btrfs_btree_balance_dirty(fs_info);
        return err;
 
@@ -6939,10 +6955,8 @@ struct extent_map *btrfs_get_extent(struct btrfs_inode *inode,
        struct extent_map *em = NULL;
        struct extent_map_tree *em_tree = &inode->extent_tree;
        struct extent_io_tree *io_tree = &inode->io_tree;
-       struct btrfs_trans_handle *trans = NULL;
        const bool new_inline = !page || create;
 
-again:
        read_lock(&em_tree->lock);
        em = lookup_extent_mapping(em_tree, start, len);
        if (em)
@@ -6981,8 +6995,7 @@ again:
                path->reada = READA_FORWARD;
        }
 
-       ret = btrfs_lookup_file_extent(trans, root, path,
-                                      objectid, start, trans != NULL);
+       ret = btrfs_lookup_file_extent(NULL, root, path, objectid, start, 0);
        if (ret < 0) {
                err = ret;
                goto out;
@@ -7083,7 +7096,7 @@ next:
                em->orig_block_len = em->len;
                em->orig_start = em->start;
                ptr = btrfs_file_extent_inline_start(item) + extent_offset;
-               if (create == 0 && !PageUptodate(page)) {
+               if (!PageUptodate(page)) {
                        if (btrfs_file_extent_compression(leaf, item) !=
                            BTRFS_COMPRESS_NONE) {
                                ret = uncompress_inline(path, page, pg_offset,
@@ -7104,25 +7117,6 @@ next:
                                kunmap(page);
                        }
                        flush_dcache_page(page);
-               } else if (create && PageUptodate(page)) {
-                       BUG();
-                       if (!trans) {
-                               kunmap(page);
-                               free_extent_map(em);
-                               em = NULL;
-
-                               btrfs_release_path(path);
-                               trans = btrfs_join_transaction(root);
-
-                               if (IS_ERR(trans))
-                                       return ERR_CAST(trans);
-                               goto again;
-                       }
-                       map = kmap(page);
-                       write_extent_buffer(leaf, map + pg_offset, ptr,
-                                           copy_size);
-                       kunmap(page);
-                       btrfs_mark_buffer_dirty(leaf);
                }
                set_extent_uptodate(io_tree, em->start,
                                    extent_map_end(em) - 1, NULL, GFP_NOFS);
@@ -7134,7 +7128,6 @@ not_found:
        em->len = len;
 not_found_em:
        em->block_start = EXTENT_MAP_HOLE;
-       set_bit(EXTENT_FLAG_VACANCY, &em->flags);
 insert:
        btrfs_release_path(path);
        if (em->start > start || extent_map_end(em) <= start) {
@@ -7198,11 +7191,6 @@ out:
        trace_btrfs_get_extent(root, inode, em);
 
        btrfs_free_path(path);
-       if (trans) {
-               ret = btrfs_end_transaction(trans);
-               if (!err)
-                       err = ret;
-       }
        if (err) {
                free_extent_map(em);
                return ERR_PTR(err);
@@ -7324,7 +7312,7 @@ struct extent_map *btrfs_get_extent_fiemap(struct btrfs_inode *inode,
                        em->block_start = EXTENT_MAP_DELALLOC;
                        em->block_len = found;
                }
-       } else if (hole_em) {
+       } else {
                return hole_em;
        }
 out:
@@ -7926,7 +7914,7 @@ unlock:
        if (lockstart < lockend) {
                clear_extent_bit(&BTRFS_I(inode)->io_tree, lockstart,
                                 lockend, unlock_bits, 1, 0,
-                                &cached_state, GFP_NOFS);
+                                &cached_state);
        } else {
                free_extent_state(cached_state);
        }
@@ -7937,7 +7925,7 @@ unlock:
 
 unlock_err:
        clear_extent_bit(&BTRFS_I(inode)->io_tree, lockstart, lockend,
-                        unlock_bits, 1, 0, &cached_state, GFP_NOFS);
+                        unlock_bits, 1, 0, &cached_state);
 err:
        if (dio_data)
                current->journal_info = dio_data;
@@ -8460,6 +8448,7 @@ __btrfs_submit_dio_bio(struct bio *bio, struct inode *inode, u64 file_offset,
        bool write = bio_op(bio) == REQ_OP_WRITE;
        blk_status_t ret;
 
+       /* Check btrfs_submit_bio_hook() for rules about async submit. */
        if (async_submit)
                async_submit = !atomic_read(&BTRFS_I(inode)->sync_writers);
 
@@ -8854,7 +8843,7 @@ static int btrfs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
        if (ret)
                return ret;
 
-       return extent_fiemap(inode, fieinfo, start, len, btrfs_get_extent_fiemap);
+       return extent_fiemap(inode, fieinfo, start, len);
 }
 
 int btrfs_readpage(struct file *file, struct page *page)
@@ -8886,7 +8875,7 @@ static int btrfs_writepage(struct page *page, struct writeback_control *wbc)
                return AOP_WRITEPAGE_ACTIVATE;
        }
        tree = &BTRFS_I(page->mapping->host)->io_tree;
-       ret = extent_write_full_page(tree, page, btrfs_get_extent, wbc);
+       ret = extent_write_full_page(tree, page, wbc);
        btrfs_add_delayed_iput(inode);
        return ret;
 }
@@ -8897,7 +8886,7 @@ static int btrfs_writepages(struct address_space *mapping,
        struct extent_io_tree *tree;
 
        tree = &BTRFS_I(mapping->host)->io_tree;
-       return extent_writepages(tree, mapping, btrfs_get_extent, wbc);
+       return extent_writepages(tree, mapping, wbc);
 }
 
 static int
@@ -8906,8 +8895,7 @@ btrfs_readpages(struct file *file, struct address_space *mapping,
 {
        struct extent_io_tree *tree;
        tree = &BTRFS_I(mapping->host)->io_tree;
-       return extent_readpages(tree, mapping, pages, nr_pages,
-                               btrfs_get_extent);
+       return extent_readpages(tree, mapping, pages, nr_pages);
 }
 static int __btrfs_releasepage(struct page *page, gfp_t gfp_flags)
 {
@@ -8978,8 +8966,7 @@ again:
                                         EXTENT_DIRTY | EXTENT_DELALLOC |
                                         EXTENT_DELALLOC_NEW |
                                         EXTENT_LOCKED | EXTENT_DO_ACCOUNTING |
-                                        EXTENT_DEFRAG, 1, 0, &cached_state,
-                                        GFP_NOFS);
+                                        EXTENT_DEFRAG, 1, 0, &cached_state);
                /*
                 * whoever cleared the private bit is responsible
                 * for the finish_ordered_io
@@ -9036,7 +9023,7 @@ again:
                                 EXTENT_LOCKED | EXTENT_DIRTY |
                                 EXTENT_DELALLOC | EXTENT_DELALLOC_NEW |
                                 EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG, 1, 1,
-                                &cached_state, GFP_NOFS);
+                                &cached_state);
 
                __btrfs_releasepage(page, GFP_NOFS);
        }
@@ -9164,7 +9151,7 @@ again:
        clear_extent_bit(&BTRFS_I(inode)->io_tree, page_start, end,
                          EXTENT_DIRTY | EXTENT_DELALLOC |
                          EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG,
-                         0, 0, &cached_state, GFP_NOFS);
+                         0, 0, &cached_state);
 
        ret = btrfs_set_extent_delalloc(inode, page_start, end, 0,
                                        &cached_state, 0);
@@ -9421,7 +9408,7 @@ struct inode *btrfs_alloc_inode(struct super_block *sb)
        struct btrfs_inode *ei;
        struct inode *inode;
 
-       ei = kmem_cache_alloc(btrfs_inode_cachep, GFP_NOFS);
+       ei = kmem_cache_alloc(btrfs_inode_cachep, GFP_KERNEL);
        if (!ei)
                return NULL;
 
@@ -9573,7 +9560,7 @@ void btrfs_destroy_cachep(void)
        kmem_cache_destroy(btrfs_free_space_cachep);
 }
 
-int btrfs_init_cachep(void)
+int __init btrfs_init_cachep(void)
 {
        btrfs_inode_cachep = kmem_cache_create("btrfs_inode",
                        sizeof(struct btrfs_inode), 0,
@@ -10688,7 +10675,6 @@ out:
        btrfs_end_transaction(trans);
        if (ret)
                iput(inode);
-       btrfs_balance_delayed_items(fs_info);
        btrfs_btree_balance_dirty(fs_info);
        return ret;