Blame view

net/ceph/ceph_common.c 18.9 KB
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
1
2
3
4
5
6
7
  
  #include <linux/ceph/ceph_debug.h>
  #include <linux/backing-dev.h>
  #include <linux/ctype.h>
  #include <linux/fs.h>
  #include <linux/inet.h>
  #include <linux/in6.h>
e2c3d29b4   Tommi Virtanen   libceph: Get secr...
8
  #include <linux/key.h>
4b2a58abd   Tommi Virtanen   libceph: Create a...
9
  #include <keys/ceph-type.h>
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
10
11
  #include <linux/module.h>
  #include <linux/mount.h>
757856d2b   Ilya Dryomov   libceph: enable c...
12
  #include <linux/nsproxy.h>
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
13
14
15
16
17
18
  #include <linux/parser.h>
  #include <linux/sched.h>
  #include <linux/seq_file.h>
  #include <linux/slab.h>
  #include <linux/statfs.h>
  #include <linux/string.h>
eeb0bed55   Ilya Dryomov   libceph: add ceph...
19
  #include <linux/vmalloc.h>
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
20

1fe60e51a   Sage Weil   libceph: move fea...
21
  #include <linux/ceph/ceph_features.h>
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
22
23
24
25
26
  #include <linux/ceph/libceph.h>
  #include <linux/ceph/debugfs.h>
  #include <linux/ceph/decode.h>
  #include <linux/ceph/mon_client.h>
  #include <linux/ceph/auth.h>
8323c3aa7   Tommi Virtanen   ceph: Move secret...
27
  #include "crypto.h"
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
28

72fe25e34   Alex Elder   libceph: add a co...
29
30
31
32
33
34
35
36
37
38
39
40
41
  /*
   * Module compatibility interface.  For now it doesn't do anything,
   * but its existence signals a certain level of functionality.
   *
   * The data buffer is used to pass information both to and from
   * libceph.  The return value indicates whether libceph determines
   * it is compatible with the caller (from another kernel module),
   * given the provided data.
   *
   * The data pointer can be null.
   */
  bool libceph_compatible(void *data)
  {
1e32d34cf   Alex Elder   rbd: don't take e...
42
  	return true;
72fe25e34   Alex Elder   libceph: add a co...
43
44
  }
  EXPORT_SYMBOL(libceph_compatible);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
45

d6a3408a7   Ilya Dryomov   libceph: supporte...
46
47
48
49
50
51
52
53
54
55
  static int param_get_supported_features(char *buffer,
  					const struct kernel_param *kp)
  {
  	return sprintf(buffer, "0x%llx", CEPH_FEATURES_SUPPORTED_DEFAULT);
  }
  static const struct kernel_param_ops param_ops_supported_features = {
  	.get = param_get_supported_features,
  };
  module_param_cb(supported_features, &param_ops_supported_features, NULL,
  		S_IRUGO);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
