1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun
3*4882a593Smuzhiyun #include <linux/ceph/ceph_debug.h>
4*4882a593Smuzhiyun #include <linux/backing-dev.h>
5*4882a593Smuzhiyun #include <linux/ctype.h>
6*4882a593Smuzhiyun #include <linux/fs.h>
7*4882a593Smuzhiyun #include <linux/inet.h>
8*4882a593Smuzhiyun #include <linux/in6.h>
9*4882a593Smuzhiyun #include <linux/key.h>
10*4882a593Smuzhiyun #include <keys/ceph-type.h>
11*4882a593Smuzhiyun #include <linux/module.h>
12*4882a593Smuzhiyun #include <linux/mount.h>
13*4882a593Smuzhiyun #include <linux/nsproxy.h>
14*4882a593Smuzhiyun #include <linux/fs_parser.h>
15*4882a593Smuzhiyun #include <linux/sched.h>
16*4882a593Smuzhiyun #include <linux/sched/mm.h>
17*4882a593Smuzhiyun #include <linux/seq_file.h>
18*4882a593Smuzhiyun #include <linux/slab.h>
19*4882a593Smuzhiyun #include <linux/statfs.h>
20*4882a593Smuzhiyun #include <linux/string.h>
21*4882a593Smuzhiyun #include <linux/vmalloc.h>
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun #include <linux/ceph/ceph_features.h>
25*4882a593Smuzhiyun #include <linux/ceph/libceph.h>
26*4882a593Smuzhiyun #include <linux/ceph/debugfs.h>
27*4882a593Smuzhiyun #include <linux/ceph/decode.h>
28*4882a593Smuzhiyun #include <linux/ceph/mon_client.h>
29*4882a593Smuzhiyun #include <linux/ceph/auth.h>
30*4882a593Smuzhiyun #include "crypto.h"
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun /*
34*4882a593Smuzhiyun * Module compatibility interface. For now it doesn't do anything,
35*4882a593Smuzhiyun * but its existence signals a certain level of functionality.
36*4882a593Smuzhiyun *
37*4882a593Smuzhiyun * The data buffer is used to pass information both to and from
38*4882a593Smuzhiyun * libceph. The return value indicates whether libceph determines
39*4882a593Smuzhiyun * it is compatible with the caller (from another kernel module),
40*4882a593Smuzhiyun * given the provided data.
41*4882a593Smuzhiyun *
42*4882a593Smuzhiyun * The data pointer can be null.
43*4882a593Smuzhiyun */
libceph_compatible(void * data)44*4882a593Smuzhiyun bool libceph_compatible(void *data)
45*4882a593Smuzhiyun {
46*4882a593Smuzhiyun return true;
47*4882a593Smuzhiyun }
48*4882a593Smuzhiyun EXPORT_SYMBOL(libceph_compatible);
49*4882a593Smuzhiyun
param_get_supported_features(char * buffer,const struct kernel_param * kp)50*4882a593Smuzhiyun static int param_get_supported_features(char *buffer,
51*4882a593Smuzhiyun const struct kernel_param *kp)
52*4882a593Smuzhiyun {
53*4882a593Smuzhiyun return sprintf(buffer, "0x%llx", CEPH_FEATURES_SUPPORTED_DEFAULT);
54*4882a593Smuzhiyun }
55*4882a593Smuzhiyun static const struct kernel_param_ops param_ops_supported_features = {
56*4882a593Smuzhiyun .get = param_get_supported_features,
57*4882a593Smuzhiyun };
58*4882a593Smuzhiyun module_param_cb(supported_features, ¶m_ops_supported_features, NULL,
59*4882a593Smuzhiyun 0444);
60*4882a593Smuzhiyun
ceph_msg_type_name(int type)61*4882a593Smuzhiyun const char *ceph_msg_type_name(int type)
62*4882a593Smuzhiyun {
63*4882a593Smuzhiyun switch (type) {
64*4882a593Smuzhiyun case CEPH_MSG_SHUTDOWN: return "shutdown";
65*4882a593Smuzhiyun case CEPH_MSG_PING: return "ping";
66*4882a593Smuzhiyun case CEPH_MSG_AUTH: return "auth";
67*4882a593Smuzhiyun case CEPH_MSG_AUTH_REPLY: return "auth_reply";
68*4882a593Smuzhiyun case CEPH_MSG_MON_MAP: return "mon_map";
69*4882a593Smuzhiyun case CEPH_MSG_MON_GET_MAP: return "mon_get_map";
70*4882a593Smuzhiyun case CEPH_MSG_MON_SUBSCRIBE: return "mon_subscribe";
71*4882a593Smuzhiyun case CEPH_MSG_MON_SUBSCRIBE_ACK: return "mon_subscribe_ack";
72*4882a593Smuzhiyun case CEPH_MSG_STATFS: return "statfs";
73*4882a593Smuzhiyun case CEPH_MSG_STATFS_REPLY: return "statfs_reply";
74*4882a593Smuzhiyun case CEPH_MSG_MON_GET_VERSION: return "mon_get_version";
75*4882a593Smuzhiyun case CEPH_MSG_MON_GET_VERSION_REPLY: return "mon_get_version_reply";
76*4882a593Smuzhiyun case CEPH_MSG_MDS_MAP: return "mds_map";
77*4882a593Smuzhiyun case CEPH_MSG_FS_MAP_USER: return "fs_map_user";
78*4882a593Smuzhiyun case CEPH_MSG_CLIENT_SESSION: return "client_session";
79*4882a593Smuzhiyun case CEPH_MSG_CLIENT_RECONNECT: return "client_reconnect";
80*4882a593Smuzhiyun case CEPH_MSG_CLIENT_REQUEST: return "client_request";
81*4882a593Smuzhiyun case CEPH_MSG_CLIENT_REQUEST_FORWARD: return "client_request_forward";
82*4882a593Smuzhiyun case CEPH_MSG_CLIENT_REPLY: return "client_reply";
83*4882a593Smuzhiyun case CEPH_MSG_CLIENT_CAPS: return "client_caps";
84*4882a593Smuzhiyun case CEPH_MSG_CLIENT_CAPRELEASE: return "client_cap_release";
85*4882a593Smuzhiyun case CEPH_MSG_CLIENT_QUOTA: return "client_quota";
86*4882a593Smuzhiyun case CEPH_MSG_CLIENT_SNAP: return "client_snap";
87*4882a593Smuzhiyun case CEPH_MSG_CLIENT_LEASE: return "client_lease";
88*4882a593Smuzhiyun case CEPH_MSG_POOLOP_REPLY: return "poolop_reply";
89*4882a593Smuzhiyun case CEPH_MSG_POOLOP: return "poolop";
90*4882a593Smuzhiyun case CEPH_MSG_MON_COMMAND: return "mon_command";
91*4882a593Smuzhiyun case CEPH_MSG_MON_COMMAND_ACK: return "mon_command_ack";
92*4882a593Smuzhiyun case CEPH_MSG_OSD_MAP: return "osd_map";
93*4882a593Smuzhiyun case CEPH_MSG_OSD_OP: return "osd_op";
94*4882a593Smuzhiyun case CEPH_MSG_OSD_OPREPLY: return "osd_opreply";
95*4882a593Smuzhiyun case CEPH_MSG_WATCH_NOTIFY: return "watch_notify";
96*4882a593Smuzhiyun case CEPH_MSG_OSD_BACKOFF: return "osd_backoff";
97*4882a593Smuzhiyun default: return "unknown";
98*4882a593Smuzhiyun }
99*4882a593Smuzhiyun }
100*4882a593Smuzhiyun EXPORT_SYMBOL(ceph_msg_type_name);
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun /*
103*4882a593Smuzhiyun * Initially learn our fsid, or verify an fsid matches.
104*4882a593Smuzhiyun */
ceph_check_fsid(struct ceph_client * client,struct ceph_fsid * fsid)105*4882a593Smuzhiyun int ceph_check_fsid(struct ceph_client *client, struct ceph_fsid *fsid)
106*4882a593Smuzhiyun {
107*4882a593Smuzhiyun if (client->have_fsid) {
108*4882a593Smuzhiyun if (ceph_fsid_compare(&client->fsid, fsid)) {
109*4882a593Smuzhiyun pr_err("bad fsid, had %pU got %pU",
110*4882a593Smuzhiyun &client->fsid, fsid);
111*4882a593Smuzhiyun return -1;
112*4882a593Smuzhiyun }
113*4882a593Smuzhiyun } else {
114*4882a593Smuzhiyun memcpy(&client->fsid, fsid, sizeof(*fsid));
115*4882a593Smuzhiyun }
116*4882a593Smuzhiyun return 0;
117*4882a593Smuzhiyun }
118*4882a593Smuzhiyun EXPORT_SYMBOL(ceph_check_fsid);
119*4882a593Smuzhiyun
strcmp_null(const char * s1,const char * s2)120*4882a593Smuzhiyun static int strcmp_null(const char *s1, const char *s2)
121*4882a593Smuzhiyun {
122*4882a593Smuzhiyun if (!s1 && !s2)
123*4882a593Smuzhiyun return 0;
124*4882a593Smuzhiyun if (s1 && !s2)
125*4882a593Smuzhiyun return -1;
126*4882a593Smuzhiyun if (!s1 && s2)
127*4882a593Smuzhiyun return 1;
128*4882a593Smuzhiyun return strcmp(s1, s2);
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun
ceph_compare_options(struct ceph_options * new_opt,struct ceph_client * client)131*4882a593Smuzhiyun int ceph_compare_options(struct ceph_options *new_opt,
132*4882a593Smuzhiyun struct ceph_client *client)
133*4882a593Smuzhiyun {
134*4882a593Smuzhiyun struct ceph_options *opt1 = new_opt;
135*4882a593Smuzhiyun struct ceph_options *opt2 = client->options;
136*4882a593Smuzhiyun int ofs = offsetof(struct ceph_options, mon_addr);
137*4882a593Smuzhiyun int i;
138*4882a593Smuzhiyun int ret;
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun /*
141*4882a593Smuzhiyun * Don't bother comparing options if network namespaces don't
142*4882a593Smuzhiyun * match.
143*4882a593Smuzhiyun */
144*4882a593Smuzhiyun if (!net_eq(current->nsproxy->net_ns, read_pnet(&client->msgr.net)))
145*4882a593Smuzhiyun return -1;
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun ret = memcmp(opt1, opt2, ofs);
148*4882a593Smuzhiyun if (ret)
149*4882a593Smuzhiyun return ret;
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun ret = strcmp_null(opt1->name, opt2->name);
152*4882a593Smuzhiyun if (ret)
153*4882a593Smuzhiyun return ret;
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun if (opt1->key && !opt2->key)
156*4882a593Smuzhiyun return -1;
157*4882a593Smuzhiyun if (!opt1->key && opt2->key)
158*4882a593Smuzhiyun return 1;
159*4882a593Smuzhiyun if (opt1->key && opt2->key) {
160*4882a593Smuzhiyun if (opt1->key->type != opt2->key->type)
161*4882a593Smuzhiyun return -1;
162*4882a593Smuzhiyun if (opt1->key->created.tv_sec != opt2->key->created.tv_sec)
163*4882a593Smuzhiyun return -1;
164*4882a593Smuzhiyun if (opt1->key->created.tv_nsec != opt2->key->created.tv_nsec)
165*4882a593Smuzhiyun return -1;
166*4882a593Smuzhiyun if (opt1->key->len != opt2->key->len)
167*4882a593Smuzhiyun return -1;
168*4882a593Smuzhiyun if (opt1->key->key && !opt2->key->key)
169*4882a593Smuzhiyun return -1;
170*4882a593Smuzhiyun if (!opt1->key->key && opt2->key->key)
171*4882a593Smuzhiyun return 1;
172*4882a593Smuzhiyun if (opt1->key->key && opt2->key->key) {
173*4882a593Smuzhiyun ret = memcmp(opt1->key->key, opt2->key->key, opt1->key->len);
174*4882a593Smuzhiyun if (ret)
175*4882a593Smuzhiyun return ret;
176*4882a593Smuzhiyun }
177*4882a593Smuzhiyun }
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun ret = ceph_compare_crush_locs(&opt1->crush_locs, &opt2->crush_locs);
180*4882a593Smuzhiyun if (ret)
181*4882a593Smuzhiyun return ret;
182*4882a593Smuzhiyun
183*4882a593Smuzhiyun /* any matching mon ip implies a match */
184*4882a593Smuzhiyun for (i = 0; i < opt1->num_mon; i++) {
185*4882a593Smuzhiyun if (ceph_monmap_contains(client->monc.monmap,
186*4882a593Smuzhiyun &opt1->mon_addr[i]))
187*4882a593Smuzhiyun return 0;
188*4882a593Smuzhiyun }
189*4882a593Smuzhiyun return -1;
190*4882a593Smuzhiyun }
191*4882a593Smuzhiyun EXPORT_SYMBOL(ceph_compare_options);
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun /*
194*4882a593Smuzhiyun * kvmalloc() doesn't fall back to the vmalloc allocator unless flags are
195*4882a593Smuzhiyun * compatible with (a superset of) GFP_KERNEL. This is because while the
196*4882a593Smuzhiyun * actual pages are allocated with the specified flags, the page table pages
197*4882a593Smuzhiyun * are always allocated with GFP_KERNEL.
198*4882a593Smuzhiyun *
199*4882a593Smuzhiyun * ceph_kvmalloc() may be called with GFP_KERNEL, GFP_NOFS or GFP_NOIO.
200*4882a593Smuzhiyun */
ceph_kvmalloc(size_t size,gfp_t flags)201*4882a593Smuzhiyun void *ceph_kvmalloc(size_t size, gfp_t flags)
202*4882a593Smuzhiyun {
203*4882a593Smuzhiyun void *p;
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun if ((flags & (__GFP_IO | __GFP_FS)) == (__GFP_IO | __GFP_FS)) {
206*4882a593Smuzhiyun p = kvmalloc(size, flags);
207*4882a593Smuzhiyun } else if ((flags & (__GFP_IO | __GFP_FS)) == __GFP_IO) {
208*4882a593Smuzhiyun unsigned int nofs_flag = memalloc_nofs_save();
209*4882a593Smuzhiyun p = kvmalloc(size, GFP_KERNEL);
210*4882a593Smuzhiyun memalloc_nofs_restore(nofs_flag);
211*4882a593Smuzhiyun } else {
212*4882a593Smuzhiyun unsigned int noio_flag = memalloc_noio_save();
213*4882a593Smuzhiyun p = kvmalloc(size, GFP_KERNEL);
214*4882a593Smuzhiyun memalloc_noio_restore(noio_flag);
215*4882a593Smuzhiyun }
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun return p;
218*4882a593Smuzhiyun }
219*4882a593Smuzhiyun
parse_fsid(const char * str,struct ceph_fsid * fsid)220*4882a593Smuzhiyun static int parse_fsid(const char *str, struct ceph_fsid *fsid)
221*4882a593Smuzhiyun {
222*4882a593Smuzhiyun int i = 0;
223*4882a593Smuzhiyun char tmp[3];
224*4882a593Smuzhiyun int err = -EINVAL;
225*4882a593Smuzhiyun int d;
226*4882a593Smuzhiyun
227*4882a593Smuzhiyun dout("parse_fsid '%s'\n", str);
228*4882a593Smuzhiyun tmp[2] = 0;
229*4882a593Smuzhiyun while (*str && i < 16) {
230*4882a593Smuzhiyun if (ispunct(*str)) {
231*4882a593Smuzhiyun str++;
232*4882a593Smuzhiyun continue;
233*4882a593Smuzhiyun }
234*4882a593Smuzhiyun if (!isxdigit(str[0]) || !isxdigit(str[1]))
235*4882a593Smuzhiyun break;
236*4882a593Smuzhiyun tmp[0] = str[0];
237*4882a593Smuzhiyun tmp[1] = str[1];
238*4882a593Smuzhiyun if (sscanf(tmp, "%x", &d) < 1)
239*4882a593Smuzhiyun break;
240*4882a593Smuzhiyun fsid->fsid[i] = d & 0xff;
241*4882a593Smuzhiyun i++;
242*4882a593Smuzhiyun str += 2;
243*4882a593Smuzhiyun }
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun if (i == 16)
246*4882a593Smuzhiyun err = 0;
247*4882a593Smuzhiyun dout("parse_fsid ret %d got fsid %pU\n", err, fsid);
248*4882a593Smuzhiyun return err;
249*4882a593Smuzhiyun }
250*4882a593Smuzhiyun
251*4882a593Smuzhiyun /*
252*4882a593Smuzhiyun * ceph options
253*4882a593Smuzhiyun */
254*4882a593Smuzhiyun enum {
255*4882a593Smuzhiyun Opt_osdtimeout,
256*4882a593Smuzhiyun Opt_osdkeepalivetimeout,
257*4882a593Smuzhiyun Opt_mount_timeout,
258*4882a593Smuzhiyun Opt_osd_idle_ttl,
259*4882a593Smuzhiyun Opt_osd_request_timeout,
260*4882a593Smuzhiyun /* int args above */
261*4882a593Smuzhiyun Opt_fsid,
262*4882a593Smuzhiyun Opt_name,
263*4882a593Smuzhiyun Opt_secret,
264*4882a593Smuzhiyun Opt_key,
265*4882a593Smuzhiyun Opt_ip,
266*4882a593Smuzhiyun Opt_crush_location,
267*4882a593Smuzhiyun Opt_read_from_replica,
268*4882a593Smuzhiyun /* string args above */
269*4882a593Smuzhiyun Opt_share,
270*4882a593Smuzhiyun Opt_crc,
271*4882a593Smuzhiyun Opt_cephx_require_signatures,
272*4882a593Smuzhiyun Opt_cephx_sign_messages,
273*4882a593Smuzhiyun Opt_tcp_nodelay,
274*4882a593Smuzhiyun Opt_abort_on_full,
275*4882a593Smuzhiyun };
276*4882a593Smuzhiyun
277*4882a593Smuzhiyun enum {
278*4882a593Smuzhiyun Opt_read_from_replica_no,
279*4882a593Smuzhiyun Opt_read_from_replica_balance,
280*4882a593Smuzhiyun Opt_read_from_replica_localize,
281*4882a593Smuzhiyun };
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun static const struct constant_table ceph_param_read_from_replica[] = {
284*4882a593Smuzhiyun {"no", Opt_read_from_replica_no},
285*4882a593Smuzhiyun {"balance", Opt_read_from_replica_balance},
286*4882a593Smuzhiyun {"localize", Opt_read_from_replica_localize},
287*4882a593Smuzhiyun {}
288*4882a593Smuzhiyun };
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun static const struct fs_parameter_spec ceph_parameters[] = {
291*4882a593Smuzhiyun fsparam_flag ("abort_on_full", Opt_abort_on_full),
292*4882a593Smuzhiyun fsparam_flag_no ("cephx_require_signatures", Opt_cephx_require_signatures),
293*4882a593Smuzhiyun fsparam_flag_no ("cephx_sign_messages", Opt_cephx_sign_messages),
294*4882a593Smuzhiyun fsparam_flag_no ("crc", Opt_crc),
295*4882a593Smuzhiyun fsparam_string ("crush_location", Opt_crush_location),
296*4882a593Smuzhiyun fsparam_string ("fsid", Opt_fsid),
297*4882a593Smuzhiyun fsparam_string ("ip", Opt_ip),
298*4882a593Smuzhiyun fsparam_string ("key", Opt_key),
299*4882a593Smuzhiyun fsparam_u32 ("mount_timeout", Opt_mount_timeout),
300*4882a593Smuzhiyun fsparam_string ("name", Opt_name),
301*4882a593Smuzhiyun fsparam_u32 ("osd_idle_ttl", Opt_osd_idle_ttl),
302*4882a593Smuzhiyun fsparam_u32 ("osd_request_timeout", Opt_osd_request_timeout),
303*4882a593Smuzhiyun fsparam_u32 ("osdkeepalive", Opt_osdkeepalivetimeout),
304*4882a593Smuzhiyun __fsparam (fs_param_is_s32, "osdtimeout", Opt_osdtimeout,
305*4882a593Smuzhiyun fs_param_deprecated, NULL),
306*4882a593Smuzhiyun fsparam_enum ("read_from_replica", Opt_read_from_replica,
307*4882a593Smuzhiyun ceph_param_read_from_replica),
308*4882a593Smuzhiyun fsparam_string ("secret", Opt_secret),
309*4882a593Smuzhiyun fsparam_flag_no ("share", Opt_share),
310*4882a593Smuzhiyun fsparam_flag_no ("tcp_nodelay", Opt_tcp_nodelay),
311*4882a593Smuzhiyun {}
312*4882a593Smuzhiyun };
313*4882a593Smuzhiyun
ceph_alloc_options(void)314*4882a593Smuzhiyun struct ceph_options *ceph_alloc_options(void)
315*4882a593Smuzhiyun {
316*4882a593Smuzhiyun struct ceph_options *opt;
317*4882a593Smuzhiyun
318*4882a593Smuzhiyun opt = kzalloc(sizeof(*opt), GFP_KERNEL);
319*4882a593Smuzhiyun if (!opt)
320*4882a593Smuzhiyun return NULL;
321*4882a593Smuzhiyun
322*4882a593Smuzhiyun opt->crush_locs = RB_ROOT;
323*4882a593Smuzhiyun opt->mon_addr = kcalloc(CEPH_MAX_MON, sizeof(*opt->mon_addr),
324*4882a593Smuzhiyun GFP_KERNEL);
325*4882a593Smuzhiyun if (!opt->mon_addr) {
326*4882a593Smuzhiyun kfree(opt);
327*4882a593Smuzhiyun return NULL;
328*4882a593Smuzhiyun }
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun opt->flags = CEPH_OPT_DEFAULT;
331*4882a593Smuzhiyun opt->osd_keepalive_timeout = CEPH_OSD_KEEPALIVE_DEFAULT;
332*4882a593Smuzhiyun opt->mount_timeout = CEPH_MOUNT_TIMEOUT_DEFAULT;
333*4882a593Smuzhiyun opt->osd_idle_ttl = CEPH_OSD_IDLE_TTL_DEFAULT;
334*4882a593Smuzhiyun opt->osd_request_timeout = CEPH_OSD_REQUEST_TIMEOUT_DEFAULT;
335*4882a593Smuzhiyun opt->read_from_replica = CEPH_READ_FROM_REPLICA_DEFAULT;
336*4882a593Smuzhiyun return opt;
337*4882a593Smuzhiyun }
338*4882a593Smuzhiyun EXPORT_SYMBOL(ceph_alloc_options);
339*4882a593Smuzhiyun
ceph_destroy_options(struct ceph_options * opt)340*4882a593Smuzhiyun void ceph_destroy_options(struct ceph_options *opt)
341*4882a593Smuzhiyun {
342*4882a593Smuzhiyun dout("destroy_options %p\n", opt);
343*4882a593Smuzhiyun if (!opt)
344*4882a593Smuzhiyun return;
345*4882a593Smuzhiyun
346*4882a593Smuzhiyun ceph_clear_crush_locs(&opt->crush_locs);
347*4882a593Smuzhiyun kfree(opt->name);
348*4882a593Smuzhiyun if (opt->key) {
349*4882a593Smuzhiyun ceph_crypto_key_destroy(opt->key);
350*4882a593Smuzhiyun kfree(opt->key);
351*4882a593Smuzhiyun }
352*4882a593Smuzhiyun kfree(opt->mon_addr);
353*4882a593Smuzhiyun kfree(opt);
354*4882a593Smuzhiyun }
355*4882a593Smuzhiyun EXPORT_SYMBOL(ceph_destroy_options);
356*4882a593Smuzhiyun
357*4882a593Smuzhiyun /* get secret from key store */
get_secret(struct ceph_crypto_key * dst,const char * name,struct p_log * log)358*4882a593Smuzhiyun static int get_secret(struct ceph_crypto_key *dst, const char *name,
359*4882a593Smuzhiyun struct p_log *log)
360*4882a593Smuzhiyun {
361*4882a593Smuzhiyun struct key *ukey;
362*4882a593Smuzhiyun int key_err;
363*4882a593Smuzhiyun int err = 0;
364*4882a593Smuzhiyun struct ceph_crypto_key *ckey;
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun ukey = request_key(&key_type_ceph, name, NULL);
367*4882a593Smuzhiyun if (IS_ERR(ukey)) {
368*4882a593Smuzhiyun /* request_key errors don't map nicely to mount(2)
369*4882a593Smuzhiyun errors; don't even try, but still printk */
370*4882a593Smuzhiyun key_err = PTR_ERR(ukey);
371*4882a593Smuzhiyun switch (key_err) {
372*4882a593Smuzhiyun case -ENOKEY:
373*4882a593Smuzhiyun error_plog(log, "Failed due to key not found: %s",
374*4882a593Smuzhiyun name);
375*4882a593Smuzhiyun break;
376*4882a593Smuzhiyun case -EKEYEXPIRED:
377*4882a593Smuzhiyun error_plog(log, "Failed due to expired key: %s",
378*4882a593Smuzhiyun name);
379*4882a593Smuzhiyun break;
380*4882a593Smuzhiyun case -EKEYREVOKED:
381*4882a593Smuzhiyun error_plog(log, "Failed due to revoked key: %s",
382*4882a593Smuzhiyun name);
383*4882a593Smuzhiyun break;
384*4882a593Smuzhiyun default:
385*4882a593Smuzhiyun error_plog(log, "Failed due to key error %d: %s",
386*4882a593Smuzhiyun key_err, name);
387*4882a593Smuzhiyun }
388*4882a593Smuzhiyun err = -EPERM;
389*4882a593Smuzhiyun goto out;
390*4882a593Smuzhiyun }
391*4882a593Smuzhiyun
392*4882a593Smuzhiyun ckey = ukey->payload.data[0];
393*4882a593Smuzhiyun err = ceph_crypto_key_clone(dst, ckey);
394*4882a593Smuzhiyun if (err)
395*4882a593Smuzhiyun goto out_key;
396*4882a593Smuzhiyun /* pass through, err is 0 */
397*4882a593Smuzhiyun
398*4882a593Smuzhiyun out_key:
399*4882a593Smuzhiyun key_put(ukey);
400*4882a593Smuzhiyun out:
401*4882a593Smuzhiyun return err;
402*4882a593Smuzhiyun }
403*4882a593Smuzhiyun
ceph_parse_mon_ips(const char * buf,size_t len,struct ceph_options * opt,struct fc_log * l)404*4882a593Smuzhiyun int ceph_parse_mon_ips(const char *buf, size_t len, struct ceph_options *opt,
405*4882a593Smuzhiyun struct fc_log *l)
406*4882a593Smuzhiyun {
407*4882a593Smuzhiyun struct p_log log = {.prefix = "libceph", .log = l};
408*4882a593Smuzhiyun int ret;
409*4882a593Smuzhiyun
410*4882a593Smuzhiyun /* ip1[:port1][,ip2[:port2]...] */
411*4882a593Smuzhiyun ret = ceph_parse_ips(buf, buf + len, opt->mon_addr, CEPH_MAX_MON,
412*4882a593Smuzhiyun &opt->num_mon);
413*4882a593Smuzhiyun if (ret) {
414*4882a593Smuzhiyun error_plog(&log, "Failed to parse monitor IPs: %d", ret);
415*4882a593Smuzhiyun return ret;
416*4882a593Smuzhiyun }
417*4882a593Smuzhiyun
418*4882a593Smuzhiyun return 0;
419*4882a593Smuzhiyun }
420*4882a593Smuzhiyun EXPORT_SYMBOL(ceph_parse_mon_ips);
421*4882a593Smuzhiyun
ceph_parse_param(struct fs_parameter * param,struct ceph_options * opt,struct fc_log * l)422*4882a593Smuzhiyun int ceph_parse_param(struct fs_parameter *param, struct ceph_options *opt,
423*4882a593Smuzhiyun struct fc_log *l)
424*4882a593Smuzhiyun {
425*4882a593Smuzhiyun struct fs_parse_result result;
426*4882a593Smuzhiyun int token, err;
427*4882a593Smuzhiyun struct p_log log = {.prefix = "libceph", .log = l};
428*4882a593Smuzhiyun
429*4882a593Smuzhiyun token = __fs_parse(&log, ceph_parameters, param, &result);
430*4882a593Smuzhiyun dout("%s fs_parse '%s' token %d\n", __func__, param->key, token);
431*4882a593Smuzhiyun if (token < 0)
432*4882a593Smuzhiyun return token;
433*4882a593Smuzhiyun
434*4882a593Smuzhiyun switch (token) {
435*4882a593Smuzhiyun case Opt_ip:
436*4882a593Smuzhiyun err = ceph_parse_ips(param->string,
437*4882a593Smuzhiyun param->string + param->size,
438*4882a593Smuzhiyun &opt->my_addr,
439*4882a593Smuzhiyun 1, NULL);
440*4882a593Smuzhiyun if (err) {
441*4882a593Smuzhiyun error_plog(&log, "Failed to parse ip: %d", err);
442*4882a593Smuzhiyun return err;
443*4882a593Smuzhiyun }
444*4882a593Smuzhiyun opt->flags |= CEPH_OPT_MYIP;
445*4882a593Smuzhiyun break;
446*4882a593Smuzhiyun
447*4882a593Smuzhiyun case Opt_fsid:
448*4882a593Smuzhiyun err = parse_fsid(param->string, &opt->fsid);
449*4882a593Smuzhiyun if (err) {
450*4882a593Smuzhiyun error_plog(&log, "Failed to parse fsid: %d", err);
451*4882a593Smuzhiyun return err;
452*4882a593Smuzhiyun }
453*4882a593Smuzhiyun opt->flags |= CEPH_OPT_FSID;
454*4882a593Smuzhiyun break;
455*4882a593Smuzhiyun case Opt_name:
456*4882a593Smuzhiyun kfree(opt->name);
457*4882a593Smuzhiyun opt->name = param->string;
458*4882a593Smuzhiyun param->string = NULL;
459*4882a593Smuzhiyun break;
460*4882a593Smuzhiyun case Opt_secret:
461*4882a593Smuzhiyun ceph_crypto_key_destroy(opt->key);
462*4882a593Smuzhiyun kfree(opt->key);
463*4882a593Smuzhiyun
464*4882a593Smuzhiyun opt->key = kzalloc(sizeof(*opt->key), GFP_KERNEL);
465*4882a593Smuzhiyun if (!opt->key)
466*4882a593Smuzhiyun return -ENOMEM;
467*4882a593Smuzhiyun err = ceph_crypto_key_unarmor(opt->key, param->string);
468*4882a593Smuzhiyun if (err) {
469*4882a593Smuzhiyun error_plog(&log, "Failed to parse secret: %d", err);
470*4882a593Smuzhiyun return err;
471*4882a593Smuzhiyun }
472*4882a593Smuzhiyun break;
473*4882a593Smuzhiyun case Opt_key:
474*4882a593Smuzhiyun ceph_crypto_key_destroy(opt->key);
475*4882a593Smuzhiyun kfree(opt->key);
476*4882a593Smuzhiyun
477*4882a593Smuzhiyun opt->key = kzalloc(sizeof(*opt->key), GFP_KERNEL);
478*4882a593Smuzhiyun if (!opt->key)
479*4882a593Smuzhiyun return -ENOMEM;
480*4882a593Smuzhiyun return get_secret(opt->key, param->string, &log);
481*4882a593Smuzhiyun case Opt_crush_location:
482*4882a593Smuzhiyun ceph_clear_crush_locs(&opt->crush_locs);
483*4882a593Smuzhiyun err = ceph_parse_crush_location(param->string,
484*4882a593Smuzhiyun &opt->crush_locs);
485*4882a593Smuzhiyun if (err) {
486*4882a593Smuzhiyun error_plog(&log, "Failed to parse CRUSH location: %d",
487*4882a593Smuzhiyun err);
488*4882a593Smuzhiyun return err;
489*4882a593Smuzhiyun }
490*4882a593Smuzhiyun break;
491*4882a593Smuzhiyun case Opt_read_from_replica:
492*4882a593Smuzhiyun switch (result.uint_32) {
493*4882a593Smuzhiyun case Opt_read_from_replica_no:
494*4882a593Smuzhiyun opt->read_from_replica = 0;
495*4882a593Smuzhiyun break;
496*4882a593Smuzhiyun case Opt_read_from_replica_balance:
497*4882a593Smuzhiyun opt->read_from_replica = CEPH_OSD_FLAG_BALANCE_READS;
498*4882a593Smuzhiyun break;
499*4882a593Smuzhiyun case Opt_read_from_replica_localize:
500*4882a593Smuzhiyun opt->read_from_replica = CEPH_OSD_FLAG_LOCALIZE_READS;
501*4882a593Smuzhiyun break;
502*4882a593Smuzhiyun default:
503*4882a593Smuzhiyun BUG();
504*4882a593Smuzhiyun }
505*4882a593Smuzhiyun break;
506*4882a593Smuzhiyun
507*4882a593Smuzhiyun case Opt_osdtimeout:
508*4882a593Smuzhiyun warn_plog(&log, "Ignoring osdtimeout");
509*4882a593Smuzhiyun break;
510*4882a593Smuzhiyun case Opt_osdkeepalivetimeout:
511*4882a593Smuzhiyun /* 0 isn't well defined right now, reject it */
512*4882a593Smuzhiyun if (result.uint_32 < 1 || result.uint_32 > INT_MAX / 1000)
513*4882a593Smuzhiyun goto out_of_range;
514*4882a593Smuzhiyun opt->osd_keepalive_timeout =
515*4882a593Smuzhiyun msecs_to_jiffies(result.uint_32 * 1000);
516*4882a593Smuzhiyun break;
517*4882a593Smuzhiyun case Opt_osd_idle_ttl:
518*4882a593Smuzhiyun /* 0 isn't well defined right now, reject it */
519*4882a593Smuzhiyun if (result.uint_32 < 1 || result.uint_32 > INT_MAX / 1000)
520*4882a593Smuzhiyun goto out_of_range;
521*4882a593Smuzhiyun opt->osd_idle_ttl = msecs_to_jiffies(result.uint_32 * 1000);
522*4882a593Smuzhiyun break;
523*4882a593Smuzhiyun case Opt_mount_timeout:
524*4882a593Smuzhiyun /* 0 is "wait forever" (i.e. infinite timeout) */
525*4882a593Smuzhiyun if (result.uint_32 > INT_MAX / 1000)
526*4882a593Smuzhiyun goto out_of_range;
527*4882a593Smuzhiyun opt->mount_timeout = msecs_to_jiffies(result.uint_32 * 1000);
528*4882a593Smuzhiyun break;
529*4882a593Smuzhiyun case Opt_osd_request_timeout:
530*4882a593Smuzhiyun /* 0 is "wait forever" (i.e. infinite timeout) */
531*4882a593Smuzhiyun if (result.uint_32 > INT_MAX / 1000)
532*4882a593Smuzhiyun goto out_of_range;
533*4882a593Smuzhiyun opt->osd_request_timeout =
534*4882a593Smuzhiyun msecs_to_jiffies(result.uint_32 * 1000);
535*4882a593Smuzhiyun break;
536*4882a593Smuzhiyun
537*4882a593Smuzhiyun case Opt_share:
538*4882a593Smuzhiyun if (!result.negated)
539*4882a593Smuzhiyun opt->flags &= ~CEPH_OPT_NOSHARE;
540*4882a593Smuzhiyun else
541*4882a593Smuzhiyun opt->flags |= CEPH_OPT_NOSHARE;
542*4882a593Smuzhiyun break;
543*4882a593Smuzhiyun case Opt_crc:
544*4882a593Smuzhiyun if (!result.negated)
545*4882a593Smuzhiyun opt->flags &= ~CEPH_OPT_NOCRC;
546*4882a593Smuzhiyun else
547*4882a593Smuzhiyun opt->flags |= CEPH_OPT_NOCRC;
548*4882a593Smuzhiyun break;
549*4882a593Smuzhiyun case Opt_cephx_require_signatures:
550*4882a593Smuzhiyun if (!result.negated)
551*4882a593Smuzhiyun opt->flags &= ~CEPH_OPT_NOMSGAUTH;
552*4882a593Smuzhiyun else
553*4882a593Smuzhiyun opt->flags |= CEPH_OPT_NOMSGAUTH;
554*4882a593Smuzhiyun break;
555*4882a593Smuzhiyun case Opt_cephx_sign_messages:
556*4882a593Smuzhiyun if (!result.negated)
557*4882a593Smuzhiyun opt->flags &= ~CEPH_OPT_NOMSGSIGN;
558*4882a593Smuzhiyun else
559*4882a593Smuzhiyun opt->flags |= CEPH_OPT_NOMSGSIGN;
560*4882a593Smuzhiyun break;
561*4882a593Smuzhiyun case Opt_tcp_nodelay:
562*4882a593Smuzhiyun if (!result.negated)
563*4882a593Smuzhiyun opt->flags |= CEPH_OPT_TCP_NODELAY;
564*4882a593Smuzhiyun else
565*4882a593Smuzhiyun opt->flags &= ~CEPH_OPT_TCP_NODELAY;
566*4882a593Smuzhiyun break;
567*4882a593Smuzhiyun
568*4882a593Smuzhiyun case Opt_abort_on_full:
569*4882a593Smuzhiyun opt->flags |= CEPH_OPT_ABORT_ON_FULL;
570*4882a593Smuzhiyun break;
571*4882a593Smuzhiyun
572*4882a593Smuzhiyun default:
573*4882a593Smuzhiyun BUG();
574*4882a593Smuzhiyun }
575*4882a593Smuzhiyun
576*4882a593Smuzhiyun return 0;
577*4882a593Smuzhiyun
578*4882a593Smuzhiyun out_of_range:
579*4882a593Smuzhiyun return inval_plog(&log, "%s out of range", param->key);
580*4882a593Smuzhiyun }
581*4882a593Smuzhiyun EXPORT_SYMBOL(ceph_parse_param);
582*4882a593Smuzhiyun
ceph_print_client_options(struct seq_file * m,struct ceph_client * client,bool show_all)583*4882a593Smuzhiyun int ceph_print_client_options(struct seq_file *m, struct ceph_client *client,
584*4882a593Smuzhiyun bool show_all)
585*4882a593Smuzhiyun {
586*4882a593Smuzhiyun struct ceph_options *opt = client->options;
587*4882a593Smuzhiyun size_t pos = m->count;
588*4882a593Smuzhiyun struct rb_node *n;
589*4882a593Smuzhiyun
590*4882a593Smuzhiyun if (opt->name) {
591*4882a593Smuzhiyun seq_puts(m, "name=");
592*4882a593Smuzhiyun seq_escape(m, opt->name, ", \t\n\\");
593*4882a593Smuzhiyun seq_putc(m, ',');
594*4882a593Smuzhiyun }
595*4882a593Smuzhiyun if (opt->key)
596*4882a593Smuzhiyun seq_puts(m, "secret=<hidden>,");
597*4882a593Smuzhiyun
598*4882a593Smuzhiyun if (!RB_EMPTY_ROOT(&opt->crush_locs)) {
599*4882a593Smuzhiyun seq_puts(m, "crush_location=");
600*4882a593Smuzhiyun for (n = rb_first(&opt->crush_locs); ; ) {
601*4882a593Smuzhiyun struct crush_loc_node *loc =
602*4882a593Smuzhiyun rb_entry(n, struct crush_loc_node, cl_node);
603*4882a593Smuzhiyun
604*4882a593Smuzhiyun seq_printf(m, "%s:%s", loc->cl_loc.cl_type_name,
605*4882a593Smuzhiyun loc->cl_loc.cl_name);
606*4882a593Smuzhiyun n = rb_next(n);
607*4882a593Smuzhiyun if (!n)
608*4882a593Smuzhiyun break;
609*4882a593Smuzhiyun
610*4882a593Smuzhiyun seq_putc(m, '|');
611*4882a593Smuzhiyun }
612*4882a593Smuzhiyun seq_putc(m, ',');
613*4882a593Smuzhiyun }
614*4882a593Smuzhiyun if (opt->read_from_replica == CEPH_OSD_FLAG_BALANCE_READS) {
615*4882a593Smuzhiyun seq_puts(m, "read_from_replica=balance,");
616*4882a593Smuzhiyun } else if (opt->read_from_replica == CEPH_OSD_FLAG_LOCALIZE_READS) {
617*4882a593Smuzhiyun seq_puts(m, "read_from_replica=localize,");
618*4882a593Smuzhiyun }
619*4882a593Smuzhiyun
620*4882a593Smuzhiyun if (opt->flags & CEPH_OPT_FSID)
621*4882a593Smuzhiyun seq_printf(m, "fsid=%pU,", &opt->fsid);
622*4882a593Smuzhiyun if (opt->flags & CEPH_OPT_NOSHARE)
623*4882a593Smuzhiyun seq_puts(m, "noshare,");
624*4882a593Smuzhiyun if (opt->flags & CEPH_OPT_NOCRC)
625*4882a593Smuzhiyun seq_puts(m, "nocrc,");
626*4882a593Smuzhiyun if (opt->flags & CEPH_OPT_NOMSGAUTH)
627*4882a593Smuzhiyun seq_puts(m, "nocephx_require_signatures,");
628*4882a593Smuzhiyun if (opt->flags & CEPH_OPT_NOMSGSIGN)
629*4882a593Smuzhiyun seq_puts(m, "nocephx_sign_messages,");
630*4882a593Smuzhiyun if ((opt->flags & CEPH_OPT_TCP_NODELAY) == 0)
631*4882a593Smuzhiyun seq_puts(m, "notcp_nodelay,");
632*4882a593Smuzhiyun if (show_all && (opt->flags & CEPH_OPT_ABORT_ON_FULL))
633*4882a593Smuzhiyun seq_puts(m, "abort_on_full,");
634*4882a593Smuzhiyun
635*4882a593Smuzhiyun if (opt->mount_timeout != CEPH_MOUNT_TIMEOUT_DEFAULT)
636*4882a593Smuzhiyun seq_printf(m, "mount_timeout=%d,",
637*4882a593Smuzhiyun jiffies_to_msecs(opt->mount_timeout) / 1000);
638*4882a593Smuzhiyun if (opt->osd_idle_ttl != CEPH_OSD_IDLE_TTL_DEFAULT)
639*4882a593Smuzhiyun seq_printf(m, "osd_idle_ttl=%d,",
640*4882a593Smuzhiyun jiffies_to_msecs(opt->osd_idle_ttl) / 1000);
641*4882a593Smuzhiyun if (opt->osd_keepalive_timeout != CEPH_OSD_KEEPALIVE_DEFAULT)
642*4882a593Smuzhiyun seq_printf(m, "osdkeepalivetimeout=%d,",
643*4882a593Smuzhiyun jiffies_to_msecs(opt->osd_keepalive_timeout) / 1000);
644*4882a593Smuzhiyun if (opt->osd_request_timeout != CEPH_OSD_REQUEST_TIMEOUT_DEFAULT)
645*4882a593Smuzhiyun seq_printf(m, "osd_request_timeout=%d,",
646*4882a593Smuzhiyun jiffies_to_msecs(opt->osd_request_timeout) / 1000);
647*4882a593Smuzhiyun
648*4882a593Smuzhiyun /* drop redundant comma */
649*4882a593Smuzhiyun if (m->count != pos)
650*4882a593Smuzhiyun m->count--;
651*4882a593Smuzhiyun
652*4882a593Smuzhiyun return 0;
653*4882a593Smuzhiyun }
654*4882a593Smuzhiyun EXPORT_SYMBOL(ceph_print_client_options);
655*4882a593Smuzhiyun
ceph_client_addr(struct ceph_client * client)656*4882a593Smuzhiyun struct ceph_entity_addr *ceph_client_addr(struct ceph_client *client)
657*4882a593Smuzhiyun {
658*4882a593Smuzhiyun return &client->msgr.inst.addr;
659*4882a593Smuzhiyun }
660*4882a593Smuzhiyun EXPORT_SYMBOL(ceph_client_addr);
661*4882a593Smuzhiyun
ceph_client_gid(struct ceph_client * client)662*4882a593Smuzhiyun u64 ceph_client_gid(struct ceph_client *client)
663*4882a593Smuzhiyun {
664*4882a593Smuzhiyun return client->monc.auth->global_id;
665*4882a593Smuzhiyun }
666*4882a593Smuzhiyun EXPORT_SYMBOL(ceph_client_gid);
667*4882a593Smuzhiyun
668*4882a593Smuzhiyun /*
669*4882a593Smuzhiyun * create a fresh client instance
670*4882a593Smuzhiyun */
ceph_create_client(struct ceph_options * opt,void * private)671*4882a593Smuzhiyun struct ceph_client *ceph_create_client(struct ceph_options *opt, void *private)
672*4882a593Smuzhiyun {
673*4882a593Smuzhiyun struct ceph_client *client;
674*4882a593Smuzhiyun struct ceph_entity_addr *myaddr = NULL;
675*4882a593Smuzhiyun int err;
676*4882a593Smuzhiyun
677*4882a593Smuzhiyun err = wait_for_random_bytes();
678*4882a593Smuzhiyun if (err < 0)
679*4882a593Smuzhiyun return ERR_PTR(err);
680*4882a593Smuzhiyun
681*4882a593Smuzhiyun client = kzalloc(sizeof(*client), GFP_KERNEL);
682*4882a593Smuzhiyun if (client == NULL)
683*4882a593Smuzhiyun return ERR_PTR(-ENOMEM);
684*4882a593Smuzhiyun
685*4882a593Smuzhiyun client->private = private;
686*4882a593Smuzhiyun client->options = opt;
687*4882a593Smuzhiyun
688*4882a593Smuzhiyun mutex_init(&client->mount_mutex);
689*4882a593Smuzhiyun init_waitqueue_head(&client->auth_wq);
690*4882a593Smuzhiyun client->auth_err = 0;
691*4882a593Smuzhiyun
692*4882a593Smuzhiyun client->extra_mon_dispatch = NULL;
693*4882a593Smuzhiyun client->supported_features = CEPH_FEATURES_SUPPORTED_DEFAULT;
694*4882a593Smuzhiyun client->required_features = CEPH_FEATURES_REQUIRED_DEFAULT;
695*4882a593Smuzhiyun
696*4882a593Smuzhiyun if (!ceph_test_opt(client, NOMSGAUTH))
697*4882a593Smuzhiyun client->required_features |= CEPH_FEATURE_MSG_AUTH;
698*4882a593Smuzhiyun
699*4882a593Smuzhiyun /* msgr */
700*4882a593Smuzhiyun if (ceph_test_opt(client, MYIP))
701*4882a593Smuzhiyun myaddr = &client->options->my_addr;
702*4882a593Smuzhiyun
703*4882a593Smuzhiyun ceph_messenger_init(&client->msgr, myaddr);
704*4882a593Smuzhiyun
705*4882a593Smuzhiyun /* subsystems */
706*4882a593Smuzhiyun err = ceph_monc_init(&client->monc, client);
707*4882a593Smuzhiyun if (err < 0)
708*4882a593Smuzhiyun goto fail;
709*4882a593Smuzhiyun err = ceph_osdc_init(&client->osdc, client);
710*4882a593Smuzhiyun if (err < 0)
711*4882a593Smuzhiyun goto fail_monc;
712*4882a593Smuzhiyun
713*4882a593Smuzhiyun return client;
714*4882a593Smuzhiyun
715*4882a593Smuzhiyun fail_monc:
716*4882a593Smuzhiyun ceph_monc_stop(&client->monc);
717*4882a593Smuzhiyun fail:
718*4882a593Smuzhiyun ceph_messenger_fini(&client->msgr);
719*4882a593Smuzhiyun kfree(client);
720*4882a593Smuzhiyun return ERR_PTR(err);
721*4882a593Smuzhiyun }
722*4882a593Smuzhiyun EXPORT_SYMBOL(ceph_create_client);
723*4882a593Smuzhiyun
ceph_destroy_client(struct ceph_client * client)724*4882a593Smuzhiyun void ceph_destroy_client(struct ceph_client *client)
725*4882a593Smuzhiyun {
726*4882a593Smuzhiyun dout("destroy_client %p\n", client);
727*4882a593Smuzhiyun
728*4882a593Smuzhiyun atomic_set(&client->msgr.stopping, 1);
729*4882a593Smuzhiyun
730*4882a593Smuzhiyun /* unmount */
731*4882a593Smuzhiyun ceph_osdc_stop(&client->osdc);
732*4882a593Smuzhiyun ceph_monc_stop(&client->monc);
733*4882a593Smuzhiyun ceph_messenger_fini(&client->msgr);
734*4882a593Smuzhiyun
735*4882a593Smuzhiyun ceph_debugfs_client_cleanup(client);
736*4882a593Smuzhiyun
737*4882a593Smuzhiyun ceph_destroy_options(client->options);
738*4882a593Smuzhiyun
739*4882a593Smuzhiyun kfree(client);
740*4882a593Smuzhiyun dout("destroy_client %p done\n", client);
741*4882a593Smuzhiyun }
742*4882a593Smuzhiyun EXPORT_SYMBOL(ceph_destroy_client);
743*4882a593Smuzhiyun
ceph_reset_client_addr(struct ceph_client * client)744*4882a593Smuzhiyun void ceph_reset_client_addr(struct ceph_client *client)
745*4882a593Smuzhiyun {
746*4882a593Smuzhiyun ceph_messenger_reset_nonce(&client->msgr);
747*4882a593Smuzhiyun ceph_monc_reopen_session(&client->monc);
748*4882a593Smuzhiyun ceph_osdc_reopen_osds(&client->osdc);
749*4882a593Smuzhiyun }
750*4882a593Smuzhiyun EXPORT_SYMBOL(ceph_reset_client_addr);
751*4882a593Smuzhiyun
752*4882a593Smuzhiyun /*
753*4882a593Smuzhiyun * true if we have the mon map (and have thus joined the cluster)
754*4882a593Smuzhiyun */
have_mon_and_osd_map(struct ceph_client * client)755*4882a593Smuzhiyun static bool have_mon_and_osd_map(struct ceph_client *client)
756*4882a593Smuzhiyun {
757*4882a593Smuzhiyun return client->monc.monmap && client->monc.monmap->epoch &&
758*4882a593Smuzhiyun client->osdc.osdmap && client->osdc.osdmap->epoch;
759*4882a593Smuzhiyun }
760*4882a593Smuzhiyun
761*4882a593Smuzhiyun /*
762*4882a593Smuzhiyun * mount: join the ceph cluster, and open root directory.
763*4882a593Smuzhiyun */
__ceph_open_session(struct ceph_client * client,unsigned long started)764*4882a593Smuzhiyun int __ceph_open_session(struct ceph_client *client, unsigned long started)
765*4882a593Smuzhiyun {
766*4882a593Smuzhiyun unsigned long timeout = client->options->mount_timeout;
767*4882a593Smuzhiyun long err;
768*4882a593Smuzhiyun
769*4882a593Smuzhiyun /* open session, and wait for mon and osd maps */
770*4882a593Smuzhiyun err = ceph_monc_open_session(&client->monc);
771*4882a593Smuzhiyun if (err < 0)
772*4882a593Smuzhiyun return err;
773*4882a593Smuzhiyun
774*4882a593Smuzhiyun while (!have_mon_and_osd_map(client)) {
775*4882a593Smuzhiyun if (timeout && time_after_eq(jiffies, started + timeout))
776*4882a593Smuzhiyun return -ETIMEDOUT;
777*4882a593Smuzhiyun
778*4882a593Smuzhiyun /* wait */
779*4882a593Smuzhiyun dout("mount waiting for mon_map\n");
780*4882a593Smuzhiyun err = wait_event_interruptible_timeout(client->auth_wq,
781*4882a593Smuzhiyun have_mon_and_osd_map(client) || (client->auth_err < 0),
782*4882a593Smuzhiyun ceph_timeout_jiffies(timeout));
783*4882a593Smuzhiyun if (err < 0)
784*4882a593Smuzhiyun return err;
785*4882a593Smuzhiyun if (client->auth_err < 0)
786*4882a593Smuzhiyun return client->auth_err;
787*4882a593Smuzhiyun }
788*4882a593Smuzhiyun
789*4882a593Smuzhiyun pr_info("client%llu fsid %pU\n", ceph_client_gid(client),
790*4882a593Smuzhiyun &client->fsid);
791*4882a593Smuzhiyun ceph_debugfs_client_init(client);
792*4882a593Smuzhiyun
793*4882a593Smuzhiyun return 0;
794*4882a593Smuzhiyun }
795*4882a593Smuzhiyun EXPORT_SYMBOL(__ceph_open_session);
796*4882a593Smuzhiyun
ceph_open_session(struct ceph_client * client)797*4882a593Smuzhiyun int ceph_open_session(struct ceph_client *client)
798*4882a593Smuzhiyun {
799*4882a593Smuzhiyun int ret;
800*4882a593Smuzhiyun unsigned long started = jiffies; /* note the start time */
801*4882a593Smuzhiyun
802*4882a593Smuzhiyun dout("open_session start\n");
803*4882a593Smuzhiyun mutex_lock(&client->mount_mutex);
804*4882a593Smuzhiyun
805*4882a593Smuzhiyun ret = __ceph_open_session(client, started);
806*4882a593Smuzhiyun
807*4882a593Smuzhiyun mutex_unlock(&client->mount_mutex);
808*4882a593Smuzhiyun return ret;
809*4882a593Smuzhiyun }
810*4882a593Smuzhiyun EXPORT_SYMBOL(ceph_open_session);
811*4882a593Smuzhiyun
ceph_wait_for_latest_osdmap(struct ceph_client * client,unsigned long timeout)812*4882a593Smuzhiyun int ceph_wait_for_latest_osdmap(struct ceph_client *client,
813*4882a593Smuzhiyun unsigned long timeout)
814*4882a593Smuzhiyun {
815*4882a593Smuzhiyun u64 newest_epoch;
816*4882a593Smuzhiyun int ret;
817*4882a593Smuzhiyun
818*4882a593Smuzhiyun ret = ceph_monc_get_version(&client->monc, "osdmap", &newest_epoch);
819*4882a593Smuzhiyun if (ret)
820*4882a593Smuzhiyun return ret;
821*4882a593Smuzhiyun
822*4882a593Smuzhiyun if (client->osdc.osdmap->epoch >= newest_epoch)
823*4882a593Smuzhiyun return 0;
824*4882a593Smuzhiyun
825*4882a593Smuzhiyun ceph_osdc_maybe_request_map(&client->osdc);
826*4882a593Smuzhiyun return ceph_monc_wait_osdmap(&client->monc, newest_epoch, timeout);
827*4882a593Smuzhiyun }
828*4882a593Smuzhiyun EXPORT_SYMBOL(ceph_wait_for_latest_osdmap);
829*4882a593Smuzhiyun
init_ceph_lib(void)830*4882a593Smuzhiyun static int __init init_ceph_lib(void)
831*4882a593Smuzhiyun {
832*4882a593Smuzhiyun int ret = 0;
833*4882a593Smuzhiyun
834*4882a593Smuzhiyun ceph_debugfs_init();
835*4882a593Smuzhiyun
836*4882a593Smuzhiyun ret = ceph_crypto_init();
837*4882a593Smuzhiyun if (ret < 0)
838*4882a593Smuzhiyun goto out_debugfs;
839*4882a593Smuzhiyun
840*4882a593Smuzhiyun ret = ceph_msgr_init();
841*4882a593Smuzhiyun if (ret < 0)
842*4882a593Smuzhiyun goto out_crypto;
843*4882a593Smuzhiyun
844*4882a593Smuzhiyun ret = ceph_osdc_setup();
845*4882a593Smuzhiyun if (ret < 0)
846*4882a593Smuzhiyun goto out_msgr;
847*4882a593Smuzhiyun
848*4882a593Smuzhiyun pr_info("loaded (mon/osd proto %d/%d)\n",
849*4882a593Smuzhiyun CEPH_MONC_PROTOCOL, CEPH_OSDC_PROTOCOL);
850*4882a593Smuzhiyun
851*4882a593Smuzhiyun return 0;
852*4882a593Smuzhiyun
853*4882a593Smuzhiyun out_msgr:
854*4882a593Smuzhiyun ceph_msgr_exit();
855*4882a593Smuzhiyun out_crypto:
856*4882a593Smuzhiyun ceph_crypto_shutdown();
857*4882a593Smuzhiyun out_debugfs:
858*4882a593Smuzhiyun ceph_debugfs_cleanup();
859*4882a593Smuzhiyun return ret;
860*4882a593Smuzhiyun }
861*4882a593Smuzhiyun
exit_ceph_lib(void)862*4882a593Smuzhiyun static void __exit exit_ceph_lib(void)
863*4882a593Smuzhiyun {
864*4882a593Smuzhiyun dout("exit_ceph_lib\n");
865*4882a593Smuzhiyun WARN_ON(!ceph_strings_empty());
866*4882a593Smuzhiyun
867*4882a593Smuzhiyun ceph_osdc_cleanup();
868*4882a593Smuzhiyun ceph_msgr_exit();
869*4882a593Smuzhiyun ceph_crypto_shutdown();
870*4882a593Smuzhiyun ceph_debugfs_cleanup();
871*4882a593Smuzhiyun }
872*4882a593Smuzhiyun
873*4882a593Smuzhiyun module_init(init_ceph_lib);
874*4882a593Smuzhiyun module_exit(exit_ceph_lib);
875*4882a593Smuzhiyun
876*4882a593Smuzhiyun MODULE_AUTHOR("Sage Weil <sage@newdream.net>");
877*4882a593Smuzhiyun MODULE_AUTHOR("Yehuda Sadeh <yehuda@hq.newdream.net>");
878*4882a593Smuzhiyun MODULE_AUTHOR("Patience Warnick <patience@newdream.net>");
879*4882a593Smuzhiyun MODULE_DESCRIPTION("Ceph core library");
880*4882a593Smuzhiyun MODULE_LICENSE("GPL");
881