Project

General

Profile

Bug #42771 » 0002-ceph-canonicalize-server-path-in-place.patch

Luis Henriques, 04/02/2020 11:06 AM

View differences:

fs/ceph/super.c
{-1, NULL}
};
/*
* Remove adjacent slashes and then the trailing slash, unless it is
* the only remaining character.
*
* E.g. "//dir1////dir2///" --> "/dir1/dir2", "///" --> "/".
*/
static void canonicalize_path(char *path)
{
int i, j = 0;
for (i = 0; path[i] != '\0'; i++) {
if (path[i] != '/' || j < 1 || path[j - 1] != '/')
path[j++] = path[i];
}
if (j > 1 && path[j - 1] == '/')
j--;
path[j] = '\0';
}
static int parse_fsopt_token(char *c, void *private)
{
struct ceph_mount_options *fsopt = private;
......
return strcmp(s1, s2);
}
/**
* path_remove_extra_slash - Remove the extra slashes in the server path
* @server_path: the server path and could be NULL
*
* Return NULL if the path is NULL or only consists of "/", or a string
* without any extra slashes including the leading slash(es) and the
* slash(es) at the end of the server path, such as:
* "//dir1////dir2///" --> "dir1/dir2"
*/
static char *path_remove_extra_slash(const char *server_path)
{
const char *path = server_path;
const char *cur, *end;
char *buf, *p;
int len;
/* if the server path is omitted */
if (!path)
return NULL;
/* remove all the leading slashes */
while (*path == '/')
path++;
/* if the server path only consists of slashes */
if (*path == '\0')
return NULL;
len = strlen(path);
buf = kmalloc(len + 1, GFP_KERNEL);
if (!buf)
return ERR_PTR(-ENOMEM);
end = path + len;
p = buf;
do {
cur = strchr(path, '/');
if (!cur)
cur = end;
len = cur - path;
/* including one '/' */
if (cur != end)
len += 1;
memcpy(p, path, len);
p += len;
while (cur <= end && *cur == '/')
cur++;
path = cur;
} while (path < end);
*p = '\0';
/*
* remove the last slash if there has and just to make sure that
* we will get something like "dir1/dir2"
*/
if (*(--p) == '/')
*p = '\0';
return buf;
}
static int compare_mount_options(struct ceph_mount_options *new_fsopt,
struct ceph_options *new_opt,
struct ceph_fs_client *fsc)
......
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);
......
ret = strcmp_null(fsopt1->snapdir_name, fsopt2->snapdir_name);
if (ret)
return ret;
ret = strcmp_null(fsopt1->mds_namespace, fsopt2->mds_namespace);
if (ret)
return ret;
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);
ret = strcmp_null(fsopt1->server_path, fsopt2->server_path);
if (ret)
return ret;
......
err = -ENOMEM;
goto out;
}
canonicalize_path(fsopt->server_path);
} else {
dev_name_end = dev_name + strlen(dev_name);
}
......
mutex_lock(&fsc->client->mount_mutex);
if (!fsc->sb->s_root) {
const char *path, *p;
const char *path = fsc->mount_options->server_path ?
fsc->mount_options->server_path + 1 : "";
err = __ceph_open_session(fsc->client, started);
if (err < 0)
goto out;
......
goto out;
}
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 or just consists of '/' */
if (!p)
path = "";
else
path = p;
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;
fs/ceph/super.h
char *snapdir_name; /* default ".snap" */
char *mds_namespace; /* default NULL */
char *server_path; /* default "/" */
char *server_path; /* default NULL (means "/") */
char *fscache_uniq; /* default NULL */
};
(2-2/2)