Message ID | BANLkTik9NcRhK9MS6G8aVxY9xvgXfpR=hA@mail.gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Yan, Zheng wrote: > On Tue, Jun 14, 2011 at 3:55 AM, Chris Mason <chris.mason@oracle.com> wrote: >> Excerpts from Yan, Zheng's message of 2011-06-13 10:58:35 -0400: >>> The usage of trans_mutex in relocation code is subtle. It controls >>> interaction of relocation >>> with transaction start, transaction commit and snapshot creation. >>> Simple replacing >>> trans_mutex with trans_lock is wrong. >> >> So, I've got a mutex around the reloc_root here and that was almost but >> not quite enough. It looks like the biggest problem is that we need to >> wait in btrfs_record_root_in_trans for anyone inside merge_reloc_roots. >> >> I'm surviving much longer with a patch in place that synchronizes >> btrfs_record_root_in_trans better. >> >> Zheng if you have other comments on the locking please let me know. >> > > following untested patch may help. I've tested this patch, and the bug was triggered in minutes as usual. Also I've tested a patch in an offline email from Chris, which survived the test. -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 378b5b4..0b20dda 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -951,6 +951,7 @@ struct btrfs_fs_info { struct mutex cleaner_mutex; struct mutex chunk_mutex; struct mutex volume_mutex; + struct mutex reloc_mutex; /* * this protects the ordered operations list only while we are * processing all of the entries on it. This way we make diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 9f68c68..28f8b11 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -1714,6 +1714,7 @@ struct btrfs_root *open_ctree(struct super_block *sb, mutex_init(&fs_info->transaction_kthread_mutex); mutex_init(&fs_info->cleaner_mutex); mutex_init(&fs_info->volume_mutex); + mutex_init(&fs_info->reloc_mutex); init_rwsem(&fs_info->extent_commit_sem); init_rwsem(&fs_info->cleanup_work_sem); init_rwsem(&fs_info->subvol_sem); diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index b1ef27c..620e4af 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -1330,18 +1330,20 @@ int btrfs_init_reloc_root(struct btrfs_trans_handle *trans, struct btrfs_root *root) { struct btrfs_root *reloc_root; - struct reloc_control *rc = root->fs_info->reloc_ctl; + struct reloc_control *rc; int clear_rsv = 0; + mutex_lock(&root->fs_info->reloc_mutex); if (root->reloc_root) { reloc_root = root->reloc_root; reloc_root->last_trans = trans->transid; - return 0; + goto unlock; } + rc = root->fs_info->reloc_ctl; if (!rc || !rc->create_reloc_tree || root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID) - return 0; + goto unlock; if (!trans->block_rsv) {