diff options
| -rw-r--r-- | fs/nilfs2/super.c | 44 | ||||
| -rw-r--r-- | fs/nilfs2/the_nilfs.c | 13 | ||||
| -rw-r--r-- | fs/nilfs2/the_nilfs.h | 7 |
3 files changed, 33 insertions, 31 deletions
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 1d1b6e125159..f02762fa8ea0 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c | |||
| @@ -327,10 +327,10 @@ static void nilfs_put_super(struct super_block *sb) | |||
| 327 | nilfs_commit_super(sbi, 1); | 327 | nilfs_commit_super(sbi, 1); |
| 328 | up_write(&nilfs->ns_sem); | 328 | up_write(&nilfs->ns_sem); |
| 329 | } | 329 | } |
| 330 | down_write(&nilfs->ns_sem); | 330 | down_write(&nilfs->ns_super_sem); |
| 331 | if (nilfs->ns_current == sbi) | 331 | if (nilfs->ns_current == sbi) |
| 332 | nilfs->ns_current = NULL; | 332 | nilfs->ns_current = NULL; |
| 333 | up_write(&nilfs->ns_sem); | 333 | up_write(&nilfs->ns_super_sem); |
| 334 | 334 | ||
| 335 | nilfs_detach_checkpoint(sbi); | 335 | nilfs_detach_checkpoint(sbi); |
| 336 | put_nilfs(sbi->s_nilfs); | 336 | put_nilfs(sbi->s_nilfs); |
| @@ -408,9 +408,9 @@ int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno) | |||
| 408 | struct buffer_head *bh_cp; | 408 | struct buffer_head *bh_cp; |
| 409 | int err; | 409 | int err; |
| 410 | 410 | ||
| 411 | down_write(&nilfs->ns_sem); | 411 | down_write(&nilfs->ns_super_sem); |
| 412 | list_add(&sbi->s_list, &nilfs->ns_supers); | 412 | list_add(&sbi->s_list, &nilfs->ns_supers); |
| 413 | up_write(&nilfs->ns_sem); | 413 | up_write(&nilfs->ns_super_sem); |
| 414 | 414 | ||
| 415 | sbi->s_ifile = nilfs_mdt_new( | 415 | sbi->s_ifile = nilfs_mdt_new( |
| 416 | nilfs, sbi->s_super, NILFS_IFILE_INO, NILFS_IFILE_GFP); | 416 | nilfs, sbi->s_super, NILFS_IFILE_INO, NILFS_IFILE_GFP); |
| @@ -448,9 +448,9 @@ int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno) | |||
| 448 | nilfs_mdt_destroy(sbi->s_ifile); | 448 | nilfs_mdt_destroy(sbi->s_ifile); |
| 449 | sbi->s_ifile = NULL; | 449 | sbi->s_ifile = NULL; |
| 450 | 450 | ||
| 451 | down_write(&nilfs->ns_sem); | 451 | down_write(&nilfs->ns_super_sem); |
| 452 | list_del_init(&sbi->s_list); | 452 | list_del_init(&sbi->s_list); |
| 453 | up_write(&nilfs->ns_sem); | 453 | up_write(&nilfs->ns_super_sem); |
| 454 | 454 | ||
| 455 | return err; | 455 | return err; |
| 456 | } | 456 | } |
| @@ -462,9 +462,9 @@ void nilfs_detach_checkpoint(struct nilfs_sb_info *sbi) | |||
| 462 | nilfs_mdt_clear(sbi->s_ifile); | 462 | nilfs_mdt_clear(sbi->s_ifile); |
| 463 | nilfs_mdt_destroy(sbi->s_ifile); | 463 | nilfs_mdt_destroy(sbi->s_ifile); |
| 464 | sbi->s_ifile = NULL; | 464 | sbi->s_ifile = NULL; |
| 465 | down_write(&nilfs->ns_sem); | 465 | down_write(&nilfs->ns_super_sem); |
| 466 | list_del_init(&sbi->s_list); | 466 | list_del_init(&sbi->s_list); |
| 467 | up_write(&nilfs->ns_sem); | 467 | up_write(&nilfs->ns_super_sem); |
| 468 | } | 468 | } |
| 469 | 469 | ||
| 470 | static int nilfs_mark_recovery_complete(struct nilfs_sb_info *sbi) | 470 | static int nilfs_mark_recovery_complete(struct nilfs_sb_info *sbi) |
| @@ -883,10 +883,10 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent, | |||
| 883 | goto failed_root; | 883 | goto failed_root; |
| 884 | } | 884 | } |
| 885 | 885 | ||
| 886 | down_write(&nilfs->ns_sem); | 886 | down_write(&nilfs->ns_super_sem); |
| 887 | if (!nilfs_test_opt(sbi, SNAPSHOT)) | 887 | if (!nilfs_test_opt(sbi, SNAPSHOT)) |
| 888 | nilfs->ns_current = sbi; | 888 | nilfs->ns_current = sbi; |
| 889 | up_write(&nilfs->ns_sem); | 889 | up_write(&nilfs->ns_super_sem); |
| 890 | 890 | ||
| 891 | return 0; | 891 | return 0; |
| 892 | 892 | ||
| @@ -918,6 +918,7 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) | |||
| 918 | 918 | ||
| 919 | lock_kernel(); | 919 | lock_kernel(); |
| 920 | 920 | ||
| 921 | down_write(&nilfs->ns_super_sem); | ||
| 921 | old_sb_flags = sb->s_flags; | 922 | old_sb_flags = sb->s_flags; |
| 922 | old_opts.mount_opt = sbi->s_mount_opt; | 923 | old_opts.mount_opt = sbi->s_mount_opt; |
| 923 | old_opts.snapshot_cno = sbi->s_snapshot_cno; | 924 | old_opts.snapshot_cno = sbi->s_snapshot_cno; |
| @@ -965,24 +966,20 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) | |||
| 965 | * store the current valid flag. (It may have been changed | 966 | * store the current valid flag. (It may have been changed |
| 966 | * by fsck since we originally mounted the partition.) | 967 | * by fsck since we originally mounted the partition.) |
| 967 | */ | 968 | */ |
| 968 | down(&sb->s_bdev->bd_mount_sem); | ||
| 969 | down_read(&nilfs->ns_sem); | ||
| 970 | if (nilfs->ns_current && nilfs->ns_current != sbi) { | 969 | if (nilfs->ns_current && nilfs->ns_current != sbi) { |
| 971 | printk(KERN_WARNING "NILFS (device %s): couldn't " | 970 | printk(KERN_WARNING "NILFS (device %s): couldn't " |
| 972 | "remount because an RW-mount exists.\n", | 971 | "remount because an RW-mount exists.\n", |
| 973 | sb->s_id); | 972 | sb->s_id); |
| 974 | up_read(&nilfs->ns_sem); | ||
| 975 | err = -EBUSY; | 973 | err = -EBUSY; |
| 976 | goto rw_remount_failed; | 974 | goto restore_opts; |
| 977 | } | 975 | } |
| 978 | up_read(&nilfs->ns_sem); | ||
| 979 | if (sbi->s_snapshot_cno != nilfs_last_cno(nilfs)) { | 976 | if (sbi->s_snapshot_cno != nilfs_last_cno(nilfs)) { |
| 980 | printk(KERN_WARNING "NILFS (device %s): couldn't " | 977 | printk(KERN_WARNING "NILFS (device %s): couldn't " |
| 981 | "remount because the current RO-mount is not " | 978 | "remount because the current RO-mount is not " |
| 982 | "the latest one.\n", | 979 | "the latest one.\n", |
| 983 | sb->s_id); | 980 | sb->s_id); |
| 984 | err = -EINVAL; | 981 | err = -EINVAL; |
| 985 | goto rw_remount_failed; | 982 | goto restore_opts; |
| 986 | } | 983 | } |
| 987 | sb->s_flags &= ~MS_RDONLY; | 984 | sb->s_flags &= ~MS_RDONLY; |
| 988 | nilfs_clear_opt(sbi, SNAPSHOT); | 985 | nilfs_clear_opt(sbi, SNAPSHOT); |
| @@ -990,25 +987,24 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) | |||
| 990 | 987 | ||
| 991 | err = nilfs_attach_segment_constructor(sbi); | 988 | err = nilfs_attach_segment_constructor(sbi); |
| 992 | if (err) | 989 | if (err) |
| 993 | goto rw_remount_failed; | 990 | goto restore_opts; |
| 994 | 991 | ||
| 995 | down_write(&nilfs->ns_sem); | 992 | down_write(&nilfs->ns_sem); |
| 996 | nilfs_setup_super(sbi); | 993 | nilfs_setup_super(sbi); |
| 997 | nilfs->ns_current = sbi; | ||
| 998 | up_write(&nilfs->ns_sem); | 994 | up_write(&nilfs->ns_sem); |
| 999 | 995 | ||
| 1000 | up(&sb->s_bdev->bd_mount_sem); | 996 | nilfs->ns_current = sbi; |
| 1001 | } | 997 | } |
| 1002 | out: | 998 | out: |
| 999 | up_write(&nilfs->ns_super_sem); | ||
| 1003 | unlock_kernel(); | 1000 | unlock_kernel(); |
| 1004 | return 0; | 1001 | return 0; |
| 1005 | 1002 | ||
| 1006 | rw_remount_failed: | ||
| 1007 | up(&sb->s_bdev->bd_mount_sem); | ||
| 1008 | restore_opts: | 1003 | restore_opts: |
| 1009 | sb->s_flags = old_sb_flags; | 1004 | sb->s_flags = old_sb_flags; |
| 1010 | sbi->s_mount_opt = old_opts.mount_opt; | 1005 | sbi->s_mount_opt = old_opts.mount_opt; |
| 1011 | sbi->s_snapshot_cno = old_opts.snapshot_cno; | 1006 | sbi->s_snapshot_cno = old_opts.snapshot_cno; |
| 1007 | up_write(&nilfs->ns_super_sem); | ||
| 1012 | unlock_kernel(); | 1008 | unlock_kernel(); |
| 1013 | return err; | 1009 | return err; |
| 1014 | } | 1010 | } |
| @@ -1118,15 +1114,15 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags, | |||
| 1118 | * (i.e. rw-mount or ro-mount), whereas rw-mount and | 1114 | * (i.e. rw-mount or ro-mount), whereas rw-mount and |
| 1119 | * ro-mount are mutually exclusive. | 1115 | * ro-mount are mutually exclusive. |
| 1120 | */ | 1116 | */ |
| 1121 | down_read(&nilfs->ns_sem); | 1117 | down_read(&nilfs->ns_super_sem); |
| 1122 | if (nilfs->ns_current && | 1118 | if (nilfs->ns_current && |
| 1123 | ((nilfs->ns_current->s_super->s_flags ^ flags) | 1119 | ((nilfs->ns_current->s_super->s_flags ^ flags) |
| 1124 | & MS_RDONLY)) { | 1120 | & MS_RDONLY)) { |
| 1125 | up_read(&nilfs->ns_sem); | 1121 | up_read(&nilfs->ns_super_sem); |
| 1126 | err = -EBUSY; | 1122 | err = -EBUSY; |
| 1127 | goto failed_unlock; | 1123 | goto failed_unlock; |
| 1128 | } | 1124 | } |
| 1129 | up_read(&nilfs->ns_sem); | 1125 | up_read(&nilfs->ns_super_sem); |
| 1130 | } | 1126 | } |
| 1131 | 1127 | ||
| 1132 | /* | 1128 | /* |
diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c index 221953bfc859..06e8dfd538d6 100644 --- a/fs/nilfs2/the_nilfs.c +++ b/fs/nilfs2/the_nilfs.c | |||
| @@ -72,6 +72,7 @@ static struct the_nilfs *alloc_nilfs(struct block_device *bdev) | |||
| 72 | atomic_set(&nilfs->ns_writer_refcount, -1); | 72 | atomic_set(&nilfs->ns_writer_refcount, -1); |
| 73 | atomic_set(&nilfs->ns_ndirtyblks, 0); | 73 | atomic_set(&nilfs->ns_ndirtyblks, 0); |
| 74 | init_rwsem(&nilfs->ns_sem); | 74 | init_rwsem(&nilfs->ns_sem); |
| 75 | init_rwsem(&nilfs->ns_super_sem); | ||
| 75 | mutex_init(&nilfs->ns_writer_mutex); | 76 | mutex_init(&nilfs->ns_writer_mutex); |
| 76 | INIT_LIST_HEAD(&nilfs->ns_list); | 77 | INIT_LIST_HEAD(&nilfs->ns_list); |
| 77 | INIT_LIST_HEAD(&nilfs->ns_supers); | 78 | INIT_LIST_HEAD(&nilfs->ns_supers); |
| @@ -681,10 +682,10 @@ struct nilfs_sb_info *nilfs_find_sbinfo(struct the_nilfs *nilfs, | |||
| 681 | { | 682 | { |
| 682 | struct nilfs_sb_info *sbi; | 683 | struct nilfs_sb_info *sbi; |
| 683 | 684 | ||
| 684 | down_read(&nilfs->ns_sem); | 685 | down_read(&nilfs->ns_super_sem); |
| 685 | /* | 686 | /* |
| 686 | * The SNAPSHOT flag and sb->s_flags are supposed to be | 687 | * The SNAPSHOT flag and sb->s_flags are supposed to be |
| 687 | * protected with nilfs->ns_sem. | 688 | * protected with nilfs->ns_super_sem. |
| 688 | */ | 689 | */ |
| 689 | sbi = nilfs->ns_current; | 690 | sbi = nilfs->ns_current; |
| 690 | if (rw_mount) { | 691 | if (rw_mount) { |
| @@ -705,12 +706,12 @@ struct nilfs_sb_info *nilfs_find_sbinfo(struct the_nilfs *nilfs, | |||
| 705 | goto found; /* snapshot mount */ | 706 | goto found; /* snapshot mount */ |
| 706 | } | 707 | } |
| 707 | out: | 708 | out: |
| 708 | up_read(&nilfs->ns_sem); | 709 | up_read(&nilfs->ns_super_sem); |
| 709 | return NULL; | 710 | return NULL; |
| 710 | 711 | ||
| 711 | found: | 712 | found: |
| 712 | atomic_inc(&sbi->s_count); | 713 | atomic_inc(&sbi->s_count); |
| 713 | up_read(&nilfs->ns_sem); | 714 | up_read(&nilfs->ns_super_sem); |
| 714 | return sbi; | 715 | return sbi; |
| 715 | } | 716 | } |
| 716 | 717 | ||
| @@ -720,7 +721,7 @@ int nilfs_checkpoint_is_mounted(struct the_nilfs *nilfs, __u64 cno, | |||
| 720 | struct nilfs_sb_info *sbi; | 721 | struct nilfs_sb_info *sbi; |
| 721 | int ret = 0; | 722 | int ret = 0; |
| 722 | 723 | ||
| 723 | down_read(&nilfs->ns_sem); | 724 | down_read(&nilfs->ns_super_sem); |
| 724 | if (cno == 0 || cno > nilfs->ns_cno) | 725 | if (cno == 0 || cno > nilfs->ns_cno) |
| 725 | goto out_unlock; | 726 | goto out_unlock; |
| 726 | 727 | ||
| @@ -737,6 +738,6 @@ int nilfs_checkpoint_is_mounted(struct the_nilfs *nilfs, __u64 cno, | |||
| 737 | ret++; | 738 | ret++; |
| 738 | 739 | ||
| 739 | out_unlock: | 740 | out_unlock: |
| 740 | up_read(&nilfs->ns_sem); | 741 | up_read(&nilfs->ns_super_sem); |
| 741 | return ret; | 742 | return ret; |
| 742 | } | 743 | } |
diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h index be4c040fd629..d0cf4fb7c9ce 100644 --- a/fs/nilfs2/the_nilfs.h +++ b/fs/nilfs2/the_nilfs.h | |||
| @@ -48,6 +48,7 @@ enum { | |||
| 48 | * @ns_bdi: backing dev info | 48 | * @ns_bdi: backing dev info |
| 49 | * @ns_writer: back pointer to writable nilfs_sb_info | 49 | * @ns_writer: back pointer to writable nilfs_sb_info |
| 50 | * @ns_sem: semaphore for shared states | 50 | * @ns_sem: semaphore for shared states |
| 51 | * @ns_super_sem: semaphore for global operations across super block instances | ||
| 51 | * @ns_writer_mutex: mutex protecting ns_writer attach/detach | 52 | * @ns_writer_mutex: mutex protecting ns_writer attach/detach |
| 52 | * @ns_writer_refcount: number of referrers on ns_writer | 53 | * @ns_writer_refcount: number of referrers on ns_writer |
| 53 | * @ns_current: back pointer to current mount | 54 | * @ns_current: back pointer to current mount |
| @@ -96,10 +97,15 @@ struct the_nilfs { | |||
| 96 | struct backing_dev_info *ns_bdi; | 97 | struct backing_dev_info *ns_bdi; |
| 97 | struct nilfs_sb_info *ns_writer; | 98 | struct nilfs_sb_info *ns_writer; |
| 98 | struct rw_semaphore ns_sem; | 99 | struct rw_semaphore ns_sem; |
| 100 | struct rw_semaphore ns_super_sem; | ||
| 99 | struct mutex ns_writer_mutex; | 101 | struct mutex ns_writer_mutex; |
| 100 | atomic_t ns_writer_refcount; | 102 | atomic_t ns_writer_refcount; |
| 101 | 103 | ||
| 104 | /* | ||
| 105 | * components protected by ns_super_sem | ||
| 106 | */ | ||
| 102 | struct nilfs_sb_info *ns_current; | 107 | struct nilfs_sb_info *ns_current; |
| 108 | struct list_head ns_supers; | ||
| 103 | 109 | ||
| 104 | /* | 110 | /* |
| 105 | * used for | 111 | * used for |
| @@ -113,7 +119,6 @@ struct the_nilfs { | |||
| 113 | time_t ns_sbwtime[2]; | 119 | time_t ns_sbwtime[2]; |
| 114 | unsigned ns_sbsize; | 120 | unsigned ns_sbsize; |
| 115 | unsigned ns_mount_state; | 121 | unsigned ns_mount_state; |
| 116 | struct list_head ns_supers; | ||
| 117 | 122 | ||
| 118 | /* | 123 | /* |
| 119 | * Following fields are dedicated to a writable FS-instance. | 124 | * Following fields are dedicated to a writable FS-instance. |
