diff options
Diffstat (limited to 'fs/nilfs2/super.c')
-rw-r--r-- | fs/nilfs2/super.c | 216 |
1 files changed, 100 insertions, 116 deletions
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index ebeb746c4845..2e58e7c629b5 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c | |||
@@ -355,16 +355,11 @@ static void nilfs_put_super(struct super_block *sb) | |||
355 | nilfs_cleanup_super(sbi); | 355 | nilfs_cleanup_super(sbi); |
356 | up_write(&nilfs->ns_sem); | 356 | up_write(&nilfs->ns_sem); |
357 | } | 357 | } |
358 | down_write(&nilfs->ns_super_sem); | ||
359 | if (nilfs->ns_current == sbi) | ||
360 | nilfs->ns_current = NULL; | ||
361 | list_del_init(&sbi->s_list); | ||
362 | up_write(&nilfs->ns_super_sem); | ||
363 | 358 | ||
364 | put_nilfs(sbi->s_nilfs); | 359 | put_nilfs(sbi->s_nilfs); |
365 | sbi->s_super = NULL; | 360 | sbi->s_super = NULL; |
366 | sb->s_fs_info = NULL; | 361 | sb->s_fs_info = NULL; |
367 | nilfs_put_sbinfo(sbi); | 362 | kfree(sbi); |
368 | } | 363 | } |
369 | 364 | ||
370 | static int nilfs_sync_fs(struct super_block *sb, int wait) | 365 | static int nilfs_sync_fs(struct super_block *sb, int wait) |
@@ -500,12 +495,12 @@ static int nilfs_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
500 | { | 495 | { |
501 | struct super_block *sb = vfs->mnt_sb; | 496 | struct super_block *sb = vfs->mnt_sb; |
502 | struct nilfs_sb_info *sbi = NILFS_SB(sb); | 497 | struct nilfs_sb_info *sbi = NILFS_SB(sb); |
498 | struct nilfs_root *root = NILFS_I(vfs->mnt_root->d_inode)->i_root; | ||
503 | 499 | ||
504 | if (!nilfs_test_opt(sbi, BARRIER)) | 500 | if (!nilfs_test_opt(sbi, BARRIER)) |
505 | seq_puts(seq, ",nobarrier"); | 501 | seq_puts(seq, ",nobarrier"); |
506 | if (nilfs_test_opt(sbi, SNAPSHOT)) | 502 | if (root->cno != NILFS_CPTREE_CURRENT_CNO) |
507 | seq_printf(seq, ",cp=%llu", | 503 | seq_printf(seq, ",cp=%llu", (unsigned long long)root->cno); |
508 | (unsigned long long int)sbi->s_snapshot_cno); | ||
509 | if (nilfs_test_opt(sbi, ERRORS_PANIC)) | 504 | if (nilfs_test_opt(sbi, ERRORS_PANIC)) |
510 | seq_puts(seq, ",errors=panic"); | 505 | seq_puts(seq, ",errors=panic"); |
511 | if (nilfs_test_opt(sbi, ERRORS_CONT)) | 506 | if (nilfs_test_opt(sbi, ERRORS_CONT)) |
@@ -605,27 +600,11 @@ static int parse_options(char *options, struct super_block *sb, int is_remount) | |||
605 | if (match_int(&args[0], &option) || option <= 0) | 600 | if (match_int(&args[0], &option) || option <= 0) |
606 | return 0; | 601 | return 0; |
607 | if (is_remount) { | 602 | if (is_remount) { |
608 | if (!nilfs_test_opt(sbi, SNAPSHOT)) { | 603 | printk(KERN_ERR |
609 | printk(KERN_ERR | 604 | "NILFS: \"%s\" option is invalid " |
610 | "NILFS: cannot change regular " | 605 | "for remount.\n", p); |
611 | "mount to snapshot.\n"); | ||
612 | return 0; | ||
613 | } else if (option != sbi->s_snapshot_cno) { | ||
614 | printk(KERN_ERR | ||
615 | "NILFS: cannot remount to a " | ||
616 | "different snapshot.\n"); | ||
617 | return 0; | ||
618 | } | ||
619 | break; | ||
620 | } | ||
621 | if (!(sb->s_flags & MS_RDONLY)) { | ||
622 | printk(KERN_ERR "NILFS: cannot mount snapshot " | ||
623 | "read/write. A read-only option is " | ||
624 | "required.\n"); | ||
625 | return 0; | 606 | return 0; |
626 | } | 607 | } |
627 | sbi->s_snapshot_cno = option; | ||
628 | nilfs_set_opt(sbi, SNAPSHOT); | ||
629 | break; | 608 | break; |
630 | case Opt_norecovery: | 609 | case Opt_norecovery: |
631 | nilfs_set_opt(sbi, NORECOVERY); | 610 | nilfs_set_opt(sbi, NORECOVERY); |
@@ -771,16 +750,32 @@ static int nilfs_get_root_dentry(struct super_block *sb, | |||
771 | goto out; | 750 | goto out; |
772 | } | 751 | } |
773 | 752 | ||
774 | dentry = d_alloc_root(inode); | 753 | if (root->cno == NILFS_CPTREE_CURRENT_CNO) { |
775 | if (!dentry) { | 754 | dentry = d_find_alias(inode); |
776 | iput(inode); | 755 | if (!dentry) { |
777 | printk(KERN_ERR "NILFS: get root dentry failed\n"); | 756 | dentry = d_alloc_root(inode); |
778 | ret = -ENOMEM; | 757 | if (!dentry) { |
779 | goto out; | 758 | iput(inode); |
759 | ret = -ENOMEM; | ||
760 | goto failed_dentry; | ||
761 | } | ||
762 | } else { | ||
763 | iput(inode); | ||
764 | } | ||
765 | } else { | ||
766 | dentry = d_obtain_alias(inode); | ||
767 | if (IS_ERR(dentry)) { | ||
768 | ret = PTR_ERR(dentry); | ||
769 | goto failed_dentry; | ||
770 | } | ||
780 | } | 771 | } |
781 | *root_dentry = dentry; | 772 | *root_dentry = dentry; |
782 | out: | 773 | out: |
783 | return ret; | 774 | return ret; |
775 | |||
776 | failed_dentry: | ||
777 | printk(KERN_ERR "NILFS: get root dentry failed\n"); | ||
778 | goto out; | ||
784 | } | 779 | } |
785 | 780 | ||
786 | static int nilfs_attach_snapshot(struct super_block *s, __u64 cno, | 781 | static int nilfs_attach_snapshot(struct super_block *s, __u64 cno, |
@@ -817,6 +812,25 @@ static int nilfs_attach_snapshot(struct super_block *s, __u64 cno, | |||
817 | return ret; | 812 | return ret; |
818 | } | 813 | } |
819 | 814 | ||
815 | static int nilfs_tree_was_touched(struct dentry *root_dentry) | ||
816 | { | ||
817 | return atomic_read(&root_dentry->d_count) > 1; | ||
818 | } | ||
819 | |||
820 | /** | ||
821 | * nilfs_try_to_shrink_tree() - try to shrink dentries of a checkpoint | ||
822 | * @root_dentry: root dentry of the tree to be shrunk | ||
823 | * | ||
824 | * This function returns true if the tree was in-use. | ||
825 | */ | ||
826 | static int nilfs_try_to_shrink_tree(struct dentry *root_dentry) | ||
827 | { | ||
828 | if (have_submounts(root_dentry)) | ||
829 | return true; | ||
830 | shrink_dcache_parent(root_dentry); | ||
831 | return nilfs_tree_was_touched(root_dentry); | ||
832 | } | ||
833 | |||
820 | /** | 834 | /** |
821 | * nilfs_fill_super() - initialize a super block instance | 835 | * nilfs_fill_super() - initialize a super block instance |
822 | * @sb: super_block | 836 | * @sb: super_block |
@@ -845,7 +859,6 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent, | |||
845 | get_nilfs(nilfs); | 859 | get_nilfs(nilfs); |
846 | sbi->s_nilfs = nilfs; | 860 | sbi->s_nilfs = nilfs; |
847 | sbi->s_super = sb; | 861 | sbi->s_super = sb; |
848 | atomic_set(&sbi->s_count, 1); | ||
849 | 862 | ||
850 | err = init_nilfs(nilfs, sbi, (char *)data); | 863 | err = init_nilfs(nilfs, sbi, (char *)data); |
851 | if (err) | 864 | if (err) |
@@ -853,7 +866,6 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent, | |||
853 | 866 | ||
854 | spin_lock_init(&sbi->s_inode_lock); | 867 | spin_lock_init(&sbi->s_inode_lock); |
855 | INIT_LIST_HEAD(&sbi->s_dirty_files); | 868 | INIT_LIST_HEAD(&sbi->s_dirty_files); |
856 | INIT_LIST_HEAD(&sbi->s_list); | ||
857 | 869 | ||
858 | /* | 870 | /* |
859 | * Following initialization is overlapped because | 871 | * Following initialization is overlapped because |
@@ -875,20 +887,11 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent, | |||
875 | if (err) | 887 | if (err) |
876 | goto failed_sbi; | 888 | goto failed_sbi; |
877 | 889 | ||
878 | if (nilfs_test_opt(sbi, SNAPSHOT)) { | ||
879 | err = nilfs_attach_snapshot(sb, sbi->s_snapshot_cno, | ||
880 | &sb->s_root); | ||
881 | if (err) | ||
882 | goto failed_sbi; | ||
883 | |||
884 | goto add_to_supers; | ||
885 | } | ||
886 | |||
887 | cno = nilfs_last_cno(nilfs); | 890 | cno = nilfs_last_cno(nilfs); |
888 | err = nilfs_attach_checkpoint(sbi, cno, true, &fsroot); | 891 | err = nilfs_attach_checkpoint(sbi, cno, true, &fsroot); |
889 | if (err) { | 892 | if (err) { |
890 | printk(KERN_ERR "NILFS: error loading a checkpoint" | 893 | printk(KERN_ERR "NILFS: error loading last checkpoint " |
891 | " (checkpoint number=%llu).\n", (unsigned long long)cno); | 894 | "(checkpoint number=%llu).\n", (unsigned long long)cno); |
892 | goto failed_sbi; | 895 | goto failed_sbi; |
893 | } | 896 | } |
894 | 897 | ||
@@ -910,13 +913,6 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent, | |||
910 | up_write(&nilfs->ns_sem); | 913 | up_write(&nilfs->ns_sem); |
911 | } | 914 | } |
912 | 915 | ||
913 | add_to_supers: | ||
914 | down_write(&nilfs->ns_super_sem); | ||
915 | list_add(&sbi->s_list, &nilfs->ns_supers); | ||
916 | if (!nilfs_test_opt(sbi, SNAPSHOT)) | ||
917 | nilfs->ns_current = sbi; | ||
918 | up_write(&nilfs->ns_super_sem); | ||
919 | |||
920 | return 0; | 916 | return 0; |
921 | 917 | ||
922 | failed_segctor: | 918 | failed_segctor: |
@@ -928,7 +924,7 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent, | |||
928 | failed_sbi: | 924 | failed_sbi: |
929 | put_nilfs(nilfs); | 925 | put_nilfs(nilfs); |
930 | sb->s_fs_info = NULL; | 926 | sb->s_fs_info = NULL; |
931 | nilfs_put_sbinfo(sbi); | 927 | kfree(sbi); |
932 | return err; | 928 | return err; |
933 | } | 929 | } |
934 | 930 | ||
@@ -938,13 +934,10 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) | |||
938 | struct the_nilfs *nilfs = sbi->s_nilfs; | 934 | struct the_nilfs *nilfs = sbi->s_nilfs; |
939 | unsigned long old_sb_flags; | 935 | unsigned long old_sb_flags; |
940 | struct nilfs_mount_options old_opts; | 936 | struct nilfs_mount_options old_opts; |
941 | int was_snapshot, err; | 937 | int err; |
942 | 938 | ||
943 | down_write(&nilfs->ns_super_sem); | ||
944 | old_sb_flags = sb->s_flags; | 939 | old_sb_flags = sb->s_flags; |
945 | old_opts.mount_opt = sbi->s_mount_opt; | 940 | old_opts.mount_opt = sbi->s_mount_opt; |
946 | old_opts.snapshot_cno = sbi->s_snapshot_cno; | ||
947 | was_snapshot = nilfs_test_opt(sbi, SNAPSHOT); | ||
948 | 941 | ||
949 | if (!parse_options(data, sb, 1)) { | 942 | if (!parse_options(data, sb, 1)) { |
950 | err = -EINVAL; | 943 | err = -EINVAL; |
@@ -953,11 +946,6 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) | |||
953 | sb->s_flags = (sb->s_flags & ~MS_POSIXACL); | 946 | sb->s_flags = (sb->s_flags & ~MS_POSIXACL); |
954 | 947 | ||
955 | err = -EINVAL; | 948 | err = -EINVAL; |
956 | if (was_snapshot && !(*flags & MS_RDONLY)) { | ||
957 | printk(KERN_ERR "NILFS (device %s): cannot remount snapshot " | ||
958 | "read/write.\n", sb->s_id); | ||
959 | goto restore_opts; | ||
960 | } | ||
961 | 949 | ||
962 | if (!nilfs_valid_fs(nilfs)) { | 950 | if (!nilfs_valid_fs(nilfs)) { |
963 | printk(KERN_WARNING "NILFS (device %s): couldn't " | 951 | printk(KERN_WARNING "NILFS (device %s): couldn't " |
@@ -1014,14 +1002,11 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) | |||
1014 | up_write(&nilfs->ns_sem); | 1002 | up_write(&nilfs->ns_sem); |
1015 | } | 1003 | } |
1016 | out: | 1004 | out: |
1017 | up_write(&nilfs->ns_super_sem); | ||
1018 | return 0; | 1005 | return 0; |
1019 | 1006 | ||
1020 | restore_opts: | 1007 | restore_opts: |
1021 | sb->s_flags = old_sb_flags; | 1008 | sb->s_flags = old_sb_flags; |
1022 | sbi->s_mount_opt = old_opts.mount_opt; | 1009 | sbi->s_mount_opt = old_opts.mount_opt; |
1023 | sbi->s_snapshot_cno = old_opts.snapshot_cno; | ||
1024 | up_write(&nilfs->ns_super_sem); | ||
1025 | return err; | 1010 | return err; |
1026 | } | 1011 | } |
1027 | 1012 | ||
@@ -1075,18 +1060,14 @@ static int nilfs_identify(char *data, struct nilfs_super_data *sd) | |||
1075 | 1060 | ||
1076 | static int nilfs_set_bdev_super(struct super_block *s, void *data) | 1061 | static int nilfs_set_bdev_super(struct super_block *s, void *data) |
1077 | { | 1062 | { |
1078 | struct nilfs_super_data *sd = data; | 1063 | s->s_bdev = data; |
1079 | |||
1080 | s->s_bdev = sd->bdev; | ||
1081 | s->s_dev = s->s_bdev->bd_dev; | 1064 | s->s_dev = s->s_bdev->bd_dev; |
1082 | return 0; | 1065 | return 0; |
1083 | } | 1066 | } |
1084 | 1067 | ||
1085 | static int nilfs_test_bdev_super(struct super_block *s, void *data) | 1068 | static int nilfs_test_bdev_super(struct super_block *s, void *data) |
1086 | { | 1069 | { |
1087 | struct nilfs_super_data *sd = data; | 1070 | return (void *)s->s_bdev == data; |
1088 | |||
1089 | return sd->sbi && s->s_fs_info == (void *)sd->sbi; | ||
1090 | } | 1071 | } |
1091 | 1072 | ||
1092 | static int | 1073 | static int |
@@ -1097,7 +1078,8 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags, | |||
1097 | struct super_block *s; | 1078 | struct super_block *s; |
1098 | fmode_t mode = FMODE_READ; | 1079 | fmode_t mode = FMODE_READ; |
1099 | struct the_nilfs *nilfs; | 1080 | struct the_nilfs *nilfs; |
1100 | int err, need_to_close = 1; | 1081 | struct dentry *root_dentry; |
1082 | int err, s_new = false; | ||
1101 | 1083 | ||
1102 | if (!(flags & MS_RDONLY)) | 1084 | if (!(flags & MS_RDONLY)) |
1103 | mode |= FMODE_WRITE; | 1085 | mode |= FMODE_WRITE; |
@@ -1106,12 +1088,6 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags, | |||
1106 | if (IS_ERR(sd.bdev)) | 1088 | if (IS_ERR(sd.bdev)) |
1107 | return PTR_ERR(sd.bdev); | 1089 | return PTR_ERR(sd.bdev); |
1108 | 1090 | ||
1109 | /* | ||
1110 | * To get mount instance using sget() vfs-routine, NILFS needs | ||
1111 | * much more information than normal filesystems to identify mount | ||
1112 | * instance. For snapshot mounts, not only a mount type (ro-mount | ||
1113 | * or rw-mount) but also a checkpoint number is required. | ||
1114 | */ | ||
1115 | sd.cno = 0; | 1091 | sd.cno = 0; |
1116 | sd.flags = flags; | 1092 | sd.flags = flags; |
1117 | if (nilfs_identify((char *)data, &sd)) { | 1093 | if (nilfs_identify((char *)data, &sd)) { |
@@ -1127,38 +1103,7 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags, | |||
1127 | 1103 | ||
1128 | mutex_lock(&nilfs->ns_mount_mutex); | 1104 | mutex_lock(&nilfs->ns_mount_mutex); |
1129 | 1105 | ||
1130 | if (!sd.cno) { | 1106 | s = sget(fs_type, nilfs_test_bdev_super, nilfs_set_bdev_super, sd.bdev); |
1131 | /* | ||
1132 | * Check if an exclusive mount exists or not. | ||
1133 | * Snapshot mounts coexist with a current mount | ||
1134 | * (i.e. rw-mount or ro-mount), whereas rw-mount and | ||
1135 | * ro-mount are mutually exclusive. | ||
1136 | */ | ||
1137 | down_read(&nilfs->ns_super_sem); | ||
1138 | if (nilfs->ns_current && | ||
1139 | ((nilfs->ns_current->s_super->s_flags ^ flags) | ||
1140 | & MS_RDONLY)) { | ||
1141 | up_read(&nilfs->ns_super_sem); | ||
1142 | err = -EBUSY; | ||
1143 | goto failed_unlock; | ||
1144 | } | ||
1145 | up_read(&nilfs->ns_super_sem); | ||
1146 | } | ||
1147 | |||
1148 | /* | ||
1149 | * Find existing nilfs_sb_info struct | ||
1150 | */ | ||
1151 | sd.sbi = nilfs_find_sbinfo(nilfs, !(flags & MS_RDONLY), sd.cno); | ||
1152 | |||
1153 | /* | ||
1154 | * Get super block instance holding the nilfs_sb_info struct. | ||
1155 | * A new instance is allocated if no existing mount is present or | ||
1156 | * existing instance has been unmounted. | ||
1157 | */ | ||
1158 | s = sget(fs_type, nilfs_test_bdev_super, nilfs_set_bdev_super, &sd); | ||
1159 | if (sd.sbi) | ||
1160 | nilfs_put_sbinfo(sd.sbi); | ||
1161 | |||
1162 | if (IS_ERR(s)) { | 1107 | if (IS_ERR(s)) { |
1163 | err = PTR_ERR(s); | 1108 | err = PTR_ERR(s); |
1164 | goto failed_unlock; | 1109 | goto failed_unlock; |
@@ -1167,6 +1112,8 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags, | |||
1167 | if (!s->s_root) { | 1112 | if (!s->s_root) { |
1168 | char b[BDEVNAME_SIZE]; | 1113 | char b[BDEVNAME_SIZE]; |
1169 | 1114 | ||
1115 | s_new = true; | ||
1116 | |||
1170 | /* New superblock instance created */ | 1117 | /* New superblock instance created */ |
1171 | s->s_flags = flags; | 1118 | s->s_flags = flags; |
1172 | s->s_mode = mode; | 1119 | s->s_mode = mode; |
@@ -1179,16 +1126,53 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags, | |||
1179 | goto cancel_new; | 1126 | goto cancel_new; |
1180 | 1127 | ||
1181 | s->s_flags |= MS_ACTIVE; | 1128 | s->s_flags |= MS_ACTIVE; |
1182 | need_to_close = 0; | 1129 | } else if (!sd.cno) { |
1130 | int busy = false; | ||
1131 | |||
1132 | if (nilfs_tree_was_touched(s->s_root)) { | ||
1133 | busy = nilfs_try_to_shrink_tree(s->s_root); | ||
1134 | if (busy && (flags ^ s->s_flags) & MS_RDONLY) { | ||
1135 | printk(KERN_ERR "NILFS: the device already " | ||
1136 | "has a %s mount.\n", | ||
1137 | (s->s_flags & MS_RDONLY) ? | ||
1138 | "read-only" : "read/write"); | ||
1139 | err = -EBUSY; | ||
1140 | goto failed_super; | ||
1141 | } | ||
1142 | } | ||
1143 | if (!busy) { | ||
1144 | /* | ||
1145 | * Try remount to setup mount states if the current | ||
1146 | * tree is not mounted and only snapshots use this sb. | ||
1147 | */ | ||
1148 | err = nilfs_remount(s, &flags, data); | ||
1149 | if (err) | ||
1150 | goto failed_super; | ||
1151 | } | ||
1152 | } | ||
1153 | |||
1154 | if (sd.cno) { | ||
1155 | err = nilfs_attach_snapshot(s, sd.cno, &root_dentry); | ||
1156 | if (err) { | ||
1157 | if (s_new) | ||
1158 | goto cancel_new; | ||
1159 | goto failed_super; | ||
1160 | } | ||
1161 | } else { | ||
1162 | root_dentry = dget(s->s_root); | ||
1183 | } | 1163 | } |
1184 | 1164 | ||
1185 | mutex_unlock(&nilfs->ns_mount_mutex); | 1165 | mutex_unlock(&nilfs->ns_mount_mutex); |
1186 | put_nilfs(nilfs); | 1166 | put_nilfs(nilfs); |
1187 | if (need_to_close) | 1167 | if (!s_new) |
1188 | close_bdev_exclusive(sd.bdev, mode); | 1168 | close_bdev_exclusive(sd.bdev, mode); |
1189 | simple_set_mnt(mnt, s); | 1169 | |
1170 | mnt->mnt_sb = s; | ||
1171 | mnt->mnt_root = root_dentry; | ||
1190 | return 0; | 1172 | return 0; |
1191 | 1173 | ||
1174 | failed_super: | ||
1175 | deactivate_locked_super(s); | ||
1192 | failed_unlock: | 1176 | failed_unlock: |
1193 | mutex_unlock(&nilfs->ns_mount_mutex); | 1177 | mutex_unlock(&nilfs->ns_mount_mutex); |
1194 | put_nilfs(nilfs); | 1178 | put_nilfs(nilfs); |
@@ -1202,7 +1186,7 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags, | |||
1202 | put_nilfs(nilfs); | 1186 | put_nilfs(nilfs); |
1203 | deactivate_locked_super(s); | 1187 | deactivate_locked_super(s); |
1204 | /* | 1188 | /* |
1205 | * deactivate_locked_super() invokes close_bdev_exclusive(). | 1189 | * This deactivate_locked_super() invokes close_bdev_exclusive(). |
1206 | * We must finish all post-cleaning before this call; | 1190 | * We must finish all post-cleaning before this call; |
1207 | * put_nilfs() needs the block device. | 1191 | * put_nilfs() needs the block device. |
1208 | */ | 1192 | */ |