|
@@ -4475,9 +4475,80 @@ again:
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void btrfs_cleanup_bg_io(struct btrfs_block_group_cache *cache)
|
|
|
|
+{
|
|
|
|
+ struct inode *inode;
|
|
|
|
+
|
|
|
|
+ inode = cache->io_ctl.inode;
|
|
|
|
+ if (inode) {
|
|
|
|
+ invalidate_inode_pages2(inode->i_mapping);
|
|
|
|
+ BTRFS_I(inode)->generation = 0;
|
|
|
|
+ cache->io_ctl.inode = NULL;
|
|
|
|
+ iput(inode);
|
|
|
|
+ }
|
|
|
|
+ btrfs_put_block_group(cache);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void btrfs_cleanup_dirty_bgs(struct btrfs_transaction *cur_trans,
|
|
|
|
+ struct btrfs_root *root)
|
|
|
|
+{
|
|
|
|
+ struct btrfs_block_group_cache *cache;
|
|
|
|
+
|
|
|
|
+ spin_lock(&cur_trans->dirty_bgs_lock);
|
|
|
|
+ while (!list_empty(&cur_trans->dirty_bgs)) {
|
|
|
|
+ cache = list_first_entry(&cur_trans->dirty_bgs,
|
|
|
|
+ struct btrfs_block_group_cache,
|
|
|
|
+ dirty_list);
|
|
|
|
+ if (!cache) {
|
|
|
|
+ btrfs_err(root->fs_info,
|
|
|
|
+ "orphan block group dirty_bgs list");
|
|
|
|
+ spin_unlock(&cur_trans->dirty_bgs_lock);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!list_empty(&cache->io_list)) {
|
|
|
|
+ spin_unlock(&cur_trans->dirty_bgs_lock);
|
|
|
|
+ list_del_init(&cache->io_list);
|
|
|
|
+ btrfs_cleanup_bg_io(cache);
|
|
|
|
+ spin_lock(&cur_trans->dirty_bgs_lock);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ list_del_init(&cache->dirty_list);
|
|
|
|
+ spin_lock(&cache->lock);
|
|
|
|
+ cache->disk_cache_state = BTRFS_DC_ERROR;
|
|
|
|
+ spin_unlock(&cache->lock);
|
|
|
|
+
|
|
|
|
+ spin_unlock(&cur_trans->dirty_bgs_lock);
|
|
|
|
+ btrfs_put_block_group(cache);
|
|
|
|
+ spin_lock(&cur_trans->dirty_bgs_lock);
|
|
|
|
+ }
|
|
|
|
+ spin_unlock(&cur_trans->dirty_bgs_lock);
|
|
|
|
+
|
|
|
|
+ while (!list_empty(&cur_trans->io_bgs)) {
|
|
|
|
+ cache = list_first_entry(&cur_trans->io_bgs,
|
|
|
|
+ struct btrfs_block_group_cache,
|
|
|
|
+ io_list);
|
|
|
|
+ if (!cache) {
|
|
|
|
+ btrfs_err(root->fs_info,
|
|
|
|
+ "orphan block group on io_bgs list");
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ list_del_init(&cache->io_list);
|
|
|
|
+ spin_lock(&cache->lock);
|
|
|
|
+ cache->disk_cache_state = BTRFS_DC_ERROR;
|
|
|
|
+ spin_unlock(&cache->lock);
|
|
|
|
+ btrfs_cleanup_bg_io(cache);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
void btrfs_cleanup_one_transaction(struct btrfs_transaction *cur_trans,
|
|
void btrfs_cleanup_one_transaction(struct btrfs_transaction *cur_trans,
|
|
struct btrfs_root *root)
|
|
struct btrfs_root *root)
|
|
{
|
|
{
|
|
|
|
+ btrfs_cleanup_dirty_bgs(cur_trans, root);
|
|
|
|
+ ASSERT(list_empty(&cur_trans->dirty_bgs));
|
|
|
|
+ ASSERT(list_empty(&cur_trans->io_bgs));
|
|
|
|
+
|
|
btrfs_destroy_delayed_refs(cur_trans, root);
|
|
btrfs_destroy_delayed_refs(cur_trans, root);
|
|
|
|
|
|
cur_trans->state = TRANS_STATE_COMMIT_START;
|
|
cur_trans->state = TRANS_STATE_COMMIT_START;
|