btrfs: merge btrfs_submit_bio_done to its caller
[sfrench/cifs-2.6.git] / fs / btrfs / disk-io.c
index 6d776717d8b39b566e6ec14f479648ad6f788905..19b270368308d8063b536cb7aa785802f7c4364b 100644 (file)
@@ -542,7 +542,7 @@ static int csum_dirty_buffer(struct btrfs_fs_info *fs_info, struct page *page)
        if (WARN_ON(!PageUptodate(page)))
                return -EUCLEAN;
 
-       ASSERT(memcmp_extent_buffer(eb, fs_info->fsid,
+       ASSERT(memcmp_extent_buffer(eb, fs_info->fs_devices->metadata_uuid,
                        btrfs_header_fsid(), BTRFS_FSID_SIZE) == 0);
 
        return csum_tree_block(fs_info, eb, 0);
@@ -557,7 +557,20 @@ static int check_tree_block_fsid(struct btrfs_fs_info *fs_info,
 
        read_extent_buffer(eb, fsid, btrfs_header_fsid(), BTRFS_FSID_SIZE);
        while (fs_devices) {
-               if (!memcmp(fsid, fs_devices->fsid, BTRFS_FSID_SIZE)) {
+               u8 *metadata_uuid;
+
+               /*
+                * Checking the incompat flag is only valid for the current
+                * fs. For seed devices it's forbidden to have their uuid
+                * changed so reading ->fsid in this case is fine
+                */
+               if (fs_devices == fs_info->fs_devices &&
+                   btrfs_fs_incompat(fs_info, METADATA_UUID))
+                       metadata_uuid = fs_devices->metadata_uuid;
+               else
+                       metadata_uuid = fs_devices->fsid;
+
+               if (!memcmp(fsid, metadata_uuid, BTRFS_FSID_SIZE)) {
                        ret = 0;
                        break;
                }
@@ -751,11 +764,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) {
@@ -764,7 +788,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)
@@ -1178,6 +1207,7 @@ static void __setup_root(struct btrfs_root *root, struct btrfs_fs_info *fs_info,
        refcount_set(&root->refs, 1);
        atomic_set(&root->will_be_snapshotted, 0);
        atomic_set(&root->snapshot_force_cow, 0);
+       atomic_set(&root->nr_swapfiles, 0);
        root->log_transid = 0;
        root->log_transid_committed = -1;
        root->last_log_commit = 0;
@@ -2442,10 +2472,11 @@ static int validate_super(struct btrfs_fs_info *fs_info,
                ret = -EINVAL;
        }
 
-       if (memcmp(fs_info->fsid, sb->dev_item.fsid, BTRFS_FSID_SIZE) != 0) {
+       if (memcmp(fs_info->fs_devices->metadata_uuid, sb->dev_item.fsid,
+                  BTRFS_FSID_SIZE) != 0) {
                btrfs_err(fs_info,
-                          "dev_item UUID does not match fsid: %pU != %pU",
-                          fs_info->fsid, sb->dev_item.fsid);
+                       "dev_item UUID does not match metadata fsid: %pU != %pU",
+                       fs_info->fs_devices->metadata_uuid, sb->dev_item.fsid);
                ret = -EINVAL;
        }
 
@@ -2745,6 +2776,9 @@ int open_ctree(struct super_block *sb,
        fs_info->sectorsize = 4096;
        fs_info->stripesize = 4096;
 
+       spin_lock_init(&fs_info->swapfile_pins_lock);
+       fs_info->swapfile_pins = RB_ROOT;
+
        ret = btrfs_alloc_stripe_hash_table(fs_info);
        if (ret) {
                err = ret;
@@ -2781,11 +2815,29 @@ int open_ctree(struct super_block *sb,
         * the whole block of INFO_SIZE
         */
        memcpy(fs_info->super_copy, bh->b_data, sizeof(*fs_info->super_copy));
-       memcpy(fs_info->super_for_commit, fs_info->super_copy,
-              sizeof(*fs_info->super_for_commit));
        brelse(bh);
 
-       memcpy(fs_info->fsid, fs_info->super_copy->fsid, BTRFS_FSID_SIZE);
+       disk_super = fs_info->super_copy;
+
+       ASSERT(!memcmp(fs_info->fs_devices->fsid, fs_info->super_copy->fsid,
+                      BTRFS_FSID_SIZE));
+
+       if (btrfs_fs_incompat(fs_info, METADATA_UUID)) {
+               ASSERT(!memcmp(fs_info->fs_devices->metadata_uuid,
+                               fs_info->super_copy->metadata_uuid,
+                               BTRFS_FSID_SIZE));
+       }
+
+       features = btrfs_super_flags(disk_super);
+       if (features & BTRFS_SUPER_FLAG_CHANGING_FSID_V2) {
+               features &= ~BTRFS_SUPER_FLAG_CHANGING_FSID_V2;
+               btrfs_set_super_flags(disk_super, features);
+               btrfs_info(fs_info,
+                       "found metadata UUID change in progress flag, clearing");
+       }
+
+       memcpy(fs_info->super_for_commit, fs_info->super_copy,
+              sizeof(*fs_info->super_for_commit));
 
        ret = btrfs_validate_mount_super(fs_info);
        if (ret) {
@@ -2794,7 +2846,6 @@ int open_ctree(struct super_block *sb,
                goto fail_alloc;
        }
 
-       disk_super = fs_info->super_copy;
        if (!btrfs_super_root(disk_super))
                goto fail_alloc;
 
@@ -2906,7 +2957,7 @@ int open_ctree(struct super_block *sb,
 
        sb->s_blocksize = sectorsize;
        sb->s_blocksize_bits = blksize_bits(sectorsize);
-       memcpy(&sb->s_uuid, fs_info->fsid, BTRFS_FSID_SIZE);
+       memcpy(&sb->s_uuid, fs_info->fs_devices->fsid, BTRFS_FSID_SIZE);
 
        mutex_lock(&fs_info->chunk_mutex);
        ret = btrfs_read_sys_array(fs_info);
@@ -3724,7 +3775,8 @@ int write_all_supers(struct btrfs_fs_info *fs_info, int max_mirrors)
                btrfs_set_stack_device_io_width(dev_item, dev->io_width);
                btrfs_set_stack_device_sector_size(dev_item, dev->sector_size);
                memcpy(dev_item->uuid, dev->uuid, BTRFS_UUID_SIZE);
-               memcpy(dev_item->fsid, dev->fs_devices->fsid, BTRFS_FSID_SIZE);
+               memcpy(dev_item->fsid, dev->fs_devices->metadata_uuid,
+                      BTRFS_FSID_SIZE);
 
                flags = btrfs_super_flags(sb);
                btrfs_set_super_flags(sb, flags | BTRFS_HEADER_FLAG_WRITTEN);
@@ -4329,6 +4381,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.
@@ -4337,13 +4391,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();