1*3d14c5d2SYehuda Sadeh 2*3d14c5d2SYehuda Sadeh #include <linux/ceph/ceph_debug.h> 3*3d14c5d2SYehuda Sadeh #include <linux/backing-dev.h> 4*3d14c5d2SYehuda Sadeh #include <linux/ctype.h> 5*3d14c5d2SYehuda Sadeh #include <linux/fs.h> 6*3d14c5d2SYehuda Sadeh #include <linux/inet.h> 7*3d14c5d2SYehuda Sadeh #include <linux/in6.h> 8*3d14c5d2SYehuda Sadeh #include <linux/module.h> 9*3d14c5d2SYehuda Sadeh #include <linux/mount.h> 10*3d14c5d2SYehuda Sadeh #include <linux/parser.h> 11*3d14c5d2SYehuda Sadeh #include <linux/sched.h> 12*3d14c5d2SYehuda Sadeh #include <linux/seq_file.h> 13*3d14c5d2SYehuda Sadeh #include <linux/slab.h> 14*3d14c5d2SYehuda Sadeh #include <linux/statfs.h> 15*3d14c5d2SYehuda Sadeh #include <linux/string.h> 16*3d14c5d2SYehuda Sadeh 17*3d14c5d2SYehuda Sadeh 18*3d14c5d2SYehuda Sadeh #include <linux/ceph/libceph.h> 19*3d14c5d2SYehuda Sadeh #include <linux/ceph/debugfs.h> 20*3d14c5d2SYehuda Sadeh #include <linux/ceph/decode.h> 21*3d14c5d2SYehuda Sadeh #include <linux/ceph/mon_client.h> 22*3d14c5d2SYehuda Sadeh #include <linux/ceph/auth.h> 23*3d14c5d2SYehuda Sadeh 24*3d14c5d2SYehuda Sadeh 25*3d14c5d2SYehuda Sadeh 26*3d14c5d2SYehuda Sadeh /* 27*3d14c5d2SYehuda Sadeh * find filename portion of a path (/foo/bar/baz -> baz) 28*3d14c5d2SYehuda Sadeh */ 29*3d14c5d2SYehuda Sadeh const char *ceph_file_part(const char *s, int len) 30*3d14c5d2SYehuda Sadeh { 31*3d14c5d2SYehuda Sadeh const char *e = s + len; 32*3d14c5d2SYehuda Sadeh 33*3d14c5d2SYehuda Sadeh while (e != s && *(e-1) != '/') 34*3d14c5d2SYehuda Sadeh e--; 35*3d14c5d2SYehuda Sadeh return e; 36*3d14c5d2SYehuda Sadeh } 37*3d14c5d2SYehuda Sadeh EXPORT_SYMBOL(ceph_file_part); 38*3d14c5d2SYehuda Sadeh 39*3d14c5d2SYehuda Sadeh const char *ceph_msg_type_name(int type) 40*3d14c5d2SYehuda Sadeh { 41*3d14c5d2SYehuda Sadeh switch (type) { 42*3d14c5d2SYehuda Sadeh case CEPH_MSG_SHUTDOWN: return "shutdown"; 43*3d14c5d2SYehuda Sadeh case CEPH_MSG_PING: return "ping"; 44*3d14c5d2SYehuda Sadeh case CEPH_MSG_AUTH: return "auth"; 45*3d14c5d2SYehuda Sadeh case CEPH_MSG_AUTH_REPLY: return "auth_reply"; 46*3d14c5d2SYehuda Sadeh case CEPH_MSG_MON_MAP: return "mon_map"; 47*3d14c5d2SYehuda Sadeh case CEPH_MSG_MON_GET_MAP: return "mon_get_map"; 48*3d14c5d2SYehuda Sadeh case CEPH_MSG_MON_SUBSCRIBE: return "mon_subscribe"; 49*3d14c5d2SYehuda Sadeh case CEPH_MSG_MON_SUBSCRIBE_ACK: return "mon_subscribe_ack"; 50*3d14c5d2SYehuda Sadeh case CEPH_MSG_STATFS: return "statfs"; 51*3d14c5d2SYehuda Sadeh case CEPH_MSG_STATFS_REPLY: return "statfs_reply"; 52*3d14c5d2SYehuda Sadeh case CEPH_MSG_MDS_MAP: return "mds_map"; 53*3d14c5d2SYehuda Sadeh case CEPH_MSG_CLIENT_SESSION: return "client_session"; 54*3d14c5d2SYehuda Sadeh case CEPH_MSG_CLIENT_RECONNECT: return "client_reconnect"; 55*3d14c5d2SYehuda Sadeh case CEPH_MSG_CLIENT_REQUEST: return "client_request"; 56*3d14c5d2SYehuda Sadeh case CEPH_MSG_CLIENT_REQUEST_FORWARD: return "client_request_forward"; 57*3d14c5d2SYehuda Sadeh case CEPH_MSG_CLIENT_REPLY: return "client_reply"; 58*3d14c5d2SYehuda Sadeh case CEPH_MSG_CLIENT_CAPS: return "client_caps"; 59*3d14c5d2SYehuda Sadeh case CEPH_MSG_CLIENT_CAPRELEASE: return "client_cap_release"; 60*3d14c5d2SYehuda Sadeh case CEPH_MSG_CLIENT_SNAP: return "client_snap"; 61*3d14c5d2SYehuda Sadeh case CEPH_MSG_CLIENT_LEASE: return "client_lease"; 62*3d14c5d2SYehuda Sadeh case CEPH_MSG_OSD_MAP: return "osd_map"; 63*3d14c5d2SYehuda Sadeh case CEPH_MSG_OSD_OP: return "osd_op"; 64*3d14c5d2SYehuda Sadeh case CEPH_MSG_OSD_OPREPLY: return "osd_opreply"; 65*3d14c5d2SYehuda Sadeh default: return "unknown"; 66*3d14c5d2SYehuda Sadeh } 67*3d14c5d2SYehuda Sadeh } 68*3d14c5d2SYehuda Sadeh EXPORT_SYMBOL(ceph_msg_type_name); 69*3d14c5d2SYehuda Sadeh 70*3d14c5d2SYehuda Sadeh /* 71*3d14c5d2SYehuda Sadeh * Initially learn our fsid, or verify an fsid matches. 72*3d14c5d2SYehuda Sadeh */ 73*3d14c5d2SYehuda Sadeh int ceph_check_fsid(struct ceph_client *client, struct ceph_fsid *fsid) 74*3d14c5d2SYehuda Sadeh { 75*3d14c5d2SYehuda Sadeh if (client->have_fsid) { 76*3d14c5d2SYehuda Sadeh if (ceph_fsid_compare(&client->fsid, fsid)) { 77*3d14c5d2SYehuda Sadeh pr_err("bad fsid, had %pU got %pU", 78*3d14c5d2SYehuda Sadeh &client->fsid, fsid); 79*3d14c5d2SYehuda Sadeh return -1; 80*3d14c5d2SYehuda Sadeh } 81*3d14c5d2SYehuda Sadeh } else { 82*3d14c5d2SYehuda Sadeh pr_info("client%lld fsid %pU\n", ceph_client_id(client), fsid); 83*3d14c5d2SYehuda Sadeh memcpy(&client->fsid, fsid, sizeof(*fsid)); 84*3d14c5d2SYehuda Sadeh ceph_debugfs_client_init(client); 85*3d14c5d2SYehuda Sadeh client->have_fsid = true; 86*3d14c5d2SYehuda Sadeh } 87*3d14c5d2SYehuda Sadeh return 0; 88*3d14c5d2SYehuda Sadeh } 89*3d14c5d2SYehuda Sadeh EXPORT_SYMBOL(ceph_check_fsid); 90*3d14c5d2SYehuda Sadeh 91*3d14c5d2SYehuda Sadeh static int strcmp_null(const char *s1, const char *s2) 92*3d14c5d2SYehuda Sadeh { 93*3d14c5d2SYehuda Sadeh if (!s1 && !s2) 94*3d14c5d2SYehuda Sadeh return 0; 95*3d14c5d2SYehuda Sadeh if (s1 && !s2) 96*3d14c5d2SYehuda Sadeh return -1; 97*3d14c5d2SYehuda Sadeh if (!s1 && s2) 98*3d14c5d2SYehuda Sadeh return 1; 99*3d14c5d2SYehuda Sadeh return strcmp(s1, s2); 100*3d14c5d2SYehuda Sadeh } 101*3d14c5d2SYehuda Sadeh 102*3d14c5d2SYehuda Sadeh int ceph_compare_options(struct ceph_options *new_opt, 103*3d14c5d2SYehuda Sadeh struct ceph_client *client) 104*3d14c5d2SYehuda Sadeh { 105*3d14c5d2SYehuda Sadeh struct ceph_options *opt1 = new_opt; 106*3d14c5d2SYehuda Sadeh struct ceph_options *opt2 = client->options; 107*3d14c5d2SYehuda Sadeh int ofs = offsetof(struct ceph_options, mon_addr); 108*3d14c5d2SYehuda Sadeh int i; 109*3d14c5d2SYehuda Sadeh int ret; 110*3d14c5d2SYehuda Sadeh 111*3d14c5d2SYehuda Sadeh ret = memcmp(opt1, opt2, ofs); 112*3d14c5d2SYehuda Sadeh if (ret) 113*3d14c5d2SYehuda Sadeh return ret; 114*3d14c5d2SYehuda Sadeh 115*3d14c5d2SYehuda Sadeh ret = strcmp_null(opt1->name, opt2->name); 116*3d14c5d2SYehuda Sadeh if (ret) 117*3d14c5d2SYehuda Sadeh return ret; 118*3d14c5d2SYehuda Sadeh 119*3d14c5d2SYehuda Sadeh ret = strcmp_null(opt1->secret, opt2->secret); 120*3d14c5d2SYehuda Sadeh if (ret) 121*3d14c5d2SYehuda Sadeh return ret; 122*3d14c5d2SYehuda Sadeh 123*3d14c5d2SYehuda Sadeh /* any matching mon ip implies a match */ 124*3d14c5d2SYehuda Sadeh for (i = 0; i < opt1->num_mon; i++) { 125*3d14c5d2SYehuda Sadeh if (ceph_monmap_contains(client->monc.monmap, 126*3d14c5d2SYehuda Sadeh &opt1->mon_addr[i])) 127*3d14c5d2SYehuda Sadeh return 0; 128*3d14c5d2SYehuda Sadeh } 129*3d14c5d2SYehuda Sadeh return -1; 130*3d14c5d2SYehuda Sadeh } 131*3d14c5d2SYehuda Sadeh EXPORT_SYMBOL(ceph_compare_options); 132*3d14c5d2SYehuda Sadeh 133*3d14c5d2SYehuda Sadeh 134*3d14c5d2SYehuda Sadeh static int parse_fsid(const char *str, struct ceph_fsid *fsid) 135*3d14c5d2SYehuda Sadeh { 136*3d14c5d2SYehuda Sadeh int i = 0; 137*3d14c5d2SYehuda Sadeh char tmp[3]; 138*3d14c5d2SYehuda Sadeh int err = -EINVAL; 139*3d14c5d2SYehuda Sadeh int d; 140*3d14c5d2SYehuda Sadeh 141*3d14c5d2SYehuda Sadeh dout("parse_fsid '%s'\n", str); 142*3d14c5d2SYehuda Sadeh tmp[2] = 0; 143*3d14c5d2SYehuda Sadeh while (*str && i < 16) { 144*3d14c5d2SYehuda Sadeh if (ispunct(*str)) { 145*3d14c5d2SYehuda Sadeh str++; 146*3d14c5d2SYehuda Sadeh continue; 147*3d14c5d2SYehuda Sadeh } 148*3d14c5d2SYehuda Sadeh if (!isxdigit(str[0]) || !isxdigit(str[1])) 149*3d14c5d2SYehuda Sadeh break; 150*3d14c5d2SYehuda Sadeh tmp[0] = str[0]; 151*3d14c5d2SYehuda Sadeh tmp[1] = str[1]; 152*3d14c5d2SYehuda Sadeh if (sscanf(tmp, "%x", &d) < 1) 153*3d14c5d2SYehuda Sadeh break; 154*3d14c5d2SYehuda Sadeh fsid->fsid[i] = d & 0xff; 155*3d14c5d2SYehuda Sadeh i++; 156*3d14c5d2SYehuda Sadeh str += 2; 157*3d14c5d2SYehuda Sadeh } 158*3d14c5d2SYehuda Sadeh 159*3d14c5d2SYehuda Sadeh if (i == 16) 160*3d14c5d2SYehuda Sadeh err = 0; 161*3d14c5d2SYehuda Sadeh dout("parse_fsid ret %d got fsid %pU", err, fsid); 162*3d14c5d2SYehuda Sadeh return err; 163*3d14c5d2SYehuda Sadeh } 164*3d14c5d2SYehuda Sadeh 165*3d14c5d2SYehuda Sadeh /* 166*3d14c5d2SYehuda Sadeh * ceph options 167*3d14c5d2SYehuda Sadeh */ 168*3d14c5d2SYehuda Sadeh enum { 169*3d14c5d2SYehuda Sadeh Opt_osdtimeout, 170*3d14c5d2SYehuda Sadeh Opt_osdkeepalivetimeout, 171*3d14c5d2SYehuda Sadeh Opt_mount_timeout, 172*3d14c5d2SYehuda Sadeh Opt_osd_idle_ttl, 173*3d14c5d2SYehuda Sadeh Opt_last_int, 174*3d14c5d2SYehuda Sadeh /* int args above */ 175*3d14c5d2SYehuda Sadeh Opt_fsid, 176*3d14c5d2SYehuda Sadeh Opt_name, 177*3d14c5d2SYehuda Sadeh Opt_secret, 178*3d14c5d2SYehuda Sadeh Opt_ip, 179*3d14c5d2SYehuda Sadeh Opt_last_string, 180*3d14c5d2SYehuda Sadeh /* string args above */ 181*3d14c5d2SYehuda Sadeh Opt_noshare, 182*3d14c5d2SYehuda Sadeh Opt_nocrc, 183*3d14c5d2SYehuda Sadeh }; 184*3d14c5d2SYehuda Sadeh 185*3d14c5d2SYehuda Sadeh static match_table_t opt_tokens = { 186*3d14c5d2SYehuda Sadeh {Opt_osdtimeout, "osdtimeout=%d"}, 187*3d14c5d2SYehuda Sadeh {Opt_osdkeepalivetimeout, "osdkeepalive=%d"}, 188*3d14c5d2SYehuda Sadeh {Opt_mount_timeout, "mount_timeout=%d"}, 189*3d14c5d2SYehuda Sadeh {Opt_osd_idle_ttl, "osd_idle_ttl=%d"}, 190*3d14c5d2SYehuda Sadeh /* int args above */ 191*3d14c5d2SYehuda Sadeh {Opt_fsid, "fsid=%s"}, 192*3d14c5d2SYehuda Sadeh {Opt_name, "name=%s"}, 193*3d14c5d2SYehuda Sadeh {Opt_secret, "secret=%s"}, 194*3d14c5d2SYehuda Sadeh {Opt_ip, "ip=%s"}, 195*3d14c5d2SYehuda Sadeh /* string args above */ 196*3d14c5d2SYehuda Sadeh {Opt_noshare, "noshare"}, 197*3d14c5d2SYehuda Sadeh {Opt_nocrc, "nocrc"}, 198*3d14c5d2SYehuda Sadeh {-1, NULL} 199*3d14c5d2SYehuda Sadeh }; 200*3d14c5d2SYehuda Sadeh 201*3d14c5d2SYehuda Sadeh void ceph_destroy_options(struct ceph_options *opt) 202*3d14c5d2SYehuda Sadeh { 203*3d14c5d2SYehuda Sadeh dout("destroy_options %p\n", opt); 204*3d14c5d2SYehuda Sadeh kfree(opt->name); 205*3d14c5d2SYehuda Sadeh kfree(opt->secret); 206*3d14c5d2SYehuda Sadeh kfree(opt); 207*3d14c5d2SYehuda Sadeh } 208*3d14c5d2SYehuda Sadeh EXPORT_SYMBOL(ceph_destroy_options); 209*3d14c5d2SYehuda Sadeh 210*3d14c5d2SYehuda Sadeh int ceph_parse_options(struct ceph_options **popt, char *options, 211*3d14c5d2SYehuda Sadeh const char *dev_name, const char *dev_name_end, 212*3d14c5d2SYehuda Sadeh int (*parse_extra_token)(char *c, void *private), 213*3d14c5d2SYehuda Sadeh void *private) 214*3d14c5d2SYehuda Sadeh { 215*3d14c5d2SYehuda Sadeh struct ceph_options *opt; 216*3d14c5d2SYehuda Sadeh const char *c; 217*3d14c5d2SYehuda Sadeh int err = -ENOMEM; 218*3d14c5d2SYehuda Sadeh substring_t argstr[MAX_OPT_ARGS]; 219*3d14c5d2SYehuda Sadeh 220*3d14c5d2SYehuda Sadeh opt = kzalloc(sizeof(*opt), GFP_KERNEL); 221*3d14c5d2SYehuda Sadeh if (!opt) 222*3d14c5d2SYehuda Sadeh return err; 223*3d14c5d2SYehuda Sadeh opt->mon_addr = kcalloc(CEPH_MAX_MON, sizeof(*opt->mon_addr), 224*3d14c5d2SYehuda Sadeh GFP_KERNEL); 225*3d14c5d2SYehuda Sadeh if (!opt->mon_addr) 226*3d14c5d2SYehuda Sadeh goto out; 227*3d14c5d2SYehuda Sadeh 228*3d14c5d2SYehuda Sadeh dout("parse_options %p options '%s' dev_name '%s'\n", opt, options, 229*3d14c5d2SYehuda Sadeh dev_name); 230*3d14c5d2SYehuda Sadeh 231*3d14c5d2SYehuda Sadeh /* start with defaults */ 232*3d14c5d2SYehuda Sadeh opt->flags = CEPH_OPT_DEFAULT; 233*3d14c5d2SYehuda Sadeh opt->osd_timeout = CEPH_OSD_TIMEOUT_DEFAULT; 234*3d14c5d2SYehuda Sadeh opt->osd_keepalive_timeout = CEPH_OSD_KEEPALIVE_DEFAULT; 235*3d14c5d2SYehuda Sadeh opt->mount_timeout = CEPH_MOUNT_TIMEOUT_DEFAULT; /* seconds */ 236*3d14c5d2SYehuda Sadeh opt->osd_idle_ttl = CEPH_OSD_IDLE_TTL_DEFAULT; /* seconds */ 237*3d14c5d2SYehuda Sadeh 238*3d14c5d2SYehuda Sadeh /* get mon ip(s) */ 239*3d14c5d2SYehuda Sadeh /* ip1[:port1][,ip2[:port2]...] */ 240*3d14c5d2SYehuda Sadeh err = ceph_parse_ips(dev_name, dev_name_end, opt->mon_addr, 241*3d14c5d2SYehuda Sadeh CEPH_MAX_MON, &opt->num_mon); 242*3d14c5d2SYehuda Sadeh if (err < 0) 243*3d14c5d2SYehuda Sadeh goto out; 244*3d14c5d2SYehuda Sadeh 245*3d14c5d2SYehuda Sadeh /* parse mount options */ 246*3d14c5d2SYehuda Sadeh while ((c = strsep(&options, ",")) != NULL) { 247*3d14c5d2SYehuda Sadeh int token, intval, ret; 248*3d14c5d2SYehuda Sadeh if (!*c) 249*3d14c5d2SYehuda Sadeh continue; 250*3d14c5d2SYehuda Sadeh err = -EINVAL; 251*3d14c5d2SYehuda Sadeh token = match_token((char *)c, opt_tokens, argstr); 252*3d14c5d2SYehuda Sadeh if (token < 0) { 253*3d14c5d2SYehuda Sadeh /* extra? */ 254*3d14c5d2SYehuda Sadeh err = parse_extra_token((char *)c, private); 255*3d14c5d2SYehuda Sadeh if (err < 0) { 256*3d14c5d2SYehuda Sadeh pr_err("bad option at '%s'\n", c); 257*3d14c5d2SYehuda Sadeh goto out; 258*3d14c5d2SYehuda Sadeh } 259*3d14c5d2SYehuda Sadeh continue; 260*3d14c5d2SYehuda Sadeh } 261*3d14c5d2SYehuda Sadeh if (token < Opt_last_int) { 262*3d14c5d2SYehuda Sadeh ret = match_int(&argstr[0], &intval); 263*3d14c5d2SYehuda Sadeh if (ret < 0) { 264*3d14c5d2SYehuda Sadeh pr_err("bad mount option arg (not int) " 265*3d14c5d2SYehuda Sadeh "at '%s'\n", c); 266*3d14c5d2SYehuda Sadeh continue; 267*3d14c5d2SYehuda Sadeh } 268*3d14c5d2SYehuda Sadeh dout("got int token %d val %d\n", token, intval); 269*3d14c5d2SYehuda Sadeh } else if (token > Opt_last_int && token < Opt_last_string) { 270*3d14c5d2SYehuda Sadeh dout("got string token %d val %s\n", token, 271*3d14c5d2SYehuda Sadeh argstr[0].from); 272*3d14c5d2SYehuda Sadeh } else { 273*3d14c5d2SYehuda Sadeh dout("got token %d\n", token); 274*3d14c5d2SYehuda Sadeh } 275*3d14c5d2SYehuda Sadeh switch (token) { 276*3d14c5d2SYehuda Sadeh case Opt_ip: 277*3d14c5d2SYehuda Sadeh err = ceph_parse_ips(argstr[0].from, 278*3d14c5d2SYehuda Sadeh argstr[0].to, 279*3d14c5d2SYehuda Sadeh &opt->my_addr, 280*3d14c5d2SYehuda Sadeh 1, NULL); 281*3d14c5d2SYehuda Sadeh if (err < 0) 282*3d14c5d2SYehuda Sadeh goto out; 283*3d14c5d2SYehuda Sadeh opt->flags |= CEPH_OPT_MYIP; 284*3d14c5d2SYehuda Sadeh break; 285*3d14c5d2SYehuda Sadeh 286*3d14c5d2SYehuda Sadeh case Opt_fsid: 287*3d14c5d2SYehuda Sadeh err = parse_fsid(argstr[0].from, &opt->fsid); 288*3d14c5d2SYehuda Sadeh if (err == 0) 289*3d14c5d2SYehuda Sadeh opt->flags |= CEPH_OPT_FSID; 290*3d14c5d2SYehuda Sadeh break; 291*3d14c5d2SYehuda Sadeh case Opt_name: 292*3d14c5d2SYehuda Sadeh opt->name = kstrndup(argstr[0].from, 293*3d14c5d2SYehuda Sadeh argstr[0].to-argstr[0].from, 294*3d14c5d2SYehuda Sadeh GFP_KERNEL); 295*3d14c5d2SYehuda Sadeh break; 296*3d14c5d2SYehuda Sadeh case Opt_secret: 297*3d14c5d2SYehuda Sadeh opt->secret = kstrndup(argstr[0].from, 298*3d14c5d2SYehuda Sadeh argstr[0].to-argstr[0].from, 299*3d14c5d2SYehuda Sadeh GFP_KERNEL); 300*3d14c5d2SYehuda Sadeh break; 301*3d14c5d2SYehuda Sadeh 302*3d14c5d2SYehuda Sadeh /* misc */ 303*3d14c5d2SYehuda Sadeh case Opt_osdtimeout: 304*3d14c5d2SYehuda Sadeh opt->osd_timeout = intval; 305*3d14c5d2SYehuda Sadeh break; 306*3d14c5d2SYehuda Sadeh case Opt_osdkeepalivetimeout: 307*3d14c5d2SYehuda Sadeh opt->osd_keepalive_timeout = intval; 308*3d14c5d2SYehuda Sadeh break; 309*3d14c5d2SYehuda Sadeh case Opt_osd_idle_ttl: 310*3d14c5d2SYehuda Sadeh opt->osd_idle_ttl = intval; 311*3d14c5d2SYehuda Sadeh break; 312*3d14c5d2SYehuda Sadeh case Opt_mount_timeout: 313*3d14c5d2SYehuda Sadeh opt->mount_timeout = intval; 314*3d14c5d2SYehuda Sadeh break; 315*3d14c5d2SYehuda Sadeh 316*3d14c5d2SYehuda Sadeh case Opt_noshare: 317*3d14c5d2SYehuda Sadeh opt->flags |= CEPH_OPT_NOSHARE; 318*3d14c5d2SYehuda Sadeh break; 319*3d14c5d2SYehuda Sadeh 320*3d14c5d2SYehuda Sadeh case Opt_nocrc: 321*3d14c5d2SYehuda Sadeh opt->flags |= CEPH_OPT_NOCRC; 322*3d14c5d2SYehuda Sadeh break; 323*3d14c5d2SYehuda Sadeh 324*3d14c5d2SYehuda Sadeh default: 325*3d14c5d2SYehuda Sadeh BUG_ON(token); 326*3d14c5d2SYehuda Sadeh } 327*3d14c5d2SYehuda Sadeh } 328*3d14c5d2SYehuda Sadeh 329*3d14c5d2SYehuda Sadeh /* success */ 330*3d14c5d2SYehuda Sadeh *popt = opt; 331*3d14c5d2SYehuda Sadeh return 0; 332*3d14c5d2SYehuda Sadeh 333*3d14c5d2SYehuda Sadeh out: 334*3d14c5d2SYehuda Sadeh ceph_destroy_options(opt); 335*3d14c5d2SYehuda Sadeh return err; 336*3d14c5d2SYehuda Sadeh } 337*3d14c5d2SYehuda Sadeh EXPORT_SYMBOL(ceph_parse_options); 338*3d14c5d2SYehuda Sadeh 339*3d14c5d2SYehuda Sadeh u64 ceph_client_id(struct ceph_client *client) 340*3d14c5d2SYehuda Sadeh { 341*3d14c5d2SYehuda Sadeh return client->monc.auth->global_id; 342*3d14c5d2SYehuda Sadeh } 343*3d14c5d2SYehuda Sadeh EXPORT_SYMBOL(ceph_client_id); 344*3d14c5d2SYehuda Sadeh 345*3d14c5d2SYehuda Sadeh /* 346*3d14c5d2SYehuda Sadeh * create a fresh client instance 347*3d14c5d2SYehuda Sadeh */ 348*3d14c5d2SYehuda Sadeh struct ceph_client *ceph_create_client(struct ceph_options *opt, void *private) 349*3d14c5d2SYehuda Sadeh { 350*3d14c5d2SYehuda Sadeh struct ceph_client *client; 351*3d14c5d2SYehuda Sadeh int err = -ENOMEM; 352*3d14c5d2SYehuda Sadeh 353*3d14c5d2SYehuda Sadeh client = kzalloc(sizeof(*client), GFP_KERNEL); 354*3d14c5d2SYehuda Sadeh if (client == NULL) 355*3d14c5d2SYehuda Sadeh return ERR_PTR(-ENOMEM); 356*3d14c5d2SYehuda Sadeh 357*3d14c5d2SYehuda Sadeh client->private = private; 358*3d14c5d2SYehuda Sadeh client->options = opt; 359*3d14c5d2SYehuda Sadeh 360*3d14c5d2SYehuda Sadeh mutex_init(&client->mount_mutex); 361*3d14c5d2SYehuda Sadeh init_waitqueue_head(&client->auth_wq); 362*3d14c5d2SYehuda Sadeh client->auth_err = 0; 363*3d14c5d2SYehuda Sadeh 364*3d14c5d2SYehuda Sadeh client->extra_mon_dispatch = NULL; 365*3d14c5d2SYehuda Sadeh client->supported_features = CEPH_FEATURE_SUPPORTED_DEFAULT; 366*3d14c5d2SYehuda Sadeh client->required_features = CEPH_FEATURE_REQUIRED_DEFAULT; 367*3d14c5d2SYehuda Sadeh 368*3d14c5d2SYehuda Sadeh client->msgr = NULL; 369*3d14c5d2SYehuda Sadeh 370*3d14c5d2SYehuda Sadeh /* subsystems */ 371*3d14c5d2SYehuda Sadeh err = ceph_monc_init(&client->monc, client); 372*3d14c5d2SYehuda Sadeh if (err < 0) 373*3d14c5d2SYehuda Sadeh goto fail; 374*3d14c5d2SYehuda Sadeh err = ceph_osdc_init(&client->osdc, client); 375*3d14c5d2SYehuda Sadeh if (err < 0) 376*3d14c5d2SYehuda Sadeh goto fail_monc; 377*3d14c5d2SYehuda Sadeh 378*3d14c5d2SYehuda Sadeh return client; 379*3d14c5d2SYehuda Sadeh 380*3d14c5d2SYehuda Sadeh fail_monc: 381*3d14c5d2SYehuda Sadeh ceph_monc_stop(&client->monc); 382*3d14c5d2SYehuda Sadeh fail: 383*3d14c5d2SYehuda Sadeh kfree(client); 384*3d14c5d2SYehuda Sadeh return ERR_PTR(err); 385*3d14c5d2SYehuda Sadeh } 386*3d14c5d2SYehuda Sadeh EXPORT_SYMBOL(ceph_create_client); 387*3d14c5d2SYehuda Sadeh 388*3d14c5d2SYehuda Sadeh void ceph_destroy_client(struct ceph_client *client) 389*3d14c5d2SYehuda Sadeh { 390*3d14c5d2SYehuda Sadeh dout("destroy_client %p\n", client); 391*3d14c5d2SYehuda Sadeh 392*3d14c5d2SYehuda Sadeh /* unmount */ 393*3d14c5d2SYehuda Sadeh ceph_osdc_stop(&client->osdc); 394*3d14c5d2SYehuda Sadeh 395*3d14c5d2SYehuda Sadeh /* 396*3d14c5d2SYehuda Sadeh * make sure mds and osd connections close out before destroying 397*3d14c5d2SYehuda Sadeh * the auth module, which is needed to free those connections' 398*3d14c5d2SYehuda Sadeh * ceph_authorizers. 399*3d14c5d2SYehuda Sadeh */ 400*3d14c5d2SYehuda Sadeh ceph_msgr_flush(); 401*3d14c5d2SYehuda Sadeh 402*3d14c5d2SYehuda Sadeh ceph_monc_stop(&client->monc); 403*3d14c5d2SYehuda Sadeh 404*3d14c5d2SYehuda Sadeh ceph_debugfs_client_cleanup(client); 405*3d14c5d2SYehuda Sadeh 406*3d14c5d2SYehuda Sadeh if (client->msgr) 407*3d14c5d2SYehuda Sadeh ceph_messenger_destroy(client->msgr); 408*3d14c5d2SYehuda Sadeh 409*3d14c5d2SYehuda Sadeh ceph_destroy_options(client->options); 410*3d14c5d2SYehuda Sadeh 411*3d14c5d2SYehuda Sadeh kfree(client); 412*3d14c5d2SYehuda Sadeh dout("destroy_client %p done\n", client); 413*3d14c5d2SYehuda Sadeh } 414*3d14c5d2SYehuda Sadeh EXPORT_SYMBOL(ceph_destroy_client); 415*3d14c5d2SYehuda Sadeh 416*3d14c5d2SYehuda Sadeh /* 417*3d14c5d2SYehuda Sadeh * true if we have the mon map (and have thus joined the cluster) 418*3d14c5d2SYehuda Sadeh */ 419*3d14c5d2SYehuda Sadeh static int have_mon_and_osd_map(struct ceph_client *client) 420*3d14c5d2SYehuda Sadeh { 421*3d14c5d2SYehuda Sadeh return client->monc.monmap && client->monc.monmap->epoch && 422*3d14c5d2SYehuda Sadeh client->osdc.osdmap && client->osdc.osdmap->epoch; 423*3d14c5d2SYehuda Sadeh } 424*3d14c5d2SYehuda Sadeh 425*3d14c5d2SYehuda Sadeh /* 426*3d14c5d2SYehuda Sadeh * mount: join the ceph cluster, and open root directory. 427*3d14c5d2SYehuda Sadeh */ 428*3d14c5d2SYehuda Sadeh int __ceph_open_session(struct ceph_client *client, unsigned long started) 429*3d14c5d2SYehuda Sadeh { 430*3d14c5d2SYehuda Sadeh struct ceph_entity_addr *myaddr = NULL; 431*3d14c5d2SYehuda Sadeh int err; 432*3d14c5d2SYehuda Sadeh unsigned long timeout = client->options->mount_timeout * HZ; 433*3d14c5d2SYehuda Sadeh 434*3d14c5d2SYehuda Sadeh /* initialize the messenger */ 435*3d14c5d2SYehuda Sadeh if (client->msgr == NULL) { 436*3d14c5d2SYehuda Sadeh if (ceph_test_opt(client, MYIP)) 437*3d14c5d2SYehuda Sadeh myaddr = &client->options->my_addr; 438*3d14c5d2SYehuda Sadeh client->msgr = ceph_messenger_create(myaddr, 439*3d14c5d2SYehuda Sadeh client->supported_features, 440*3d14c5d2SYehuda Sadeh client->required_features); 441*3d14c5d2SYehuda Sadeh if (IS_ERR(client->msgr)) { 442*3d14c5d2SYehuda Sadeh client->msgr = NULL; 443*3d14c5d2SYehuda Sadeh return PTR_ERR(client->msgr); 444*3d14c5d2SYehuda Sadeh } 445*3d14c5d2SYehuda Sadeh client->msgr->nocrc = ceph_test_opt(client, NOCRC); 446*3d14c5d2SYehuda Sadeh } 447*3d14c5d2SYehuda Sadeh 448*3d14c5d2SYehuda Sadeh /* open session, and wait for mon and osd maps */ 449*3d14c5d2SYehuda Sadeh err = ceph_monc_open_session(&client->monc); 450*3d14c5d2SYehuda Sadeh if (err < 0) 451*3d14c5d2SYehuda Sadeh return err; 452*3d14c5d2SYehuda Sadeh 453*3d14c5d2SYehuda Sadeh while (!have_mon_and_osd_map(client)) { 454*3d14c5d2SYehuda Sadeh err = -EIO; 455*3d14c5d2SYehuda Sadeh if (timeout && time_after_eq(jiffies, started + timeout)) 456*3d14c5d2SYehuda Sadeh return err; 457*3d14c5d2SYehuda Sadeh 458*3d14c5d2SYehuda Sadeh /* wait */ 459*3d14c5d2SYehuda Sadeh dout("mount waiting for mon_map\n"); 460*3d14c5d2SYehuda Sadeh err = wait_event_interruptible_timeout(client->auth_wq, 461*3d14c5d2SYehuda Sadeh have_mon_and_osd_map(client) || (client->auth_err < 0), 462*3d14c5d2SYehuda Sadeh timeout); 463*3d14c5d2SYehuda Sadeh if (err == -EINTR || err == -ERESTARTSYS) 464*3d14c5d2SYehuda Sadeh return err; 465*3d14c5d2SYehuda Sadeh if (client->auth_err < 0) 466*3d14c5d2SYehuda Sadeh return client->auth_err; 467*3d14c5d2SYehuda Sadeh } 468*3d14c5d2SYehuda Sadeh 469*3d14c5d2SYehuda Sadeh return 0; 470*3d14c5d2SYehuda Sadeh } 471*3d14c5d2SYehuda Sadeh EXPORT_SYMBOL(__ceph_open_session); 472*3d14c5d2SYehuda Sadeh 473*3d14c5d2SYehuda Sadeh 474*3d14c5d2SYehuda Sadeh int ceph_open_session(struct ceph_client *client) 475*3d14c5d2SYehuda Sadeh { 476*3d14c5d2SYehuda Sadeh int ret; 477*3d14c5d2SYehuda Sadeh unsigned long started = jiffies; /* note the start time */ 478*3d14c5d2SYehuda Sadeh 479*3d14c5d2SYehuda Sadeh dout("open_session start\n"); 480*3d14c5d2SYehuda Sadeh mutex_lock(&client->mount_mutex); 481*3d14c5d2SYehuda Sadeh 482*3d14c5d2SYehuda Sadeh ret = __ceph_open_session(client, started); 483*3d14c5d2SYehuda Sadeh 484*3d14c5d2SYehuda Sadeh mutex_unlock(&client->mount_mutex); 485*3d14c5d2SYehuda Sadeh return ret; 486*3d14c5d2SYehuda Sadeh } 487*3d14c5d2SYehuda Sadeh EXPORT_SYMBOL(ceph_open_session); 488*3d14c5d2SYehuda Sadeh 489*3d14c5d2SYehuda Sadeh 490*3d14c5d2SYehuda Sadeh static int __init init_ceph_lib(void) 491*3d14c5d2SYehuda Sadeh { 492*3d14c5d2SYehuda Sadeh int ret = 0; 493*3d14c5d2SYehuda Sadeh 494*3d14c5d2SYehuda Sadeh ret = ceph_debugfs_init(); 495*3d14c5d2SYehuda Sadeh if (ret < 0) 496*3d14c5d2SYehuda Sadeh goto out; 497*3d14c5d2SYehuda Sadeh 498*3d14c5d2SYehuda Sadeh ret = ceph_msgr_init(); 499*3d14c5d2SYehuda Sadeh if (ret < 0) 500*3d14c5d2SYehuda Sadeh goto out_debugfs; 501*3d14c5d2SYehuda Sadeh 502*3d14c5d2SYehuda Sadeh pr_info("loaded (mon/osd proto %d/%d, osdmap %d/%d %d/%d)\n", 503*3d14c5d2SYehuda Sadeh CEPH_MONC_PROTOCOL, CEPH_OSDC_PROTOCOL, 504*3d14c5d2SYehuda Sadeh CEPH_OSDMAP_VERSION, CEPH_OSDMAP_VERSION_EXT, 505*3d14c5d2SYehuda Sadeh CEPH_OSDMAP_INC_VERSION, CEPH_OSDMAP_INC_VERSION_EXT); 506*3d14c5d2SYehuda Sadeh 507*3d14c5d2SYehuda Sadeh return 0; 508*3d14c5d2SYehuda Sadeh 509*3d14c5d2SYehuda Sadeh out_debugfs: 510*3d14c5d2SYehuda Sadeh ceph_debugfs_cleanup(); 511*3d14c5d2SYehuda Sadeh out: 512*3d14c5d2SYehuda Sadeh return ret; 513*3d14c5d2SYehuda Sadeh } 514*3d14c5d2SYehuda Sadeh 515*3d14c5d2SYehuda Sadeh static void __exit exit_ceph_lib(void) 516*3d14c5d2SYehuda Sadeh { 517*3d14c5d2SYehuda Sadeh dout("exit_ceph_lib\n"); 518*3d14c5d2SYehuda Sadeh ceph_msgr_exit(); 519*3d14c5d2SYehuda Sadeh ceph_debugfs_cleanup(); 520*3d14c5d2SYehuda Sadeh } 521*3d14c5d2SYehuda Sadeh 522*3d14c5d2SYehuda Sadeh module_init(init_ceph_lib); 523*3d14c5d2SYehuda Sadeh module_exit(exit_ceph_lib); 524*3d14c5d2SYehuda Sadeh 525*3d14c5d2SYehuda Sadeh MODULE_AUTHOR("Sage Weil <sage@newdream.net>"); 526*3d14c5d2SYehuda Sadeh MODULE_AUTHOR("Yehuda Sadeh <yehuda@hq.newdream.net>"); 527*3d14c5d2SYehuda Sadeh MODULE_AUTHOR("Patience Warnick <patience@newdream.net>"); 528*3d14c5d2SYehuda Sadeh MODULE_DESCRIPTION("Ceph filesystem for Linux"); 529*3d14c5d2SYehuda Sadeh MODULE_LICENSE("GPL"); 530