diff options
author | Jan Schmidt <list.btrfs@jan-o-sch.net> | 2012-05-31 08:00:15 -0400 |
---|---|---|
committer | Jan Schmidt <list.btrfs@jan-o-sch.net> | 2012-05-31 13:56:18 -0400 |
commit | 926dd8a640da1bbf7478eebea1c23a842fc9c890 (patch) | |
tree | 92ca5d559964d910575de487fdb66372ad5caa60 /fs/btrfs/ctree.c | |
parent | 3301958b7c1dae8f0f5ded63aa881e0b71e78464 (diff) |
Btrfs: add missing spin_lock for insertion into tree mod log
tree_mod_alloc calls __get_tree_mod_seq and must acquire a spinlock before
doing so.
Signed-off-by: Jan Schmidt <list.btrfs@jan-o-sch.net>
Diffstat (limited to 'fs/btrfs/ctree.c')
-rw-r--r-- | fs/btrfs/ctree.c | 23 |
1 files changed, 18 insertions, 5 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 0954f1770fd0..26e8dc1681b0 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -455,11 +455,11 @@ unlock: | |||
455 | return ret; | 455 | return ret; |
456 | } | 456 | } |
457 | 457 | ||
458 | int tree_mod_alloc(struct btrfs_fs_info *fs_info, gfp_t flags, | 458 | static inline int tree_mod_alloc(struct btrfs_fs_info *fs_info, gfp_t flags, |
459 | struct tree_mod_elem **tm_ret) | 459 | struct tree_mod_elem **tm_ret) |
460 | { | 460 | { |
461 | struct tree_mod_elem *tm; | 461 | struct tree_mod_elem *tm; |
462 | u64 seq = 0; | 462 | int seq; |
463 | 463 | ||
464 | smp_mb(); | 464 | smp_mb(); |
465 | if (list_empty(&fs_info->tree_mod_seq_list)) | 465 | if (list_empty(&fs_info->tree_mod_seq_list)) |
@@ -469,9 +469,22 @@ int tree_mod_alloc(struct btrfs_fs_info *fs_info, gfp_t flags, | |||
469 | if (!tm) | 469 | if (!tm) |
470 | return -ENOMEM; | 470 | return -ENOMEM; |
471 | 471 | ||
472 | __get_tree_mod_seq(fs_info, &tm->elem); | ||
473 | seq = tm->elem.seq; | ||
474 | tm->elem.flags = 0; | 472 | tm->elem.flags = 0; |
473 | spin_lock(&fs_info->tree_mod_seq_lock); | ||
474 | if (list_empty(&fs_info->tree_mod_seq_list)) { | ||
475 | /* | ||
476 | * someone emptied the list while we were waiting for the lock. | ||
477 | * we must not add to the list, because no blocker exists. items | ||
478 | * are removed from the list only when the existing blocker is | ||
479 | * removed from the list. | ||
480 | */ | ||
481 | kfree(tm); | ||
482 | seq = 0; | ||
483 | } else { | ||
484 | __get_tree_mod_seq(fs_info, &tm->elem); | ||
485 | seq = tm->elem.seq; | ||
486 | } | ||
487 | spin_unlock(&fs_info->tree_mod_seq_lock); | ||
475 | 488 | ||
476 | return seq; | 489 | return seq; |
477 | } | 490 | } |