Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[pandora-kernel.git] / fs / btrfs / super.c
index 915ac14..d8982e9 100644 (file)
@@ -55,6 +55,7 @@
 #include "export.h"
 #include "compression.h"
 #include "rcu-string.h"
+#include "dev-replace.h"
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/btrfs.h>
@@ -116,7 +117,16 @@ static void btrfs_handle_error(struct btrfs_fs_info *fs_info)
        if (fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) {
                sb->s_flags |= MS_RDONLY;
                printk(KERN_INFO "btrfs is forced readonly\n");
-               __btrfs_scrub_cancel(fs_info);
+               /*
+                * Note that a running device replace operation is not
+                * canceled here although there is no way to update
+                * the progress. It would add the risk of a deadlock,
+                * therefore the canceling is ommited. The only penalty
+                * is that some I/O remains active until the procedure
+                * completes. The next time when the filesystem is
+                * mounted writeable again, the device replace
+                * operation continues.
+                */
 //             WARN_ON(1);
        }
 }
@@ -257,7 +267,7 @@ void __btrfs_abort_transaction(struct btrfs_trans_handle *trans,
                             function, line, errstr);
                return;
        }
-       trans->transaction->aborted = errno;
+       ACCESS_ONCE(trans->transaction->aborted) = errno;
        __btrfs_std_error(root->fs_info, function, line, errno, NULL);
 }
 /*
@@ -1186,7 +1196,8 @@ static void btrfs_resize_thread_pool(struct btrfs_fs_info *fs_info,
        btrfs_set_max_workers(&fs_info->endio_freespace_worker, new_pool_size);
        btrfs_set_max_workers(&fs_info->delayed_workers, new_pool_size);
        btrfs_set_max_workers(&fs_info->readahead_workers, new_pool_size);
-       btrfs_set_max_workers(&fs_info->scrub_workers, new_pool_size);
+       btrfs_set_max_workers(&fs_info->scrub_wr_completion_workers,
+                             new_pool_size);
 }
 
 static int btrfs_remount(struct super_block *sb, int *flags, char *data)
@@ -1215,8 +1226,15 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
                return 0;
 
        if (*flags & MS_RDONLY) {
+               /*
+                * this also happens on 'umount -rf' or on shutdown, when
+                * the filesystem is busy.
+                */
                sb->s_flags |= MS_RDONLY;
 
+               btrfs_dev_replace_suspend_for_unmount(fs_info);
+               btrfs_scrub_cancel(fs_info);
+
                ret = btrfs_commit_super(root);
                if (ret)
                        goto restore;
@@ -1226,6 +1244,15 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
                        goto restore;
                }
 
+               if (fs_info->fs_devices->missing_devices >
+                    fs_info->num_tolerated_disk_barrier_failures &&
+                   !(*flags & MS_RDONLY)) {
+                       printk(KERN_WARNING
+                              "Btrfs: too many missing devices, writeable remount is not allowed\n");
+                       ret = -EACCES;
+                       goto restore;
+               }
+
                if (btrfs_super_log_root(fs_info->super_copy) != 0) {
                        ret = -EINVAL;
                        goto restore;
@@ -1244,6 +1271,11 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
                if (ret)
                        goto restore;
 
+               ret = btrfs_resume_dev_replace_async(fs_info);
+               if (ret) {
+                       pr_warn("btrfs: failed to resume dev_replace\n");
+                       goto restore;
+               }
                sb->s_flags &= ~MS_RDONLY;
        }
 
@@ -1336,7 +1368,8 @@ static int btrfs_calc_avail_data_space(struct btrfs_root *root, u64 *free_bytes)
                min_stripe_size = BTRFS_STRIPE_LEN;
 
        list_for_each_entry(device, &fs_devices->devices, dev_list) {
-               if (!device->in_fs_metadata || !device->bdev)
+               if (!device->in_fs_metadata || !device->bdev ||
+                   device->is_tgtdev_for_dev_replace)
                        continue;
 
                avail_space = device->total_bytes - device->bytes_used;
@@ -1647,10 +1680,14 @@ static int __init init_btrfs_fs(void)
        if (err)
                goto free_ordered_data;
 
-       err = btrfs_interface_init();
+       err = btrfs_auto_defrag_init();
        if (err)
                goto free_delayed_inode;
 
+       err = btrfs_interface_init();
+       if (err)
+               goto free_auto_defrag;
+
        err = register_filesystem(&btrfs_fs_type);
        if (err)
                goto unregister_ioctl;
@@ -1662,6 +1699,8 @@ static int __init init_btrfs_fs(void)
 
 unregister_ioctl:
        btrfs_interface_exit();
+free_auto_defrag:
+       btrfs_auto_defrag_exit();
 free_delayed_inode:
        btrfs_delayed_inode_exit();
 free_ordered_data:
@@ -1681,6 +1720,7 @@ free_compress:
 static void __exit exit_btrfs_fs(void)
 {
        btrfs_destroy_cachep();
+       btrfs_auto_defrag_exit();
        btrfs_delayed_inode_exit();
        ordered_data_exit();
        extent_map_exit();