diff options
author | Qu Wenruo <quwenruo@cn.fujitsu.com> | 2015-04-19 21:53:50 -0400 |
---|---|---|
committer | Chris Mason <clm@fb.com> | 2015-06-10 12:26:23 -0400 |
commit | 9086db86e0b09c39abead4d747119695553e3978 (patch) | |
tree | 26cba099d0d7c8209e036024f70b32d3bd2615e0 | |
parent | d4b804045924d7f8d2ea988be22c4b9e6492ec11 (diff) |
btrfs: qgroup: Add the ability to skip given qgroup for old/new_roots.
This is used by later qgroup fix patches for snapshot.
As current snapshot accounting is done by btrfs_qgroup_inherit(), but
new extent oriented quota mechanism will account extent from
btrfs_copy_root() and other snapshot things, causing wrong result.
So add this ability to handle snapshot accounting.
Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
Signed-off-by: Chris Mason <clm@fb.com>
-rw-r--r-- | fs/btrfs/delayed-ref.h | 8 | ||||
-rw-r--r-- | fs/btrfs/qgroup.c | 8 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 1 | ||||
-rw-r--r-- | fs/btrfs/transaction.h | 23 |
4 files changed, 40 insertions, 0 deletions
diff --git a/fs/btrfs/delayed-ref.h b/fs/btrfs/delayed-ref.h index 4016f963599e..13fb5e6090fe 100644 --- a/fs/btrfs/delayed-ref.h +++ b/fs/btrfs/delayed-ref.h | |||
@@ -175,6 +175,14 @@ struct btrfs_delayed_ref_root { | |||
175 | int flushing; | 175 | int flushing; |
176 | 176 | ||
177 | u64 run_delayed_start; | 177 | u64 run_delayed_start; |
178 | |||
179 | /* | ||
180 | * To make qgroup to skip given root. | ||
181 | * This is for snapshot, as btrfs_qgroup_inherit() will manully | ||
182 | * modify counters for snapshot and its source, so we should skip | ||
183 | * the snapshot in new_root/old_roots or it will get calculated twice | ||
184 | */ | ||
185 | u64 qgroup_to_skip; | ||
178 | }; | 186 | }; |
179 | 187 | ||
180 | extern struct kmem_cache *btrfs_delayed_ref_head_cachep; | 188 | extern struct kmem_cache *btrfs_delayed_ref_head_cachep; |
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c index c5aa0d34940e..d5f1f033b7a0 100644 --- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c | |||
@@ -1394,9 +1394,11 @@ int btrfs_qgroup_prepare_account_extents(struct btrfs_trans_handle *trans, | |||
1394 | struct btrfs_qgroup_extent_record *record; | 1394 | struct btrfs_qgroup_extent_record *record; |
1395 | struct btrfs_delayed_ref_root *delayed_refs; | 1395 | struct btrfs_delayed_ref_root *delayed_refs; |
1396 | struct rb_node *node; | 1396 | struct rb_node *node; |
1397 | u64 qgroup_to_skip; | ||
1397 | int ret = 0; | 1398 | int ret = 0; |
1398 | 1399 | ||
1399 | delayed_refs = &trans->transaction->delayed_refs; | 1400 | delayed_refs = &trans->transaction->delayed_refs; |
1401 | qgroup_to_skip = delayed_refs->qgroup_to_skip; | ||
1400 | 1402 | ||
1401 | /* | 1403 | /* |
1402 | * No need to do lock, since this function will only be called in | 1404 | * No need to do lock, since this function will only be called in |
@@ -1410,6 +1412,8 @@ int btrfs_qgroup_prepare_account_extents(struct btrfs_trans_handle *trans, | |||
1410 | &record->old_roots); | 1412 | &record->old_roots); |
1411 | if (ret < 0) | 1413 | if (ret < 0) |
1412 | break; | 1414 | break; |
1415 | if (qgroup_to_skip) | ||
1416 | ulist_del(record->old_roots, qgroup_to_skip, 0); | ||
1413 | node = rb_next(node); | 1417 | node = rb_next(node); |
1414 | } | 1418 | } |
1415 | return ret; | 1419 | return ret; |
@@ -1702,9 +1706,11 @@ int btrfs_qgroup_account_extents(struct btrfs_trans_handle *trans, | |||
1702 | struct btrfs_delayed_ref_root *delayed_refs; | 1706 | struct btrfs_delayed_ref_root *delayed_refs; |
1703 | struct ulist *new_roots = NULL; | 1707 | struct ulist *new_roots = NULL; |
1704 | struct rb_node *node; | 1708 | struct rb_node *node; |
1709 | u64 qgroup_to_skip; | ||
1705 | int ret = 0; | 1710 | int ret = 0; |
1706 | 1711 | ||
1707 | delayed_refs = &trans->transaction->delayed_refs; | 1712 | delayed_refs = &trans->transaction->delayed_refs; |
1713 | qgroup_to_skip = delayed_refs->qgroup_to_skip; | ||
1708 | while ((node = rb_first(&delayed_refs->dirty_extent_root))) { | 1714 | while ((node = rb_first(&delayed_refs->dirty_extent_root))) { |
1709 | record = rb_entry(node, struct btrfs_qgroup_extent_record, | 1715 | record = rb_entry(node, struct btrfs_qgroup_extent_record, |
1710 | node); | 1716 | node); |
@@ -1719,6 +1725,8 @@ int btrfs_qgroup_account_extents(struct btrfs_trans_handle *trans, | |||
1719 | record->bytenr, (u64)-1, &new_roots); | 1725 | record->bytenr, (u64)-1, &new_roots); |
1720 | if (ret < 0) | 1726 | if (ret < 0) |
1721 | goto cleanup; | 1727 | goto cleanup; |
1728 | if (qgroup_to_skip) | ||
1729 | ulist_del(new_roots, qgroup_to_skip, 0); | ||
1722 | ret = btrfs_qgroup_account_extent(trans, fs_info, | 1730 | ret = btrfs_qgroup_account_extent(trans, fs_info, |
1723 | record->bytenr, record->num_bytes, | 1731 | record->bytenr, record->num_bytes, |
1724 | record->old_roots, new_roots); | 1732 | record->old_roots, new_roots); |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 6f49715cc127..3e3793dcb4c2 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -232,6 +232,7 @@ loop: | |||
232 | cur_trans->delayed_refs.num_heads = 0; | 232 | cur_trans->delayed_refs.num_heads = 0; |
233 | cur_trans->delayed_refs.flushing = 0; | 233 | cur_trans->delayed_refs.flushing = 0; |
234 | cur_trans->delayed_refs.run_delayed_start = 0; | 234 | cur_trans->delayed_refs.run_delayed_start = 0; |
235 | cur_trans->delayed_refs.qgroup_to_skip = 0; | ||
235 | 236 | ||
236 | /* | 237 | /* |
237 | * although the tree mod log is per file system and not per transaction, | 238 | * although the tree mod log is per file system and not per transaction, |
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h index 036fa83d6ccb..eb09c2067fa8 100644 --- a/fs/btrfs/transaction.h +++ b/fs/btrfs/transaction.h | |||
@@ -154,6 +154,29 @@ static inline void btrfs_set_inode_last_trans(struct btrfs_trans_handle *trans, | |||
154 | spin_unlock(&BTRFS_I(inode)->lock); | 154 | spin_unlock(&BTRFS_I(inode)->lock); |
155 | } | 155 | } |
156 | 156 | ||
157 | /* | ||
158 | * Make qgroup codes to skip given qgroupid, means the old/new_roots for | ||
159 | * qgroup won't contain the qgroupid in it. | ||
160 | */ | ||
161 | static inline void btrfs_set_skip_qgroup(struct btrfs_trans_handle *trans, | ||
162 | u64 qgroupid) | ||
163 | { | ||
164 | struct btrfs_delayed_ref_root *delayed_refs; | ||
165 | |||
166 | delayed_refs = &trans->transaction->delayed_refs; | ||
167 | WARN_ON(delayed_refs->qgroup_to_skip); | ||
168 | delayed_refs->qgroup_to_skip = qgroupid; | ||
169 | } | ||
170 | |||
171 | static inline void btrfs_clear_skip_qgroup(struct btrfs_trans_handle *trans) | ||
172 | { | ||
173 | struct btrfs_delayed_ref_root *delayed_refs; | ||
174 | |||
175 | delayed_refs = &trans->transaction->delayed_refs; | ||
176 | WARN_ON(!delayed_refs->qgroup_to_skip); | ||
177 | delayed_refs->qgroup_to_skip = 0; | ||
178 | } | ||
179 | |||
157 | int btrfs_end_transaction(struct btrfs_trans_handle *trans, | 180 | int btrfs_end_transaction(struct btrfs_trans_handle *trans, |
158 | struct btrfs_root *root); | 181 | struct btrfs_root *root); |
159 | struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root, | 182 | struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root, |