btrfs: avoid blocking open_ctree from cleaner_kthread
[sfrench/cifs-2.6.git] / fs / btrfs / super.c
index 00b8f37cc306df540989a9a888f0fb6cf0eb8a0e..60e7179ed4b77ff8dcd9de1d8eb1c0cebce9f95d 100644 (file)
@@ -97,15 +97,6 @@ const char *btrfs_decode_error(int errno)
        return errstr;
 }
 
-static void save_error_info(struct btrfs_fs_info *fs_info)
-{
-       /*
-        * today we only save the error info into ram.  Long term we'll
-        * also send it down to the disk
-        */
-       set_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state);
-}
-
 /* btrfs handle error by forcing the filesystem readonly */
 static void btrfs_handle_error(struct btrfs_fs_info *fs_info)
 {
@@ -121,7 +112,7 @@ static void btrfs_handle_error(struct btrfs_fs_info *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
+                * therefore the canceling is omitted. 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
@@ -131,11 +122,11 @@ static void btrfs_handle_error(struct btrfs_fs_info *fs_info)
 }
 
 /*
- * __btrfs_std_error decodes expected errors from the caller and
+ * __btrfs_handle_fs_error decodes expected errors from the caller and
  * invokes the approciate error response.
  */
 __cold
-void __btrfs_std_error(struct btrfs_fs_info *fs_info, const char *function,
+void __btrfs_handle_fs_error(struct btrfs_fs_info *fs_info, const char *function,
                       unsigned int line, int errno, const char *fmt, ...)
 {
        struct super_block *sb = fs_info->sb;
@@ -170,8 +161,13 @@ void __btrfs_std_error(struct btrfs_fs_info *fs_info, const char *function,
        }
 #endif
 
+       /*
+        * Today we only save the error info to memory.  Long term we'll
+        * also send it down to the disk
+        */
+       set_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state);
+
        /* Don't go through full error handling during mount */
-       save_error_info(fs_info);
        if (sb->s_flags & MS_BORN)
                btrfs_handle_error(fs_info);
 }
@@ -239,7 +235,7 @@ void __btrfs_abort_transaction(struct btrfs_trans_handle *trans,
        trans->aborted = errno;
        /* Nothing used. The other threads that have joined this
         * transaction may be able to continue. */
-       if (!trans->blocks_used && list_empty(&trans->new_bgs)) {
+       if (!trans->dirty && list_empty(&trans->new_bgs)) {
                const char *errstr;
 
                errstr = btrfs_decode_error(errno);
@@ -252,7 +248,7 @@ void __btrfs_abort_transaction(struct btrfs_trans_handle *trans,
        /* Wake up anybody who may be waiting on this transaction */
        wake_up(&root->fs_info->transaction_wait);
        wake_up(&root->fs_info->transaction_blocked_wait);
-       __btrfs_std_error(root->fs_info, function, line, errno, NULL);
+       __btrfs_handle_fs_error(root->fs_info, function, line, errno, NULL);
 }
 /*
  * __btrfs_panic decodes unexpected, fatal errors from the caller,
@@ -1160,7 +1156,7 @@ int btrfs_sync_fs(struct super_block *sb, int wait)
                return 0;
        }
 
-       btrfs_wait_ordered_roots(fs_info, -1);
+       btrfs_wait_ordered_roots(fs_info, -1, 0, (u64)-1);
 
        trans = btrfs_attach_transaction_barrier(root);
        if (IS_ERR(trans)) {
@@ -1488,10 +1484,10 @@ static int setup_security_options(struct btrfs_fs_info *fs_info,
                memcpy(&fs_info->security_opts, sec_opts, sizeof(*sec_opts));
        } else {
                /*
-                * Since SELinux(the only one supports security_mnt_opts) does
-                * NOT support changing context during remount/mount same sb,
-                * This must be the same or part of the same security options,
-                * just free it.
+                * Since SELinux (the only one supporting security_mnt_opts)
+                * does NOT support changing context during remount/mount of
+                * the same sb, this must be the same or part of the same
+                * security options, just free it.
                 */
                security_free_mnt_opts(sec_opts);
        }
@@ -1669,8 +1665,8 @@ static inline void btrfs_remount_cleanup(struct btrfs_fs_info *fs_info,
                                         unsigned long old_opts)
 {
        /*
-        * We need cleanup all defragable inodes if the autodefragment is
-        * close or the fs is R/O.
+        * We need to cleanup all defragable inodes if the autodefragment is
+        * close or the filesystem is read only.
         */
        if (btrfs_raw_test_opt(old_opts, AUTO_DEFRAG) &&
            (!btrfs_raw_test_opt(fs_info->mount_opt, AUTO_DEFRAG) ||
@@ -1811,6 +1807,8 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
                        }
                }
                sb->s_flags &= ~MS_RDONLY;
+
+               fs_info->open = 1;
        }
 out:
        wake_up_process(fs_info->transaction_kthread);
@@ -1881,7 +1879,7 @@ static int btrfs_calc_avail_data_space(struct btrfs_root *root, u64 *free_bytes)
        int ret;
 
        /*
-        * We aren't under the device list lock, so this is racey-ish, but good
+        * We aren't under the device list lock, so this is racy-ish, but good
         * enough for our purposes.
         */
        nr_devices = fs_info->fs_devices->open_devices;
@@ -1900,7 +1898,7 @@ static int btrfs_calc_avail_data_space(struct btrfs_root *root, u64 *free_bytes)
        if (!devices_info)
                return -ENOMEM;
 
-       /* calc min stripe number for data space alloction */
+       /* calc min stripe number for data space allocation */
        type = btrfs_get_alloc_profile(root, 1);
        if (type & BTRFS_BLOCK_GROUP_RAID0) {
                min_stripes = 2;
@@ -1936,7 +1934,7 @@ static int btrfs_calc_avail_data_space(struct btrfs_root *root, u64 *free_bytes)
                avail_space *= BTRFS_STRIPE_LEN;
 
                /*
-                * In order to avoid overwritting the superblock on the drive,
+                * In order to avoid overwriting the superblock on the drive,
                 * btrfs starts at an offset of at least 1MB when doing chunk
                 * allocation.
                 */
@@ -2051,9 +2049,10 @@ static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf)
        struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv;
        int ret;
        u64 thresh = 0;
+       int mixed = 0;
 
        /*
-        * holding chunk_muext to avoid allocating new chunks, holding
+        * holding chunk_mutex to avoid allocating new chunks, holding
         * device_list_mutex to avoid the device being removed
         */
        rcu_read_lock();
@@ -2076,8 +2075,17 @@ static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf)
                                }
                        }
                }
