diff options
-rw-r--r-- | fs/gfs2/ops_fstype.c | 135 | ||||
-rw-r--r-- | fs/gfs2/super.c | 16 | ||||
-rw-r--r-- | fs/gfs2/super.h | 2 |
3 files changed, 127 insertions, 26 deletions
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 52fb6c048981..e5ee06231ae5 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c | |||
@@ -1114,7 +1114,7 @@ void gfs2_online_uevent(struct gfs2_sbd *sdp) | |||
1114 | * Returns: errno | 1114 | * Returns: errno |
1115 | */ | 1115 | */ |
1116 | 1116 | ||
1117 | static int fill_super(struct super_block *sb, void *data, int silent) | 1117 | static int fill_super(struct super_block *sb, struct gfs2_args *args, int silent) |
1118 | { | 1118 | { |
1119 | struct gfs2_sbd *sdp; | 1119 | struct gfs2_sbd *sdp; |
1120 | struct gfs2_holder mount_gh; | 1120 | struct gfs2_holder mount_gh; |
@@ -1125,17 +1125,7 @@ static int fill_super(struct super_block *sb, void *data, int silent) | |||
1125 | printk(KERN_WARNING "GFS2: can't alloc struct gfs2_sbd\n"); | 1125 | printk(KERN_WARNING "GFS2: can't alloc struct gfs2_sbd\n"); |
1126 | return -ENOMEM; | 1126 | return -ENOMEM; |
1127 | } | 1127 | } |
1128 | 1128 | sdp->sd_args = *args; | |
1129 | sdp->sd_args.ar_quota = GFS2_QUOTA_DEFAULT; | ||
1130 | sdp->sd_args.ar_data = GFS2_DATA_DEFAULT; | ||
1131 | sdp->sd_args.ar_commit = 60; | ||
1132 | sdp->sd_args.ar_errors = GFS2_ERRORS_DEFAULT; | ||
1133 | |||
1134 | error = gfs2_mount_args(sdp, &sdp->sd_args, data); | ||
1135 | if (error) { | ||
1136 | printk(KERN_WARNING "GFS2: can't parse mount arguments\n"); | ||
1137 | goto fail; | ||
1138 | } | ||
1139 | 1129 | ||
1140 | if (sdp->sd_args.ar_spectator) { | 1130 | if (sdp->sd_args.ar_spectator) { |
1141 | sb->s_flags |= MS_RDONLY; | 1131 | sb->s_flags |= MS_RDONLY; |
@@ -1243,18 +1233,125 @@ fail: | |||
1243 | return error; | 1233 | return error; |
1244 | } | 1234 | } |
1245 | 1235 | ||
1246 | static int gfs2_get_sb(struct file_system_type *fs_type, int flags, | 1236 | static int set_gfs2_super(struct super_block *s, void *data) |
1247 | const char *dev_name, void *data, struct vfsmount *mnt) | ||
1248 | { | 1237 | { |
1249 | return get_sb_bdev(fs_type, flags, dev_name, data, fill_super, mnt); | 1238 | s->s_bdev = data; |
1239 | s->s_dev = s->s_bdev->bd_dev; | ||
1240 | |||
1241 | /* | ||
1242 | * We set the bdi here to the queue backing, file systems can | ||
1243 | * overwrite this in ->fill_super() | ||
1244 | */ | ||
1245 | s->s_bdi = &bdev_get_queue(s->s_bdev)->backing_dev_info; | ||
1246 | return 0; | ||
1250 | } | 1247 | } |
1251 | 1248 | ||
1252 | static int test_meta_super(struct super_block *s, void *ptr) | 1249 | static int test_gfs2_super(struct super_block *s, void *ptr) |
1253 | { | 1250 | { |
1254 | struct block_device *bdev = ptr; | 1251 | struct block_device *bdev = ptr; |
1255 | return (bdev == s->s_bdev); | 1252 | return (bdev == s->s_bdev); |
1256 | } | 1253 | } |
1257 | 1254 | ||
1255 | /** | ||
1256 | * gfs2_get_sb - Get the GFS2 superblock | ||
1257 | * @fs_type: The GFS2 filesystem type | ||
1258 | * @flags: Mount flags | ||
1259 | * @dev_name: The name of the device | ||
1260 | * @data: The mount arguments | ||
1261 | * @mnt: The vfsmnt for this mount | ||
1262 | * | ||
1263 | * Q. Why not use get_sb_bdev() ? | ||
1264 | * A. We need to select one of two root directories to mount, independent | ||
1265 | * of whether this is the initial, or subsequent, mount of this sb | ||
1266 | * | ||
1267 | * Returns: 0 or -ve on error | ||
1268 | */ | ||
1269 | |||
1270 | static int gfs2_get_sb(struct file_system_type *fs_type, int flags, | ||
1271 | const char *dev_name, void *data, struct vfsmount *mnt) | ||
1272 | { | ||
1273 | struct block_device *bdev; | ||
1274 | struct super_block *s; | ||
1275 | fmode_t mode = FMODE_READ; | ||
1276 | int error; | ||
1277 | struct gfs2_args args; | ||
1278 | struct gfs2_sbd *sdp; | ||
1279 | |||
1280 | if (!(flags & MS_RDONLY)) | ||
1281 | mode |= FMODE_WRITE; | ||
1282 | |||
1283 | bdev = open_bdev_exclusive(dev_name, mode, fs_type); | ||
1284 | if (IS_ERR(bdev)) | ||
1285 | return PTR_ERR(bdev); | ||
1286 | |||
1287 | /* | ||
1288 | * once the super is inserted into the list by sget, s_umount | ||
1289 | * will protect the lockfs code from trying to start a snapshot | ||
1290 | * while we are mounting | ||
1291 | */ | ||
1292 | mutex_lock(&bdev->bd_fsfreeze_mutex); | ||
1293 | if (bdev->bd_fsfreeze_count > 0) { | ||
1294 | mutex_unlock(&bdev->bd_fsfreeze_mutex); | ||
1295 | error = -EBUSY; | ||
1296 | goto error_bdev; | ||
1297 | } | ||
1298 | s = sget(fs_type, test_gfs2_super, set_gfs2_super, bdev); | ||
1299 | mutex_unlock(&bdev->bd_fsfreeze_mutex); | ||
1300 | error = PTR_ERR(s); | ||
1301 | if (IS_ERR(s)) | ||
1302 | goto error_bdev; | ||
1303 | |||
1304 | memset(&args, 0, sizeof(args)); | ||
1305 | args.ar_quota = GFS2_QUOTA_DEFAULT; | ||
1306 | args.ar_data = GFS2_DATA_DEFAULT; | ||
1307 | args.ar_commit = 60; | ||
1308 | args.ar_errors = GFS2_ERRORS_DEFAULT; | ||
1309 | |||
1310 | error = gfs2_mount_args(&args, data); | ||
1311 | if (error) { | ||
1312 | printk(KERN_WARNING "GFS2: can't parse mount arguments\n"); | ||
1313 | if (s->s_root) | ||
1314 | goto error_super; | ||
1315 | deactivate_locked_super(s); | ||
1316 | return error; | ||
1317 | } | ||
1318 | |||
1319 | if (s->s_root) { | ||
1320 | error = -EBUSY; | ||
1321 | if ((flags ^ s->s_flags) & MS_RDONLY) | ||
1322 | goto error_super; | ||
1323 | close_bdev_exclusive(bdev, mode); | ||
1324 | } else { | ||
1325 | char b[BDEVNAME_SIZE]; | ||
1326 | |||
1327 | s->s_flags = flags; | ||
1328 | s->s_mode = mode; | ||
1329 | strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id)); | ||
1330 | sb_set_blocksize(s, block_size(bdev)); | ||
1331 | error = fill_super(s, &args, flags & MS_SILENT ? 1 : 0); | ||
1332 | if (error) { | ||
1333 | deactivate_locked_super(s); | ||
1334 | return error; | ||
1335 | } | ||
1336 | s->s_flags |= MS_ACTIVE; | ||
1337 | bdev->bd_super = s; | ||
1338 | } | ||
1339 | |||
1340 | sdp = s->s_fs_info; | ||
1341 | mnt->mnt_sb = s; | ||
1342 | if (args.ar_meta) | ||
1343 | mnt->mnt_root = dget(sdp->sd_master_dir); | ||
1344 | else | ||
1345 | mnt->mnt_root = dget(sdp->sd_root_dir); | ||
1346 | return 0; | ||
1347 | |||
1348 | error_super: | ||
1349 | deactivate_locked_super(s); | ||
1350 | error_bdev: | ||
1351 | close_bdev_exclusive(bdev, mode); | ||
1352 | return error; | ||
1353 | } | ||
1354 | |||
1258 | static int set_meta_super(struct super_block *s, void *ptr) | 1355 | static int set_meta_super(struct super_block *s, void *ptr) |
1259 | { | 1356 | { |
1260 | return -EINVAL; | 1357 | return -EINVAL; |
@@ -1274,13 +1371,17 @@ static int gfs2_get_sb_meta(struct file_system_type *fs_type, int flags, | |||
1274 | dev_name, error); | 1371 | dev_name, error); |
1275 | return error; | 1372 | return error; |
1276 | } | 1373 | } |
1277 | s = sget(&gfs2_fs_type, test_meta_super, set_meta_super, | 1374 | s = sget(&gfs2_fs_type, test_gfs2_super, set_meta_super, |
1278 | path.dentry->d_inode->i_sb->s_bdev); | 1375 | path.dentry->d_inode->i_sb->s_bdev); |
1279 | path_put(&path); | 1376 | path_put(&path); |
1280 | if (IS_ERR(s)) { | 1377 | if (IS_ERR(s)) { |
1281 | printk(KERN_WARNING "GFS2: gfs2 mount does not exist\n"); | 1378 | printk(KERN_WARNING "GFS2: gfs2 mount does not exist\n"); |
1282 | return PTR_ERR(s); | 1379 | return PTR_ERR(s); |
1283 | } | 1380 | } |
1381 | if ((flags ^ s->s_flags) & MS_RDONLY) { | ||
1382 | deactivate_locked_super(s); | ||
1383 | return -EBUSY; | ||
1384 | } | ||
1284 | sdp = s->s_fs_info; | 1385 | sdp = s->s_fs_info; |
1285 | mnt->mnt_sb = s; | 1386 | mnt->mnt_sb = s; |
1286 | mnt->mnt_root = dget(sdp->sd_master_dir); | 1387 | mnt->mnt_root = dget(sdp->sd_master_dir); |
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index 0ec3ec672de1..42e5458703f0 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c | |||
@@ -106,13 +106,13 @@ static const match_table_t tokens = { | |||
106 | 106 | ||
107 | /** | 107 | /** |
108 | * gfs2_mount_args - Parse mount options | 108 | * gfs2_mount_args - Parse mount options |
109 | * @sdp: | 109 | * @args: The structure into which the parsed options will be written |
110 | * @data: | 110 | * @options: The options to parse |
111 | * | 111 | * |
112 | * Return: errno | 112 | * Return: errno |
113 | */ | 113 | */ |
114 | 114 | ||
115 | int gfs2_mount_args(struct gfs2_sbd *sdp, struct gfs2_args *args, char *options) | 115 | int gfs2_mount_args(struct gfs2_args *args, char *options) |
116 | { | 116 | { |
117 | char *o; | 117 | char *o; |
118 | int token; | 118 | int token; |
@@ -157,7 +157,7 @@ int gfs2_mount_args(struct gfs2_sbd *sdp, struct gfs2_args *args, char *options) | |||
157 | break; | 157 | break; |
158 | case Opt_debug: | 158 | case Opt_debug: |
159 | if (args->ar_errors == GFS2_ERRORS_PANIC) { | 159 | if (args->ar_errors == GFS2_ERRORS_PANIC) { |
160 | fs_info(sdp, "-o debug and -o errors=panic " | 160 | printk(KERN_WARNING "GFS2: -o debug and -o errors=panic " |
161 | "are mutually exclusive.\n"); | 161 | "are mutually exclusive.\n"); |
162 | return -EINVAL; | 162 | return -EINVAL; |
163 | } | 163 | } |
@@ -210,7 +210,7 @@ int gfs2_mount_args(struct gfs2_sbd *sdp, struct gfs2_args *args, char *options) | |||
210 | case Opt_commit: | 210 | case Opt_commit: |
211 | rv = match_int(&tmp[0], &args->ar_commit); | 211 | rv = match_int(&tmp[0], &args->ar_commit); |
212 | if (rv || args->ar_commit <= 0) { | 212 | if (rv || args->ar_commit <= 0) { |
213 | fs_info(sdp, "commit mount option requires a positive numeric argument\n"); | 213 | printk(KERN_WARNING "GFS2: commit mount option requires a positive numeric argument\n"); |
214 | return rv ? rv : -EINVAL; | 214 | return rv ? rv : -EINVAL; |
215 | } | 215 | } |
216 | break; | 216 | break; |
@@ -219,7 +219,7 @@ int gfs2_mount_args(struct gfs2_sbd *sdp, struct gfs2_args *args, char *options) | |||
219 | break; | 219 | break; |
220 | case Opt_err_panic: | 220 | case Opt_err_panic: |
221 | if (args->ar_debug) { | 221 | if (args->ar_debug) { |
222 | fs_info(sdp, "-o debug and -o errors=panic " | 222 | printk(KERN_WARNING "GFS2: -o debug and -o errors=panic " |
223 | "are mutually exclusive.\n"); | 223 | "are mutually exclusive.\n"); |
224 | return -EINVAL; | 224 | return -EINVAL; |
225 | } | 225 | } |
@@ -227,7 +227,7 @@ int gfs2_mount_args(struct gfs2_sbd *sdp, struct gfs2_args *args, char *options) | |||
227 | break; | 227 | break; |
228 | case Opt_error: | 228 | case Opt_error: |
229 | default: | 229 | default: |
230 | fs_info(sdp, "invalid mount option: %s\n", o); | 230 | printk(KERN_WARNING "GFS2: invalid mount option: %s\n", o); |
231 | return -EINVAL; | 231 | return -EINVAL; |
232 | } | 232 | } |
233 | } | 233 | } |
@@ -1062,7 +1062,7 @@ static int gfs2_remount_fs(struct super_block *sb, int *flags, char *data) | |||
1062 | spin_lock(>->gt_spin); | 1062 | spin_lock(>->gt_spin); |
1063 | args.ar_commit = gt->gt_log_flush_secs; | 1063 | args.ar_commit = gt->gt_log_flush_secs; |
1064 | spin_unlock(>->gt_spin); | 1064 | spin_unlock(>->gt_spin); |
1065 | error = gfs2_mount_args(sdp, &args, data); | 1065 | error = gfs2_mount_args(&args, data); |
1066 | if (error) | 1066 | if (error) |
1067 | return error; | 1067 | return error; |
1068 | 1068 | ||
diff --git a/fs/gfs2/super.h b/fs/gfs2/super.h index 235db3682885..ed962ea68c3a 100644 --- a/fs/gfs2/super.h +++ b/fs/gfs2/super.h | |||
@@ -27,7 +27,7 @@ static inline unsigned int gfs2_jindex_size(struct gfs2_sbd *sdp) | |||
27 | 27 | ||
28 | extern void gfs2_jindex_free(struct gfs2_sbd *sdp); | 28 | extern void gfs2_jindex_free(struct gfs2_sbd *sdp); |
29 | 29 | ||
30 | extern int gfs2_mount_args(struct gfs2_sbd *sdp, struct gfs2_args *args, char *data); | 30 | extern int gfs2_mount_args(struct gfs2_args *args, char *data); |
31 | 31 | ||
32 | extern struct gfs2_jdesc *gfs2_jdesc_find(struct gfs2_sbd *sdp, unsigned int jid); | 32 | extern struct gfs2_jdesc *gfs2_jdesc_find(struct gfs2_sbd *sdp, unsigned int jid); |
33 | extern int gfs2_jdesc_check(struct gfs2_jdesc *jd); | 33 | extern int gfs2_jdesc_check(struct gfs2_jdesc *jd); |