diff options
Diffstat (limited to 'fs/nilfs2/super.c')
-rw-r--r-- | fs/nilfs2/super.c | 104 |
1 files changed, 40 insertions, 64 deletions
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 151964f0de4c..644e66727dd0 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c | |||
@@ -50,6 +50,8 @@ | |||
50 | #include <linux/writeback.h> | 50 | #include <linux/writeback.h> |
51 | #include <linux/kobject.h> | 51 | #include <linux/kobject.h> |
52 | #include <linux/exportfs.h> | 52 | #include <linux/exportfs.h> |
53 | #include <linux/seq_file.h> | ||
54 | #include <linux/mount.h> | ||
53 | #include "nilfs.h" | 55 | #include "nilfs.h" |
54 | #include "mdt.h" | 56 | #include "mdt.h" |
55 | #include "alloc.h" | 57 | #include "alloc.h" |
@@ -65,7 +67,6 @@ MODULE_DESCRIPTION("A New Implementation of the Log-structured Filesystem " | |||
65 | "(NILFS)"); | 67 | "(NILFS)"); |
66 | MODULE_LICENSE("GPL"); | 68 | MODULE_LICENSE("GPL"); |
67 | 69 | ||
68 | static void nilfs_write_super(struct super_block *sb); | ||
69 | static int nilfs_remount(struct super_block *sb, int *flags, char *data); | 70 | static int nilfs_remount(struct super_block *sb, int *flags, char *data); |
70 | 71 | ||
71 | /** | 72 | /** |
@@ -311,9 +312,6 @@ static void nilfs_put_super(struct super_block *sb) | |||
311 | 312 | ||
312 | lock_kernel(); | 313 | lock_kernel(); |
313 | 314 | ||
314 | if (sb->s_dirt) | ||
315 | nilfs_write_super(sb); | ||
316 | |||
317 | nilfs_detach_segment_constructor(sbi); | 315 | nilfs_detach_segment_constructor(sbi); |
318 | 316 | ||
319 | if (!(sb->s_flags & MS_RDONLY)) { | 317 | if (!(sb->s_flags & MS_RDONLY)) { |
@@ -336,63 +334,21 @@ static void nilfs_put_super(struct super_block *sb) | |||
336 | unlock_kernel(); | 334 | unlock_kernel(); |
337 | } | 335 | } |
338 | 336 | ||
339 | /** | 337 | static int nilfs_sync_fs(struct super_block *sb, int wait) |
340 | * nilfs_write_super - write super block(s) of NILFS | ||
341 | * @sb: super_block | ||
342 | * | ||
343 | * nilfs_write_super() gets a fs-dependent lock, writes super block(s), and | ||
344 | * clears s_dirt. This function is called in the section protected by | ||
345 | * lock_super(). | ||
346 | * | ||
347 | * The s_dirt flag is managed by each filesystem and we protect it by ns_sem | ||
348 | * of the struct the_nilfs. Lock order must be as follows: | ||
349 | * | ||
350 | * 1. lock_super() | ||
351 | * 2. down_write(&nilfs->ns_sem) | ||
352 | * | ||
353 | * Inside NILFS, locking ns_sem is enough to protect s_dirt and the buffer | ||
354 | * of the super block (nilfs->ns_sbp[]). | ||
355 | * | ||
356 | * In most cases, VFS functions call lock_super() before calling these | ||
357 | * methods. So we must be careful not to bring on deadlocks when using | ||
358 | * lock_super(); see generic_shutdown_super(), write_super(), and so on. | ||
359 | * | ||
360 | * Note that order of lock_kernel() and lock_super() depends on contexts | ||
361 | * of VFS. We should also note that lock_kernel() can be used in its | ||
362 | * protective section and only the outermost one has an effect. | ||
363 | */ | ||
364 | static void nilfs_write_super(struct super_block *sb) | ||
365 | { | 338 | { |
366 | struct nilfs_sb_info *sbi = NILFS_SB(sb); | 339 | struct nilfs_sb_info *sbi = NILFS_SB(sb); |
367 | struct the_nilfs *nilfs = sbi->s_nilfs; | 340 | struct the_nilfs *nilfs = sbi->s_nilfs; |
368 | |||
369 | down_write(&nilfs->ns_sem); | ||
370 | if (!(sb->s_flags & MS_RDONLY)) { | ||
371 | struct nilfs_super_block **sbp = nilfs->ns_sbp; | ||
372 | u64 t = get_seconds(); | ||
373 | int dupsb; | ||
374 | |||
375 | if (!nilfs_discontinued(nilfs) && t >= nilfs->ns_sbwtime[0] && | ||
376 | t < nilfs->ns_sbwtime[0] + NILFS_SB_FREQ) { | ||
377 | up_write(&nilfs->ns_sem); | ||
378 | return; | ||
379 | } | ||
380 | dupsb = sbp[1] && t > nilfs->ns_sbwtime[1] + NILFS_ALTSB_FREQ; | ||
381 | nilfs_commit_super(sbi, dupsb); | ||
382 | } | ||
383 | sb->s_dirt = 0; | ||
384 | up_write(&nilfs->ns_sem); | ||
385 | } | ||
386 | |||
387 | static int nilfs_sync_fs(struct super_block *sb, int wait) | ||
388 | { | ||
389 | int err = 0; | 341 | int err = 0; |
390 | 342 | ||
391 | nilfs_write_super(sb); | ||
392 | |||
393 | /* This function is called when super block should be written back */ | 343 | /* This function is called when super block should be written back */ |
394 | if (wait) | 344 | if (wait) |
395 | err = nilfs_construct_segment(sb); | 345 | err = nilfs_construct_segment(sb); |
346 | |||
347 | down_write(&nilfs->ns_sem); | ||
348 | if (sb->s_dirt) | ||
349 | nilfs_commit_super(sbi, 1); | ||
350 | up_write(&nilfs->ns_sem); | ||
351 | |||
396 | return err; | 352 | return err; |
397 | } | 353 | } |
398 | 354 | ||
@@ -407,8 +363,7 @@ int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno) | |||
407 | list_add(&sbi->s_list, &nilfs->ns_supers); | 363 | list_add(&sbi->s_list, &nilfs->ns_supers); |
408 | up_write(&nilfs->ns_super_sem); | 364 | up_write(&nilfs->ns_super_sem); |
409 | 365 | ||
410 | sbi->s_ifile = nilfs_mdt_new( | 366 | sbi->s_ifile = nilfs_mdt_new(nilfs, sbi->s_super, NILFS_IFILE_INO); |
411 | nilfs, sbi->s_super, NILFS_IFILE_INO, NILFS_IFILE_GFP); | ||
412 | if (!sbi->s_ifile) | 367 | if (!sbi->s_ifile) |
413 | return -ENOMEM; | 368 | return -ENOMEM; |
414 | 369 | ||
@@ -529,7 +484,27 @@ static int nilfs_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
529 | return 0; | 484 | return 0; |
530 | } | 485 | } |
531 | 486 | ||
532 | static struct super_operations nilfs_sops = { | 487 | static int nilfs_show_options(struct seq_file *seq, struct vfsmount *vfs) |
488 | { | ||
489 | struct super_block *sb = vfs->mnt_sb; | ||
490 | struct nilfs_sb_info *sbi = NILFS_SB(sb); | ||
491 | |||
492 | if (!nilfs_test_opt(sbi, BARRIER)) | ||
493 | seq_printf(seq, ",barrier=off"); | ||
494 | if (nilfs_test_opt(sbi, SNAPSHOT)) | ||
495 | seq_printf(seq, ",cp=%llu", | ||
496 | (unsigned long long int)sbi->s_snapshot_cno); | ||
497 | if (nilfs_test_opt(sbi, ERRORS_RO)) | ||
498 | seq_printf(seq, ",errors=remount-ro"); | ||
499 | if (nilfs_test_opt(sbi, ERRORS_PANIC)) | ||
500 | seq_printf(seq, ",errors=panic"); | ||
501 | if (nilfs_test_opt(sbi, STRICT_ORDER)) | ||
502 | seq_printf(seq, ",order=strict"); | ||
503 | |||
504 | return 0; | ||
505 | } | ||
506 | |||
507 | static const struct super_operations nilfs_sops = { | ||
533 | .alloc_inode = nilfs_alloc_inode, | 508 | .alloc_inode = nilfs_alloc_inode, |
534 | .destroy_inode = nilfs_destroy_inode, | 509 | .destroy_inode = nilfs_destroy_inode, |
535 | .dirty_inode = nilfs_dirty_inode, | 510 | .dirty_inode = nilfs_dirty_inode, |
@@ -538,7 +513,7 @@ static struct super_operations nilfs_sops = { | |||
538 | /* .drop_inode = nilfs_drop_inode, */ | 513 | /* .drop_inode = nilfs_drop_inode, */ |
539 | .delete_inode = nilfs_delete_inode, | 514 | .delete_inode = nilfs_delete_inode, |
540 | .put_super = nilfs_put_super, | 515 | .put_super = nilfs_put_super, |
541 | .write_super = nilfs_write_super, | 516 | /* .write_super = nilfs_write_super, */ |
542 | .sync_fs = nilfs_sync_fs, | 517 | .sync_fs = nilfs_sync_fs, |
543 | /* .write_super_lockfs */ | 518 | /* .write_super_lockfs */ |
544 | /* .unlockfs */ | 519 | /* .unlockfs */ |
@@ -546,7 +521,7 @@ static struct super_operations nilfs_sops = { | |||
546 | .remount_fs = nilfs_remount, | 521 | .remount_fs = nilfs_remount, |
547 | .clear_inode = nilfs_clear_inode, | 522 | .clear_inode = nilfs_clear_inode, |
548 | /* .umount_begin */ | 523 | /* .umount_begin */ |
549 | /* .show_options */ | 524 | .show_options = nilfs_show_options |
550 | }; | 525 | }; |
551 | 526 | ||
552 | static struct inode * | 527 | static struct inode * |
@@ -585,7 +560,7 @@ nilfs_fh_to_parent(struct super_block *sb, struct fid *fid, int fh_len, | |||
585 | nilfs_nfs_get_inode); | 560 | nilfs_nfs_get_inode); |
586 | } | 561 | } |
587 | 562 | ||
588 | static struct export_operations nilfs_export_ops = { | 563 | static const struct export_operations nilfs_export_ops = { |
589 | .fh_to_dentry = nilfs_fh_to_dentry, | 564 | .fh_to_dentry = nilfs_fh_to_dentry, |
590 | .fh_to_parent = nilfs_fh_to_parent, | 565 | .fh_to_parent = nilfs_fh_to_parent, |
591 | .get_parent = nilfs_get_parent, | 566 | .get_parent = nilfs_get_parent, |
@@ -816,10 +791,15 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent, | |||
816 | 791 | ||
817 | if (sb->s_flags & MS_RDONLY) { | 792 | if (sb->s_flags & MS_RDONLY) { |
818 | if (nilfs_test_opt(sbi, SNAPSHOT)) { | 793 | if (nilfs_test_opt(sbi, SNAPSHOT)) { |
794 | down_read(&nilfs->ns_segctor_sem); | ||
819 | err = nilfs_cpfile_is_snapshot(nilfs->ns_cpfile, | 795 | err = nilfs_cpfile_is_snapshot(nilfs->ns_cpfile, |
820 | sbi->s_snapshot_cno); | 796 | sbi->s_snapshot_cno); |
821 | if (err < 0) | 797 | up_read(&nilfs->ns_segctor_sem); |
798 | if (err < 0) { | ||
799 | if (err == -ENOENT) | ||
800 | err = -EINVAL; | ||
822 | goto failed_sbi; | 801 | goto failed_sbi; |
802 | } | ||
823 | if (!err) { | 803 | if (!err) { |
824 | printk(KERN_ERR | 804 | printk(KERN_ERR |
825 | "NILFS: The specified checkpoint is " | 805 | "NILFS: The specified checkpoint is " |
@@ -1127,10 +1107,6 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags, | |||
1127 | */ | 1107 | */ |
1128 | sd.sbi = nilfs_find_sbinfo(nilfs, !(flags & MS_RDONLY), sd.cno); | 1108 | sd.sbi = nilfs_find_sbinfo(nilfs, !(flags & MS_RDONLY), sd.cno); |
1129 | 1109 | ||
1130 | if (!sd.cno) | ||
1131 | /* trying to get the latest checkpoint. */ | ||
1132 | sd.cno = nilfs_last_cno(nilfs); | ||
1133 | |||
1134 | /* | 1110 | /* |
1135 | * Get super block instance holding the nilfs_sb_info struct. | 1111 | * Get super block instance holding the nilfs_sb_info struct. |
1136 | * A new instance is allocated if no existing mount is present or | 1112 | * A new instance is allocated if no existing mount is present or |