X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fceph%2Fsrc%2Fmount%2Fmount.ceph.c;fp=src%2Fceph%2Fsrc%2Fmount%2Fmount.ceph.c;h=e8fdfcd5496d5edb6ab8377563f0a08b2fd6db6c;hb=812ff6ca9fcd3e629e49d4328905f33eee8ca3f5;hp=0000000000000000000000000000000000000000;hpb=15280273faafb77777eab341909a3f495cf248d9;p=stor4nfv.git diff --git a/src/ceph/src/mount/mount.ceph.c b/src/ceph/src/mount/mount.ceph.c new file mode 100644 index 0000000..e8fdfcd --- /dev/null +++ b/src/ceph/src/mount/mount.ceph.c @@ -0,0 +1,373 @@ +#include +#include +#include +#include +#include + +#include "common/module.h" +#include "common/secret.h" +#include "include/addr_parsing.h" + +#ifndef MS_RELATIME +# define MS_RELATIME (1<<21) +#endif + +#define MAX_SECRET_LEN 1000 +#define MAX_SECRET_OPTION_LEN (MAX_SECRET_LEN + 7) + +int verboseflag = 0; +int skip_mtab_flag = 0; +static const char * const EMPTY_STRING = ""; + +/* TODO duplicates logic from kernel */ +#define CEPH_AUTH_NAME_DEFAULT "guest" + +#include "mtab.c" + +static void block_signals (int how) +{ + sigset_t sigs; + + sigfillset (&sigs); + sigdelset(&sigs, SIGTRAP); + sigdelset(&sigs, SIGSEGV); + sigprocmask (how, &sigs, (sigset_t *) 0); +} + +static char *mount_resolve_src(const char *orig_str) +{ + int len, pos; + char *mount_path; + char *src; + char *buf = strdup(orig_str); + + mount_path = strstr(buf, ":/"); + if (!mount_path) { + printf("source mount path was not specified\n"); + free(buf); + return NULL; + } + if (mount_path == buf) { + printf("server address expected\n"); + free(buf); + return NULL; + } + + *mount_path = '\0'; + mount_path++; + + if (!*mount_path) { + printf("incorrect source mount path\n"); + free(buf); + return NULL; + } + + src = resolve_addrs(buf); + if (!src) { + free(buf); + return NULL; + } + + len = strlen(src); + pos = safe_cat(&src, &len, len, ":"); + safe_cat(&src, &len, pos, mount_path); + + free(buf); + return src; +} + +/* + * this one is partialy based on parse_options() from cifs.mount.c + */ +static char *parse_options(const char *data, int *filesys_flags) +{ + char * next_keyword = NULL; + char * out = NULL; + int out_len = 0; + int pos = 0; + char *name = NULL; + int name_len = 0; + int name_pos = 0; + char secret[MAX_SECRET_LEN]; + char *saw_name = NULL; + char *saw_secret = NULL; + + if(verboseflag) + printf("parsing options: %s\n", data); + + do { + char * value = NULL; + /* check if ends with trailing comma */ + if(*data == 0) + break; + next_keyword = strchr(data,','); + + /* temporarily null terminate end of keyword=value pair */ + if(next_keyword) + *next_keyword++ = 0; + + /* temporarily null terminate keyword to make keyword and value distinct */ + if ((value = strchr(data, '=')) != NULL) { + *value = '\0'; + value++; + } + + int skip = 1; + + if (strncmp(data, "ro", 2) == 0) { + *filesys_flags |= MS_RDONLY; + } else if (strncmp(data, "rw", 2) == 0) { + *filesys_flags &= ~MS_RDONLY; + } else if (strncmp(data, "nosuid", 6) == 0) { + *filesys_flags |= MS_NOSUID; + } else if (strncmp(data, "suid", 4) == 0) { + *filesys_flags &= ~MS_NOSUID; + } else if (strncmp(data, "dev", 3) == 0) { + *filesys_flags &= ~MS_NODEV; + } else if (strncmp(data, "nodev", 5) == 0) { + *filesys_flags |= MS_NODEV; + } else if (strncmp(data, "noexec", 6) == 0) { + *filesys_flags |= MS_NOEXEC; + } else if (strncmp(data, "exec", 4) == 0) { + *filesys_flags &= ~MS_NOEXEC; + } else if (strncmp(data, "sync", 4) == 0) { + *filesys_flags |= MS_SYNCHRONOUS; + } else if (strncmp(data, "remount", 7) == 0) { + *filesys_flags |= MS_REMOUNT; + } else if (strncmp(data, "mandlock", 8) == 0) { + *filesys_flags |= MS_MANDLOCK; + } else if ((strncmp(data, "nobrl", 5) == 0) || + (strncmp(data, "nolock", 6) == 0)) { + *filesys_flags &= ~MS_MANDLOCK; + } else if (strncmp(data, "noatime", 7) == 0) { + *filesys_flags |= MS_NOATIME; + } else if (strncmp(data, "nodiratime", 10) == 0) { + *filesys_flags |= MS_NODIRATIME; + } else if (strncmp(data, "relatime", 8) == 0) { + *filesys_flags |= MS_RELATIME; + + } else if (strncmp(data, "noauto", 6) == 0) { + skip = 1; /* ignore */ + } else if (strncmp(data, "_netdev", 7) == 0) { + skip = 1; /* ignore */ + + } else if (strncmp(data, "secretfile", 10) == 0) { + if (!value || !*value) { + printf("keyword secretfile found, but no secret file specified\n"); + free(saw_name); + return NULL; + } + + if (read_secret_from_file(value, secret, sizeof(secret)) < 0) { + printf("error reading secret file\n"); + return NULL; + } + + /* see comment for "secret" */ + saw_secret = secret; + skip = 1; + } else if (strncmp(data, "secret", 6) == 0) { + if (!value || !*value) { + printf("mount option secret requires a value.\n"); + free(saw_name); + return NULL; + } + + /* secret is only added to kernel options as + backwards compatibility, if add_key doesn't + recognize our keytype; hence, it is skipped + here and appended to options on add_key + failure */ + size_t len = sizeof(secret); + strncpy(secret, value, len-1); + secret[len-1] = '\0'; + saw_secret = secret; + skip = 1; + } else if (strncmp(data, "name", 4) == 0) { + if (!value || !*value) { + printf("mount option name requires a value.\n"); + return NULL; + } + + /* take a copy of the name, to be used for + naming the keys that we add to kernel; */ + free(saw_name); + saw_name = strdup(value); + if (!saw_name) { + printf("out of memory.\n"); + return NULL; + } + skip = 0; + } else { + skip = 0; + if (verboseflag) { + fprintf(stderr, "mount.ceph: unrecognized mount option \"%s\", " + "passing to kernel.\n", data); + } + } + + /* Copy (possibly modified) option to out */ + if (!skip) { + if (pos) + pos = safe_cat(&out, &out_len, pos, ","); + + if (value) { + pos = safe_cat(&out, &out_len, pos, data); + pos = safe_cat(&out, &out_len, pos, "="); + pos = safe_cat(&out, &out_len, pos, value); + } else { + pos = safe_cat(&out, &out_len, pos, data); + } + + } + data = next_keyword; + } while (data); + + name_pos = safe_cat(&name, &name_len, name_pos, "client."); + if (!saw_name) { + name_pos = safe_cat(&name, &name_len, name_pos, CEPH_AUTH_NAME_DEFAULT); + } else { + name_pos = safe_cat(&name, &name_len, name_pos, saw_name); + } + if (saw_secret || is_kernel_secret(name)) { + int ret; + char secret_option[MAX_SECRET_OPTION_LEN]; + ret = get_secret_option(saw_secret, name, secret_option, sizeof(secret_option)); + if (ret < 0) { + free(saw_name); + return NULL; + } else { + if (pos) { + pos = safe_cat(&out, &out_len, pos, ","); + } + pos = safe_cat(&out, &out_len, pos, secret_option); + } + } + + free(saw_name); + if (!out) + return strdup(EMPTY_STRING); + return out; +} + + +static int parse_arguments(int argc, char *const *const argv, + const char **src, const char **node, const char **opts) +{ + int i; + + if (argc < 2) { + // There were no arguments. Just show the usage. + return 1; + } + if ((!strcmp(argv[1], "-h")) || (!strcmp(argv[1], "--help"))) { + // The user asked for help. + return 1; + } + + // The first two arguments are positional + if (argc < 3) + return -EINVAL; + *src = argv[1]; + *node = argv[2]; + + // Parse the remaining options + *opts = EMPTY_STRING; + for (i = 3; i < argc; ++i) { + if (!strcmp("-h", argv[i])) + return 1; + else if (!strcmp("-n", argv[i])) + skip_mtab_flag = 1; + else if (!strcmp("-v", argv[i])) + verboseflag = 1; + else if (!strcmp("-o", argv[i])) { + ++i; + if (i >= argc) { + printf("Option -o requires an argument.\n\n"); + return -EINVAL; + } + *opts = argv[i]; + } + else { + printf("Can't understand option: '%s'\n\n", argv[i]); + return -EINVAL; + } + } + return 0; +} + +/* modprobe failing doesn't necessarily prevent from working, so this + returns void */ +static void modprobe(void) +{ + int r; + + r = module_load("ceph", NULL); + if (r) + printf("failed to load ceph kernel module (%d)\n", r); +} + +static void usage(const char *prog_name) +{ + printf("usage: %s [src] [mount-point] [-n] [-v] [-o ceph-options]\n", + prog_name); + printf("options:\n"); + printf("\t-h: Print this help\n"); + printf("\t-n: Do not update /etc/mtab\n"); + printf("\t-v: Verbose\n"); + printf("\tceph-options: refer to mount.ceph(8)\n"); + printf("\n"); +} + +int main(int argc, char *argv[]) +{ + const char *src, *node, *opts; + char *rsrc = NULL; + char *popts = NULL; + int flags = 0; + int retval = 0; + + retval = parse_arguments(argc, argv, &src, &node, &opts); + if (retval) { + usage(argv[0]); + exit((retval > 0) ? EXIT_SUCCESS : EXIT_FAILURE); + } + + rsrc = mount_resolve_src(src); + if (!rsrc) { + printf("failed to resolve source\n"); + exit(1); + } + + modprobe(); + + popts = parse_options(opts, &flags); + if (!popts) { + printf("failed to parse ceph_options\n"); + exit(1); + } + + block_signals(SIG_BLOCK); + + if (mount(rsrc, node, "ceph", flags, popts)) { + retval = errno; + switch (errno) { + case ENODEV: + printf("mount error: ceph filesystem not supported by the system\n"); + break; + default: + printf("mount error %d = %s\n",errno,strerror(errno)); + } + } else { + if (!skip_mtab_flag) { + update_mtab_entry(rsrc, node, "ceph", popts, flags, 0, 0); + } + } + + block_signals(SIG_UNBLOCK); + + free(popts); + free(rsrc); + exit(retval); +} +