diff options
Diffstat (limited to 'fs/super.c')
-rw-r--r-- | fs/super.c | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/fs/super.c b/fs/super.c index 73ab9f9b3571..e63c754447ce 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -243,6 +243,39 @@ static int grab_super(struct super_block *s) __releases(sb_lock) | |||
243 | } | 243 | } |
244 | 244 | ||
245 | /* | 245 | /* |
246 | * grab_super_passive - acquire a passive reference | ||
247 | * @s: reference we are trying to grab | ||
248 | * | ||
249 | * Tries to acquire a passive reference. This is used in places where we | ||
250 | * cannot take an active reference but we need to ensure that the | ||
251 | * superblock does not go away while we are working on it. It returns | ||
252 | * false if a reference was not gained, and returns true with the s_umount | ||
253 | * lock held in read mode if a reference is gained. On successful return, | ||
254 | * the caller must drop the s_umount lock and the passive reference when | ||
255 | * done. | ||
256 | */ | ||
257 | bool grab_super_passive(struct super_block *sb) | ||
258 | { | ||
259 | spin_lock(&sb_lock); | ||
260 | if (list_empty(&sb->s_instances)) { | ||
261 | spin_unlock(&sb_lock); | ||
262 | return false; | ||
263 | } | ||
264 | |||
265 | sb->s_count++; | ||
266 | spin_unlock(&sb_lock); | ||
267 | |||
268 | if (down_read_trylock(&sb->s_umount)) { | ||
269 | if (sb->s_root) | ||
270 | return true; | ||
271 | up_read(&sb->s_umount); | ||
272 | } | ||
273 | |||
274 | put_super(sb); | ||
275 | return false; | ||
276 | } | ||
277 | |||
278 | /* | ||
246 | * Superblock locking. We really ought to get rid of these two. | 279 | * Superblock locking. We really ought to get rid of these two. |
247 | */ | 280 | */ |
248 | void lock_super(struct super_block * sb) | 281 | void lock_super(struct super_block * sb) |