aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIlya Dryomov <idryomov@gmail.com>2012-01-16 15:04:48 -0500
committerIlya Dryomov <idryomov@gmail.com>2012-01-16 15:04:48 -0500
commit0940ebf6b92ea10a6f30ae5ac3993a3b75745da6 (patch)
tree30942cd4eaa259951b549abf7c5c972abc8ab289
parentcfa4c961cc69ffb7bda450972320a25cbd413e19 (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>
-rw-r--r--fs/btrfs/ctree.h133
-rw-r--r--fs/btrfs/volumes.c99
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
698struct 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 */
735struct 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,
2103BTRFS_SETGET_STACK_FUNCS(backup_num_devices, struct btrfs_root_backup, 2156BTRFS_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 */
2160BTRFS_SETGET_FUNCS(balance_flags, struct btrfs_balance_item, flags, 64);
2161
2162static 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
2169static 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
2176static 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
2183static 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
2190static 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
2197static 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
2204static inline void
2205btrfs_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
2221static inline void
2222btrfs_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 */
2108BTRFS_SETGET_STACK_FUNCS(super_bytenr, struct btrfs_super_block, bytenr, 64); 2239BTRFS_SETGET_STACK_FUNCS(super_bytenr, struct btrfs_super_block, bytenr, 64);
2109BTRFS_SETGET_STACK_FUNCS(super_flags, struct btrfs_super_block, flags, 64); 2240BTRFS_SETGET_STACK_FUNCS(super_flags, struct btrfs_super_block, flags, 64);
2110BTRFS_SETGET_STACK_FUNCS(super_generation, struct btrfs_super_block, 2241BTRFS_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
2076static 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);
2121out:
2122 btrfs_free_path(path);
2123 err = btrfs_commit_transaction(trans, root);
2124 if (err && !ret)
2125 ret = err;
2126 return ret;
2127}
2128
2129static 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);
2159out:
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
2424static void __cancel_balance(struct btrfs_fs_info *fs_info) 2515static 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
2429void update_ioctl_balance_args(struct btrfs_fs_info *fs_info, 2524void 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
2532do_balance: 2627do_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);