Commit 572d9ab7845ea0e043ec34cd733a75228130ad03

Authored by David Sterba
1 parent 206c5f60a3

btrfs: add support for processing pending changes

There are some actions that modify global filesystem state but cannot be
performed at the time of request, but later at the transaction commit
time when the filesystem is in a known state.

For example enabling new incompat features on-the-fly or issuing
transaction commit from unsafe contexts (sysfs handlers).

Signed-off-by: David Sterba <dsterba@suse.cz>

Showing 4 changed files with 69 additions and 0 deletions Side-by-side Diff

... ... @@ -1402,6 +1402,11 @@
1402 1402 */
1403 1403 u64 last_trans_log_full_commit;
1404 1404 unsigned long mount_opt;
  1405 + /*
  1406 + * Track requests for actions that need to be done during transaction
  1407 + * commit (like for some mount options).
  1408 + */
  1409 + unsigned long pending_changes;
1405 1410 unsigned long compress_type:4;
1406 1411 int commit_interval;
1407 1412 /*
... ... @@ -2103,6 +2108,7 @@
2103 2108 #define btrfs_raw_test_opt(o, opt) ((o) & BTRFS_MOUNT_##opt)
2104 2109 #define btrfs_test_opt(root, opt) ((root)->fs_info->mount_opt & \
2105 2110 BTRFS_MOUNT_##opt)
  2111 +
2106 2112 #define btrfs_set_and_info(root, opt, fmt, args...) \
2107 2113 { \
2108 2114 if (!btrfs_test_opt(root, opt)) \
... ... @@ -2116,6 +2122,45 @@
2116 2122 btrfs_info(root->fs_info, fmt, ##args); \
2117 2123 btrfs_clear_opt(root->fs_info->mount_opt, opt); \
2118 2124 }
  2125 +
  2126 +/*
  2127 + * Requests for changes that need to be done during transaction commit.
  2128 + *
  2129 + * Internal mount options that are used for special handling of the real
  2130 + * mount options (eg. cannot be set during remount and have to be set during
  2131 + * transaction commit)
  2132 + */
  2133 +
  2134 +#define btrfs_test_pending(info, opt) \
  2135 + test_bit(BTRFS_PENDING_##opt, &(info)->pending_changes)
  2136 +#define btrfs_set_pending(info, opt) \
  2137 + set_bit(BTRFS_PENDING_##opt, &(info)->pending_changes)
  2138 +#define btrfs_clear_pending(info, opt) \
  2139 + clear_bit(BTRFS_PENDING_##opt, &(info)->pending_changes)
  2140 +
  2141 +/*
  2142 + * Helpers for setting pending mount option changes.
  2143 + *
  2144 + * Expects corresponding macros
  2145 + * BTRFS_PENDING_SET_ and CLEAR_ + short mount option name
  2146 + */
  2147 +#define btrfs_set_pending_and_info(info, opt, fmt, args...) \
  2148 +do { \
  2149 + if (!btrfs_raw_test_opt((info)->mount_opt, opt)) { \
  2150 + btrfs_info((info), fmt, ##args); \
  2151 + btrfs_set_pending((info), SET_##opt); \
  2152 + btrfs_clear_pending((info), CLEAR_##opt); \
  2153 + } \
  2154 +} while(0)
  2155 +
  2156 +#define btrfs_clear_pending_and_info(info, opt, fmt, args...) \
  2157 +do { \
  2158 + if (btrfs_raw_test_opt((info)->mount_opt, opt)) { \
  2159 + btrfs_info((info), fmt, ##args); \
  2160 + btrfs_set_pending((info), CLEAR_##opt); \
  2161 + btrfs_clear_pending((info), SET_##opt); \
  2162 + } \
  2163 +} while(0)
2119 2164  
2120 2165 /*
2121 2166 * Inode flags
... ... @@ -2834,6 +2834,12 @@
2834 2834 if (btrfs_test_opt(tree_root, CHANGE_INODE_CACHE))
2835 2835 btrfs_set_opt(tree_root->fs_info->mount_opt, INODE_MAP_CACHE);
2836 2836  
  2837 + /*
  2838 + * Mount does not set all options immediatelly, we can do it now and do
  2839 + * not have to wait for transaction commit
  2840 + */
  2841 + btrfs_apply_pending_changes(fs_info);
  2842 +
2837 2843 #ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
2838 2844 if (btrfs_test_opt(tree_root, CHECK_INTEGRITY)) {
2839 2845 ret = btrfsic_mount(tree_root, fs_devices,
fs/btrfs/transaction.c
... ... @@ -1850,6 +1850,8 @@
1850 1850 else
1851 1851 btrfs_clear_opt(root->fs_info->mount_opt, INODE_MAP_CACHE);
1852 1852  
  1853 + btrfs_apply_pending_changes(root->fs_info);
  1854 +
1853 1855 /* commit_fs_roots gets rid of all the tree log roots, it is now
1854 1856 * safe to free the root of tree log roots
1855 1857 */
... ... @@ -2018,5 +2020,19 @@
2018 2020 ret = btrfs_drop_snapshot(root, NULL, 1, 0);
2019 2021  
2020 2022 return (ret < 0) ? 0 : 1;
  2023 +}
  2024 +
  2025 +void btrfs_apply_pending_changes(struct btrfs_fs_info *fs_info)
  2026 +{
  2027 + unsigned long prev;
  2028 + unsigned long bit;
  2029 +
  2030 + prev = cmpxchg(&fs_info->pending_changes, 0, 0);
  2031 + if (!prev)
  2032 + return;
  2033 +
  2034 + if (prev)
  2035 + btrfs_warn(fs_info,
  2036 + "unknown pending changes left 0x%lx, ignoring", prev);
2021 2037 }
fs/btrfs/transaction.h
... ... @@ -170,5 +170,7 @@
170 170 int btrfs_transaction_blocked(struct btrfs_fs_info *info);
171 171 int btrfs_transaction_in_commit(struct btrfs_fs_info *info);
172 172 void btrfs_put_transaction(struct btrfs_transaction *transaction);
  173 +void btrfs_apply_pending_changes(struct btrfs_fs_info *fs_info);
  174 +
173 175 #endif