]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - fs/btrfs/volumes.c
Merge tag 'for-linus-4.13-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git...
[karo-tx-linux.git] / fs / btrfs / volumes.c
index e28c113785bbf323b95474b4afde541b8a3f1575..5eb7217738edbba5a49237736c3263b9b044d46f 100644 (file)
@@ -242,6 +242,17 @@ static struct btrfs_device *__alloc_device(void)
        if (!dev)
                return ERR_PTR(-ENOMEM);
 
+       /*
+        * Preallocate a bio that's always going to be used for flushing device
+        * barriers and matches the device lifespan
+        */
+       dev->flush_bio = bio_alloc_bioset(GFP_KERNEL, 0, NULL);
+       if (!dev->flush_bio) {
+               kfree(dev);
+               return ERR_PTR(-ENOMEM);
+       }
+       bio_get(dev->flush_bio);
+
        INIT_LIST_HEAD(&dev->dev_list);
        INIT_LIST_HEAD(&dev->dev_alloc_list);
        INIT_LIST_HEAD(&dev->resized_list);
@@ -838,6 +849,7 @@ static void __free_device(struct work_struct *work)
 
        device = container_of(work, struct btrfs_device, rcu_work);
        rcu_string_free(device->name);
+       bio_put(device->flush_bio);
        kfree(device);
 }
 
@@ -1353,15 +1365,13 @@ int find_free_dev_extent_start(struct btrfs_transaction *transaction,
        int ret;
        int slot;
        struct extent_buffer *l;
-       u64 min_search_start;
 
        /*
         * We don't want to overwrite the superblock on the drive nor any area
         * used by the boot loader (grub for example), so we make sure to start
         * at an offset of at least 1MB.
         */
-       min_search_start = max(fs_info->alloc_start, 1024ull * 1024);
-       search_start = max(search_start, min_search_start);
+       search_start = max_t(u64, search_start, SZ_1M);
 
        path = btrfs_alloc_path();
        if (!path)
@@ -2387,7 +2397,8 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path
        device->io_width = fs_info->sectorsize;
        device->io_align = fs_info->sectorsize;
        device->sector_size = fs_info->sectorsize;
-       device->total_bytes = i_size_read(bdev->bd_inode);
+       device->total_bytes = round_down(i_size_read(bdev->bd_inode),
+                                        fs_info->sectorsize);
        device->disk_total_bytes = device->total_bytes;
        device->commit_total_bytes = device->total_bytes;
        device->fs_info = fs_info;
@@ -2424,7 +2435,7 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path
 
        tmp = btrfs_super_total_bytes(fs_info->super_copy);
        btrfs_set_super_total_bytes(fs_info->super_copy,
-                                   tmp + device->total_bytes);
+               round_down(tmp + device->total_bytes, fs_info->sectorsize));
 
        tmp = btrfs_super_num_devices(fs_info->super_copy);
        btrfs_set_super_num_devices(fs_info->super_copy, tmp + 1);
@@ -2572,7 +2583,7 @@ int btrfs_init_dev_replace_tgtdev(struct btrfs_fs_info *fs_info,
                goto error;
        }
 
-       name = rcu_string_strdup(device_path, GFP_NOFS);
+       name = rcu_string_strdup(device_path, GFP_KERNEL);
        if (!name) {
                kfree(device);
                ret = -ENOMEM;
@@ -2687,6 +2698,8 @@ int btrfs_grow_device(struct btrfs_trans_handle *trans,
        if (!device->writeable)
                return -EACCES;
 
+       new_size = round_down(new_size, fs_info->sectorsize);
+
        mutex_lock(&fs_info->chunk_mutex);
        old_total = btrfs_super_total_bytes(super_copy);
        diff = new_size - device->total_bytes;
@@ -2699,7 +2712,8 @@ int btrfs_grow_device(struct btrfs_trans_handle *trans,
 
        fs_devices = fs_info->fs_devices;
 
-       btrfs_set_super_total_bytes(super_copy, old_total + diff);
+       btrfs_set_super_total_bytes(super_copy,
+                       round_down(old_total + diff, fs_info->sectorsize));
        device->fs_devices->total_rw_bytes += diff;
 
        btrfs_device_set_total_bytes(device, new_size);
@@ -4389,7 +4403,10 @@ int btrfs_shrink_device(struct btrfs_device *device, u64 new_size)
        struct btrfs_super_block *super_copy = fs_info->super_copy;
        u64 old_total = btrfs_super_total_bytes(super_copy);
        u64 old_size = btrfs_device_get_total_bytes(device);
-       u64 diff = old_size - new_size;
+       u64 diff;
+
+       new_size = round_down(new_size, fs_info->sectorsize);
+       diff = old_size - new_size;
 
        if (device->is_tgtdev_for_dev_replace)
                return -EINVAL;
@@ -4516,7 +4533,8 @@ again:
                              &fs_info->fs_devices->resized_devices);
 
        WARN_ON(diff > old_total);
-       btrfs_set_super_total_bytes(super_copy, old_total - diff);
+       btrfs_set_super_total_bytes(super_copy,
+                       round_down(old_total - diff, fs_info->sectorsize));
        mutex_unlock(&fs_info->chunk_mutex);
 
        /* Now btrfs_update_device() will change the on-disk size. */
@@ -6031,9 +6049,10 @@ static void btrfs_end_bio(struct bio *bio)
        struct btrfs_bio *bbio = bio->bi_private;
        int is_orig_bio = 0;
 
-       if (bio->bi_error) {
+       if (bio->bi_status) {
                atomic_inc(&bbio->error);
-               if (bio->bi_error == -EIO || bio->bi_error == -EREMOTEIO) {
+               if (bio->bi_status == BLK_STS_IOERR ||
+                   bio->bi_status == BLK_STS_TARGET) {
                        unsigned int stripe_index =
                                btrfs_io_bio(bio)->stripe_index;
                        struct btrfs_device *dev;
@@ -6071,13 +6090,13 @@ static void btrfs_end_bio(struct bio *bio)
                 * beyond the tolerance of the btrfs bio
                 */
                if (atomic_read(&bbio->error) > bbio->max_errors) {
-                       bio->bi_error = -EIO;
+                       bio->bi_status = BLK_STS_IOERR;
                } else {
                        /*
                         * this bio is actually up to date, we didn't
                         * go over the max number of errors
                         */
-                       bio->bi_error = 0;
+                       bio->bi_status = 0;
                }
 
                btrfs_end_bbio(bbio, bio);
@@ -6188,7 +6207,7 @@ static void bbio_error(struct btrfs_bio *bbio, struct bio *bio, u64 logical)
 
                btrfs_io_bio(bio)->mirror_num = bbio->mirror_num;
                bio->bi_iter.bi_sector = logical >> 9;
-               bio->bi_error = -EIO;
+               bio->bi_status = BLK_STS_IOERR;
                btrfs_end_bbio(bbio, bio);
        }
 }
@@ -6255,10 +6274,9 @@ int btrfs_map_bio(struct btrfs_fs_info *fs_info, struct bio *bio,
                        continue;
                }
 
-               if (dev_nr < total_devs - 1) {
-                       bio = btrfs_bio_clone(first_bio, GFP_NOFS);
-                       BUG_ON(!bio); /* -ENOMEM */
-               } else
+               if (dev_nr < total_devs - 1)
+                       bio = btrfs_bio_clone(first_bio);
+               else
                        bio = first_bio;
 
                submit_stripe_bio(bbio, bio, bbio->stripes[dev_nr].physical,