aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/qgroup.c
diff options
context:
space:
mode:
authorJan Schmidt <list.btrfs@jan-o-sch.net>2013-04-24 12:57:33 -0400
committerJosef Bacik <jbacik@fusionio.com>2013-05-06 15:55:17 -0400
commitfc36ed7e0b13955ba66fc56dc5067e67ac105150 (patch)
treedea2b4ebd056c6e87e5dea53c8df20e0509b88db /fs/btrfs/qgroup.c
parent6d49ba1b47b9c6822d08f90af6f1a2d8ca1cf533 (diff)
Btrfs: separate sequence numbers for delayed ref tracking and tree mod log
Sequence numbers for delayed refs have been introduced in the first version of the qgroup patch set. To solve the problem of find_all_roots on a busy file system, the tree mod log was introduced. The sequence numbers for that were simply shared between those two users. However, at one point in qgroup's quota accounting, there's a statement accessing the previous sequence number, that's still just doing (seq - 1) just as it would have to in the very first version. To satisfy that requirement, this patch makes the sequence number counter 64 bit and splits it into a major part (used for qgroup sequence number counting) and a minor part (incremented for each tree modification in the log). This enables us to go exactly one major step backwards, as required for qgroups, while still incrementing the sequence counter for tree mod log insertions to keep track of their order. Keeping them in a single variable means there's no need to change all the code dealing with comparisons of two sequence numbers. The sequence number is reset to 0 on commit (not new in this patch), which ensures we won't overflow the two 32 bit counters. Without this fix, the qgroup tracking can occasionally go wrong and WARN_ONs from the tree mod log code may happen. Signed-off-by: Jan Schmidt <list.btrfs@jan-o-sch.net> Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Diffstat (limited to 'fs/btrfs/qgroup.c')
-rw-r--r--fs/btrfs/qgroup.c13
1 files changed, 8 insertions, 5 deletions
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
index f175471da882..e5c56238b6c6 100644
--- a/fs/btrfs/qgroup.c
+++ b/fs/btrfs/qgroup.c
@@ -1242,9 +1242,11 @@ int btrfs_qgroup_account_ref(struct btrfs_trans_handle *trans,
1242 case BTRFS_ADD_DELAYED_REF: 1242 case BTRFS_ADD_DELAYED_REF:
1243 case BTRFS_ADD_DELAYED_EXTENT: 1243 case BTRFS_ADD_DELAYED_EXTENT:
1244 sgn = 1; 1244 sgn = 1;
1245 seq = btrfs_tree_mod_seq_prev(node->seq);
1245 break; 1246 break;
1246 case BTRFS_DROP_DELAYED_REF: 1247 case BTRFS_DROP_DELAYED_REF:
1247 sgn = -1; 1248 sgn = -1;
1249 seq = node->seq;
1248 break; 1250 break;
1249 case BTRFS_UPDATE_DELAYED_HEAD: 1251 case BTRFS_UPDATE_DELAYED_HEAD:
1250 return 0; 1252 return 0;
@@ -1254,14 +1256,14 @@ int btrfs_qgroup_account_ref(struct btrfs_trans_handle *trans,
1254 1256
1255 /* 1257 /*
1256 * the delayed ref sequence number we pass depends on the direction of 1258 * the delayed ref sequence number we pass depends on the direction of
1257 * the operation. for add operations, we pass (node->seq - 1) to skip 1259 * the operation. for add operations, we pass
1260 * tree_mod_log_prev_seq(node->seq) to skip
1258 * the delayed ref's current sequence number, because we need the state 1261 * the delayed ref's current sequence number, because we need the state
1259 * of the tree before the add operation. for delete operations, we pass 1262 * of the tree before the add operation. for delete operations, we pass
1260 * (node->seq) to include the delayed ref's current sequence number, 1263 * (node->seq) to include the delayed ref's current sequence number,
1261 * because we need the state of the tree after the delete operation. 1264 * because we need the state of the tree after the delete operation.
1262 */ 1265 */
1263 ret = btrfs_find_all_roots(trans, fs_info, node->bytenr, 1266 ret = btrfs_find_all_roots(trans, fs_info, node->bytenr, seq, &roots);
1264 sgn > 0 ? node->seq - 1 : node->seq, &roots);
1265 if (ret < 0) 1267 if (ret < 0)
1266 return ret; 1268 return ret;
1267 1269
@@ -1772,8 +1774,9 @@ void assert_qgroups_uptodate(struct btrfs_trans_handle *trans)
1772{ 1774{
1773 if (list_empty(&trans->qgroup_ref_list) && !trans->delayed_ref_elem.seq) 1775 if (list_empty(&trans->qgroup_ref_list) && !trans->delayed_ref_elem.seq)
1774 return; 1776 return;
1775 printk(KERN_ERR "btrfs: qgroups not uptodate in trans handle %p: list is%s empty, seq is %llu\n", 1777 pr_err("btrfs: qgroups not uptodate in trans handle %p: list is%s empty, seq is %#x.%x\n",
1776 trans, list_empty(&trans->qgroup_ref_list) ? "" : " not", 1778 trans, list_empty(&trans->qgroup_ref_list) ? "" : " not",
1777 trans->delayed_ref_elem.seq); 1779 (u32)(trans->delayed_ref_elem.seq >> 32),
1780 (u32)trans->delayed_ref_elem.seq);
1778 BUG(); 1781 BUG();
1779} 1782}