super.c (c9d35ee049b40f1d73e890bf88dd55f83b1e9be8) super.c (b27a939e8376a3f1ed09b9c33ef44d20f18ec3d0)
1// SPDX-License-Identifier: GPL-2.0-only
2
3#include <linux/ceph/ceph_debug.h>
4
5#include <linux/backing-dev.h>
6#include <linux/ctype.h>
7#include <linux/fs.h>
8#include <linux/inet.h>

--- 189 unchanged lines hidden (view full) ---

198};
199
200struct ceph_parse_opts_ctx {
201 struct ceph_options *copts;
202 struct ceph_mount_options *opts;
203};
204
205/*
1// SPDX-License-Identifier: GPL-2.0-only
2
3#include <linux/ceph/ceph_debug.h>
4
5#include <linux/backing-dev.h>
6#include <linux/ctype.h>
7#include <linux/fs.h>
8#include <linux/inet.h>

--- 189 unchanged lines hidden (view full) ---

198};
199
200struct ceph_parse_opts_ctx {
201 struct ceph_options *copts;
202 struct ceph_mount_options *opts;
203};
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 */
211static 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
225/*
206 * Parse the source parameter. Distinguish the server list from the path.
207 *
208 * The source will look like:
209 * <server_spec>[,<server_spec>...]:[<path>]
210 * where
211 * <server_spec> is <ip>[:<port>]
212 * <path> is optional, but if present must begin with '/'
213 */

--- 5 unchanged lines hidden (view full) ---

219 int ret;
220
221 dout("%s '%s'\n", __func__, dev_name);
222 if (!dev_name || !*dev_name)
223 return invalfc(fc, "Empty source");
224
225 dev_name_end = strchr(dev_name, '/');
226 if (dev_name_end) {
226 * Parse the source parameter. Distinguish the server list from the path.
227 *
228 * The source will look like:
229 * <server_spec>[,<server_spec>...]:[<path>]
230 * where
231 * <server_spec> is <ip>[:<port>]
232 * <path> is optional, but if present must begin with '/'
233 */

--- 5 unchanged lines hidden (view full) ---

239 int ret;
240
241 dout("%s '%s'\n", __func__, dev_name);
242 if (!dev_name || !*dev_name)
243 return invalfc(fc, "Empty source");
244
245 dev_name_end = strchr(dev_name, '/');
246 if (dev_name_end) {
227 kfree(fsopt->server_path);
228
229 /*
230 * The server_path will include the whole chars from userland
231 * including the leading '/'.
232 */
247 /*
248 * The server_path will include the whole chars from userland
249 * including the leading '/'.
250 */
251 kfree(fsopt->server_path);
233 fsopt->server_path = kstrdup(dev_name_end, GFP_KERNEL);
234 if (!fsopt->server_path)
235 return -ENOMEM;
252 fsopt->server_path = kstrdup(dev_name_end, GFP_KERNEL);
253 if (!fsopt->server_path)
254 return -ENOMEM;
255
256 canonicalize_path(fsopt->server_path);
236 } else {
237 dev_name_end = dev_name + strlen(dev_name);
238 }
239
240 dev_name_end--; /* back up to ':' separator */
241 if (dev_name_end < dev_name || *dev_name_end != ':')
242 return invalfc(fc, "No path or : separator in source");
243

--- 207 unchanged lines hidden (view full) ---

451 return 0;
452 if (s1 && !s2)
453 return -1;
454 if (!s1 && s2)
455 return 1;
456 return strcmp(s1, s2);
457}
458
257 } else {
258 dev_name_end = dev_name + strlen(dev_name);
259 }
260
261 dev_name_end--; /* back up to ':' separator */
262 if (dev_name_end < dev_name || *dev_name_end != ':')
263 return invalfc(fc, "No path or : separator in source");
264

--- 207 unchanged lines hidden (view full) ---

