diff options
author | Ilya Dryomov <idryomov@gmail.com> | 2012-01-16 15:04:48 -0500 |
---|---|---|
committer | Ilya Dryomov <idryomov@gmail.com> | 2012-01-16 15:04:48 -0500 |
commit | 0940ebf6b92ea10a6f30ae5ac3993a3b75745da6 (patch) | |
tree | 30942cd4eaa259951b549abf7c5c972abc8ab289 /fs | |
parent | cfa4c961cc69ffb7bda450972320a25cbd413e19 (diff) |
Btrfs: save balance parameters to disk
Introduce a new btree objectid for storing balance item. The reason is
to be able to resume restriper after a crash with the same parameters.
Balance item has a very high objectid and goes into tree of tree roots.
The key for the new item is as follows:
[ BTRFS_BALANCE_OBJECTID ; BTRFS_BALANCE_ITEM_KEY ; 0 ]
Older kernels simply ignore it so it's safe to mount with an older
kernel and then go back to the newer one.
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/ctree.h | 133 | ||||
-rw-r--r-- | fs/btrfs/volumes.c | 99 |
2 files changed, 231 insertions, 1 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 1e7aea60da2b..9997a59e4f58 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -86,6 +86,9 @@ struct btrfs_ordered_sum; | |||
86 | /* holds checksums of all the data extents */ | 86 | /* holds checksums of all the data extents */ |
87 | #define BTRFS_CSUM_TREE_OBJECTID 7ULL | 87 | #define BTRFS_CSUM_TREE_OBJECTID 7ULL |
88 | 88 | ||
89 | /* for storing balance parameters in the root tree */ | ||
90 | #define BTRFS_BALANCE_OBJECTID -4ULL | ||
91 | |||
89 | /* orhpan objectid for tracking unlinked/truncated files */ | 92 | /* orhpan objectid for tracking unlinked/truncated files */ |
90 | #define BTRFS_ORPHAN_OBJECTID -5ULL | 93 | #define BTRFS_ORPHAN_OBJECTID -5ULL |
91 | 94 | ||
@@ -692,6 +695,54 @@ struct btrfs_root_ref { | |||
692 | __le16 name_len; | 695 | __le16 name_len; |
693 | } __attribute__ ((__packed__)); | 696 | } __attribute__ ((__packed__)); |
694 | 697 | ||
698 | struct btrfs_disk_balance_args { | ||
699 | /* | ||
700 | * profiles to operate on, single is denoted by | ||
701 | * BTRFS_AVAIL_ALLOC_BIT_SINGLE | ||
702 | */ | ||
703 | __le64 profiles; | ||
704 | |||
705 | /* usage filter */ | ||
706 | __le64 usage; | ||
707 | |||
708 | /* devid filter */ | ||
709 | __le64 devid; | ||
710 | |||
711 | /* devid subset filter [pstart..pend) */ | ||
712 | __le64 pstart; | ||
713 | __le64 pend; | ||
714 | |||
715 | /* btrfs virtual address space subset filter [vstart..vend) */ | ||
716 | __le64 vstart; | ||
717 | __le64 vend; | ||
718 | |||
719 | /* | ||
720 | * profile to convert to, single is denoted by | ||
721 | * BTRFS_AVAIL_ALLOC_BIT_SINGLE | ||
722 | */ | ||
723 | __le64 target; | ||
724 | |||
725 | /* BTRFS_BALANCE_ARGS_* */ | ||
726 | __le64 flags; | ||
727 | |||
728 | __le64 unused[8]; | ||
729 | } __attribute__ ((__packed__)); | ||
730 | |||
731 | /* | ||
732 | * store balance parameters to disk so that balance can be properly | ||
733 | * resumed after crash or unmount | ||
734 | */ | ||
735 | struct btrfs_balance_item { | ||
736 | /* BTRFS_BALANCE_* */ | ||
737 | __le64 flags; | ||
738 | |||
739 | struct btrfs_disk_balance_args data; | ||
740 | struct btrfs_disk_balance_args meta; | ||
741 | struct btrfs_disk_balance_args sys; | ||
742 | |||
743 | __le64 unused[4]; | ||
744 | } __attribute__ ((__packed__)); | ||
745 | |||
695 | #define BTRFS_FILE_EXTENT_INLINE 0 | 746 | #define BTRFS_FILE_EXTENT_INLINE 0 |
696 | #define BTRFS_FILE_EXTENT_REG 1 | 747 | #define BTRFS_FILE_EXTENT_REG 1 |
697 | #define BTRFS_FILE_EXTENT_PREALLOC 2 | 748 | #define BTRFS_FILE_EXTENT_PREALLOC 2 |
@@ -1409,6 +1460,8 @@ struct btrfs_ioctl_defrag_range_args { | |||
1409 | #define BTRFS_DEV_ITEM_KEY 216 | 1460 | #define BTRFS_DEV_ITEM_KEY 216 |
1410 | #define BTRFS_CHUNK_ITEM_KEY 228 | 1461 | #define BTRFS_CHUNK_ITEM_KEY 228 |
1411 | 1462 | ||
1463 | #define BTRFS_BALANCE_ITEM_KEY 248 | ||
1464 | |||
1412 | /* | 1465 | /* |
1413 | * string items are for debugging. They just store a short string of | 1466 | * string items are for debugging. They just store a short string of |
1414 | * data in the FS | 1467 | * data in the FS |
@@ -2103,8 +2156,86 @@ BTRFS_SETGET_STACK_FUNCS(backup_bytes_used, struct btrfs_root_backup, | |||
2103 | BTRFS_SETGET_STACK_FUNCS(backup_num_devices, struct btrfs_root_backup, | 2156 | BTRFS_SETGET_STACK_FUNCS(backup_num_devices, struct btrfs_root_backup, |
2104 | num_devices, 64); | 2157 | num_devices, 64); |
2105 | 2158 | ||
2106 | /* struct btrfs_super_block */ | 2159 | /* struct btrfs_balance_item */ |
2160 | BTRFS_SETGET_FUNCS(balance_flags, struct btrfs_balance_item, flags, 64); | ||
2161 | |||
2162 | static inline void btrfs_balance_data(struct extent_buffer *eb, | ||
2163 | struct btrfs_balance_item *bi, | ||
2164 | struct btrfs_disk_balance_args *ba) | ||
2165 | { | ||
2166 | read_eb_member(eb, bi, struct btrfs_balance_item, data, ba); | ||
2167 | } | ||
2168 | |||
2169 | static inline void btrfs_set_balance_data(struct extent_buffer *eb, | ||
2170 | struct btrfs_balance_item *bi, | ||
2171 | struct btrfs_disk_balance_args *ba) | ||
2172 | { | ||
2173 | write_eb_member(eb, bi, struct btrfs_balance_item, data, ba); | ||
2174 | } | ||
2175 | |||
2176 | static inline void btrfs_balance_meta(struct extent_buffer *eb, | ||
2177 | struct btrfs_balance_item *bi, | ||
2178 | struct btrfs_disk_balance_args *ba) | ||
2179 | { | ||
2180 | read_eb_member(eb, bi, struct btrfs_balance_item, meta, ba); | ||
2181 | } | ||
2182 | |||
2183 | static inline void btrfs_set_balance_meta(struct extent_buffer *eb, | ||
2184 | struct btrfs_balance_item *bi, | ||
2185 | struct btrfs_disk_balance_args *ba) | ||
2186 | { | ||
2187 | write_eb_member(eb, bi, struct btrfs_balance_item, meta, ba); | ||
2188 | } | ||
2189 | |||
2190 | static inline void btrfs_balance_sys(struct extent_buffer *eb, | ||
2191 | struct btrfs_balance_item *bi, | ||
2192 | struct btrfs_disk_balance_args *ba) | ||
2193 | { | ||
2194 | read_eb_member(eb, bi, struct btrfs_balance_item, sys, ba); | ||
2195 | } | ||
2196 | |||
2197 | static inline void btrfs_set_balance_sys(struct extent_buffer *eb, | ||
2198 | struct btrfs_balance_item *bi, | ||
2199 | struct btrfs_disk_balance_args *ba) | ||
2200 | { | ||
2201 | write_eb_member(eb, bi, struct btrfs_balance_item, sys, ba); | ||
2202 | } | ||
2107 | 2203 | ||
2204 | static inline void | ||
2205 | btrfs_disk_balance_args_to_cpu(struct btrfs_balance_args *cpu, | ||
2206 | struct btrfs_disk_balance_args *disk) | ||
2207 | { | ||
2208 | memset(cpu, 0, sizeof(*cpu)); | ||
2209 | |||
2210 | cpu->profiles = le64_to_cpu(disk->profiles); | ||
2211 | cpu->usage = le64_to_cpu(disk->usage); | ||
2212 | cpu->devid = le64_to_cpu(disk->devid); | ||
2213 | cpu->pstart = le64_to_cpu(disk->pstart); | ||
2214 | cpu->pend = le64_to_cpu(disk->pend); | ||
2215 | cpu->vstart = le64_to_cpu(disk->vstart); | ||
2216 | cpu->vend = le64_to_cpu(disk->vend); | ||
2217 | cpu->target = le64_to_cpu(disk->target); | ||
2218 | cpu->flags = le64_to_cpu(disk->flags); | ||
2219 | } | ||
2220 | |||
2221 | static inline void | ||
2222 | btrfs_cpu_balance_args_to_disk(struct btrfs_disk_balance_args *disk, | ||
2223 | struct btrfs_balance_args *cpu) | ||
2224 | { | ||
2225 | memset(disk, 0, sizeof(*disk)); | ||
2226 | |||
2227 | disk->profiles = cpu_to_le64(cpu->profiles); | ||
2228 | disk->usage = cpu_to_le64(cpu->usage); | ||
2229 | disk->devid = cpu_to_le64(cpu->devid); | ||
2230 | disk->pstart = cpu_to_le64(cpu->pstart); | ||
2231 | disk->pend = cpu_to_le64(cpu->pend); | ||
2232 | disk->vstart = cpu_to_le64(cpu->vstart); | ||
2233 | disk->vend = cpu_to_le64(cpu->vend); | ||
2234 | disk->target = cpu_to_le64(cpu->target); | ||
2235 | disk->flags = cpu_to_le64(cpu->flags); | ||
2236 | } | ||
2237 | |||
2238 | /* struct btrfs_super_block */ | ||
2108 | BTRFS_SETGET_STACK_FUNCS(super_bytenr, struct btrfs_super_block, bytenr, 64); | 2239 | BTRFS_SETGET_STACK_FUNCS(super_bytenr, struct btrfs_super_block, bytenr, 64); |
2109 | BTRFS_SETGET_STACK_FUNCS(super_flags, struct btrfs_super_block, flags, 64); | 2240 | BTRFS_SETGET_STACK_FUNCS(super_flags, struct btrfs_super_block, flags, 64); |
2110 | BTRFS_SETGET_STACK_FUNCS(super_generation, struct btrfs_super_block, | 2241 | BTRFS_SETGET_STACK_FUNCS(super_generation, struct btrfs_super_block, |
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 98b4067017ff..4c60ca0ae90b 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -2073,6 +2073,97 @@ error: | |||
2073 | return ret; | 2073 | return ret; |
2074 | } | 2074 | } |
2075 | 2075 | ||
2076 | static int insert_balance_item(struct btrfs_root *root, | ||
2077 | struct btrfs_balance_control *bctl) | ||
2078 | { | ||
2079 | struct btrfs_trans_handle *trans; | ||
2080 | struct btrfs_balance_item *item; | ||
2081 | struct btrfs_disk_balance_args disk_bargs; | ||
2082 | struct btrfs_path *path; | ||
2083 | struct extent_buffer *leaf; | ||
2084 | struct btrfs_key key; | ||
2085 | int ret, err; | ||
2086 | |||
2087 | path = btrfs_alloc_path(); | ||
2088 | if (!path) | ||
2089 | return -ENOMEM; | ||
2090 | |||
2091 | trans = btrfs_start_transaction(root, 0); | ||
2092 | if (IS_ERR(trans)) { | ||
2093 | btrfs_free_path(path); | ||
2094 | return PTR_ERR(trans); | ||
2095 | } | ||
2096 | |||
2097 | key.objectid = BTRFS_BALANCE_OBJECTID; | ||
2098 | key.type = BTRFS_BALANCE_ITEM_KEY; | ||
2099 | key.offset = 0; | ||
2100 | |||
2101 | ret = btrfs_insert_empty_item(trans, root, path, &key, | ||
2102 | sizeof(*item)); | ||
2103 | if (ret) | ||
2104 | goto out; | ||
2105 | |||
2106 | leaf = path->nodes[0]; | ||
2107 | item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_balance_item); | ||
2108 | |||
2109 | memset_extent_buffer(leaf, 0, (unsigned long)item, sizeof(*item)); | ||
2110 | |||
2111 | btrfs_cpu_balance_args_to_disk(&disk_bargs, &bctl->data); | ||
2112 | btrfs_set_balance_data(leaf, item, &disk_bargs); | ||
2113 | btrfs_cpu_balance_args_to_disk(&disk_bargs, &bctl->meta); | ||
2114 | btrfs_set_balance_meta(leaf, item, &disk_bargs); | ||
2115 | btrfs_cpu_balance_args_to_disk(&disk_bargs, &bctl->sys); | ||
2116 | btrfs_set_balance_sys(leaf, item, &disk_bargs); | ||
2117 | |||
2118 | btrfs_set_balance_flags(leaf, item, bctl->flags); | ||
2119 | |||
2120 | btrfs_mark_buffer_dirty(leaf); | ||
2121 | out: | ||
2122 | btrfs_free_path(path); | ||
2123 | err = btrfs_commit_transaction(trans, root); | ||
2124 | if (err && !ret) | ||
2125 | ret = err; | ||
2126 | return ret; | ||
2127 | } | ||
2128 | |||
2129 | static int del_balance_item(struct btrfs_root *root) | ||
2130 | { | ||
2131 | struct btrfs_trans_handle *trans; | ||
2132 | struct btrfs_path *path; | ||
2133 | struct btrfs_key key; | ||
2134 | int ret, err; | ||
2135 | |||
2136 | path = btrfs_alloc_path(); | ||
2137 | if (!path) | ||
2138 | return -ENOMEM; | ||
2139 | |||
2140 | trans = btrfs_start_transaction(root, 0); | ||
2141 | if (IS_ERR(trans)) { | ||
2142 | btrfs_free_path(path); | ||
2143 | return PTR_ERR(trans); | ||
2144 | } | ||
2145 | |||
2146 | key.objectid = BTRFS_BALANCE_OBJECTID; | ||
2147 | key.type = BTRFS_BALANCE_ITEM_KEY; | ||
2148 | key.offset = 0; | ||
2149 | |||
2150 | ret = btrfs_search_slot(trans, root, &key, path, -1, 1); | ||
2151 | if (ret < 0) | ||
2152 | goto out; | ||
2153 | if (ret > 0) { | ||
2154 | ret = -ENOENT; | ||
2155 | goto out; | ||
2156 | } | ||
2157 | |||
2158 | ret = btrfs_del_item(trans, root, path); | ||
2159 | out: | ||
2160 | btrfs_free_path(path); | ||
2161 | err = btrfs_commit_transaction(trans, root); | ||
2162 | if (err && !ret) | ||
2163 | ret = err; | ||
2164 | return ret; | ||
2165 | } | ||
2166 | |||
2076 | /* | 2167 | /* |
2077 | * Should be called with both balance and volume mutexes held to | 2168 | * Should be called with both balance and volume mutexes held to |
2078 | * serialize other volume operations (add_dev/rm_dev/resize) with | 2169 | * serialize other volume operations (add_dev/rm_dev/resize) with |
@@ -2423,7 +2514,11 @@ error: | |||
2423 | 2514 | ||
2424 | static void __cancel_balance(struct btrfs_fs_info *fs_info) | 2515 | static void __cancel_balance(struct btrfs_fs_info *fs_info) |
2425 | { | 2516 | { |
2517 | int ret; | ||
2518 | |||
2426 | unset_balance_control(fs_info); | 2519 | unset_balance_control(fs_info); |
2520 | ret = del_balance_item(fs_info->tree_root); | ||
2521 | BUG_ON(ret); | ||
2427 | } | 2522 | } |
2428 | 2523 | ||
2429 | void update_ioctl_balance_args(struct btrfs_fs_info *fs_info, | 2524 | void update_ioctl_balance_args(struct btrfs_fs_info *fs_info, |
@@ -2530,6 +2625,10 @@ int btrfs_balance(struct btrfs_balance_control *bctl, | |||
2530 | } | 2625 | } |
2531 | 2626 | ||
2532 | do_balance: | 2627 | do_balance: |
2628 | ret = insert_balance_item(fs_info->tree_root, bctl); | ||
2629 | if (ret) | ||
2630 | goto out; | ||
2631 | |||
2533 | set_balance_control(bctl); | 2632 | set_balance_control(bctl); |
2534 | 2633 | ||
2535 | mutex_unlock(&fs_info->balance_mutex); | 2634 | mutex_unlock(&fs_info->balance_mutex); |