diff options
Diffstat (limited to 'fs/super.c')
-rw-r--r-- | fs/super.c | 321 |
1 files changed, 183 insertions, 138 deletions
diff --git a/fs/super.c b/fs/super.c index 1527e6a0ee35..69688b15f1fa 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -22,23 +22,15 @@ | |||
22 | 22 | ||
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <linux/init.h> | ||
26 | #include <linux/smp_lock.h> | ||
27 | #include <linux/acct.h> | 25 | #include <linux/acct.h> |
28 | #include <linux/blkdev.h> | 26 | #include <linux/blkdev.h> |
29 | #include <linux/quotaops.h> | 27 | #include <linux/quotaops.h> |
30 | #include <linux/namei.h> | ||
31 | #include <linux/mount.h> | 28 | #include <linux/mount.h> |
32 | #include <linux/security.h> | 29 | #include <linux/security.h> |
33 | #include <linux/syscalls.h> | ||
34 | #include <linux/vfs.h> | ||
35 | #include <linux/writeback.h> /* for the emergency remount stuff */ | 30 | #include <linux/writeback.h> /* for the emergency remount stuff */ |
36 | #include <linux/idr.h> | 31 | #include <linux/idr.h> |
37 | #include <linux/kobject.h> | ||
38 | #include <linux/mutex.h> | 32 | #include <linux/mutex.h> |
39 | #include <linux/file.h> | ||
40 | #include <linux/backing-dev.h> | 33 | #include <linux/backing-dev.h> |
41 | #include <asm/uaccess.h> | ||
42 | #include "internal.h" | 34 | #include "internal.h" |
43 | 35 | ||
44 | 36 | ||
@@ -93,9 +85,10 @@ static struct super_block *alloc_super(struct file_system_type *type) | |||
93 | * subclass. | 85 | * subclass. |
94 | */ | 86 | */ |
95 | down_write_nested(&s->s_umount, SINGLE_DEPTH_NESTING); | 87 | down_write_nested(&s->s_umount, SINGLE_DEPTH_NESTING); |
96 | s->s_count = S_BIAS; | 88 | s->s_count = 1; |
97 | atomic_set(&s->s_active, 1); | 89 | atomic_set(&s->s_active, 1); |
98 | mutex_init(&s->s_vfs_rename_mutex); | 90 | mutex_init(&s->s_vfs_rename_mutex); |
91 | lockdep_set_class(&s->s_vfs_rename_mutex, &type->s_vfs_rename_key); | ||
99 | mutex_init(&s->s_dquot.dqio_mutex); | 92 | mutex_init(&s->s_dquot.dqio_mutex); |
100 | mutex_init(&s->s_dquot.dqonoff_mutex); | 93 | mutex_init(&s->s_dquot.dqonoff_mutex); |
101 | init_rwsem(&s->s_dquot.dqptr_sem); | 94 | init_rwsem(&s->s_dquot.dqptr_sem); |
@@ -127,39 +120,14 @@ static inline void destroy_super(struct super_block *s) | |||
127 | /* Superblock refcounting */ | 120 | /* Superblock refcounting */ |
128 | 121 | ||
129 | /* | 122 | /* |
130 | * Drop a superblock's refcount. Returns non-zero if the superblock was | 123 | * Drop a superblock's refcount. The caller must hold sb_lock. |
131 | * destroyed. The caller must hold sb_lock. | ||
132 | */ | 124 | */ |
133 | static int __put_super(struct super_block *sb) | 125 | void __put_super(struct super_block *sb) |
134 | { | 126 | { |
135 | int ret = 0; | ||
136 | |||
137 | if (!--sb->s_count) { | 127 | if (!--sb->s_count) { |
128 | list_del_init(&sb->s_list); | ||
138 | destroy_super(sb); | 129 | destroy_super(sb); |
139 | ret = 1; | ||
140 | } | 130 | } |
141 | return ret; | ||
142 | } | ||
143 | |||
144 | /* | ||
145 | * Drop a superblock's refcount. | ||
146 | * Returns non-zero if the superblock is about to be destroyed and | ||
147 | * at least is already removed from super_blocks list, so if we are | ||
148 | * making a loop through super blocks then we need to restart. | ||
149 | * The caller must hold sb_lock. | ||
150 | */ | ||
151 | int __put_super_and_need_restart(struct super_block *sb) | ||
152 | { | ||
153 | /* check for race with generic_shutdown_super() */ | ||
154 | if (list_empty(&sb->s_list)) { | ||
155 | /* super block is removed, need to restart... */ | ||
156 | __put_super(sb); | ||
157 | return 1; | ||
158 | } | ||
159 | /* can't be the last, since s_list is still in use */ | ||
160 | sb->s_count--; | ||
161 | BUG_ON(sb->s_count == 0); | ||
162 | return 0; | ||
163 | } | 131 | } |
164 | 132 | ||
165 | /** | 133 | /** |
@@ -178,57 +146,48 @@ void put_super(struct super_block *sb) | |||
178 | 146 | ||
179 | 147 | ||
180 | /** | 148 | /** |
181 | * deactivate_super - drop an active reference to superblock | 149 | * deactivate_locked_super - drop an active reference to superblock |
182 | * @s: superblock to deactivate | 150 | * @s: superblock to deactivate |
183 | * | 151 | * |
184 | * Drops an active reference to superblock, acquiring a temprory one if | 152 | * Drops an active reference to superblock, converting it into a temprory |
185 | * there is no active references left. In that case we lock superblock, | 153 | * 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 | 154 | * tell fs driver to shut it down and drop the temporary reference we |
187 | * had just acquired. | 155 | * had just acquired. |
156 | * | ||
157 | * Caller holds exclusive lock on superblock; that lock is released. | ||
188 | */ | 158 | */ |
189 | void deactivate_super(struct super_block *s) | 159 | void deactivate_locked_super(struct super_block *s) |
190 | { | 160 | { |
191 | struct file_system_type *fs = s->s_type; | 161 | struct file_system_type *fs = s->s_type; |
192 | if (atomic_dec_and_lock(&s->s_active, &sb_lock)) { | 162 | if (atomic_dec_and_test(&s->s_active)) { |
193 | s->s_count -= S_BIAS-1; | ||
194 | spin_unlock(&sb_lock); | ||
195 | vfs_dq_off(s, 0); | 163 | vfs_dq_off(s, 0); |
196 | down_write(&s->s_umount); | ||
197 | fs->kill_sb(s); | 164 | fs->kill_sb(s); |
198 | put_filesystem(fs); | 165 | put_filesystem(fs); |
199 | put_super(s); | 166 | put_super(s); |
167 | } else { | ||
168 | up_write(&s->s_umount); | ||
200 | } | 169 | } |
201 | } | 170 | } |
202 | 171 | ||
203 | EXPORT_SYMBOL(deactivate_super); | 172 | EXPORT_SYMBOL(deactivate_locked_super); |
204 | 173 | ||
205 | /** | 174 | /** |
206 | * deactivate_locked_super - drop an active reference to superblock | 175 | * deactivate_super - drop an active reference to superblock |
207 | * @s: superblock to deactivate | 176 | * @s: superblock to deactivate |
208 | * | 177 | * |
209 | * Equivalent of up_write(&s->s_umount); deactivate_super(s);, except that | 178 | * Variant of deactivate_locked_super(), except that superblock is *not* |
210 | * it does not unlock it until it's all over. As the result, it's safe to | 179 | * locked by caller. If we are going to drop the final active reference, |
211 | * use to dispose of new superblock on ->get_sb() failure exits - nobody | 180 | * lock will be acquired prior to that. |
212 | * will see the sucker until it's all over. Equivalent using up_write + | ||
213 | * deactivate_super is safe for that purpose only if superblock is either | ||
214 | * safe to use or has NULL ->s_root when we unlock. | ||
215 | */ | 181 | */ |
216 | void deactivate_locked_super(struct super_block *s) | 182 | void deactivate_super(struct super_block *s) |
217 | { | 183 | { |
218 | struct file_system_type *fs = s->s_type; | 184 | if (!atomic_add_unless(&s->s_active, -1, 1)) { |
219 | if (atomic_dec_and_lock(&s->s_active, &sb_lock)) { | 185 | down_write(&s->s_umount); |
220 | s->s_count -= S_BIAS-1; | 186 | deactivate_locked_super(s); |
221 | spin_unlock(&sb_lock); | ||
222 | vfs_dq_off(s, 0); | ||
223 | fs->kill_sb(s); | ||
224 | put_filesystem(fs); | ||
225 | put_super(s); | ||
226 | } else { | ||
227 | up_write(&s->s_umount); | ||
228 | } | 187 | } |
229 | } | 188 | } |
230 | 189 | ||
231 | EXPORT_SYMBOL(deactivate_locked_super); | 190 | EXPORT_SYMBOL(deactivate_super); |
232 | 191 | ||
233 | /** | 192 | /** |
234 | * grab_super - acquire an active reference | 193 | * grab_super - acquire an active reference |
@@ -243,22 +202,17 @@ EXPORT_SYMBOL(deactivate_locked_super); | |||
243 | */ | 202 | */ |
244 | static int grab_super(struct super_block *s) __releases(sb_lock) | 203 | static int grab_super(struct super_block *s) __releases(sb_lock) |
245 | { | 204 | { |
205 | if (atomic_inc_not_zero(&s->s_active)) { | ||
206 | spin_unlock(&sb_lock); | ||
207 | return 1; | ||
208 | } | ||
209 | /* it's going away */ | ||
246 | s->s_count++; | 210 | s->s_count++; |
247 | spin_unlock(&sb_lock); | 211 | spin_unlock(&sb_lock); |
212 | /* wait for it to die */ | ||
248 | down_write(&s->s_umount); | 213 | down_write(&s->s_umount); |
249 | if (s->s_root) { | ||
250 | spin_lock(&sb_lock); | ||
251 | if (s->s_count > S_BIAS) { | ||
252 | atomic_inc(&s->s_active); | ||
253 | s->s_count--; | ||
254 | spin_unlock(&sb_lock); | ||
255 | return 1; | ||
256 | } | ||
257 | spin_unlock(&sb_lock); | ||
258 | } | ||
259 | up_write(&s->s_umount); | 214 | up_write(&s->s_umount); |
260 | put_super(s); | 215 | put_super(s); |
261 | yield(); | ||
262 | return 0; | 216 | return 0; |
263 | } | 217 | } |
264 | 218 | ||
@@ -321,8 +275,7 @@ void generic_shutdown_super(struct super_block *sb) | |||
321 | } | 275 | } |
322 | spin_lock(&sb_lock); | 276 | spin_lock(&sb_lock); |
323 | /* should be initialized for __put_super_and_need_restart() */ | 277 | /* should be initialized for __put_super_and_need_restart() */ |
324 | list_del_init(&sb->s_list); | 278 | list_del_init(&sb->s_instances); |
325 | list_del(&sb->s_instances); | ||
326 | spin_unlock(&sb_lock); | 279 | spin_unlock(&sb_lock); |
327 | up_write(&sb->s_umount); | 280 | up_write(&sb->s_umount); |
328 | } | 281 | } |
@@ -357,6 +310,7 @@ retry: | |||
357 | up_write(&s->s_umount); | 310 | up_write(&s->s_umount); |
358 | destroy_super(s); | 311 | destroy_super(s); |
359 | } | 312 | } |
313 | down_write(&old->s_umount); | ||
360 | return old; | 314 | return old; |
361 | } | 315 | } |
362 | } | 316 | } |
@@ -408,11 +362,12 @@ EXPORT_SYMBOL(drop_super); | |||
408 | */ | 362 | */ |
409 | void sync_supers(void) | 363 | void sync_supers(void) |
410 | { | 364 | { |
411 | struct super_block *sb; | 365 | struct super_block *sb, *n; |
412 | 366 | ||
413 | spin_lock(&sb_lock); | 367 | spin_lock(&sb_lock); |
414 | restart: | 368 | list_for_each_entry_safe(sb, n, &super_blocks, s_list) { |
415 | list_for_each_entry(sb, &super_blocks, s_list) { | 369 | if (list_empty(&sb->s_instances)) |
370 | continue; | ||
416 | if (sb->s_op->write_super && sb->s_dirt) { | 371 | if (sb->s_op->write_super && sb->s_dirt) { |
417 | sb->s_count++; | 372 | sb->s_count++; |
418 | spin_unlock(&sb_lock); | 373 | spin_unlock(&sb_lock); |
@@ -423,14 +378,43 @@ restart: | |||
423 | up_read(&sb->s_umount); | 378 | up_read(&sb->s_umount); |
424 | 379 | ||
425 | spin_lock(&sb_lock); | 380 | spin_lock(&sb_lock); |
426 | if (__put_super_and_need_restart(sb)) | 381 | __put_super(sb); |
427 | goto restart; | ||
428 | } | 382 | } |
429 | } | 383 | } |
430 | spin_unlock(&sb_lock); | 384 | spin_unlock(&sb_lock); |
431 | } | 385 | } |
432 | 386 | ||
433 | /** | 387 | /** |
388 | * iterate_supers - call function for all active superblocks | ||
389 | * @f: function to call | ||
390 | * @arg: argument to pass to it | ||
391 | * | ||
392 | * Scans the superblock list and calls given function, passing it | ||
393 | * locked superblock and given argument. | ||
394 | */ | ||
395 | void iterate_supers(void (*f)(struct super_block *, void *), void *arg) | ||
396 | { | ||
397 | struct super_block *sb, *n; | ||
398 | |||
399 | spin_lock(&sb_lock); | ||
400 | list_for_each_entry_safe(sb, n, &super_blocks, s_list) { | ||
401 | if (list_empty(&sb->s_instances)) | ||
402 | continue; | ||
403 | sb->s_count++; | ||
404 | spin_unlock(&sb_lock); | ||
405 | |||
406 | down_read(&sb->s_umount); | ||
407 | if (sb->s_root) | ||
408 | f(sb, arg); | ||
409 | up_read(&sb->s_umount); | ||
410 | |||
411 | spin_lock(&sb_lock); | ||
412 | __put_super(sb); | ||
413 | } | ||
414 | spin_unlock(&sb_lock); | ||
415 | } | ||
416 | |||
417 | /** | ||
434 | * get_super - get the superblock of a device | 418 | * get_super - get the superblock of a device |
435 | * @bdev: device to get the superblock for | 419 | * @bdev: device to get the superblock for |
436 | * | 420 | * |
@@ -438,7 +422,7 @@ restart: | |||
438 | * mounted on the device given. %NULL is returned if no match is found. | 422 | * mounted on the device given. %NULL is returned if no match is found. |
439 | */ | 423 | */ |
440 | 424 | ||
441 | struct super_block * get_super(struct block_device *bdev) | 425 | struct super_block *get_super(struct block_device *bdev) |
442 | { | 426 | { |
443 | struct super_block *sb; | 427 | struct super_block *sb; |
444 | 428 | ||
@@ -448,17 +432,20 @@ struct super_block * get_super(struct block_device *bdev) | |||
448 | spin_lock(&sb_lock); | 432 | spin_lock(&sb_lock); |
449 | rescan: | 433 | rescan: |
450 | list_for_each_entry(sb, &super_blocks, s_list) { | 434 | list_for_each_entry(sb, &super_blocks, s_list) { |
435 | if (list_empty(&sb->s_instances)) | ||
436 | continue; | ||
451 | if (sb->s_bdev == bdev) { | 437 | if (sb->s_bdev == bdev) { |
452 | sb->s_count++; | 438 | sb->s_count++; |
453 | spin_unlock(&sb_lock); | 439 | spin_unlock(&sb_lock); |
454 | down_read(&sb->s_umount); | 440 | down_read(&sb->s_umount); |
441 | /* still alive? */ | ||
455 | if (sb->s_root) | 442 | if (sb->s_root) |
456 | return sb; | 443 | return sb; |
457 | up_read(&sb->s_umount); | 444 | up_read(&sb->s_umount); |
458 | /* restart only when sb is no longer on the list */ | 445 | /* nope, got unmounted */ |
459 | spin_lock(&sb_lock); | 446 | spin_lock(&sb_lock); |
460 | if (__put_super_and_need_restart(sb)) | 447 | __put_super(sb); |
461 | goto rescan; | 448 | goto rescan; |
462 | } | 449 | } |
463 | } | 450 | } |
464 | spin_unlock(&sb_lock); | 451 | spin_unlock(&sb_lock); |
@@ -473,7 +460,7 @@ EXPORT_SYMBOL(get_super); | |||
473 | * | 460 | * |
474 | * Scans the superblock list and finds the superblock of the file system | 461 | * Scans the superblock list and finds the superblock of the file system |
475 | * mounted on the device given. Returns the superblock with an active | 462 | * mounted on the device given. Returns the superblock with an active |
476 | * reference and s_umount held exclusively or %NULL if none was found. | 463 | * reference or %NULL if none was found. |
477 | */ | 464 | */ |
478 | struct super_block *get_active_super(struct block_device *bdev) | 465 | struct super_block *get_active_super(struct block_device *bdev) |
479 | { | 466 | { |
@@ -482,81 +469,49 @@ struct super_block *get_active_super(struct block_device *bdev) | |||
482 | if (!bdev) | 469 | if (!bdev) |
483 | return NULL; | 470 | return NULL; |
484 | 471 | ||
472 | restart: | ||
485 | spin_lock(&sb_lock); | 473 | spin_lock(&sb_lock); |
486 | list_for_each_entry(sb, &super_blocks, s_list) { | 474 | list_for_each_entry(sb, &super_blocks, s_list) { |
487 | if (sb->s_bdev != bdev) | 475 | if (list_empty(&sb->s_instances)) |
488 | continue; | 476 | continue; |
489 | 477 | if (sb->s_bdev == bdev) { | |
490 | sb->s_count++; | 478 | if (grab_super(sb)) /* drops sb_lock */ |
491 | spin_unlock(&sb_lock); | ||
492 | down_write(&sb->s_umount); | ||
493 | if (sb->s_root) { | ||
494 | spin_lock(&sb_lock); | ||
495 | if (sb->s_count > S_BIAS) { | ||
496 | atomic_inc(&sb->s_active); | ||
497 | sb->s_count--; | ||
498 | spin_unlock(&sb_lock); | ||
499 | return sb; | 479 | return sb; |
500 | } | 480 | else |
501 | spin_unlock(&sb_lock); | 481 | goto restart; |
502 | } | 482 | } |
503 | up_write(&sb->s_umount); | ||
504 | put_super(sb); | ||
505 | yield(); | ||
506 | spin_lock(&sb_lock); | ||
507 | } | 483 | } |
508 | spin_unlock(&sb_lock); | 484 | spin_unlock(&sb_lock); |
509 | return NULL; | 485 | return NULL; |
510 | } | 486 | } |
511 | 487 | ||
512 | struct super_block * user_get_super(dev_t dev) | 488 | struct super_block *user_get_super(dev_t dev) |
513 | { | 489 | { |
514 | struct super_block *sb; | 490 | struct super_block *sb; |
515 | 491 | ||
516 | spin_lock(&sb_lock); | 492 | spin_lock(&sb_lock); |
517 | rescan: | 493 | rescan: |
518 | list_for_each_entry(sb, &super_blocks, s_list) { | 494 | list_for_each_entry(sb, &super_blocks, s_list) { |
495 | if (list_empty(&sb->s_instances)) | ||
496 | continue; | ||
519 | if (sb->s_dev == dev) { | 497 | if (sb->s_dev == dev) { |
520 | sb->s_count++; | 498 | sb->s_count++; |
521 | spin_unlock(&sb_lock); | 499 | spin_unlock(&sb_lock); |
522 | down_read(&sb->s_umount); | 500 | down_read(&sb->s_umount); |
501 | /* still alive? */ | ||
523 | if (sb->s_root) | 502 | if (sb->s_root) |
524 | return sb; | 503 | return sb; |
525 | up_read(&sb->s_umount); | 504 | up_read(&sb->s_umount); |
526 | /* restart only when sb is no longer on the list */ | 505 | /* nope, got unmounted */ |
527 | spin_lock(&sb_lock); | 506 | spin_lock(&sb_lock); |
528 | if (__put_super_and_need_restart(sb)) | 507 | __put_super(sb); |
529 | goto rescan; | 508 | goto rescan; |
530 | } | 509 | } |
531 | } | 510 | } |
532 | spin_unlock(&sb_lock); | 511 | spin_unlock(&sb_lock); |
533 | return NULL; | 512 | return NULL; |
534 | } | 513 | } |
535 | 514 | ||
536 | SYSCALL_DEFINE2(ustat, unsigned, dev, struct ustat __user *, ubuf) | ||
537 | { | ||
538 | struct super_block *s; | ||
539 | struct ustat tmp; | ||
540 | struct kstatfs sbuf; | ||
541 | int err = -EINVAL; | ||
542 | |||
543 | s = user_get_super(new_decode_dev(dev)); | ||
544 | if (s == NULL) | ||
545 | goto out; | ||
546 | err = vfs_statfs(s->s_root, &sbuf); | ||
547 | drop_super(s); | ||
548 | if (err) | ||
549 | goto out; | ||
550 | |||
551 | memset(&tmp,0,sizeof(struct ustat)); | ||
552 | tmp.f_tfree = sbuf.f_bfree; | ||
553 | tmp.f_tinode = sbuf.f_ffree; | ||
554 | |||
555 | err = copy_to_user(ubuf,&tmp,sizeof(struct ustat)) ? -EFAULT : 0; | ||
556 | out: | ||
557 | return err; | ||
558 | } | ||
559 | |||
560 | /** | 515 | /** |
561 | * do_remount_sb - asks filesystem to change mount options. | 516 | * do_remount_sb - asks filesystem to change mount options. |
562 | * @sb: superblock in question | 517 | * @sb: superblock in question |
@@ -622,24 +577,24 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force) | |||
622 | 577 | ||
623 | static void do_emergency_remount(struct work_struct *work) | 578 | static void do_emergency_remount(struct work_struct *work) |
624 | { | 579 | { |
625 | struct super_block *sb; | 580 | struct super_block *sb, *n; |
626 | 581 | ||
627 | spin_lock(&sb_lock); | 582 | spin_lock(&sb_lock); |
628 | list_for_each_entry(sb, &super_blocks, s_list) { | 583 | list_for_each_entry_safe(sb, n, &super_blocks, s_list) { |
584 | if (list_empty(&sb->s_instances)) | ||
585 | continue; | ||
629 | sb->s_count++; | 586 | sb->s_count++; |
630 | spin_unlock(&sb_lock); | 587 | spin_unlock(&sb_lock); |
631 | down_write(&sb->s_umount); | 588 | down_write(&sb->s_umount); |
632 | if (sb->s_root && sb->s_bdev && !(sb->s_flags & MS_RDONLY)) { | 589 | if (sb->s_root && sb->s_bdev && !(sb->s_flags & MS_RDONLY)) { |
633 | /* | 590 | /* |
634 | * ->remount_fs needs lock_kernel(). | ||
635 | * | ||
636 | * What lock protects sb->s_flags?? | 591 | * What lock protects sb->s_flags?? |
637 | */ | 592 | */ |
638 | do_remount_sb(sb, MS_RDONLY, NULL, 1); | 593 | do_remount_sb(sb, MS_RDONLY, NULL, 1); |
639 | } | 594 | } |
640 | up_write(&sb->s_umount); | 595 | up_write(&sb->s_umount); |
641 | put_super(sb); | ||
642 | spin_lock(&sb_lock); | 596 | spin_lock(&sb_lock); |
597 | __put_super(sb); | ||
643 | } | 598 | } |
644 | spin_unlock(&sb_lock); | 599 | spin_unlock(&sb_lock); |
645 | kfree(work); | 600 | kfree(work); |
@@ -990,6 +945,96 @@ out: | |||
990 | 945 | ||
991 | EXPORT_SYMBOL_GPL(vfs_kern_mount); | 946 | EXPORT_SYMBOL_GPL(vfs_kern_mount); |
992 | 947 | ||
948 | /** | ||
949 | * freeze_super -- lock the filesystem and force it into a consistent state | ||
950 | * @super: the super to lock | ||
951 | * | ||
952 | * Syncs the super to make sure the filesystem is consistent and calls the fs's | ||
953 | * freeze_fs. Subsequent calls to this without first thawing the fs will return | ||
954 | * -EBUSY. | ||
955 | */ | ||
956 | int freeze_super(struct super_block *sb) | ||
957 | { | ||
958 | int ret; | ||
959 | |||
960 | atomic_inc(&sb->s_active); | ||
961 | down_write(&sb->s_umount); | ||
962 | if (sb->s_frozen) { | ||
963 | deactivate_locked_super(sb); | ||
964 | return -EBUSY; | ||
965 | } | ||
966 | |||
967 | if (sb->s_flags & MS_RDONLY) { | ||
968 | sb->s_frozen = SB_FREEZE_TRANS; | ||
969 | smp_wmb(); | ||
970 | up_write(&sb->s_umount); | ||
971 | return 0; | ||
972 | } | ||
973 | |||
974 | sb->s_frozen = SB_FREEZE_WRITE; | ||
975 | smp_wmb(); | ||
976 | |||
977 | sync_filesystem(sb); | ||
978 | |||
979 | sb->s_frozen = SB_FREEZE_TRANS; | ||
980 | smp_wmb(); | ||
981 | |||
982 | sync_blockdev(sb->s_bdev); | ||
983 | if (sb->s_op->freeze_fs) { | ||
984 | ret = sb->s_op->freeze_fs(sb); | ||
985 | if (ret) { | ||
986 | printk(KERN_ERR | ||
987 | "VFS:Filesystem freeze failed\n"); | ||
988 | sb->s_frozen = SB_UNFROZEN; | ||
989 | deactivate_locked_super(sb); | ||
990 | return ret; | ||
991 | } | ||
992 | } | ||
993 | up_write(&sb->s_umount); | ||
994 | return 0; | ||
995 | } | ||
996 | EXPORT_SYMBOL(freeze_super); | ||
997 | |||
998 | /** | ||
999 | * thaw_super -- unlock filesystem | ||
1000 | * @sb: the super to thaw | ||
1001 | * | ||
1002 | * Unlocks the filesystem and marks it writeable again after freeze_super(). | ||
1003 | */ | ||
1004 | int thaw_super(struct super_block *sb) | ||
1005 | { | ||
1006 | int error; | ||
1007 | |||
1008 | down_write(&sb->s_umount); | ||
1009 | if (sb->s_frozen == SB_UNFROZEN) { | ||
1010 | up_write(&sb->s_umount); | ||
1011 | return -EINVAL; | ||
1012 | } | ||
1013 | |||
1014 | if (sb->s_flags & MS_RDONLY) | ||
1015 | goto out; | ||
1016 | |||
1017 | if (sb->s_op->unfreeze_fs) { | ||
1018 | error = sb->s_op->unfreeze_fs(sb); | ||
1019 | if (error) { | ||
1020 | printk(KERN_ERR | ||
1021 | "VFS:Filesystem thaw failed\n"); | ||
1022 | sb->s_frozen = SB_FREEZE_TRANS; | ||
1023 | up_write(&sb->s_umount); | ||
1024 | return error; | ||
1025 | } | ||
1026 | } | ||
1027 | |||
1028 | out: | ||
1029 | sb->s_frozen = SB_UNFROZEN; | ||
1030 | smp_wmb(); | ||
1031 | wake_up(&sb->s_wait_unfrozen); | ||
1032 | deactivate_locked_super(sb); | ||
1033 | |||
1034 | return 0; | ||
1035 | } | ||
1036 | EXPORT_SYMBOL(thaw_super); | ||
1037 | |||
993 | static struct vfsmount *fs_set_subtype(struct vfsmount *mnt, const char *fstype) | 1038 | static struct vfsmount *fs_set_subtype(struct vfsmount *mnt, const char *fstype) |
994 | { | 1039 | { |
995 | int err; | 1040 | int err; |