@@ -202,6 +202,26 @@ struct ceph_parse_opts_ctx {
202
202
struct ceph_mount_options * opts ;
203
203
};
204
204
205
+ /*
206
+ * Remove adjacent slashes and then the trailing slash, unless it is
207
+ * the only remaining character.
208
+ *
209
+ * E.g. "//dir1////dir2///" --> "/dir1/dir2", "///" --> "/".
210
+ */
211
+ static void canonicalize_path (char * path )
212
+ {
213
+ int i , j = 0 ;
214
+
215
+ for (i = 0 ; path [i ] != '\0' ; i ++ ) {
216
+ if (path [i ] != '/' || j < 1 || path [j - 1 ] != '/' )
217
+ path [j ++ ] = path [i ];
218
+ }
219
+
220
+ if (j > 1 && path [j - 1 ] == '/' )
221
+ j -- ;
222
+ path [j ] = '\0' ;
223
+ }
224
+
205
225
/*
206
226
* Parse the source parameter. Distinguish the server list from the path.
207
227
*
@@ -224,15 +244,16 @@ static int ceph_parse_source(struct fs_parameter *param, struct fs_context *fc)
224
244
225
245
dev_name_end = strchr (dev_name , '/' );
226
246
if (dev_name_end ) {
227
- kfree (fsopt -> server_path );
228
-
229
247
/*
230
248
* The server_path will include the whole chars from userland
231
249
* including the leading '/'.
232
250
*/
251
+ kfree (fsopt -> server_path );
233
252
fsopt -> server_path = kstrdup (dev_name_end , GFP_KERNEL );
234
253
if (!fsopt -> server_path )
235
254
return - ENOMEM ;
255
+
256
+ canonicalize_path (fsopt -> server_path );
236
257
} else {
237
258
dev_name_end = dev_name + strlen (dev_name );
238
259
}
@@ -456,81 +477,13 @@ static int strcmp_null(const char *s1, const char *s2)
456
477
return strcmp (s1 , s2 );
457
478
}
458
479
459
- /**
460
- * path_remove_extra_slash - Remove the extra slashes in the server path
461
- * @server_path: the server path and could be NULL
462
- *
463
- * Return NULL if the path is NULL or only consists of "/", or a string
464
- * without any extra slashes including the leading slash(es) and the
465
- * slash(es) at the end of the server path, such as:
466
- * "//dir1////dir2///" --> "dir1/dir2"
467
- */
468
- static char * path_remove_extra_slash (const char * server_path )
469
- {
470
- const char * path = server_path ;
471
- const char * cur , * end ;
472
- char * buf , * p ;
473
- int len ;
474
-
475
- /* if the server path is omitted */
476
- if (!path )
477
- return NULL ;
478
-
479
- /* remove all the leading slashes */
480
- while (* path == '/' )
481
- path ++ ;
482
-
483
- /* if the server path only consists of slashes */
484
- if (* path == '\0' )
485
- return NULL ;
486
-
487
- len = strlen (path );
488
-
489
- buf = kmalloc (len + 1 , GFP_KERNEL );
490
- if (!buf )
491
- return ERR_PTR (- ENOMEM );
492
-
493
- end = path + len ;
494
- p = buf ;
495
- do {
496
- cur = strchr (path , '/' );
497
- if (!cur )
498
- cur = end ;
499
-
500
- len = cur - path ;
501
-
502
- /* including one '/' */
503
- if (cur != end )
504
- len += 1 ;
505
-
506
- memcpy (p , path , len );
507
- p += len ;
508
-
509
- while (cur <= end && * cur == '/' )
510
- cur ++ ;
511
- path = cur ;
512
- } while (path < end );
513
-
514
- * p = '\0' ;
515
-
516
- /*
517
- * remove the last slash if there has and just to make sure that
518
- * we will get something like "dir1/dir2"
519
- */
520
- if (* (-- p ) == '/' )
521
- * p = '\0' ;
522
-
523
- return buf ;
524
- }
525
-
526
480
static int compare_mount_options (struct ceph_mount_options * new_fsopt ,
527
481
struct ceph_options * new_opt ,
528
482
struct ceph_fs_client * fsc )
529
483
{
530
484
struct ceph_mount_options * fsopt1 = new_fsopt ;
531
485
struct ceph_mount_options * fsopt2 = fsc -> mount_options ;
532
486
int ofs = offsetof(struct ceph_mount_options , snapdir_name );
533
- char * p1 , * p2 ;
534
487
int ret ;
535
488
536
489
ret = memcmp (fsopt1 , fsopt2 , ofs );
@@ -540,21 +493,12 @@ static int compare_mount_options(struct ceph_mount_options *new_fsopt,
540
493
ret = strcmp_null (fsopt1 -> snapdir_name , fsopt2 -> snapdir_name );
541
494
if (ret )
542
495
return ret ;
496
+
543
497
ret = strcmp_null (fsopt1 -> mds_namespace , fsopt2 -> mds_namespace );
544
498
if (ret )
545
499
return ret ;
546
500
547
- p1 = path_remove_extra_slash (fsopt1 -> server_path );
548
- if (IS_ERR (p1 ))
549
- return PTR_ERR (p1 );
550
- p2 = path_remove_extra_slash (fsopt2 -> server_path );
551
- if (IS_ERR (p2 )) {
552
- kfree (p1 );
553
- return PTR_ERR (p2 );
554
- }
555
- ret = strcmp_null (p1 , p2 );
556
- kfree (p1 );
557
- kfree (p2 );
501
+ ret = strcmp_null (fsopt1 -> server_path , fsopt2 -> server_path );
558
502
if (ret )
559
503
return ret ;
560
504
@@ -957,7 +901,9 @@ static struct dentry *ceph_real_mount(struct ceph_fs_client *fsc,
957
901
mutex_lock (& fsc -> client -> mount_mutex );
958
902
959
903
if (!fsc -> sb -> s_root ) {
960
- const char * path , * p ;
904
+ const char * path = fsc -> mount_options -> server_path ?
905
+ fsc -> mount_options -> server_path + 1 : "" ;
906
+
961
907
err = __ceph_open_session (fsc -> client , started );
962
908
if (err < 0 )
963
909
goto out ;
@@ -969,22 +915,11 @@ static struct dentry *ceph_real_mount(struct ceph_fs_client *fsc,
969
915
goto out ;
970
916
}
971
917
972
- p = path_remove_extra_slash (fsc -> mount_options -> server_path );
973
- if (IS_ERR (p )) {
974
- err = PTR_ERR (p );
975
- goto out ;
976
- }
977
- /* if the server path is omitted or just consists of '/' */
978
- if (!p )
979
- path = "" ;
980
- else
981
- path = p ;
982
918
dout ("mount opening path '%s'\n" , path );
983
919
984
920
ceph_fs_debugfs_init (fsc );
985
921
986
922
root = open_root_dentry (fsc , path , started );
987
- kfree (p );
988
923
if (IS_ERR (root )) {
989
924
err = PTR_ERR (root );
990
925
goto out ;
@@ -1097,10 +1032,6 @@ static int ceph_get_tree(struct fs_context *fc)
1097
1032
if (!fc -> source )
1098
1033
return invalfc (fc , "No source" );
1099
1034
1100
- #ifdef CONFIG_CEPH_FS_POSIX_ACL
1101
- fc -> sb_flags |= SB_POSIXACL ;
1102
- #endif
1103
-
1104
1035
/* create client (which we may/may not use) */
1105
1036
fsc = create_fs_client (pctx -> opts , pctx -> copts );
1106
1037
pctx -> opts = NULL ;
@@ -1223,6 +1154,10 @@ static int ceph_init_fs_context(struct fs_context *fc)
1223
1154
fsopt -> max_readdir_bytes = CEPH_MAX_READDIR_BYTES_DEFAULT ;
1224
1155
fsopt -> congestion_kb = default_congestion_kb ();
1225
1156
1157
+ #ifdef CONFIG_CEPH_FS_POSIX_ACL
1158
+ fc -> sb_flags |= SB_POSIXACL ;
1159
+ #endif
1160
+
1226
1161
fc -> fs_private = pctx ;
1227
1162
fc -> ops = & ceph_context_ops ;
1228
1163
return 0 ;
0 commit comments