-               if (found->flags & BTRFS_BLOCK_GROUP_METADATA)
-                       total_free_meta += found->disk_total - found->disk_used;
+
+               /*
+                * Metadata in mixed block goup profiles are accounted in data
+                */
+               if (!mixed && found->flags & BTRFS_BLOCK_GROUP_METADATA) {
+                       if (found->flags & BTRFS_BLOCK_GROUP_DATA)
+                               mixed = 1;
+                       else
+                               total_free_meta += found->disk_total -
+                                       found->disk_used;
+               }
 
                total_used += found->disk_used;
        }
@@ -2090,7 +2098,11 @@ static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf)
 
        /* Account global block reserve as used, it's in logical size already */
        spin_lock(&block_rsv->lock);
-       buf->f_bfree -= block_rsv->size >> bits;
+       /* Mixed block groups accounting is not byte-accurate, avoid overflow */
+       if (buf->f_bfree >= block_rsv->size >> bits)
+               buf->f_bfree -= block_rsv->size >> bits;
+       else
+               buf->f_bfree = 0;
        spin_unlock(&block_rsv->lock);
 
        buf->f_bavail = div_u64(total_free_data, factor);
@@ -2115,7 +2127,7 @@ static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf)
         */
        thresh = 4 * 1024 * 1024;
 
-       if (total_free_meta - thresh < block_rsv->size)
+       if (!mixed && total_free_meta - thresh < block_rsv->size)
                buf->f_bavail = 0;
 
        buf->f_type = BTRFS_SUPER_MAGIC;
@@ -2293,7 +2305,7 @@ static void btrfs_interface_exit(void)
 
 static void btrfs_print_mod_info(void)
 {
-       printk(KERN_INFO "Btrfs loaded"
+       printk(KERN_INFO "Btrfs loaded, crc32c=%s"
 #ifdef CONFIG_BTRFS_DEBUG
                        ", debug=on"
 #endif
@@ -2303,33 +2315,48 @@ static void btrfs_print_mod_info(void)
 #ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
                        ", integrity-checker=on"
 #endif
-                       "\n");
+                       "\n",
+                       btrfs_crc32c_impl());
 }
 
 static int btrfs_run_sanity_tests(void)
 {
-       int ret;
-
+       int ret, i;
+       u32 sectorsize, nodesize;
+       u32 test_sectorsize[] = {
+               PAGE_SIZE,
+       };
        ret = btrfs_init_test_fs();
        if (ret)
                return ret;
-
-       ret = btrfs_test_free_space_cache();
-       if (ret)
-               goto out;
-       ret = btrfs_test_extent_buffer_operations();
-       if (ret)
-               goto out;
-       ret = btrfs_test_extent_io();
-       if (ret)
-               goto out;
-       ret = btrfs_test_inodes();
-       if (ret)
-               goto out;
-       ret = btrfs_test_qgroups();
-       if (ret)
-               goto out;
-       ret = btrfs_test_free_space_tree();
+       for (i = 0; i < ARRAY_SIZE(test_sectorsize); i++) {
+               sectorsize = test_sectorsize[i];
+               for (nodesize = sectorsize;
+                    nodesize <= BTRFS_MAX_METADATA_BLOCKSIZE;
+                    nodesize <<= 1) {
+                       pr_info("BTRFS: selftest: sectorsize: %u  nodesize: %u\n",
+                               sectorsize, nodesize);
+                       ret = btrfs_test_free_space_cache(sectorsize, nodesize);
+                       if (ret)
+                               goto out;
+                       ret = btrfs_test_extent_buffer_operations(sectorsize,
+                               nodesize);
+                       if (ret)
+                               goto out;
+                       ret = btrfs_test_extent_io(sectorsize, nodesize);
+                       if (ret)
+                               goto out;
+                       ret = btrfs_test_inodes(sectorsize, nodesize);
+                       if (ret)
+                               goto out;
+                       ret = btrfs_test_qgroups(sectorsize, nodesize);
+                       if (ret)
+                               goto out;
+                       ret = btrfs_test_free_space_tree(sectorsize, nodesize);
+                       if (ret)
+                               goto out;
+               }
+       }
 out:
        btrfs_destroy_test_fs();
        return ret;