@@ -430,6 +430,39 @@ static int strcmp_null(const char *s1, const char *s2)
return strcmp(s1, s2);
}
+static char *path_remove_extra_slash(const char *path)
+{
+ bool last_is_slash;
+ int i, j;
+ int len;
+ char *p;
+
+ if (!path)
+ return NULL;
+
+ len = strlen(path);
+
+ p = kmalloc(len, GFP_NOFS);
+ if (!p)
+ return ERR_PTR(-ENOMEM);
+
+ last_is_slash = false;
+ for (j = 0, i = 0; i < len; i++) {
+ if (path[i] == '/') {
+ if (last_is_slash)
+ continue;
+ last_is_slash = true;
+ } else {
+ last_is_slash = false;
+ }
+ p[j++] = path[i];
+ }
+
+ p[j] = '\0';
+
+ return p;
+}
+
static int compare_mount_options(struct ceph_mount_options *new_fsopt,
struct ceph_options *new_opt,
struct ceph_fs_client *fsc)
@@ -437,6 +470,7 @@ static int compare_mount_options(struct ceph_mount_options *new_fsopt,
struct ceph_mount_options *fsopt1 = new_fsopt;
struct ceph_mount_options *fsopt2 = fsc->mount_options;
int ofs = offsetof(struct ceph_mount_options, snapdir_name);
+ char *p1, *p2;
int ret;
ret = memcmp(fsopt1, fsopt2, ofs);
@@ -449,9 +483,21 @@ static int compare_mount_options(struct ceph_mount_options *new_fsopt,
ret = strcmp_null(fsopt1->mds_namespace, fsopt2->mds_namespace);
if (ret)
return ret;
- ret = strcmp_null(fsopt1->server_path, fsopt2->server_path);
+
+ p1 = path_remove_extra_slash(fsopt1->server_path);
+ if (IS_ERR(p1))
+ return PTR_ERR(p1);
+ p2 = path_remove_extra_slash(fsopt2->server_path);
+ if (IS_ERR(p2)) {
+ kfree(p1);
+ return PTR_ERR(p2);
+ }
+ ret = strcmp_null(p1, p2);
+ kfree(p1);
+ kfree(p2);
if (ret)
return ret;
+
ret = strcmp_null(fsopt1->fscache_uniq, fsopt2->fscache_uniq);
if (ret)
return ret;
@@ -507,12 +553,10 @@ static int parse_mount_options(struct ceph_mount_options **pfsopt,
*/
dev_name_end = strchr(dev_name, '/');
if (dev_name_end) {
- if (strlen(dev_name_end) > 1) {
- fsopt->server_path = kstrdup(dev_name_end, GFP_KERNEL);
- if (!fsopt->server_path) {
- err = -ENOMEM;
- goto out;
- }
+ fsopt->server_path = kstrdup(dev_name_end, GFP_KERNEL);
+ if (!fsopt->server_path) {
+ err = -ENOMEM;
+ goto out;
}
} else {
dev_name_end = dev_name + strlen(dev_name);
@@ -945,7 +989,7 @@ static struct dentry *ceph_real_mount(struct ceph_fs_client *fsc)
mutex_lock(&fsc->client->mount_mutex);
if (!fsc->sb->s_root) {
- const char *path;
+ const char *path, *p;
err = __ceph_open_session(fsc->client, started);
if (err < 0)
goto out;
@@ -957,17 +1001,24 @@ static struct dentry *ceph_real_mount(struct ceph_fs_client *fsc)
goto out;
}
- if (!fsc->mount_options->server_path) {
+ p = path_remove_extra_slash(fsc->mount_options->server_path);
+ if (IS_ERR(p)) {
+ err = PTR_ERR(p);
+ goto out;
+ }
+ /* if the server path is omitted in the dev_name or just '/' */
+ if (!p || (p && strlen(p) == 1)) {
path = "";
dout("mount opening path \\t\n");
} else {
- path = fsc->mount_options->server_path + 1;
+ path = p + 1;
dout("mount opening path %s\n", path);
}
ceph_fs_debugfs_init(fsc);
root = open_root_dentry(fsc, path, started);
+ kfree(p);
if (IS_ERR(root)) {
err = PTR_ERR(root);
goto out;