56
57
58
59
60
61
62
63
64
65
66
67
68
  const char *ceph_msg_type_name(int type)
  {
  	switch (type) {
  	case CEPH_MSG_SHUTDOWN: return "shutdown";
  	case CEPH_MSG_PING: return "ping";
  	case CEPH_MSG_AUTH: return "auth";
  	case CEPH_MSG_AUTH_REPLY: return "auth_reply";
  	case CEPH_MSG_MON_MAP: return "mon_map";
  	case CEPH_MSG_MON_GET_MAP: return "mon_get_map";
  	case CEPH_MSG_MON_SUBSCRIBE: return "mon_subscribe";
  	case CEPH_MSG_MON_SUBSCRIBE_ACK: return "mon_subscribe_ack";
  	case CEPH_MSG_STATFS: return "statfs";
  	case CEPH_MSG_STATFS_REPLY: return "statfs_reply";
513a8243d   Ilya Dryomov   libceph: mon_get_...
69
70
  	case CEPH_MSG_MON_GET_VERSION: return "mon_get_version";
  	case CEPH_MSG_MON_GET_VERSION_REPLY: return "mon_get_version_reply";
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
71
72
73
74
75
76
77
78
79
80
81
82
83
  	case CEPH_MSG_MDS_MAP: return "mds_map";
  	case CEPH_MSG_CLIENT_SESSION: return "client_session";
  	case CEPH_MSG_CLIENT_RECONNECT: return "client_reconnect";
  	case CEPH_MSG_CLIENT_REQUEST: return "client_request";
  	case CEPH_MSG_CLIENT_REQUEST_FORWARD: return "client_request_forward";
  	case CEPH_MSG_CLIENT_REPLY: return "client_reply";
  	case CEPH_MSG_CLIENT_CAPS: return "client_caps";
  	case CEPH_MSG_CLIENT_CAPRELEASE: return "client_cap_release";
  	case CEPH_MSG_CLIENT_SNAP: return "client_snap";
  	case CEPH_MSG_CLIENT_LEASE: return "client_lease";
  	case CEPH_MSG_OSD_MAP: return "osd_map";
  	case CEPH_MSG_OSD_OP: return "osd_op";
  	case CEPH_MSG_OSD_OPREPLY: return "osd_opreply";
a40c4f10e   Yehuda Sadeh   libceph: add ling...
84
  	case CEPH_MSG_WATCH_NOTIFY: return "watch_notify";
a02a946df   Ilya Dryomov   libceph: respect ...
85
  	case CEPH_MSG_OSD_BACKOFF: return "osd_backoff";
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
  	default: return "unknown";
  	}
  }
  EXPORT_SYMBOL(ceph_msg_type_name);
  
  /*
   * Initially learn our fsid, or verify an fsid matches.
   */
  int ceph_check_fsid(struct ceph_client *client, struct ceph_fsid *fsid)
  {
  	if (client->have_fsid) {
  		if (ceph_fsid_compare(&client->fsid, fsid)) {
  			pr_err("bad fsid, had %pU got %pU",
  			       &client->fsid, fsid);
  			return -1;
  		}
  	} else {
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
103
  		memcpy(&client->fsid, fsid, sizeof(*fsid));
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
  	}
  	return 0;
  }
  EXPORT_SYMBOL(ceph_check_fsid);
  
  static int strcmp_null(const char *s1, const char *s2)
  {
  	if (!s1 && !s2)
  		return 0;
  	if (s1 && !s2)
  		return -1;
  	if (!s1 && s2)
  		return 1;
  	return strcmp(s1, s2);
  }
  
  int ceph_compare_options(struct ceph_options *new_opt,
  			 struct ceph_client *client)
  {
  	struct ceph_options *opt1 = new_opt;
  	struct ceph_options *opt2 = client->options;
  	int ofs = offsetof(struct ceph_options, mon_addr);
  	int i;
  	int ret;
757856d2b   Ilya Dryomov   libceph: enable c...
128
129
130
131
132
133
  	/*
  	 * Don't bother comparing options if network namespaces don't
  	 * match.
  	 */
  	if (!net_eq(current->nsproxy->net_ns, read_pnet(&client->msgr.net)))
  		return -1;
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
134
135
136
137
138
139
140
  	ret = memcmp(opt1, opt2, ofs);
  	if (ret)
  		return ret;
  
  	ret = strcmp_null(opt1->name, opt2->name);
  	if (ret)
  		return ret;
8323c3aa7   Tommi Virtanen   ceph: Move secret...
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
  	if (opt1->key && !opt2->key)
  		return -1;
  	if (!opt1->key && opt2->key)
  		return 1;
  	if (opt1->key && opt2->key) {
  		if (opt1->key->type != opt2->key->type)
  			return -1;
  		if (opt1->key->created.tv_sec != opt2->key->created.tv_sec)
  			return -1;
  		if (opt1->key->created.tv_nsec != opt2->key->created.tv_nsec)
  			return -1;
  		if (opt1->key->len != opt2->key->len)
  			return -1;
  		if (opt1->key->key && !opt2->key->key)
  			return -1;
  		if (!opt1->key->key && opt2->key->key)
  			return 1;
  		if (opt1->key->key && opt2->key->key) {
  			ret = memcmp(opt1->key->key, opt2->key->key, opt1->key->len);
  			if (ret)
  				return ret;
  		}
  	}
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
164
165
166
167
168
169
170
171
172
173
  
  	/* any matching mon ip implies a match */
  	for (i = 0; i < opt1->num_mon; i++) {
  		if (ceph_monmap_contains(client->monc.monmap,
  				 &opt1->mon_addr[i]))
  			return 0;
  	}
  	return -1;
  }
  EXPORT_SYMBOL(ceph_compare_options);
