btrfs: handle delayed ref head accounting cleanup in abort
[sfrench/cifs-2.6.git] / fs / btrfs / disk-io.c
index feb67dfd663d72f2d265a60a799fa4debf53cdf5..469a51b4b273af30ce2aff0d50d1540b622e494b 100644 (file)
@@ -279,6 +279,12 @@ static int csum_tree_block(struct btrfs_fs_info *fs_info,
 
        len = buf->len - offset;
        while (len > 0) {
+               /*
+                * Note: we don't need to check for the err == 1 case here, as
+                * with the given combination of 'start = BTRFS_CSUM_SIZE (32)'
+                * and 'min_len = 32' and the currently implemented mapping
+                * algorithm we cannot cross a page boundary.
+                */
                err = map_private_extent_buffer(buf, offset, 32,
                                        &kaddr, &map_start, &map_len);
                if (err)
@@ -673,19 +679,6 @@ out:
        return ret;
 }
 
-static int btree_io_failed_hook(struct page *page, int failed_mirror)
-{
-       struct extent_buffer *eb;
-
-       eb = (struct extent_buffer *)page->private;
-       set_bit(EXTENT_BUFFER_READ_ERR, &eb->bflags);
-       eb->read_mirror = failed_mirror;
-       atomic_dec(&eb->io_pages);
-       if (test_and_clear_bit(EXTENT_BUFFER_READAHEAD, &eb->bflags))
-               btree_readahead_hook(eb, -EIO);
-       return -EIO;    /* we fixed nothing */
-}
-
 static void end_workqueue_bio(struct bio *bio)
 {
        struct btrfs_end_io_wq *end_io_wq = bio->bi_private;
@@ -764,11 +757,22 @@ static void run_one_async_start(struct btrfs_work *work)
                async->status = ret;
 }
 
+/*
+ * In order to insert checksums into the metadata in large chunks, we wait
+ * until bio submission time.   All the pages in the bio are checksummed and
+ * sums are attached onto the ordered extent record.
+ *
+ * At IO completion time the csums attached on the ordered extent record are
+ * inserted into the tree.
+ */
 static void run_one_async_done(struct btrfs_work *work)
 {
        struct async_submit_bio *async;
+       struct inode *inode;
+       blk_status_t ret;
 
        async = container_of(work, struct  async_submit_bio, work);
+       inode = async->private_data;
 
        /* If an error occurred we just want to clean up the bio and move on */
        if (async->status) {
@@ -777,7 +781,12 @@ static void run_one_async_done(struct btrfs_work *work)
                return;
        }
 
-       btrfs_submit_bio_done(async->private_data, async->bio, async->mirror_num);
+       ret = btrfs_map_bio(btrfs_sb(inode->i_sb), async->bio,
+                       async->mirror_num, 1);
+       if (ret) {
+               async->bio->bi_status = ret;
+               bio_endio(async->bio);
+       }
 }
 
 static void run_one_async_free(struct btrfs_work *work)
@@ -2132,10 +2141,8 @@ static void btrfs_init_btree_inode(struct btrfs_fs_info *fs_info)
 static void btrfs_init_dev_replace_locks(struct btrfs_fs_info *fs_info)
 {
        mutex_init(&fs_info->dev_replace.lock_finishing_cancel_unmount);
-       rwlock_init(&fs_info->dev_replace.lock);
-       atomic_set(&fs_info->dev_replace.blocking_readers, 0);
+       init_rwsem(&fs_info->dev_replace.rwsem);
        init_waitqueue_head(&fs_info->dev_replace.replace_wait);
-       init_waitqueue_head(&fs_info->dev_replace.read_lock_wq);
 }
 
 static void btrfs_init_qgroup(struct btrfs_fs_info *fs_info)
@@ -2671,6 +2678,9 @@ int open_ctree(struct super_block *sb,
        btrfs_init_block_rsv(&fs_info->empty_block_rsv, BTRFS_BLOCK_RSV_EMPTY);
        btrfs_init_block_rsv(&fs_info->delayed_block_rsv,
                             BTRFS_BLOCK_RSV_DELOPS);
+       btrfs_init_block_rsv(&fs_info->delayed_refs_rsv,
+                            BTRFS_BLOCK_RSV_DELREFS);
+
        atomic_set(&fs_info->async_delalloc_pages, 0);
        atomic_set(&fs_info->defrag_running, 0);
        atomic_set(&fs_info->qgroup_op_seq, 0);
@@ -3090,7 +3100,7 @@ retry_root_backup:
 
        if (!sb_rdonly(sb) && !btrfs_check_rw_degradable(fs_info, NULL)) {
                btrfs_warn(fs_info,
-               "writeable mount is not allowed due to too many missing devices");
+               "writable mount is not allowed due to too many missing devices");
                goto fail_sysfs;
        }
 
@@ -4067,7 +4077,7 @@ void btrfs_mark_buffer_dirty(struct extent_buffer *buf)
 #ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
        /*
         * This is a fast path so only do this check if we have sanity tests
-        * enabled.  Normal people shouldn't be using umapped buffers as dirty
+        * enabled.  Normal people shouldn't be using unmapped buffers as dirty
         * outside of the sanity tests.
         */
        if (unlikely(test_bit(EXTENT_BUFFER_UNMAPPED, &buf->bflags)))
@@ -4255,6 +4265,7 @@ static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans,
                if (pin_bytes)
                        btrfs_pin_extent(fs_info, head->bytenr,
                                         head->num_bytes, 1);
+               btrfs_cleanup_ref_head_accounting(fs_info, delayed_refs, head);
                btrfs_put_delayed_ref_head(head);
                cond_resched();
                spin_lock(&delayed_refs->lock);
@@ -4365,6 +4376,8 @@ static int btrfs_destroy_pinned_extent(struct btrfs_fs_info *fs_info,
        unpin = pinned_extents;
 again:
        while (1) {
+               struct extent_state *cached_state = NULL;
+
                /*
                 * The btrfs_finish_extent_commit() may get the same range as
                 * ours between find_first_extent_bit and clear_extent_dirty.
@@ -4373,13 +4386,14 @@ again:
                 */
                mutex_lock(&fs_info->unused_bg_unpin_mutex);
                ret = find_first_extent_bit(unpin, 0, &start, &end,
-                                           EXTENT_DIRTY, NULL);
+                                           EXTENT_DIRTY, &cached_state);
                if (ret) {
                        mutex_unlock(&fs_info->unused_bg_unpin_mutex);
                        break;
                }
 
-               clear_extent_dirty(unpin, start, end);
+               clear_extent_dirty(unpin, start, end, &cached_state);
+               free_extent_state(cached_state);
                btrfs_error_unpin_extent_range(fs_info, start, end);
                mutex_unlock(&fs_info->unused_bg_unpin_mutex);
                cond_resched();
@@ -4436,6 +4450,7 @@ void btrfs_cleanup_dirty_bgs(struct btrfs_transaction *cur_trans,
 
                spin_unlock(&cur_trans->dirty_bgs_lock);
                btrfs_put_block_group(cache);
+               btrfs_delayed_refs_rsv_release(fs_info, 1);
                spin_lock(&cur_trans->dirty_bgs_lock);
        }
        spin_unlock(&cur_trans->dirty_bgs_lock);
@@ -4541,7 +4556,4 @@ static const struct extent_io_ops btree_extent_io_ops = {
        /* mandatory callbacks */
        .submit_bio_hook = btree_submit_bio_hook,
        .readpage_end_io_hook = btree_readpage_end_io_hook,
-       .readpage_io_failed_hook = btree_io_failed_hook,
-
-       /* optional callbacks */
 };