aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/nilfs2/super.c92
-rw-r--r--fs/nilfs2/the_nilfs.h3
2 files changed, 35 insertions, 60 deletions
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c
index 3c9833e3e74a..5a8c5e4731b3 100644
--- a/fs/nilfs2/super.c
+++ b/fs/nilfs2/super.c
@@ -67,8 +67,6 @@ MODULE_LICENSE("GPL");
67 67
68static void nilfs_write_super(struct super_block *sb); 68static void nilfs_write_super(struct super_block *sb);
69static int nilfs_remount(struct super_block *sb, int *flags, char *data); 69static int nilfs_remount(struct super_block *sb, int *flags, char *data);
70static int test_exclusive_mount(struct file_system_type *fs_type,
71 struct block_device *bdev, int flags);
72 70
73/** 71/**
74 * nilfs_error() - report failure condition on a filesystem 72 * nilfs_error() - report failure condition on a filesystem
@@ -329,6 +327,10 @@ static void nilfs_put_super(struct super_block *sb)
329 nilfs_commit_super(sbi, 1); 327 nilfs_commit_super(sbi, 1);
330 up_write(&nilfs->ns_sem); 328 up_write(&nilfs->ns_sem);
331 } 329 }
330 down_write(&nilfs->ns_sem);
331 if (nilfs->ns_current == sbi)
332 nilfs->ns_current = NULL;
333 up_write(&nilfs->ns_sem);
332 334
333 nilfs_detach_checkpoint(sbi); 335 nilfs_detach_checkpoint(sbi);
334 put_nilfs(sbi->s_nilfs); 336 put_nilfs(sbi->s_nilfs);
@@ -880,6 +882,11 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent,
880 goto failed_root; 882 goto failed_root;
881 } 883 }
882 884
885 down_write(&nilfs->ns_sem);
886 if (!nilfs_test_opt(sbi, SNAPSHOT))
887 nilfs->ns_current = sbi;
888 up_write(&nilfs->ns_sem);
889
883 return 0; 890 return 0;
884 891
885 failed_root: 892 failed_root:
@@ -958,14 +965,16 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data)
958 * by fsck since we originally mounted the partition.) 965 * by fsck since we originally mounted the partition.)
959 */ 966 */
960 down(&sb->s_bdev->bd_mount_sem); 967 down(&sb->s_bdev->bd_mount_sem);
961 /* Check existing RW-mount */ 968 down_read(&nilfs->ns_sem);
962 if (test_exclusive_mount(sb->s_type, sb->s_bdev, 0)) { 969 if (nilfs->ns_current && nilfs->ns_current != sbi) {
963 printk(KERN_WARNING "NILFS (device %s): couldn't " 970 printk(KERN_WARNING "NILFS (device %s): couldn't "
964 "remount because a RW-mount exists.\n", 971 "remount because an RW-mount exists.\n",
965 sb->s_id); 972 sb->s_id);
973 up_read(&nilfs->ns_sem);
966 err = -EBUSY; 974 err = -EBUSY;
967 goto rw_remount_failed; 975 goto rw_remount_failed;
968 } 976 }
977 up_read(&nilfs->ns_sem);
969 if (sbi->s_snapshot_cno != nilfs_last_cno(nilfs)) { 978 if (sbi->s_snapshot_cno != nilfs_last_cno(nilfs)) {
970 printk(KERN_WARNING "NILFS (device %s): couldn't " 979 printk(KERN_WARNING "NILFS (device %s): couldn't "
971 "remount because the current RO-mount is not " 980 "remount because the current RO-mount is not "
@@ -984,6 +993,7 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data)
984 993
985 down_write(&nilfs->ns_sem); 994 down_write(&nilfs->ns_sem);
986 nilfs_setup_super(sbi); 995 nilfs_setup_super(sbi);
996 nilfs->ns_current = sbi;
987 up_write(&nilfs->ns_sem); 997 up_write(&nilfs->ns_sem);
988 998
989 up(&sb->s_bdev->bd_mount_sem); 999 up(&sb->s_bdev->bd_mount_sem);
@@ -1118,10 +1128,23 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags,
1118 } 1128 }
1119 1129
1120 down(&sd.bdev->bd_mount_sem); 1130 down(&sd.bdev->bd_mount_sem);
1121 if (!sd.cno && 1131
1122 (err = test_exclusive_mount(fs_type, sd.bdev, flags ^ MS_RDONLY))) { 1132 if (!sd.cno) {
1123 err = (err < 0) ? : -EBUSY; 1133 /*
1124 goto failed_unlock; 1134 * Check if an exclusive mount exists or not.
1135 * Snapshot mounts coexist with a current mount
1136 * (i.e. rw-mount or ro-mount), whereas rw-mount and
1137 * ro-mount are mutually exclusive.
1138 */
1139 down_read(&nilfs->ns_sem);
1140 if (nilfs->ns_current &&
1141 ((nilfs->ns_current->s_super->s_flags ^ flags)
1142 & MS_RDONLY)) {
1143 up_read(&nilfs->ns_sem);
1144 err = -EBUSY;
1145 goto failed_unlock;
1146 }
1147 up_read(&nilfs->ns_sem);
1125 } 1148 }
1126 1149
1127 /* 1150 /*
@@ -1182,57 +1205,6 @@ nilfs_get_sb(struct file_system_type *fs_type, int flags,
1182 return err; 1205 return err;
1183} 1206}
1184 1207
1185static int nilfs_test_bdev_super3(struct super_block *s, void *data)
1186{
1187 struct nilfs_super_data *sd = data;
1188 int ret;
1189
1190 if (s->s_bdev != sd->bdev)
1191 return 0;
1192 if (down_read_trylock(&s->s_umount)) {
1193 ret = (s->s_flags & MS_RDONLY) && s->s_root &&
1194 nilfs_test_opt(NILFS_SB(s), SNAPSHOT);
1195 up_read(&s->s_umount);
1196 if (ret)
1197 return 0; /* ignore snapshot mounts */
1198 }
1199 return !((sd->flags ^ s->s_flags) & MS_RDONLY);
1200}
1201
1202static int __false_bdev_super(struct super_block *s, void *data)
1203{
1204#if 0 /* XXX: workaround for lock debug. This is not good idea */
1205 up_write(&s->s_umount);
1206#endif
1207 return -EFAULT;
1208}
1209
1210/**
1211 * test_exclusive_mount - check whether an exclusive RW/RO mount exists or not.
1212 * fs_type: filesystem type
1213 * bdev: block device
1214 * flag: 0 (check rw-mount) or MS_RDONLY (check ro-mount)
1215 * res: pointer to an integer to store result
1216 *
1217 * This function must be called within a section protected by bd_mount_mutex.
1218 */
1219static int test_exclusive_mount(struct file_system_type *fs_type,
1220 struct block_device *bdev, int flags)
1221{
1222 struct super_block *s;
1223 struct nilfs_super_data sd = { .flags = flags, .bdev = bdev };
1224
1225 s = sget(fs_type, nilfs_test_bdev_super3, __false_bdev_super, &sd);
1226 if (IS_ERR(s)) {
1227 if (PTR_ERR(s) != -EFAULT)
1228 return PTR_ERR(s);
1229 return 0; /* Not found */
1230 }
1231 up_write(&s->s_umount);
1232 deactivate_super(s);
1233 return 1; /* Found */
1234}
1235
1236struct file_system_type nilfs_fs_type = { 1208struct file_system_type nilfs_fs_type = {
1237 .owner = THIS_MODULE, 1209 .owner = THIS_MODULE,
1238 .name = "nilfs2", 1210 .name = "nilfs2",
diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h
index 116caf96e7f3..99f7e29a5335 100644
--- a/fs/nilfs2/the_nilfs.h
+++ b/fs/nilfs2/the_nilfs.h
@@ -50,6 +50,7 @@ enum {
50 * @ns_sem: semaphore for shared states 50 * @ns_sem: semaphore for shared states
51 * @ns_writer_mutex: mutex protecting ns_writer attach/detach 51 * @ns_writer_mutex: mutex protecting ns_writer attach/detach
52 * @ns_writer_refcount: number of referrers on ns_writer 52 * @ns_writer_refcount: number of referrers on ns_writer
53 * @ns_current: back pointer to current mount
53 * @ns_sbh: buffer heads of on-disk super blocks 54 * @ns_sbh: buffer heads of on-disk super blocks
54 * @ns_sbp: pointers to super block data 55 * @ns_sbp: pointers to super block data
55 * @ns_sbwtime: previous write time of super blocks 56 * @ns_sbwtime: previous write time of super blocks
@@ -98,6 +99,8 @@ struct the_nilfs {
98 struct mutex ns_writer_mutex; 99 struct mutex ns_writer_mutex;
99 atomic_t ns_writer_refcount; 100 atomic_t ns_writer_refcount;
100 101
102 struct nilfs_sb_info *ns_current;
103
101 /* 104 /*
102 * used for 105 * used for
103 * - loading the latest checkpoint exclusively. 106 * - loading the latest checkpoint exclusively.