eeb0bed55   Ilya Dryomov   libceph: add ceph...
174
175
176
177
178
179
180
  void *ceph_kvmalloc(size_t size, gfp_t flags)
  {
  	if (size <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) {
  		void *ptr = kmalloc(size, flags | __GFP_NOWARN);
  		if (ptr)
  			return ptr;
  	}
19809c2da   Michal Hocko   mm, vmalloc: use ...
181
  	return __vmalloc(size, flags, PAGE_KERNEL);
eeb0bed55   Ilya Dryomov   libceph: add ceph...
182
  }
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
  
  static int parse_fsid(const char *str, struct ceph_fsid *fsid)
  {
  	int i = 0;
  	char tmp[3];
  	int err = -EINVAL;
  	int d;
  
  	dout("parse_fsid '%s'
  ", str);
  	tmp[2] = 0;
  	while (*str && i < 16) {
  		if (ispunct(*str)) {
  			str++;
  			continue;
  		}
  		if (!isxdigit(str[0]) || !isxdigit(str[1]))
  			break;
  		tmp[0] = str[0];
  		tmp[1] = str[1];
  		if (sscanf(tmp, "%x", &d) < 1)
  			break;
  		fsid->fsid[i] = d & 0xff;
  		i++;
  		str += 2;
  	}
  
  	if (i == 16)
  		err = 0;
  	dout("parse_fsid ret %d got fsid %pU", err, fsid);
  	return err;
  }
  
  /*
   * ceph options
   */
  enum {
  	Opt_osdtimeout,
  	Opt_osdkeepalivetimeout,
  	Opt_mount_timeout,
  	Opt_osd_idle_ttl,
7cc5e38f2   Ilya Dryomov   libceph: osd_requ...
224
  	Opt_osd_request_timeout,
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
225
226
227
228
229
  	Opt_last_int,
  	/* int args above */
  	Opt_fsid,
  	Opt_name,
  	Opt_secret,
e2c3d29b4   Tommi Virtanen   libceph: Get secr...
230
  	Opt_key,
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
231
232
233
  	Opt_ip,
  	Opt_last_string,
  	/* string args above */
cffaba15c   Alex Elder   ceph: ensure Bool...
234
  	Opt_share,
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
235
  	Opt_noshare,
cffaba15c   Alex Elder   ceph: ensure Bool...
236
  	Opt_crc,
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
237
  	Opt_nocrc,
a3fc98005   Yan, Zheng   libceph: require ...
238
239
  	Opt_cephx_require_signatures,
  	Opt_nocephx_require_signatures,
a51983e4d   Ilya Dryomov   libceph: add noce...
240
241
  	Opt_cephx_sign_messages,
  	Opt_nocephx_sign_messages,
ba988f87f   Chaitanya Huilgol   libceph: tcp_node...
242
243
  	Opt_tcp_nodelay,
  	Opt_notcp_nodelay,
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
244
245
246
247
248
249
250
  };
  
  static match_table_t opt_tokens = {
  	{Opt_osdtimeout, "osdtimeout=%d"},
  	{Opt_osdkeepalivetimeout, "osdkeepalive=%d"},
  	{Opt_mount_timeout, "mount_timeout=%d"},
  	{Opt_osd_idle_ttl, "osd_idle_ttl=%d"},
7cc5e38f2   Ilya Dryomov   libceph: osd_requ...
251
  	{Opt_osd_request_timeout, "osd_request_timeout=%d"},
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
252
253
254
255
  	/* int args above */
  	{Opt_fsid, "fsid=%s"},
  	{Opt_name, "name=%s"},
  	{Opt_secret, "secret=%s"},
e2c3d29b4   Tommi Virtanen   libceph: Get secr...
256
  	{Opt_key, "key=%s"},
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
257
258
  	{Opt_ip, "ip=%s"},
  	/* string args above */
cffaba15c   Alex Elder   ceph: ensure Bool...
259
  	{Opt_share, "share"},
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
260
  	{Opt_noshare, "noshare"},
cffaba15c   Alex Elder   ceph: ensure Bool...
261
  	{Opt_crc, "crc"},
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
262
  	{Opt_nocrc, "nocrc"},
a3fc98005   Yan, Zheng   libceph: require ...
263
264
  	{Opt_cephx_require_signatures, "cephx_require_signatures"},
  	{Opt_nocephx_require_signatures, "nocephx_require_signatures"},
a51983e4d   Ilya Dryomov   libceph: add noce...
265
266
  	{Opt_cephx_sign_messages, "cephx_sign_messages"},
  	{Opt_nocephx_sign_messages, "nocephx_sign_messages"},
ba988f87f   Chaitanya Huilgol   libceph: tcp_node...
267
268
  	{Opt_tcp_nodelay, "tcp_nodelay"},
  	{Opt_notcp_nodelay, "notcp_nodelay"},
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
269
270
271
272
273
274
275
276
  	{-1, NULL}
  };
  
  void ceph_destroy_options(struct ceph_options *opt)
  {
  	dout("destroy_options %p
  ", opt);
  	kfree(opt->name);
8323c3aa7   Tommi Virtanen   ceph: Move secret...
277
278
279
280
  	if (opt->key) {
  		ceph_crypto_key_destroy(opt->key);
  		kfree(opt->key);
  	}
1cad78932   Noah Watkins   libceph: fix pars...
281
  	kfree(opt->mon_addr);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
282
283
284
  	kfree(opt);
  }
  EXPORT_SYMBOL(ceph_destroy_options);
e2c3d29b4   Tommi Virtanen   libceph: Get secr...
285
286
287
288
289
  /* get secret from key store */
  static int get_secret(struct ceph_crypto_key *dst, const char *name) {
  	struct key *ukey;
  	int key_err;
  	int err = 0;
4b2a58abd   Tommi Virtanen   libceph: Create a...
290
  	struct ceph_crypto_key *ckey;
e2c3d29b4   Tommi Virtanen   libceph: Get secr...
291

4b2a58abd   Tommi Virtanen   libceph: Create a...
292
  	ukey = request_key(&key_type_ceph, name, NULL);
e2c3d29b4   Tommi Virtanen   libceph: Get secr...
293
294
295
296
297
298
  	if (!ukey || IS_ERR(ukey)) {
  		/* request_key errors don't map nicely to mount(2)
  		   errors; don't even try, but still printk */
  		key_err = PTR_ERR(ukey);
  		switch (key_err) {
  		case -ENOKEY:
b9a678994   Joe Perches   libceph: Convert ...
299
300
301
  			pr_warn("ceph: Mount failed due to key not found: %s
  ",
  				name);
e2c3d29b4   Tommi Virtanen   libceph: Get secr...
302
303
  			break;
  		case -EKEYEXPIRED:
b9a678994   Joe Perches   libceph: Convert ...
304
305
306
  			pr_warn("ceph: Mount failed due to expired key: %s
  ",
  				name);
e2c3d29b4   Tommi Virtanen   libceph: Get secr...
307
308
  			break;
  		case -EKEYREVOKED:
b9a678994   Joe Perches   libceph: Convert ...
309
310
311
  			pr_warn("ceph: Mount failed due to revoked key: %s
  ",
  				name);
e2c3d29b4   Tommi Virtanen   libceph: Get secr...
312
313
  			break;
  		default:
b9a678994   Joe Perches   libceph: Convert ...
314
315
316
  			pr_warn("ceph: Mount failed due to unknown key error %d: %s
  ",
  				key_err, name);
e2c3d29b4   Tommi Virtanen   libceph: Get secr...
317
318
319
320
  		}
  		err = -EPERM;
  		goto out;
  	}
146aa8b14   David Howells   KEYS: Merge the t...
321
  	ckey = ukey->payload.data[0];
4b2a58abd   Tommi Virtanen   libceph: Create a...
322
  	err = ceph_crypto_key_clone(dst, ckey);
e2c3d29b4   Tommi Virtanen   libceph: Get secr...
323
324
325
326
327
328
329
330
331
  	if (err)
  		goto out_key;
  	/* pass through, err is 0 */
  
  out_key:
  	key_put(ukey);
  out:
  	return err;
  }
ee57741c5   Alex Elder   rbd: make ceph_pa...
332
333
334
335
336
  struct ceph_options *
  ceph_parse_options(char *options, const char *dev_name,
  			const char *dev_name_end,
  			int (*parse_extra_token)(char *c, void *private),
  			void *private)
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
337
338
339
340
341
342
343
344
  {
  	struct ceph_options *opt;
  	const char *c;
  	int err = -ENOMEM;
  	substring_t argstr[MAX_OPT_ARGS];
  
  	opt = kzalloc(sizeof(*opt), GFP_KERNEL);
  	if (!opt)
ee57741c5   Alex Elder   rbd: make ceph_pa...
345
  		return ERR_PTR(-ENOMEM);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
346
347
348
349
350
351
352
353
354
355
356
  	opt->mon_addr = kcalloc(CEPH_MAX_MON, sizeof(*opt->mon_addr),
  				GFP_KERNEL);
  	if (!opt->mon_addr)
  		goto out;
  
  	dout("parse_options %p options '%s' dev_name '%s'
  ", opt, options,
  	     dev_name);
  
  	/* start with defaults */
  	opt->flags = CEPH_OPT_DEFAULT;
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
357
  	opt->osd_keepalive_timeout = CEPH_OSD_KEEPALIVE_DEFAULT;
a319bf56a   Ilya Dryomov   libceph: store ti...
358
359
  	opt->mount_timeout = CEPH_MOUNT_TIMEOUT_DEFAULT;
  	opt->osd_idle_ttl = CEPH_OSD_IDLE_TTL_DEFAULT;
7cc5e38f2   Ilya Dryomov   libceph: osd_requ...
360
  	opt->osd_request_timeout = CEPH_OSD_REQUEST_TIMEOUT_DEFAULT;
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
  
  	/* get mon ip(s) */
  	/* ip1[:port1][,ip2[:port2]...] */
  	err = ceph_parse_ips(dev_name, dev_name_end, opt->mon_addr,
  			     CEPH_MAX_MON, &opt->num_mon);
  	if (err < 0)
  		goto out;
  
  	/* parse mount options */
  	while ((c = strsep(&options, ",")) != NULL) {
  		int token, intval, ret;
  		if (!*c)
  			continue;
  		err = -EINVAL;
  		token = match_token((char *)c, opt_tokens, argstr);
010e3b48f   Yehuda Sadeh   ceph: don't crash...
376
  		if (token < 0 && parse_extra_token) {
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
  			/* extra? */
  			err = parse_extra_token((char *)c, private);
  			if (err < 0) {
  				pr_err("bad option at '%s'
  ", c);
  				goto out;
  			}
  			continue;
  		}
  		if (token < Opt_last_int) {
  			ret = match_int(&argstr[0], &intval);
  			if (ret < 0) {
  				pr_err("bad mount option arg (not int) "
  				       "at '%s'
  ", c);
  				continue;
  			}
  			dout("got int token %d val %d
  ", token, intval);
  		} else if (token > Opt_last_int && token < Opt_last_string) {
  			dout("got string token %d val %s
  ", token,
  			     argstr[0].from);
  		} else {
  			dout("got token %d
  ", token);
  		}
  		switch (token) {
  		case Opt_ip:
  			err = ceph_parse_ips(argstr[0].from,
  					     argstr[0].to,
  					     &opt->my_addr,
  					     1, NULL);
  			if (err < 0)
  				goto out;
  			opt->flags |= CEPH_OPT_MYIP;
  			break;
  
  		case Opt_fsid:
  			err = parse_fsid(argstr[0].from, &opt->fsid);
  			if (err == 0)
  				opt->flags |= CEPH_OPT_FSID;
  			break;
  		case Opt_name:
e080e814d   Chengguang Xu   libceph, ceph: av...
421
  			kfree(opt->name);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
422
423
424
425
426
  			opt->name = kstrndup(argstr[0].from,
  					      argstr[0].to-argstr[0].from,
  					      GFP_KERNEL);
  			break;
  		case Opt_secret:
e080e814d   Chengguang Xu   libceph, ceph: av...
427
428
  			ceph_crypto_key_destroy(opt->key);
  			kfree(opt->key);
8323c3aa7   Tommi Virtanen   ceph: Move secret...
429
430
431
432
433
434
435
436
  		        opt->key = kzalloc(sizeof(*opt->key), GFP_KERNEL);
  			if (!opt->key) {
  				err = -ENOMEM;
  				goto out;
  			}
  			err = ceph_crypto_key_unarmor(opt->key, argstr[0].from);
  			if (err < 0)
  				goto out;
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
437
  			break;
e2c3d29b4   Tommi Virtanen   libceph: Get secr...
438
  		case Opt_key:
e080e814d   Chengguang Xu   libceph, ceph: av...
439
440
  			ceph_crypto_key_destroy(opt->key);
  			kfree(opt->key);
e2c3d29b4   Tommi Virtanen   libceph: Get secr...
441
442
443
444
445
446
447
448
449
  		        opt->key = kzalloc(sizeof(*opt->key), GFP_KERNEL);
  			if (!opt->key) {
  				err = -ENOMEM;
  				goto out;
  			}
  			err = get_secret(opt->key, argstr[0].from);
  			if (err < 0)
  				goto out;
  			break;
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
450
451
452
  
  			/* misc */
  		case Opt_osdtimeout:
b9a678994   Joe Perches   libceph: Convert ...
453
454
  			pr_warn("ignoring deprecated osdtimeout option
  ");
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
455
456
  			break;
  		case Opt_osdkeepalivetimeout:
a319bf56a   Ilya Dryomov   libceph: store ti...
457
458
459
460
461
462
463
464
465
  			/* 0 isn't well defined right now, reject it */
  			if (intval < 1 || intval > INT_MAX / 1000) {
  				pr_err("osdkeepalive out of range
  ");
  				err = -EINVAL;
  				goto out;
  			}
  			opt->osd_keepalive_timeout =
  					msecs_to_jiffies(intval * 1000);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
466
467
  			break;
  		case Opt_osd_idle_ttl:
a319bf56a   Ilya Dryomov   libceph: store ti...
468
469
470
471
472
473
474
475
  			/* 0 isn't well defined right now, reject it */
  			if (intval < 1 || intval > INT_MAX / 1000) {
  				pr_err("osd_idle_ttl out of range
  ");
  				err = -EINVAL;
  				goto out;
  			}
  			opt->osd_idle_ttl = msecs_to_jiffies(intval * 1000);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
476
477
  			break;
  		case Opt_mount_timeout:
a319bf56a   Ilya Dryomov   libceph: store ti...
478
479
480
481
482
483
484
485
  			/* 0 is "wait forever" (i.e. infinite timeout) */
  			if (intval < 0 || intval > INT_MAX / 1000) {
  				pr_err("mount_timeout out of range
  ");
  				err = -EINVAL;
  				goto out;
  			}
  			opt->mount_timeout = msecs_to_jiffies(intval * 1000);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
486
  			break;
7cc5e38f2   Ilya Dryomov   libceph: osd_requ...
487
488
489
490
491
492
493
494
495
496
  		case Opt_osd_request_timeout:
  			/* 0 is "wait forever" (i.e. infinite timeout) */
  			if (intval < 0 || intval > INT_MAX / 1000) {
  				pr_err("osd_request_timeout out of range
  ");
  				err = -EINVAL;
  				goto out;
  			}
  			opt->osd_request_timeout = msecs_to_jiffies(intval * 1000);
  			break;
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
497

cffaba15c   Alex Elder   ceph: ensure Bool...
498
499
500
  		case Opt_share:
  			opt->flags &= ~CEPH_OPT_NOSHARE;
  			break;
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
501
502
503
  		case Opt_noshare:
  			opt->flags |= CEPH_OPT_NOSHARE;
  			break;
cffaba15c   Alex Elder   ceph: ensure Bool...
504
505
506
  		case Opt_crc:
  			opt->flags &= ~CEPH_OPT_NOCRC;
  			break;
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
507
508
509
  		case Opt_nocrc:
  			opt->flags |= CEPH_OPT_NOCRC;
  			break;
ba988f87f   Chaitanya Huilgol   libceph: tcp_node...
510

a3fc98005   Yan, Zheng   libceph: require ...
511
512
513
514
515
516
  		case Opt_cephx_require_signatures:
  			opt->flags &= ~CEPH_OPT_NOMSGAUTH;
  			break;
  		case Opt_nocephx_require_signatures:
  			opt->flags |= CEPH_OPT_NOMSGAUTH;
  			break;
a51983e4d   Ilya Dryomov   libceph: add noce...
517
518
519
520
521
522
  		case Opt_cephx_sign_messages:
  			opt->flags &= ~CEPH_OPT_NOMSGSIGN;
  			break;
  		case Opt_nocephx_sign_messages:
  			opt->flags |= CEPH_OPT_NOMSGSIGN;
  			break;
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
523

ba988f87f   Chaitanya Huilgol   libceph: tcp_node...
524
525
526
527
528
529
  		case Opt_tcp_nodelay:
  			opt->flags |= CEPH_OPT_TCP_NODELAY;
  			break;
  		case Opt_notcp_nodelay:
  			opt->flags &= ~CEPH_OPT_TCP_NODELAY;
  			break;
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
530
531
532
533
534
535
  		default:
  			BUG_ON(token);
  		}
  	}
  
  	/* success */
ee57741c5   Alex Elder   rbd: make ceph_pa...
536
  	return opt;
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
537
538
539
  
  out:
  	ceph_destroy_options(opt);
ee57741c5   Alex Elder   rbd: make ceph_pa...
540
  	return ERR_PTR(err);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
541
542
  }
  EXPORT_SYMBOL(ceph_parse_options);
ff40f9ae9   Ilya Dryomov   libceph, ceph: sp...
543
544
545
546
  int ceph_print_client_options(struct seq_file *m, struct ceph_client *client)
  {
  	struct ceph_options *opt = client->options;
  	size_t pos = m->count;
a068acf2e   Kees Cook   fs: create and us...
547
548
549
550
551
552
  	if (opt->name) {
  		seq_puts(m, "name=");
  		seq_escape(m, opt->name, ", \t
  \\");
  		seq_putc(m, ',');
  	}
ff40f9ae9   Ilya Dryomov   libceph, ceph: sp...
553
554
555
556
557
558
559
560
561
562
563
  	if (opt->key)
  		seq_puts(m, "secret=<hidden>,");
  
  	if (opt->flags & CEPH_OPT_FSID)
  		seq_printf(m, "fsid=%pU,", &opt->fsid);
  	if (opt->flags & CEPH_OPT_NOSHARE)
  		seq_puts(m, "noshare,");
  	if (opt->flags & CEPH_OPT_NOCRC)
  		seq_puts(m, "nocrc,");
  	if (opt->flags & CEPH_OPT_NOMSGAUTH)
  		seq_puts(m, "nocephx_require_signatures,");
a51983e4d   Ilya Dryomov   libceph: add noce...
564
565
  	if (opt->flags & CEPH_OPT_NOMSGSIGN)
  		seq_puts(m, "nocephx_sign_messages,");
ff40f9ae9   Ilya Dryomov   libceph, ceph: sp...
566
567
568
569
  	if ((opt->flags & CEPH_OPT_TCP_NODELAY) == 0)
  		seq_puts(m, "notcp_nodelay,");
  
  	if (opt->mount_timeout != CEPH_MOUNT_TIMEOUT_DEFAULT)
a319bf56a   Ilya Dryomov   libceph: store ti...
570
571
  		seq_printf(m, "mount_timeout=%d,",
  			   jiffies_to_msecs(opt->mount_timeout) / 1000);
ff40f9ae9   Ilya Dryomov   libceph, ceph: sp...
572
  	if (opt->osd_idle_ttl != CEPH_OSD_IDLE_TTL_DEFAULT)
a319bf56a   Ilya Dryomov   libceph: store ti...
573
574
  		seq_printf(m, "osd_idle_ttl=%d,",
  			   jiffies_to_msecs(opt->osd_idle_ttl) / 1000);
ff40f9ae9   Ilya Dryomov   libceph, ceph: sp...
575
576
  	if (opt->osd_keepalive_timeout != CEPH_OSD_KEEPALIVE_DEFAULT)
  		seq_printf(m, "osdkeepalivetimeout=%d,",
a319bf56a   Ilya Dryomov   libceph: store ti...
577
  		    jiffies_to_msecs(opt->osd_keepalive_timeout) / 1000);
7cc5e38f2   Ilya Dryomov   libceph: osd_requ...
578
579
580
  	if (opt->osd_request_timeout != CEPH_OSD_REQUEST_TIMEOUT_DEFAULT)
  		seq_printf(m, "osd_request_timeout=%d,",
  			   jiffies_to_msecs(opt->osd_request_timeout) / 1000);
ff40f9ae9   Ilya Dryomov   libceph, ceph: sp...
581
582
583
584
585
586
587
588
  
  	/* drop redundant comma */
  	if (m->count != pos)
  		m->count--;
  
  	return 0;
  }
  EXPORT_SYMBOL(ceph_print_client_options);
005a07bf0   Ilya Dryomov   rbd: add 'client_...
589
590
591
592
593
  struct ceph_entity_addr *ceph_client_addr(struct ceph_client *client)
  {
  	return &client->msgr.inst.addr;
  }
  EXPORT_SYMBOL(ceph_client_addr);
033268a5f   Ilya Dryomov   libceph: rename c...
594
  u64 ceph_client_gid(struct ceph_client *client)
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
595
596
597
  {
  	return client->monc.auth->global_id;
  }
033268a5f   Ilya Dryomov   libceph: rename c...
598
  EXPORT_SYMBOL(ceph_client_gid);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
599
600
601
602
  
  /*
   * create a fresh client instance
   */
74da4a0f5   Ilya Dryomov   libceph, ceph: al...
603
  struct ceph_client *ceph_create_client(struct ceph_options *opt, void *private)
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
604
605
  {
  	struct ceph_client *client;
6ab00d465   Sage Weil   libceph: create m...
606
  	struct ceph_entity_addr *myaddr = NULL;
ae5b806a3   Jason A. Donenfeld   ceph: ensure RNG ...
607
608
609
610
611
  	int err;
  
  	err = wait_for_random_bytes();
  	if (err < 0)
  		return ERR_PTR(err);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
612
613
614
615
616
617
618
619
620
621
622
623
624
  
  	client = kzalloc(sizeof(*client), GFP_KERNEL);
  	if (client == NULL)
  		return ERR_PTR(-ENOMEM);
  
  	client->private = private;
  	client->options = opt;
  
  	mutex_init(&client->mount_mutex);
  	init_waitqueue_head(&client->auth_wq);
  	client->auth_err = 0;
  
  	client->extra_mon_dispatch = NULL;
74da4a0f5   Ilya Dryomov   libceph, ceph: al...
625
626
627
628
629
  	client->supported_features = CEPH_FEATURES_SUPPORTED_DEFAULT;
  	client->required_features = CEPH_FEATURES_REQUIRED_DEFAULT;
  
  	if (!ceph_test_opt(client, NOMSGAUTH))
  		client->required_features |= CEPH_FEATURE_MSG_AUTH;
6ab00d465   Sage Weil   libceph: create m...
630
631
632
633
  
  	/* msgr */
  	if (ceph_test_opt(client, MYIP))
  		myaddr = &client->options->my_addr;
ba988f87f   Chaitanya Huilgol   libceph: tcp_node...
634

859bff51d   Ilya Dryomov   libceph: stop dup...
635
  	ceph_messenger_init(&client->msgr, myaddr);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
636
637
638
639
  
  	/* subsystems */
  	err = ceph_monc_init(&client->monc, client);
  	if (err < 0)
15d9882c3   Alex Elder   libceph: embed ce...
640
  		goto fail;
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
641
642
643
644
645
646
647
648
649
  	err = ceph_osdc_init(&client->osdc, client);
  	if (err < 0)
  		goto fail_monc;
  
  	return client;
  
  fail_monc:
  	ceph_monc_stop(&client->monc);
  fail:
757856d2b   Ilya Dryomov   libceph: enable c...
650
  	ceph_messenger_fini(&client->msgr);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
651
652
653
654
655
656
657
658
659
  	kfree(client);
  	return ERR_PTR(err);
  }
  EXPORT_SYMBOL(ceph_create_client);
  
  void ceph_destroy_client(struct ceph_client *client)
  {
  	dout("destroy_client %p
  ", client);
a2a325841   Guanjun He   libceph: prevent ...
660
  	atomic_set(&client->msgr.stopping, 1);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
661
662
  	/* unmount */
  	ceph_osdc_stop(&client->osdc);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
663
  	ceph_monc_stop(&client->monc);
757856d2b   Ilya Dryomov   libceph: enable c...
664
  	ceph_messenger_fini(&client->msgr);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
665
666
  
  	ceph_debugfs_client_cleanup(client);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
667
668
669
670
671
672
673
674
675
676
677
  	ceph_destroy_options(client->options);
  
  	kfree(client);
  	dout("destroy_client %p done
  ", client);
  }
  EXPORT_SYMBOL(ceph_destroy_client);
  
  /*
   * true if we have the mon map (and have thus joined the cluster)
   */
3b33f692c   Zhang Zhuoyu   ceph: make logica...
678
  static bool have_mon_and_osd_map(struct ceph_client *client)
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
679
680
681
682
683
684
685
686
687
688
  {
  	return client->monc.monmap && client->monc.monmap->epoch &&
  	       client->osdc.osdmap && client->osdc.osdmap->epoch;
  }
  
  /*
   * mount: join the ceph cluster, and open root directory.
   */
  int __ceph_open_session(struct ceph_client *client, unsigned long started)
  {
a319bf56a   Ilya Dryomov   libceph: store ti...
689
  	unsigned long timeout = client->options->mount_timeout;
216639dd5   Ilya Dryomov   libceph: a couple...
690
  	long err;
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
691

3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
692
693
694
695
696
697
  	/* open session, and wait for mon and osd maps */
  	err = ceph_monc_open_session(&client->monc);
  	if (err < 0)
  		return err;
  
  	while (!have_mon_and_osd_map(client)) {
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
698
  		if (timeout && time_after_eq(jiffies, started + timeout))
216639dd5   Ilya Dryomov   libceph: a couple...
699
  			return -ETIMEDOUT;
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
700
701
702
703
704
705
  
  		/* wait */
  		dout("mount waiting for mon_map
  ");
  		err = wait_event_interruptible_timeout(client->auth_wq,
  			have_mon_and_osd_map(client) || (client->auth_err < 0),
a319bf56a   Ilya Dryomov   libceph: store ti...
706
  			ceph_timeout_jiffies(timeout));
216639dd5   Ilya Dryomov   libceph: a couple...
707
  		if (err < 0)
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
708
709
710
711
  			return err;
  		if (client->auth_err < 0)
  			return client->auth_err;
  	}
033268a5f   Ilya Dryomov   libceph: rename c...
712
713
714
  	pr_info("client%llu fsid %pU
  ", ceph_client_gid(client),
  		&client->fsid);
02ac956c4   Ilya Dryomov   libceph: move deb...
715
  	ceph_debugfs_client_init(client);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
  	return 0;
  }
  EXPORT_SYMBOL(__ceph_open_session);
  
  
  int ceph_open_session(struct ceph_client *client)
  {
  	int ret;
  	unsigned long started = jiffies;  /* note the start time */
  
  	dout("open_session start
  ");
  	mutex_lock(&client->mount_mutex);
  
  	ret = __ceph_open_session(client, started);
  
  	mutex_unlock(&client->mount_mutex);
  	return ret;
  }
  EXPORT_SYMBOL(ceph_open_session);
  
  
  static int __init init_ceph_lib(void)
  {
  	int ret = 0;
  
  	ret = ceph_debugfs_init();
  	if (ret < 0)
  		goto out;
4b2a58abd   Tommi Virtanen   libceph: Create a...
745
  	ret = ceph_crypto_init();
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
746
747
  	if (ret < 0)
  		goto out_debugfs;
4b2a58abd   Tommi Virtanen   libceph: Create a...
748
749
750
  	ret = ceph_msgr_init();
  	if (ret < 0)
  		goto out_crypto;
5522ae0b6   Alex Elder   libceph: use slab...
751
752
753
  	ret = ceph_osdc_setup();
  	if (ret < 0)
  		goto out_msgr;
4f6a7e5ee   Sage Weil   ceph: update supp...
754
755
756
  	pr_info("loaded (mon/osd proto %d/%d)
  ",
  		CEPH_MONC_PROTOCOL, CEPH_OSDC_PROTOCOL);
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
757
758
  
  	return 0;
5522ae0b6   Alex Elder   libceph: use slab...
759
760
  out_msgr:
  	ceph_msgr_exit();
4b2a58abd   Tommi Virtanen   libceph: Create a...
761
762
  out_crypto:
  	ceph_crypto_shutdown();
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
763
764
765
766
767
768
769
770
771
772
  out_debugfs:
  	ceph_debugfs_cleanup();
  out:
  	return ret;
  }
  
  static void __exit exit_ceph_lib(void)
  {
  	dout("exit_ceph_lib
  ");
51e927379   Yan, Zheng   libceph: introduc...
773
  	WARN_ON(!ceph_strings_empty());
5522ae0b6   Alex Elder   libceph: use slab...
774
  	ceph_osdc_cleanup();
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
775
  	ceph_msgr_exit();
4b2a58abd   Tommi Virtanen   libceph: Create a...
776
  	ceph_crypto_shutdown();
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
777
778
779
780
781
782
783
784
785
  	ceph_debugfs_cleanup();
  }
  
  module_init(init_ceph_lib);
  module_exit(exit_ceph_lib);
  
  MODULE_AUTHOR("Sage Weil <sage@newdream.net>");
  MODULE_AUTHOR("Yehuda Sadeh <yehuda@hq.newdream.net>");
  MODULE_AUTHOR("Patience Warnick <patience@newdream.net>");
6c13a6bb5   Hong Zhiguo   libceph: fix wron...
786
  MODULE_DESCRIPTION("Ceph core library");
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
787
  MODULE_LICENSE("GPL");