diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2013-10-03 12:25:10 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2013-10-24 23:43:26 -0400 |
commit | 30687e0a47e89f56489ab73965ee88231e611986 (patch) | |
tree | 9dedafad3e3f2e54e725d9f1029a6eab159b90ae /fs | |
parent | e2fec7c35582e7bb41cccc1761faa2af4dc17627 (diff) |
hpfs: make freeing sbi and codetables rcu-delayed
makes ->d_hash() and ->d_compare() safety in RCU mode independent
from vfsmount_lock
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/hpfs/hpfs_fn.h | 1 | ||||
-rw-r--r-- | fs/hpfs/super.c | 28 |
2 files changed, 15 insertions, 14 deletions
diff --git a/fs/hpfs/hpfs_fn.h b/fs/hpfs/hpfs_fn.h index 1b398636e990..6797bf80f6e2 100644 --- a/fs/hpfs/hpfs_fn.h +++ b/fs/hpfs/hpfs_fn.h | |||
@@ -80,6 +80,7 @@ struct hpfs_sb_info { | |||
80 | unsigned sb_c_bitmap; /* current bitmap */ | 80 | unsigned sb_c_bitmap; /* current bitmap */ |
81 | unsigned sb_max_fwd_alloc; /* max forwad allocation */ | 81 | unsigned sb_max_fwd_alloc; /* max forwad allocation */ |
82 | int sb_timeshift; | 82 | int sb_timeshift; |
83 | struct rcu_head rcu; | ||
83 | }; | 84 | }; |
84 | 85 | ||
85 | /* Four 512-byte buffers and the 2k block obtained by concatenating them */ | 86 | /* Four 512-byte buffers and the 2k block obtained by concatenating them */ |
diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c index 4334cda8dba1..b8d01ef6f531 100644 --- a/fs/hpfs/super.c +++ b/fs/hpfs/super.c | |||
@@ -101,18 +101,24 @@ int hpfs_stop_cycles(struct super_block *s, int key, int *c1, int *c2, | |||
101 | return 0; | 101 | return 0; |
102 | } | 102 | } |
103 | 103 | ||
104 | static void hpfs_put_super(struct super_block *s) | 104 | static void free_sbi(struct hpfs_sb_info *sbi) |
105 | { | 105 | { |
106 | struct hpfs_sb_info *sbi = hpfs_sb(s); | 106 | kfree(sbi->sb_cp_table); |
107 | kfree(sbi->sb_bmp_dir); | ||
108 | kfree(sbi); | ||
109 | } | ||
107 | 110 | ||
111 | static void lazy_free_sbi(struct rcu_head *rcu) | ||
112 | { | ||
113 | free_sbi(container_of(rcu, struct hpfs_sb_info, rcu)); | ||
114 | } | ||
115 | |||
116 | static void hpfs_put_super(struct super_block *s) | ||
117 | { | ||
108 | hpfs_lock(s); | 118 | hpfs_lock(s); |
109 | unmark_dirty(s); | 119 | unmark_dirty(s); |
110 | hpfs_unlock(s); | 120 | hpfs_unlock(s); |
111 | 121 | call_rcu(&hpfs_sb(s)->rcu, lazy_free_sbi); | |
112 | kfree(sbi->sb_cp_table); | ||
113 | kfree(sbi->sb_bmp_dir); | ||
114 | s->s_fs_info = NULL; | ||
115 | kfree(sbi); | ||
116 | } | 122 | } |
117 | 123 | ||
118 | unsigned hpfs_count_one_bitmap(struct super_block *s, secno secno) | 124 | unsigned hpfs_count_one_bitmap(struct super_block *s, secno secno) |
@@ -485,9 +491,6 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent) | |||
485 | } | 491 | } |
486 | s->s_fs_info = sbi; | 492 | s->s_fs_info = sbi; |
487 | 493 | ||
488 | sbi->sb_bmp_dir = NULL; | ||
489 | sbi->sb_cp_table = NULL; | ||
490 | |||
491 | mutex_init(&sbi->hpfs_mutex); | 494 | mutex_init(&sbi->hpfs_mutex); |
492 | hpfs_lock(s); | 495 | hpfs_lock(s); |
493 | 496 | ||
@@ -679,10 +682,7 @@ bail2: brelse(bh0); | |||
679 | bail1: | 682 | bail1: |
680 | bail0: | 683 | bail0: |
681 | hpfs_unlock(s); | 684 | hpfs_unlock(s); |
682 | kfree(sbi->sb_bmp_dir); | 685 | free_sbi(sbi); |
683 | kfree(sbi->sb_cp_table); | ||
684 | s->s_fs_info = NULL; | ||
685 | kfree(sbi); | ||
686 | return -EINVAL; | 686 | return -EINVAL; |
687 | } | 687 | } |
688 | 688 | ||