@@ -146,6 +146,7 @@ enum {
146
146
Opt_mds_namespace ,
147
147
Opt_recover_session ,
148
148
Opt_source ,
149
+ Opt_mon_addr ,
149
150
/* string args above */
150
151
Opt_dirstat ,
151
152
Opt_rbytes ,
@@ -197,6 +198,7 @@ static const struct fs_parameter_spec ceph_mount_parameters[] = {
197
198
fsparam_u32 ("rsize" , Opt_rsize ),
198
199
fsparam_string ("snapdirname" , Opt_snapdirname ),
199
200
fsparam_string ("source" , Opt_source ),
201
+ fsparam_string ("mon_addr" , Opt_mon_addr ),
200
202
fsparam_u32 ("wsize" , Opt_wsize ),
201
203
fsparam_flag_no ("wsync" , Opt_wsync ),
202
204
{}
@@ -228,9 +230,92 @@ static void canonicalize_path(char *path)
228
230
}
229
231
230
232
/*
231
- * Parse the source parameter. Distinguish the server list from the path.
233
+ * Check if the mds namespace in ceph_mount_options matches
234
+ * the passed in namespace string. First time match (when
235
+ * ->mds_namespace is NULL) is treated specially, since
236
+ * ->mds_namespace needs to be initialized by the caller.
237
+ */
238
+ static int namespace_equals (struct ceph_mount_options * fsopt ,
239
+ const char * namespace , size_t len )
240
+ {
241
+ return !(fsopt -> mds_namespace &&
242
+ (strlen (fsopt -> mds_namespace ) != len ||
243
+ strncmp (fsopt -> mds_namespace , namespace , len )));
244
+ }
245
+
246
+ static int ceph_parse_old_source (const char * dev_name , const char * dev_name_end ,
247
+ struct fs_context * fc )
248
+ {
249
+ int r ;
250
+ struct ceph_parse_opts_ctx * pctx = fc -> fs_private ;
251
+ struct ceph_mount_options * fsopt = pctx -> opts ;
252
+
253
+ if (* dev_name_end != ':' )
254
+ return invalfc (fc , "separator ':' missing in source" );
255
+
256
+ r = ceph_parse_mon_ips (dev_name , dev_name_end - dev_name ,
257
+ pctx -> copts , fc -> log .log , ',' );
258
+ if (r )
259
+ return r ;
260
+
261
+ fsopt -> new_dev_syntax = false;
262
+ return 0 ;
263
+ }
264
+
265
+ static int ceph_parse_new_source (const char * dev_name , const char * dev_name_end ,
266
+ struct fs_context * fc )
267
+ {
268
+ size_t len ;
269
+ struct ceph_fsid fsid ;
270
+ struct ceph_parse_opts_ctx * pctx = fc -> fs_private ;
271
+ struct ceph_mount_options * fsopt = pctx -> opts ;
272
+ char * fsid_start , * fs_name_start ;
273
+
274
+ if (* dev_name_end != '=' ) {
275
+ dout ("separator '=' missing in source" );
276
+ return - EINVAL ;
277
+ }
278
+
279
+ fsid_start = strchr (dev_name , '@' );
280
+ if (!fsid_start )
281
+ return invalfc (fc , "missing cluster fsid" );
282
+ ++ fsid_start ; /* start of cluster fsid */
283
+
284
+ fs_name_start = strchr (fsid_start , '.' );
285
+ if (!fs_name_start )
286
+ return invalfc (fc , "missing file system name" );
287
+
288
+ if (ceph_parse_fsid (fsid_start , & fsid ))
289
+ return invalfc (fc , "Invalid FSID" );
290
+
291
+ ++ fs_name_start ; /* start of file system name */
292
+ len = dev_name_end - fs_name_start ;
293
+
294
+ if (!namespace_equals (fsopt , fs_name_start , len ))
295
+ return invalfc (fc , "Mismatching mds_namespace" );
296
+ kfree (fsopt -> mds_namespace );
297
+ fsopt -> mds_namespace = kstrndup (fs_name_start , len , GFP_KERNEL );
298
+ if (!fsopt -> mds_namespace )
299
+ return - ENOMEM ;
300
+ dout ("file system (mds namespace) '%s'\n" , fsopt -> mds_namespace );
301
+
302
+ fsopt -> new_dev_syntax = true;
303
+ return 0 ;
304
+ }
305
+
306
+ /*
307
+ * Parse the source parameter for new device format. Distinguish the device
308
+ * spec from the path. Try parsing new device format and fallback to old
309
+ * format if needed.
310
+ *
311
+ * New device syntax will looks like:
312
+ * <device_spec>=/<path>
313
+ * where
314
+ * <device_spec> is [email protected]
315
+ * <path> is optional, but if present must begin with '/'
316
+ * (monitor addresses are passed via mount option)
232
317
*
233
- * The source will look like :
318
+ * Old device syntax is :
234
319
* <server_spec>[,<server_spec>...]:[<path>]
235
320
* where
236
321
* <server_spec> is <ip>[:<port>]
@@ -263,24 +348,44 @@ static int ceph_parse_source(struct fs_parameter *param, struct fs_context *fc)
263
348
dev_name_end = dev_name + strlen (dev_name );
264
349
}
265
350
266
- dev_name_end -- ; /* back up to ':' separator */
267
- if (dev_name_end < dev_name || * dev_name_end != ':' )
268
- return invalfc (fc , "No path or : separator in source" );
351
+ dev_name_end -- ; /* back up to separator */
352
+ if (dev_name_end < dev_name )
353
+ return invalfc (fc , "Path missing in source" );
269
354
270
355
dout ("device name '%.*s'\n" , (int )(dev_name_end - dev_name ), dev_name );
271
356
if (fsopt -> server_path )
272
357
dout ("server path '%s'\n" , fsopt -> server_path );
273
358
274
- ret = ceph_parse_mon_ips (param -> string , dev_name_end - dev_name ,
275
- pctx -> copts , fc -> log .log , ',' );
276
- if (ret )
277
- return ret ;
359
+ dout ("trying new device syntax" );
360
+ ret = ceph_parse_new_source (dev_name , dev_name_end , fc );
361
+ if (ret ) {
362
+ if (ret != - EINVAL )
363
+ return ret ;
364
+ dout ("trying old device syntax" );
365
+ ret = ceph_parse_old_source (dev_name , dev_name_end , fc );
366
+ if (ret )
367
+ return ret ;
368
+ }
278
369
279
370
fc -> source = param -> string ;
280
371
param -> string = NULL ;
281
372
return 0 ;
282
373
}
283
374
375
+ static int ceph_parse_mon_addr (struct fs_parameter * param ,
376
+ struct fs_context * fc )
377
+ {
378
+ struct ceph_parse_opts_ctx * pctx = fc -> fs_private ;
379
+ struct ceph_mount_options * fsopt = pctx -> opts ;
380
+
381
+ kfree (fsopt -> mon_addr );
382
+ fsopt -> mon_addr = param -> string ;
383
+ param -> string = NULL ;
384
+
385
+ return ceph_parse_mon_ips (fsopt -> mon_addr , strlen (fsopt -> mon_addr ),
386
+ pctx -> copts , fc -> log .log , '/' );
387
+ }
388
+
284
389
static int ceph_parse_mount_param (struct fs_context * fc ,
285
390
struct fs_parameter * param )
286
391
{
@@ -306,6 +411,8 @@ static int ceph_parse_mount_param(struct fs_context *fc,
306
411
param -> string = NULL ;
307
412
break ;
308
413
case Opt_mds_namespace :
414
+ if (!namespace_equals (fsopt , param -> string , strlen (param -> string )))
415
+ return invalfc (fc , "Mismatching mds_namespace" );
309
416
kfree (fsopt -> mds_namespace );
310
417
fsopt -> mds_namespace = param -> string ;
311
418
param -> string = NULL ;
@@ -323,6 +430,8 @@ static int ceph_parse_mount_param(struct fs_context *fc,
323
430
if (fc -> source )
324
431
return invalfc (fc , "Multiple sources specified" );
325
432
return ceph_parse_source (param , fc );
433
+ case Opt_mon_addr :
434
+ return ceph_parse_mon_addr (param , fc );
326
435
case Opt_wsize :
327
436
if (result .uint_32 < PAGE_SIZE ||
328
437
result .uint_32 > CEPH_MAX_WRITE_SIZE )
@@ -474,6 +583,7 @@ static void destroy_mount_options(struct ceph_mount_options *args)
474
583
kfree (args -> mds_namespace );
475
584
kfree (args -> server_path );
476
585
kfree (args -> fscache_uniq );
586
+ kfree (args -> mon_addr );
477
587
kfree (args );
478
588
}
479
589
@@ -517,6 +627,10 @@ static int compare_mount_options(struct ceph_mount_options *new_fsopt,
517
627
if (ret )
518
628
return ret ;
519
629
630
+ ret = strcmp_null (fsopt1 -> mon_addr , fsopt2 -> mon_addr );
631
+ if (ret )
632
+ return ret ;
633
+
520
634
return ceph_compare_options (new_opt , fsc -> client );
521
635
}
522
636
@@ -572,9 +686,13 @@ static int ceph_show_options(struct seq_file *m, struct dentry *root)
572
686
if ((fsopt -> flags & CEPH_MOUNT_OPT_NOCOPYFROM ) == 0 )
573
687
seq_puts (m , ",copyfrom" );
574
688
575
- if (fsopt -> mds_namespace )
689
+ /* dump mds_namespace when old device syntax is in use */
690
+ if (fsopt -> mds_namespace && !fsopt -> new_dev_syntax )
576
691
seq_show_option (m , "mds_namespace" , fsopt -> mds_namespace );
577
692
693
+ if (fsopt -> mon_addr )
694
+ seq_printf (m , ",mon_addr=%s" , fsopt -> mon_addr );
695
+
578
696
if (fsopt -> flags & CEPH_MOUNT_OPT_CLEANRECOVER )
579
697
seq_show_option (m , "recover_session" , "clean" );
580
698
@@ -1060,6 +1178,7 @@ static int ceph_setup_bdi(struct super_block *sb, struct ceph_fs_client *fsc)
1060
1178
static int ceph_get_tree (struct fs_context * fc )
1061
1179
{
1062
1180
struct ceph_parse_opts_ctx * pctx = fc -> fs_private ;
1181
+ struct ceph_mount_options * fsopt = pctx -> opts ;
1063
1182
struct super_block * sb ;
1064
1183
struct ceph_fs_client * fsc ;
1065
1184
struct dentry * res ;
@@ -1071,6 +1190,8 @@ static int ceph_get_tree(struct fs_context *fc)
1071
1190
1072
1191
if (!fc -> source )
1073
1192
return invalfc (fc , "No source" );
1193
+ if (fsopt -> new_dev_syntax && !fsopt -> mon_addr )
1194
+ return invalfc (fc , "No monitor address" );
1074
1195
1075
1196
/* create client (which we may/may not use) */
1076
1197
fsc = create_fs_client (pctx -> opts , pctx -> copts );
0 commit comments