472 return 0;
473 if (s1 && !s2)
474 return -1;
475 if (!s1 && s2)
476 return 1;
477 return strcmp(s1, s2);
478}
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 */
468static 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
526static int compare_mount_options(struct ceph_mount_options *new_fsopt,
527 struct ceph_options *new_opt,
528 struct ceph_fs_client *fsc)
529{
530 struct ceph_mount_options *fsopt1 = new_fsopt;
531 struct ceph_mount_options *fsopt2 = fsc->mount_options;
532 int ofs = offsetof(struct ceph_mount_options, snapdir_name);
480static int compare_mount_options(struct ceph_mount_options *new_fsopt,
481 struct ceph_options *new_opt,
482 struct ceph_fs_client *fsc)
483{
484 struct ceph_mount_options *fsopt1 = new_fsopt;
485 struct ceph_mount_options *fsopt2 = fsc->mount_options;
486 int ofs = offsetof(struct ceph_mount_options, snapdir_name);
533 char *p1, *p2;
534 int ret;
535
536 ret = memcmp(fsopt1, fsopt2, ofs);
537 if (ret)
538 return ret;
539
540 ret = strcmp_null(fsopt1->snapdir_name, fsopt2->snapdir_name);
541 if (ret)
542 return ret;
487 int ret;
488
489 ret = memcmp(fsopt1, fsopt2, ofs);
490 if (ret)
491 return ret;
492
493 ret = strcmp_null(fsopt1->snapdir_name, fsopt2->snapdir_name);
494 if (ret)
495 return ret;
496
543 ret = strcmp_null(fsopt1->mds_namespace, fsopt2->mds_namespace);
544 if (ret)
545 return ret;
546
497 ret = strcmp_null(fsopt1->mds_namespace, fsopt2->mds_namespace);
498 if (ret)
499 return ret;
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 if (ret)
559 return ret;
560
561 ret = strcmp_null(fsopt1->fscache_uniq, fsopt2->fscache_uniq);
562 if (ret)
563 return ret;
564
565 return ceph_compare_options(new_opt, fsc->client);

--- 386 unchanged lines hidden (view full) ---

952 int err;
953 unsigned long started = jiffies; /* note the start time */
954 struct dentry *root;
955
956 dout("mount start %p\n", fsc);
957 mutex_lock(&fsc->client->mount_mutex);
958
959 if (!fsc->sb->s_root) {
502 if (ret)
503 return ret;
504
505 ret = strcmp_null(fsopt1->fscache_uniq, fsopt2->fscache_uniq);
506 if (ret)
507 return ret;
508
509 return ceph_compare_options(new_opt, fsc->client);

--- 386 unchanged lines hidden (view full) ---

896 int err;
897 unsigned long started = jiffies; /* note the start time */
898 struct dentry *root;
899
900 dout("mount start %p\n", fsc);
901 mutex_lock(&fsc->client->mount_mutex);
902
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 err = __ceph_open_session(fsc->client, started);
962 if (err < 0)
963 goto out;
964
965 /* setup fscache */
966 if (fsc->mount_options->flags & CEPH_MOUNT_OPT_FSCACHE) {
967 err = ceph_fscache_register_fs(fsc, fc);
968 if (err < 0)
969 goto out;
970 }
971
907 err = __ceph_open_session(fsc->client, started);
908 if (err < 0)
909 goto out;
910
911 /* setup fscache */
912 if (fsc->mount_options->flags & CEPH_MOUNT_OPT_FSCACHE) {
913 err = ceph_fscache_register_fs(fsc, fc);
914 if (err < 0)
915 goto out;
916 }
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 dout("mount opening path '%s'\n", path);
983
984 ceph_fs_debugfs_init(fsc);
985
986 root = open_root_dentry(fsc, path, started);
918 dout("mount opening path '%s'\n", path);
919
920 ceph_fs_debugfs_init(fsc);
921
922 root = open_root_dentry(fsc, path, started);
987 kfree(p);
988 if (IS_ERR(root)) {
989 err = PTR_ERR(root);
990 goto out;
991 }
992 fsc->sb->s_root = dget(root);
993 } else {
994 root = dget(fsc->sb->s_root);
995 }

--- 334 unchanged lines hidden ---
923 if (IS_ERR(root)) {
924 err = PTR_ERR(root);
925 goto out;
926 }
927 fsc->sb->s_root = dget(root);
928 } else {
929 root = dget(fsc->sb->s_root);
930 }

--- 334 unchanged lines hidden ---