diff options
Diffstat (limited to 'fs/super.c')
-rw-r--r-- | fs/super.c | 45 |
1 files changed, 19 insertions, 26 deletions
diff --git a/fs/super.c b/fs/super.c index bc734f8b3e18..157657b32798 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -178,53 +178,48 @@ void put_super(struct super_block *sb) | |||
178 | 178 | ||
179 | 179 | ||
180 | /** | 180 | /** |
181 | * deactivate_super - drop an active reference to superblock | 181 | * deactivate_locked_super - drop an active reference to superblock |
182 | * @s: superblock to deactivate | 182 | * @s: superblock to deactivate |
183 | * | 183 | * |
184 | * Drops an active reference to superblock, acquiring a temprory one if | 184 | * Drops an active reference to superblock, converting it into a temprory |
185 | * there is no active references left. In that case we lock superblock, | 185 | * one if there is no other active references left. In that case we |
186 | * tell fs driver to shut it down and drop the temporary reference we | 186 | * tell fs driver to shut it down and drop the temporary reference we |
187 | * had just acquired. | 187 | * had just acquired. |
188 | * | ||
189 | * Caller holds exclusive lock on superblock; that lock is released. | ||
188 | */ | 190 | */ |
189 | void deactivate_super(struct super_block *s) | 191 | void deactivate_locked_super(struct super_block *s) |
190 | { | 192 | { |
191 | struct file_system_type *fs = s->s_type; | 193 | struct file_system_type *fs = s->s_type; |
192 | if (atomic_dec_and_test(&s->s_active)) { | 194 | if (atomic_dec_and_test(&s->s_active)) { |
193 | vfs_dq_off(s, 0); | 195 | vfs_dq_off(s, 0); |
194 | down_write(&s->s_umount); | ||
195 | fs->kill_sb(s); | 196 | fs->kill_sb(s); |
196 | put_filesystem(fs); | 197 | put_filesystem(fs); |
197 | put_super(s); | 198 | put_super(s); |
199 | } else { | ||
200 | up_write(&s->s_umount); | ||
198 | } | 201 | } |
199 | } | 202 | } |
200 | 203 | ||
201 | EXPORT_SYMBOL(deactivate_super); | 204 | EXPORT_SYMBOL(deactivate_locked_super); |
202 | 205 | ||
203 | /** | 206 | /** |
204 | * deactivate_locked_super - drop an active reference to superblock | 207 | * deactivate_super - drop an active reference to superblock |
205 | * @s: superblock to deactivate | 208 | * @s: superblock to deactivate |
206 | * | 209 | * |
207 | * Equivalent of up_write(&s->s_umount); deactivate_super(s);, except that | 210 | * Variant of deactivate_locked_super(), except that superblock is *not* |
208 | * it does not unlock it until it's all over. As the result, it's safe to | 211 | * locked by caller. If we are going to drop the final active reference, |
209 | * use to dispose of new superblock on ->get_sb() failure exits - nobody | 212 | * lock will be acquired prior to that. |
210 | * will see the sucker until it's all over. Equivalent using up_write + | ||
211 | * deactivate_super is safe for that purpose only if superblock is either | ||
212 | * safe to use or has NULL ->s_root when we unlock. | ||
213 | */ | 213 | */ |
214 | void deactivate_locked_super(struct super_block *s) | 214 | void deactivate_super(struct super_block *s) |
215 | { | 215 | { |
216 | struct file_system_type *fs = s->s_type; | 216 | if (!atomic_add_unless(&s->s_active, -1, 1)) { |
217 | if (atomic_dec_and_test(&s->s_active)) { | 217 | down_write(&s->s_umount); |
218 | vfs_dq_off(s, 0); | 218 | deactivate_locked_super(s); |
219 | fs->kill_sb(s); | ||
220 | put_filesystem(fs); | ||
221 | put_super(s); | ||
222 | } else { | ||
223 | up_write(&s->s_umount); | ||
224 | } | 219 | } |
225 | } | 220 | } |
226 | 221 | ||
227 | EXPORT_SYMBOL(deactivate_locked_super); | 222 | EXPORT_SYMBOL(deactivate_super); |
228 | 223 | ||
229 | /** | 224 | /** |
230 | * grab_super - acquire an active reference | 225 | * grab_super - acquire an active reference |
@@ -247,12 +242,10 @@ static int grab_super(struct super_block *s) __releases(sb_lock) | |||
247 | /* it's going away */ | 242 | /* it's going away */ |
248 | s->s_count++; | 243 | s->s_count++; |
249 | spin_unlock(&sb_lock); | 244 | spin_unlock(&sb_lock); |
250 | /* usually that'll be enough for it to die... */ | 245 | /* wait for it to die */ |
251 | down_write(&s->s_umount); | 246 | down_write(&s->s_umount); |
252 | up_write(&s->s_umount); | 247 | up_write(&s->s_umount); |
253 | put_super(s); | 248 | put_super(s); |
254 | /* ... but in case it wasn't, let's at least yield() */ | ||
255 | yield(); | ||
256 | return 0; | 249 | return 0; |
257 | } | 250 | } |
258 | 251 | ||