aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorSage Weil <sage@newdream.net>2009-11-18 19:19:57 -0500
committerSage Weil <sage@newdream.net>2009-11-18 19:19:57 -0500
commit4e7a5dcd1bbab6560fbc8ada29a840e7a20ed7bc (patch)
treea77e9b4563022340361ca673ef2e1beebb538e2f /fs
parent5f44f142601bf94c448e2d463f0f18fd159da164 (diff)
ceph: negotiate authentication protocol; implement AUTH_NONE protocol
When we open a monitor session, we send an initial AUTH message listing the auth protocols we support, our entity name, and (possibly) a previously assigned global_id. The monitor chooses a protocol and responds with an initial message. Initially implement AUTH_NONE, a dummy protocol that provides no security, but works within the new framework. It generates 'authorizers' that are used when connecting to (mds, osd) services that simply state our entity name and global_id. This is a wire protocol change. Signed-off-by: Sage Weil <sage@newdream.net>
Diffstat (limited to 'fs')
-rw-r--r--fs/ceph/Makefile1
-rw-r--r--fs/ceph/auth.c220
-rw-r--r--fs/ceph/auth.h77
-rw-r--r--fs/ceph/auth_none.c120
-rw-r--r--fs/ceph/auth_none.h28
-rw-r--r--fs/ceph/ceph_fs.h14
-rw-r--r--fs/ceph/ceph_strings.c13
-rw-r--r--fs/ceph/decode.h6
-rw-r--r--fs/ceph/mds_client.c69
-rw-r--r--fs/ceph/mds_client.h4
-rw-r--r--fs/ceph/messenger.c54
-rw-r--r--fs/ceph/messenger.h10
-rw-r--r--fs/ceph/mon_client.c210
-rw-r--r--fs/ceph/mon_client.h14
-rw-r--r--fs/ceph/msgr.h21
-rw-r--r--fs/ceph/osd_client.c63
-rw-r--r--fs/ceph/osd_client.h4
-rw-r--r--fs/ceph/rados.h2
-rw-r--r--fs/ceph/super.c32
-rw-r--r--fs/ceph/super.h2
20 files changed, 888 insertions, 76 deletions
diff --git a/fs/ceph/Makefile b/fs/ceph/Makefile
index bdd3e6fc1609..827629c85768 100644
--- a/fs/ceph/Makefile
+++ b/fs/ceph/Makefile
@@ -13,6 +13,7 @@ ceph-objs := super.o inode.o dir.o file.o addr.o ioctl.o \
13 mon_client.o \ 13 mon_client.o \
14 osd_client.o osdmap.o crush/crush.o crush/mapper.o crush/hash.o \ 14 osd_client.o osdmap.o crush/crush.o crush/mapper.o crush/hash.o \
15 debugfs.o \ 15 debugfs.o \
16 auth.o auth_none.o \
16 ceph_fs.o ceph_strings.o ceph_hash.o ceph_frag.o 17 ceph_fs.o ceph_strings.o ceph_hash.o ceph_frag.o
17 18
18else 19else
diff --git a/fs/ceph/auth.c b/fs/ceph/auth.c
new file mode 100644
index 000000000000..c4d1eee827a3
--- /dev/null
+++ b/fs/ceph/auth.c
@@ -0,0 +1,220 @@
1#include "ceph_debug.h"
2
3#include <linux/module.h>
4#include <linux/err.h>
5
6#include "types.h"
7#include "auth_none.h"
8#include "decode.h"
9#include "super.h"
10
11#include "messenger.h"
12
13/*
14 * get protocol handler
15 */
16static u32 supported_protocols[] = {
17 CEPH_AUTH_NONE
18};
19
20int ceph_auth_init_protocol(struct ceph_auth_client *ac, int protocol)
21{
22 switch (protocol) {
23 case CEPH_AUTH_NONE:
24 return ceph_auth_none_init(ac);
25 default:
26 return -ENOENT;
27 }
28}
29
30/*
31 * setup, teardown.
32 */
33struct ceph_auth_client *ceph_auth_init(const char *name, const char *secret)
34{
35 struct ceph_auth_client *ac;
36 int ret;
37
38 dout("auth_init name '%s' secret '%s'\n", name, secret);
39
40 ret = -ENOMEM;
41 ac = kzalloc(sizeof(*ac), GFP_NOFS);
42 if (!ac)
43 goto out;
44
45 ac->negotiating = true;
46 if (name)
47 ac->name = name;
48 else
49 ac->name = CEPH_AUTH_NAME_DEFAULT;
50 dout("auth_init name %s secret %s\n", ac->name, secret);
51 ac->secret = secret;
52 return ac;
53
54out:
55 return ERR_PTR(ret);
56}
57
58void ceph_auth_destroy(struct ceph_auth_client *ac)
59{
60 dout("auth_destroy %p\n", ac);
61 if (ac->ops)
62 ac->ops->destroy(ac);
63 kfree(ac);
64}
65
66/*
67 * Reset occurs when reconnecting to the monitor.
68 */
69void ceph_auth_reset(struct ceph_auth_client *ac)
70{
71 dout("auth_reset %p\n", ac);
72 if (ac->ops && !ac->negotiating)
73 ac->ops->reset(ac);
74 ac->negotiating = true;
75}
76
77int ceph_entity_name_encode(const char *name, void **p, void *end)
78{
79 int len = strlen(name);
80
81 if (*p + 2*sizeof(u32) + len > end)
82 return -ERANGE;
83 ceph_encode_32(p, CEPH_ENTITY_TYPE_CLIENT);
84 ceph_encode_32(p, len);
85 ceph_encode_copy(p, name, len);
86 return 0;
87}
88
89/*
90 * Initiate protocol negotiation with monitor. Include entity name
91 * and list supported protocols.
92 */
93int ceph_auth_build_hello(struct ceph_auth_client *ac, void *buf, size_t len)
94{
95 struct ceph_mon_request_header *monhdr = buf;
96 void *p = monhdr + 1, *end = buf + len, *lenp;
97 int i, num;
98 int ret;
99
100 dout("auth_build_hello\n");
101 monhdr->have_version = 0;
102 monhdr->session_mon = cpu_to_le16(-1);
103 monhdr->session_mon_tid = 0;
104
105 ceph_encode_32(&p, 0); /* no protocol, yet */
106
107 lenp = p;
108 p += sizeof(u32);
109
110 num = ARRAY_SIZE(supported_protocols);
111 ceph_encode_32(&p, num);
112 for (i = 0; i < num; i++)
113 ceph_encode_32(&p, supported_protocols[i]);
114
115 ret = ceph_entity_name_encode(ac->name, &p, end);
116 if (ret < 0)
117 return ret;
118 ceph_decode_need(&p, end, sizeof(u64), bad);
119 ceph_encode_64(&p, ac->global_id);
120
121 ceph_encode_32(&lenp, p - lenp - sizeof(u32));
122 return p - buf;
123
124bad:
125 return -ERANGE;
126}
127
128/*
129 * Handle auth message from monitor.
130 */
131int ceph_handle_auth_reply(struct ceph_auth_client *ac,
132 void *buf, size_t len,
133 void *reply_buf, size_t reply_len)
134{
135 void *p = buf;
136 void *end = buf + len;
137 int protocol;
138 s32 result;
139 u64 global_id;
140 void *payload, *payload_end;
141 int payload_len;
142 char *result_msg;
143 int result_msg_len;
144 int ret = -EINVAL;
145
146 dout("handle_auth_reply %p %p\n", p, end);
147 ceph_decode_need(&p, end, sizeof(u32) * 3 + sizeof(u64), bad);
148 protocol = ceph_decode_32(&p);
149 result = ceph_decode_32(&p);
150 global_id = ceph_decode_64(&p);
151 payload_len = ceph_decode_32(&p);
152 payload = p;
153 p += payload_len;
154 ceph_decode_need(&p, end, sizeof(u32), bad);
155 result_msg_len = ceph_decode_32(&p);
156 result_msg = p;
157 p += result_msg_len;
158 if (p != end)
159 goto bad;
160
161 dout(" result %d '%.*s' gid %llu len %d\n", result, result_msg_len,
162 result_msg, global_id, payload_len);
163
164 payload_end = payload + payload_len;
165
166 if (global_id && ac->global_id != global_id) {
167 dout(" set global_id %lld -> %lld\n", ac->global_id, global_id);
168 ac->global_id = global_id;
169 }
170
171 if (ac->negotiating) {
172 /* set up (new) protocol handler? */
173 if (ac->protocol && ac->protocol != protocol) {
174 ac->ops->destroy(ac);
175 ac->protocol = 0;
176 ac->ops = NULL;
177 }
178 if (ac->protocol != protocol) {
179 ret = ceph_auth_init_protocol(ac, protocol);
180 if (ret) {
181 pr_err("error %d on auth protocol %d init\n",
182 ret, protocol);
183 goto out;
184 }
185 }
186 }
187
188 ret = ac->ops->handle_reply(ac, result, payload, payload_end);
189 if (ret == -EAGAIN) {
190 struct ceph_mon_request_header *monhdr = reply_buf;
191 void *p = reply_buf + 1;
192 void *end = reply_buf + reply_len;
193
194 monhdr->have_version = 0;
195 monhdr->session_mon = cpu_to_le16(-1);
196 monhdr->session_mon_tid = 0;
197
198 ceph_encode_32(&p, ac->protocol);
199
200 ret = ac->ops->build_request(ac, p + sizeof(u32), end);
201 if (ret < 0) {
202 pr_err("error %d building request\n", ret);
203 goto out;
204 }
205 dout(" built request %d bytes\n", ret);
206 ceph_encode_32(&p, ret);
207 return p + ret - reply_buf;
208 } else if (ret) {
209 pr_err("authentication error %d\n", ret);
210 return ret;
211 }
212 return 0;
213
214bad:
215 pr_err("failed to decode auth msg\n");
216out:
217 return ret;
218}
219
220
diff --git a/fs/ceph/auth.h b/fs/ceph/auth.h
new file mode 100644
index 000000000000..4d8cdf6bb3b6
--- /dev/null
+++ b/fs/ceph/auth.h
@@ -0,0 +1,77 @@
1#ifndef _FS_CEPH_AUTH_H
2#define _FS_CEPH_AUTH_H
3
4#include "types.h"
5#include "buffer.h"
6
7/*
8 * Abstract interface for communicating with the authenticate module.
9 * There is some handshake that takes place between us and the monitor
10 * to acquire the necessary keys. These are used to generate an
11 * 'authorizer' that we use when connecting to a service (mds, osd).
12 */
13
14struct ceph_auth_client;
15struct ceph_authorizer;
16
17struct ceph_auth_client_ops {
18 /*
19 * true if we are authenticated and can connect to
20 * services.
21 */
22 int (*is_authenticated)(struct ceph_auth_client *ac);
23
24 /*
25 * build requests and process replies during monitor
26 * handshake. if handle_reply returns -EAGAIN, we build
27 * another request.
28 */
29 int (*build_request)(struct ceph_auth_client *ac, void *buf, void *end);
30 int (*handle_reply)(struct ceph_auth_client *ac, int result,
31 void *buf, void *end);
32
33 /*
34 * Create authorizer for connecting to a service, and verify
35 * the response to authenticate the service.
36 */
37 int (*create_authorizer)(struct ceph_auth_client *ac, int peer_type,
38 struct ceph_authorizer **a,
39 void **buf, size_t *len,
40 void **reply_buf, size_t *reply_len);
41 int (*verify_authorizer_reply)(struct ceph_auth_client *ac,
42 struct ceph_authorizer *a, size_t len);
43 void (*destroy_authorizer)(struct ceph_auth_client *ac,
44 struct ceph_authorizer *a);
45
46 /* reset when we (re)connect to a monitor */
47 void (*reset)(struct ceph_auth_client *ac);
48
49 void (*destroy)(struct ceph_auth_client *ac);
50};
51
52struct ceph_auth_client {
53 u32 protocol; /* CEPH_AUTH_* */
54 void *private; /* for use by protocol implementation */
55 const struct ceph_auth_client_ops *ops; /* null iff protocol==0 */
56
57 bool negotiating; /* true if negotiating protocol */
58 const char *name; /* entity name */
59 u64 global_id; /* our unique id in system */
60 const char *secret; /* our secret key */
61 unsigned want_keys; /* which services we want */
62};
63
64extern struct ceph_auth_client *ceph_auth_init(const char *name,
65 const char *secret);
66extern void ceph_auth_destroy(struct ceph_auth_client *ac);
67
68extern void ceph_auth_reset(struct ceph_auth_client *ac);
69
70extern int ceph_auth_build_hello(struct ceph_auth_client *ac,
71 void *buf, size_t len);
72extern int ceph_handle_auth_reply(struct ceph_auth_client *ac,
73 void *buf, size_t len,
74 void *reply_buf, size_t reply_len);
75extern int ceph_entity_name_encode(const char *name, void **p, void *end);
76
77#endif
diff --git a/fs/ceph/auth_none.c b/fs/ceph/auth_none.c
new file mode 100644
index 000000000000..631017eb7117
--- /dev/null
+++ b/fs/ceph/auth_none.c
@@ -0,0 +1,120 @@
1
2#include "ceph_debug.h"
3
4#include <linux/err.h>
5#include <linux/module.h>
6#include <linux/random.h>
7
8#include "auth_none.h"
9#include "auth.h"
10#include "decode.h"
11
12static void reset(struct ceph_auth_client *ac)
13{
14 struct ceph_auth_none_info *xi = ac->private;
15
16 xi->starting = true;
17 xi->built_authorizer = false;
18}
19
20static void destroy(struct ceph_auth_client *ac)
21{
22 kfree(ac->private);
23 ac->private = NULL;
24}
25
26static int is_authenticated(struct ceph_auth_client *ac)
27{
28 struct ceph_auth_none_info *xi = ac->private;
29
30 return !xi->starting;
31}
32
33/*
34 * the generic auth code decode the global_id, and we carry no actual
35 * authenticate state, so nothing happens here.
36 */
37static int handle_reply(struct ceph_auth_client *ac, int result,
38 void *buf, void *end)
39{
40 struct ceph_auth_none_info *xi = ac->private;
41
42 xi->starting = false;
43 return result;
44}
45
46/*
47 * build an 'authorizer' with our entity_name and global_id. we can
48 * reuse a single static copy since it is identical for all services
49 * we connect to.
50 */
51static int ceph_auth_none_create_authorizer(
52 struct ceph_auth_client *ac, int peer_type,
53 struct ceph_authorizer **a,
54 void **buf, size_t *len,
55 void **reply_buf, size_t *reply_len)
56{
57 struct ceph_auth_none_info *ai = ac->private;
58 struct ceph_none_authorizer *au = &ai->au;
59 void *p, *end;
60 int ret;
61
62 if (!ai->built_authorizer) {
63 p = au->buf;
64 end = p + sizeof(au->buf);
65 ret = ceph_entity_name_encode(ac->name, &p, end - 8);
66 if (ret < 0)
67 goto bad;
68 ceph_decode_need(&p, end, sizeof(u64), bad2);
69 ceph_encode_64(&p, ac->global_id);
70 au->buf_len = p - (void *)au->buf;
71 ai->built_authorizer = true;
72 dout("built authorizer len %d\n", au->buf_len);
73 }
74
75 *a = (struct ceph_authorizer *)au;
76 *buf = au->buf;
77 *len = au->buf_len;
78 *reply_buf = au->reply_buf;
79 *reply_len = sizeof(au->reply_buf);
80 return 0;
81
82bad2:
83 ret = -ERANGE;
84bad:
85 return ret;
86}
87
88static void ceph_auth_none_destroy_authorizer(struct ceph_auth_client *ac,
89 struct ceph_authorizer *a)
90{
91 /* nothing to do */
92}
93
94static const struct ceph_auth_client_ops ceph_auth_none_ops = {
95 .reset = reset,
96 .destroy = destroy,
97 .is_authenticated = is_authenticated,
98 .handle_reply = handle_reply,
99 .create_authorizer = ceph_auth_none_create_authorizer,
100 .destroy_authorizer = ceph_auth_none_destroy_authorizer,
101};
102
103int ceph_auth_none_init(struct ceph_auth_client *ac)
104{
105 struct ceph_auth_none_info *xi;
106
107 dout("ceph_auth_none_init %p\n", ac);
108 xi = kzalloc(sizeof(*xi), GFP_NOFS);
109 if (!xi)
110 return -ENOMEM;
111
112 xi->starting = true;
113 xi->built_authorizer = false;
114
115 ac->protocol = CEPH_AUTH_NONE;
116 ac->private = xi;
117 ac->ops = &ceph_auth_none_ops;
118 return 0;
119}
120
diff --git a/fs/ceph/auth_none.h b/fs/ceph/auth_none.h
new file mode 100644
index 000000000000..56c05533a31c
--- /dev/null
+++ b/fs/ceph/auth_none.h
@@ -0,0 +1,28 @@
1#ifndef _FS_CEPH_AUTH_NONE_H
2#define _FS_CEPH_AUTH_NONE_H
3
4#include "auth.h"
5
6/*
7 * null security mode.
8 *
9 * we use a single static authorizer that simply encodes our entity name
10 * and global id.
11 */
12
13struct ceph_none_authorizer {
14 char buf[128];
15 int buf_len;
16 char reply_buf[0];
17};
18
19struct ceph_auth_none_info {
20 bool starting;
21 bool built_authorizer;
22 struct ceph_none_authorizer au; /* we only need one; it's static */
23};
24
25extern int ceph_auth_none_init(struct ceph_auth_client *ac);
26
27#endif
28
diff --git a/fs/ceph/ceph_fs.h b/fs/ceph/ceph_fs.h
index 36becb024788..1e96a9a87d8d 100644
--- a/fs/ceph/ceph_fs.h
+++ b/fs/ceph/ceph_fs.h
@@ -75,6 +75,16 @@ struct ceph_file_layout {
75int ceph_file_layout_is_valid(const struct ceph_file_layout *layout); 75int ceph_file_layout_is_valid(const struct ceph_file_layout *layout);
76 76
77 77
78/* crypto algorithms */
79#define CEPH_CRYPTO_NONE 0x0
80#define CEPH_CRYPTO_AES 0x1
81
82/* security/authentication protocols */
83#define CEPH_AUTH_UNKNOWN 0x0
84#define CEPH_AUTH_NONE 0x1
85#define CEPH_AUTH_CEPHX 0x2
86
87
78/********************************************* 88/*********************************************
79 * message layer 89 * message layer
80 */ 90 */
@@ -90,12 +100,12 @@ int ceph_file_layout_is_valid(const struct ceph_file_layout *layout);
90/* client <-> monitor */ 100/* client <-> monitor */
91#define CEPH_MSG_MON_MAP 4 101#define CEPH_MSG_MON_MAP 4
92#define CEPH_MSG_MON_GET_MAP 5 102#define CEPH_MSG_MON_GET_MAP 5
93#define CEPH_MSG_CLIENT_MOUNT 10
94#define CEPH_MSG_CLIENT_MOUNT_ACK 11
95#define CEPH_MSG_STATFS 13 103#define CEPH_MSG_STATFS 13
96#define CEPH_MSG_STATFS_REPLY 14 104#define CEPH_MSG_STATFS_REPLY 14
97#define CEPH_MSG_MON_SUBSCRIBE 15 105#define CEPH_MSG_MON_SUBSCRIBE 15
98#define CEPH_MSG_MON_SUBSCRIBE_ACK 16 106#define CEPH_MSG_MON_SUBSCRIBE_ACK 16
107#define CEPH_MSG_AUTH 17
108#define CEPH_MSG_AUTH_REPLY 18
99 109
100/* client <-> mds */ 110/* client <-> mds */
101#define CEPH_MSG_MDS_MAP 21 111#define CEPH_MSG_MDS_MAP 21
diff --git a/fs/ceph/ceph_strings.c b/fs/ceph/ceph_strings.c
index 90d19d9d8d8f..8e4be6a80c62 100644
--- a/fs/ceph/ceph_strings.c
+++ b/fs/ceph/ceph_strings.c
@@ -3,6 +3,19 @@
3 */ 3 */
4#include "types.h" 4#include "types.h"
5 5
6const char *ceph_entity_type_name(int type)
7{
8 switch (type) {
9 case CEPH_ENTITY_TYPE_MDS: return "mds";
10 case CEPH_ENTITY_TYPE_OSD: return "osd";
11 case CEPH_ENTITY_TYPE_MON: return "mon";
12 case CEPH_ENTITY_TYPE_CLIENT: return "client";
13 case CEPH_ENTITY_TYPE_ADMIN: return "admin";
14 case CEPH_ENTITY_TYPE_AUTH: return "auth";
15 default: return "unknown";
16 }
17}
18
6const char *ceph_osd_op_name(int op) 19const char *ceph_osd_op_name(int op)
7{ 20{
8 switch (op) { 21 switch (op) {
diff --git a/fs/ceph/decode.h b/fs/ceph/decode.h
index a382aecc55bb..10de84896244 100644
--- a/fs/ceph/decode.h
+++ b/fs/ceph/decode.h
@@ -98,6 +98,7 @@ static inline void ceph_encode_addr(struct ceph_entity_addr *a)
98static inline void ceph_decode_addr(struct ceph_entity_addr *a) 98static inline void ceph_decode_addr(struct ceph_entity_addr *a)
99{ 99{
100 a->in_addr.ss_family = ntohs(a->in_addr.ss_family); 100 a->in_addr.ss_family = ntohs(a->in_addr.ss_family);
101 WARN_ON(a->in_addr.ss_family == 512);
101} 102}
102 103
103/* 104/*
@@ -123,6 +124,11 @@ static inline void ceph_encode_8(void **p, u8 v)
123 *(u8 *)*p = v; 124 *(u8 *)*p = v;
124 (*p)++; 125 (*p)++;
125} 126}
127static inline void ceph_encode_copy(void **p, const void *s, int len)
128{
129 memcpy(*p, s, len);
130 *p += len;
131}
126 132
127/* 133/*
128 * filepath, string encoders 134 * filepath, string encoders
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index 69feeb1c9819..8a285158aecc 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -8,6 +8,7 @@
8#include "super.h" 8#include "super.h"
9#include "messenger.h" 9#include "messenger.h"
10#include "decode.h" 10#include "decode.h"
11#include "auth.h"
11 12
12/* 13/*
13 * A cluster of MDS (metadata server) daemons is responsible for 14 * A cluster of MDS (metadata server) daemons is responsible for
@@ -274,8 +275,12 @@ void ceph_put_mds_session(struct ceph_mds_session *s)
274{ 275{
275 dout("mdsc put_session %p %d -> %d\n", s, 276 dout("mdsc put_session %p %d -> %d\n", s,
276 atomic_read(&s->s_ref), atomic_read(&s->s_ref)-1); 277 atomic_read(&s->s_ref), atomic_read(&s->s_ref)-1);
277 if (atomic_dec_and_test(&s->s_ref)) 278 if (atomic_dec_and_test(&s->s_ref)) {
279 if (s->s_authorizer)
280 s->s_mdsc->client->monc.auth->ops->destroy_authorizer(
281 s->s_mdsc->client->monc.auth, s->s_authorizer);
278 kfree(s); 282 kfree(s);
283 }
279} 284}
280 285
281/* 286/*
@@ -2777,9 +2782,15 @@ void ceph_mdsc_handle_map(struct ceph_mds_client *mdsc, struct ceph_msg *msg)
2777 2782
2778 ceph_decode_need(&p, end, sizeof(fsid)+2*sizeof(u32), bad); 2783 ceph_decode_need(&p, end, sizeof(fsid)+2*sizeof(u32), bad);
2779 ceph_decode_copy(&p, &fsid, sizeof(fsid)); 2784 ceph_decode_copy(&p, &fsid, sizeof(fsid));
2780 if (ceph_fsid_compare(&fsid, &mdsc->client->monc.monmap->fsid)) { 2785 if (mdsc->client->monc.have_fsid) {
2781 pr_err("got mdsmap with wrong fsid\n"); 2786 if (ceph_fsid_compare(&fsid,
2782 return; 2787 &mdsc->client->monc.monmap->fsid)) {
2788 pr_err("got mdsmap with wrong fsid\n");
2789 return;
2790 }
2791 } else {
2792 ceph_fsid_set(&mdsc->client->monc.monmap->fsid, &fsid);
2793 mdsc->client->monc.have_fsid = true;
2783 } 2794 }
2784 epoch = ceph_decode_32(&p); 2795 epoch = ceph_decode_32(&p);
2785 maplen = ceph_decode_32(&p); 2796 maplen = ceph_decode_32(&p);
@@ -2895,10 +2906,60 @@ static void dispatch(struct ceph_connection *con, struct ceph_msg *msg)
2895 ceph_msg_put(msg); 2906 ceph_msg_put(msg);
2896} 2907}
2897 2908
2909/*
2910 * authentication
2911 */
2912static int get_authorizer(struct ceph_connection *con,
2913 void **buf, int *len, int *proto,
2914 void **reply_buf, int *reply_len, int force_new)
2915{
2916 struct ceph_mds_session *s = con->private;
2917 struct ceph_mds_client *mdsc = s->s_mdsc;
2918 struct ceph_auth_client *ac = mdsc->client->monc.auth;
2919 int ret = 0;
2920
2921 if (force_new && s->s_authorizer) {
2922 ac->ops->destroy_authorizer(ac, s->s_authorizer);
2923 s->s_authorizer = NULL;
2924 }
2925 if (s->s_authorizer == NULL) {
2926 if (ac->ops->create_authorizer) {
2927 ret = ac->ops->create_authorizer(
2928 ac, CEPH_ENTITY_TYPE_MDS,
2929 &s->s_authorizer,
2930 &s->s_authorizer_buf,
2931 &s->s_authorizer_buf_len,
2932 &s->s_authorizer_reply_buf,
2933 &s->s_authorizer_reply_buf_len);
2934 if (ret)
2935 return ret;
2936 }
2937 }
2938
2939 *proto = ac->protocol;
2940 *buf = s->s_authorizer_buf;
2941 *len = s->s_authorizer_buf_len;
2942 *reply_buf = s->s_authorizer_reply_buf;
2943 *reply_len = s->s_authorizer_reply_buf_len;
2944 return 0;
2945}
2946
2947
2948static int verify_authorizer_reply(struct ceph_connection *con, int len)
2949{
2950 struct ceph_mds_session *s = con->private;
2951 struct ceph_mds_client *mdsc = s->s_mdsc;
2952 struct ceph_auth_client *ac = mdsc->client->monc.auth;
2953
2954 return ac->ops->verify_authorizer_reply(ac, s->s_authorizer, len);
2955}
2956
2898const static struct ceph_connection_operations mds_con_ops = { 2957const static struct ceph_connection_operations mds_con_ops = {
2899 .get = con_get, 2958 .get = con_get,
2900 .put = con_put, 2959 .put = con_put,
2901 .dispatch = dispatch, 2960 .dispatch = dispatch,
2961 .get_authorizer = get_authorizer,
2962 .verify_authorizer_reply = verify_authorizer_reply,
2902 .peer_reset = peer_reset, 2963 .peer_reset = peer_reset,
2903 .alloc_msg = ceph_alloc_msg, 2964 .alloc_msg = ceph_alloc_msg,
2904 .alloc_middle = ceph_alloc_middle, 2965 .alloc_middle = ceph_alloc_middle,
diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h
index 7c439488cfab..9faa1b2f79a7 100644
--- a/fs/ceph/mds_client.h
+++ b/fs/ceph/mds_client.h
@@ -100,6 +100,10 @@ struct ceph_mds_session {
100 100
101 struct ceph_connection s_con; 101 struct ceph_connection s_con;
102 102
103 struct ceph_authorizer *s_authorizer;
104 void *s_authorizer_buf, *s_authorizer_reply_buf;
105 size_t s_authorizer_buf_len, s_authorizer_reply_buf_len;
106
103 /* protected by s_cap_lock */ 107 /* protected by s_cap_lock */
104 spinlock_t s_cap_lock; 108 spinlock_t s_cap_lock;
105 u32 s_cap_gen; /* inc each time we get mds stale msg */ 109 u32 s_cap_gen; /* inc each time we get mds stale msg */
diff --git a/fs/ceph/messenger.c b/fs/ceph/messenger.c
index d8a6a56a1571..0b1674854b25 100644
--- a/fs/ceph/messenger.c
+++ b/fs/ceph/messenger.c
@@ -550,6 +550,27 @@ static void prepare_write_keepalive(struct ceph_connection *con)
550 * Connection negotiation. 550 * Connection negotiation.
551 */ 551 */
552 552
553static void prepare_connect_authorizer(struct ceph_connection *con)
554{
555 void *auth_buf;
556 int auth_len = 0;
557 int auth_protocol = 0;
558
559 if (con->ops->get_authorizer)
560 con->ops->get_authorizer(con, &auth_buf, &auth_len,
561 &auth_protocol, &con->auth_reply_buf,
562 &con->auth_reply_buf_len,
563 con->auth_retry);
564
565 con->out_connect.authorizer_protocol = cpu_to_le32(auth_protocol);
566 con->out_connect.authorizer_len = cpu_to_le32(auth_len);
567
568 con->out_kvec[con->out_kvec_left].iov_base = auth_buf;
569 con->out_kvec[con->out_kvec_left].iov_len = auth_len;
570 con->out_kvec_left++;
571 con->out_kvec_bytes += auth_len;
572}
573
553/* 574/*
554 * We connected to a peer and are saying hello. 575 * We connected to a peer and are saying hello.
555 */ 576 */
@@ -592,6 +613,7 @@ static void prepare_write_connect(struct ceph_messenger *msgr,
592 613
593 dout("prepare_write_connect %p cseq=%d gseq=%d proto=%d\n", con, 614 dout("prepare_write_connect %p cseq=%d gseq=%d proto=%d\n", con,
594 con->connect_seq, global_seq, proto); 615 con->connect_seq, global_seq, proto);
616
595 con->out_connect.host_type = cpu_to_le32(CEPH_ENTITY_TYPE_CLIENT); 617 con->out_connect.host_type = cpu_to_le32(CEPH_ENTITY_TYPE_CLIENT);
596 con->out_connect.connect_seq = cpu_to_le32(con->connect_seq); 618 con->out_connect.connect_seq = cpu_to_le32(con->connect_seq);
597 con->out_connect.global_seq = cpu_to_le32(global_seq); 619 con->out_connect.global_seq = cpu_to_le32(global_seq);
@@ -611,6 +633,8 @@ static void prepare_write_connect(struct ceph_messenger *msgr,
611 con->out_kvec_cur = con->out_kvec; 633 con->out_kvec_cur = con->out_kvec;
612 con->out_more = 0; 634 con->out_more = 0;
613 set_bit(WRITE_PENDING, &con->state); 635 set_bit(WRITE_PENDING, &con->state);
636
637 prepare_connect_authorizer(con);
614} 638}
615 639
616 640
@@ -777,6 +801,13 @@ static void prepare_read_connect(struct ceph_connection *con)
777 con->in_base_pos = 0; 801 con->in_base_pos = 0;
778} 802}
779 803
804static void prepare_read_connect_retry(struct ceph_connection *con)
805{
806 dout("prepare_read_connect_retry %p\n", con);
807 con->in_base_pos = strlen(CEPH_BANNER) + sizeof(con->actual_peer_addr)
808 + sizeof(con->peer_addr_for_me);
809}
810
780static void prepare_read_ack(struct ceph_connection *con) 811static void prepare_read_ack(struct ceph_connection *con)
781{ 812{
782 dout("prepare_read_ack %p\n", con); 813 dout("prepare_read_ack %p\n", con);
@@ -853,9 +884,14 @@ static int read_partial_connect(struct ceph_connection *con)
853 ret = read_partial(con, &to, sizeof(con->in_reply), &con->in_reply); 884 ret = read_partial(con, &to, sizeof(con->in_reply), &con->in_reply);
854 if (ret <= 0) 885 if (ret <= 0)
855 goto out; 886 goto out;
887 ret = read_partial(con, &to, le32_to_cpu(con->in_reply.authorizer_len),
888 con->auth_reply_buf);
889 if (ret <= 0)
890 goto out;
856 891
857 dout("read_partial_connect %p connect_seq = %u, global_seq = %u\n", 892 dout("read_partial_connect %p tag %d, con_seq = %u, g_seq = %u\n",
858 con, le32_to_cpu(con->in_reply.connect_seq), 893 con, (int)con->in_reply.tag,
894 le32_to_cpu(con->in_reply.connect_seq),
859 le32_to_cpu(con->in_reply.global_seq)); 895 le32_to_cpu(con->in_reply.global_seq));
860out: 896out:
861 return ret; 897 return ret;
@@ -1051,6 +1087,20 @@ static int process_connect(struct ceph_connection *con)
1051 set_bit(CLOSED, &con->state); /* in case there's queued work */ 1087 set_bit(CLOSED, &con->state); /* in case there's queued work */
1052 return -1; 1088 return -1;
1053 1089
1090 case CEPH_MSGR_TAG_BADAUTHORIZER:
1091 con->auth_retry++;
1092 dout("process_connect %p got BADAUTHORIZER attempt %d\n", con,
1093 con->auth_retry);
1094 if (con->auth_retry == 2) {
1095 con->error_msg = "connect authorization failure";
1096 reset_connection(con);
1097 set_bit(CLOSED, &con->state);
1098 return -1;
1099 }
1100 con->auth_retry = 1;
1101 prepare_write_connect(con->msgr, con, 0);
1102 prepare_read_connect_retry(con);
1103 break;
1054 1104
1055 case CEPH_MSGR_TAG_RESETSESSION: 1105 case CEPH_MSGR_TAG_RESETSESSION:
1056 /* 1106 /*
diff --git a/fs/ceph/messenger.h b/fs/ceph/messenger.h
index 4bd85c36308e..f9c9f6487302 100644
--- a/fs/ceph/messenger.h
+++ b/fs/ceph/messenger.h
@@ -26,6 +26,12 @@ struct ceph_connection_operations {
26 /* handle an incoming message. */ 26 /* handle an incoming message. */
27 void (*dispatch) (struct ceph_connection *con, struct ceph_msg *m); 27 void (*dispatch) (struct ceph_connection *con, struct ceph_msg *m);
28 28
29 /* authorize an outgoing connection */
30 int (*get_authorizer) (struct ceph_connection *con,
31 void **buf, int *len, int *proto,
32 void **reply_buf, int *reply_len, int force_new);
33 int (*verify_authorizer_reply) (struct ceph_connection *con, int len);
34
29 /* protocol version mismatch */ 35 /* protocol version mismatch */
30 void (*bad_proto) (struct ceph_connection *con); 36 void (*bad_proto) (struct ceph_connection *con);
31 37
@@ -144,6 +150,10 @@ struct ceph_connection {
144 attempt for this connection, client */ 150 attempt for this connection, client */
145 u32 peer_global_seq; /* peer's global seq for this connection */ 151 u32 peer_global_seq; /* peer's global seq for this connection */
146 152
153 int auth_retry; /* true if we need a newer authorizer */
154 void *auth_reply_buf; /* where to put the authorizer reply */
155 int auth_reply_buf_len;
156
147 /* out queue */ 157 /* out queue */
148 struct mutex out_mutex; 158 struct mutex out_mutex;
149 struct list_head out_queue; 159 struct list_head out_queue;
diff --git a/fs/ceph/mon_client.c b/fs/ceph/mon_client.c
index 95b76e761e18..017d5aef8834 100644
--- a/fs/ceph/mon_client.c
+++ b/fs/ceph/mon_client.c
@@ -6,6 +6,7 @@
6 6
7#include "mon_client.h" 7#include "mon_client.h"
8#include "super.h" 8#include "super.h"
9#include "auth.h"
9#include "decode.h" 10#include "decode.h"
10 11
11/* 12/*
@@ -38,6 +39,10 @@ struct ceph_monmap *ceph_monmap_decode(void *p, void *end)
38 struct ceph_fsid fsid; 39 struct ceph_fsid fsid;
39 u32 epoch, num_mon; 40 u32 epoch, num_mon;
40 u16 version; 41 u16 version;
42 u32 len;
43
44 ceph_decode_32_safe(&p, end, len, bad);
45 ceph_decode_need(&p, end, len, bad);
41 46
42 dout("monmap_decode %p %p len %d\n", p, end, (int)(end-p)); 47 dout("monmap_decode %p %p len %d\n", p, end, (int)(end-p));
43 48
@@ -95,8 +100,10 @@ static void __close_session(struct ceph_mon_client *monc)
95{ 100{
96 if (monc->con) { 101 if (monc->con) {
97 dout("__close_session closing mon%d\n", monc->cur_mon); 102 dout("__close_session closing mon%d\n", monc->cur_mon);
103 ceph_con_revoke(monc->con, monc->m_auth);
98 ceph_con_close(monc->con); 104 ceph_con_close(monc->con);
99 monc->cur_mon = -1; 105 monc->cur_mon = -1;
106 ceph_auth_reset(monc->auth);
100 } 107 }
101} 108}
102 109
@@ -106,6 +113,7 @@ static void __close_session(struct ceph_mon_client *monc)
106static int __open_session(struct ceph_mon_client *monc) 113static int __open_session(struct ceph_mon_client *monc)
107{ 114{
108 char r; 115 char r;
116 int ret;
109 117
110 if (monc->cur_mon < 0) { 118 if (monc->cur_mon < 0) {
111 get_random_bytes(&r, 1); 119 get_random_bytes(&r, 1);
@@ -121,6 +129,15 @@ static int __open_session(struct ceph_mon_client *monc)
121 monc->con->peer_name.num = cpu_to_le64(monc->cur_mon); 129 monc->con->peer_name.num = cpu_to_le64(monc->cur_mon);
122 ceph_con_open(monc->con, 130 ceph_con_open(monc->con,
123 &monc->monmap->mon_inst[monc->cur_mon].addr); 131 &monc->monmap->mon_inst[monc->cur_mon].addr);
132
133 /* initiatiate authentication handshake */
134 ret = ceph_auth_build_hello(monc->auth,
135 monc->m_auth->front.iov_base,
136 monc->m_auth->front_max);
137 monc->m_auth->front.iov_len = ret;
138 monc->m_auth->hdr.front_len = cpu_to_le32(ret);
139 ceph_msg_get(monc->m_auth); /* keep our ref */
140 ceph_con_send(monc->con, monc->m_auth);
124 } else { 141 } else {
125 dout("open_session mon%d already open\n", monc->cur_mon); 142 dout("open_session mon%d already open\n", monc->cur_mon);
126 } 143 }
@@ -139,7 +156,7 @@ static void __schedule_delayed(struct ceph_mon_client *monc)
139{ 156{
140 unsigned delay; 157 unsigned delay;
141 158
142 if (monc->cur_mon < 0 || monc->want_mount || __sub_expired(monc)) 159 if (monc->cur_mon < 0 || __sub_expired(monc))
143 delay = 10 * HZ; 160 delay = 10 * HZ;
144 else 161 else
145 delay = 20 * HZ; 162 delay = 20 * HZ;
@@ -161,7 +178,7 @@ static void __send_subscribe(struct ceph_mon_client *monc)
161 struct ceph_mon_subscribe_item *i; 178 struct ceph_mon_subscribe_item *i;
162 void *p, *end; 179 void *p, *end;
163 180
164 msg = ceph_msg_new(CEPH_MSG_MON_SUBSCRIBE, 64, 0, 0, NULL); 181 msg = ceph_msg_new(CEPH_MSG_MON_SUBSCRIBE, 96, 0, 0, NULL);
165 if (!msg) 182 if (!msg)
166 return; 183 return;
167 184
@@ -173,7 +190,7 @@ static void __send_subscribe(struct ceph_mon_client *monc)
173 if (monc->want_next_osdmap) { 190 if (monc->want_next_osdmap) {
174 dout("__send_subscribe to 'osdmap' %u\n", 191 dout("__send_subscribe to 'osdmap' %u\n",
175 (unsigned)monc->have_osdmap); 192 (unsigned)monc->have_osdmap);
176 ceph_encode_32(&p, 2); 193 ceph_encode_32(&p, 3);
177 ceph_encode_string(&p, end, "osdmap", 6); 194 ceph_encode_string(&p, end, "osdmap", 6);
178 i = p; 195 i = p;
179 i->have = cpu_to_le64(monc->have_osdmap); 196 i->have = cpu_to_le64(monc->have_osdmap);
@@ -181,13 +198,18 @@ static void __send_subscribe(struct ceph_mon_client *monc)
181 p += sizeof(*i); 198 p += sizeof(*i);
182 monc->want_next_osdmap = 2; /* requested */ 199 monc->want_next_osdmap = 2; /* requested */
183 } else { 200 } else {
184 ceph_encode_32(&p, 1); 201 ceph_encode_32(&p, 2);
185 } 202 }
186 ceph_encode_string(&p, end, "mdsmap", 6); 203 ceph_encode_string(&p, end, "mdsmap", 6);
187 i = p; 204 i = p;
188 i->have = cpu_to_le64(monc->have_mdsmap); 205 i->have = cpu_to_le64(monc->have_mdsmap);
189 i->onetime = 0; 206 i->onetime = 0;
190 p += sizeof(*i); 207 p += sizeof(*i);
208 ceph_encode_string(&p, end, "monmap", 6);
209 i = p;
210 i->have = 0;
211 i->onetime = 0;
212 p += sizeof(*i);
191 213
192 msg->front.iov_len = p - msg->front.iov_base; 214 msg->front.iov_len = p - msg->front.iov_base;
193 msg->hdr.front_len = cpu_to_le32(msg->front.iov_len); 215 msg->hdr.front_len = cpu_to_le32(msg->front.iov_len);
@@ -256,7 +278,7 @@ void ceph_monc_request_next_osdmap(struct ceph_mon_client *monc)
256 mutex_unlock(&monc->mutex); 278 mutex_unlock(&monc->mutex);
257} 279}
258 280
259 281#if 0
260/* 282/*
261 * mount 283 * mount
262 */ 284 */
@@ -264,12 +286,8 @@ static void __request_mount(struct ceph_mon_client *monc)
264{ 286{
265 struct ceph_msg *msg; 287 struct ceph_msg *msg;
266 struct ceph_client_mount *h; 288 struct ceph_client_mount *h;
267 int err;
268 289
269 dout("__request_mount\n"); 290 dout("__request_mount\n");
270 err = __open_session(monc);
271 if (err)
272 return;
273 msg = ceph_msg_new(CEPH_MSG_CLIENT_MOUNT, sizeof(*h), 0, 0, NULL); 291 msg = ceph_msg_new(CEPH_MSG_CLIENT_MOUNT, sizeof(*h), 0, 0, NULL);
274 if (IS_ERR(msg)) 292 if (IS_ERR(msg))
275 return; 293 return;
@@ -279,8 +297,12 @@ static void __request_mount(struct ceph_mon_client *monc)
279 h->monhdr.session_mon_tid = 0; 297 h->monhdr.session_mon_tid = 0;
280 ceph_con_send(monc->con, msg); 298 ceph_con_send(monc->con, msg);
281} 299}
300#endif
282 301
283int ceph_monc_request_mount(struct ceph_mon_client *monc) 302/*
303 *
304 */
305int ceph_monc_open_session(struct ceph_mon_client *monc)
284{ 306{
285 if (!monc->con) { 307 if (!monc->con) {
286 monc->con = kmalloc(sizeof(*monc->con), GFP_KERNEL); 308 monc->con = kmalloc(sizeof(*monc->con), GFP_KERNEL);
@@ -292,12 +314,14 @@ int ceph_monc_request_mount(struct ceph_mon_client *monc)
292 } 314 }
293 315
294 mutex_lock(&monc->mutex); 316 mutex_lock(&monc->mutex);
295 __request_mount(monc); 317 __open_session(monc);
296 __schedule_delayed(monc); 318 __schedule_delayed(monc);
297 mutex_unlock(&monc->mutex); 319 mutex_unlock(&monc->mutex);
298 return 0; 320 return 0;
299} 321}
300 322
323#if 0
324
301/* 325/*
302 * The monitor responds with mount ack indicate mount success. The 326 * The monitor responds with mount ack indicate mount success. The
303 * included client ticket allows the client to talk to MDSs and OSDs. 327 * included client ticket allows the client to talk to MDSs and OSDs.
@@ -372,9 +396,65 @@ out:
372 mutex_unlock(&monc->mutex); 396 mutex_unlock(&monc->mutex);
373 wake_up(&client->mount_wq); 397 wake_up(&client->mount_wq);
374} 398}
399#endif
400
401/*
402 * The monitor responds with mount ack indicate mount success. The
403 * included client ticket allows the client to talk to MDSs and OSDs.
404 */
405static void ceph_monc_handle_map(struct ceph_mon_client *monc, struct ceph_msg *msg)
406{
407 struct ceph_client *client = monc->client;
408 struct ceph_monmap *monmap = NULL, *old = monc->monmap;
409 void *p, *end;
410
411 mutex_lock(&monc->mutex);
412
413 dout("handle_monmap\n");
414 p = msg->front.iov_base;
415 end = p + msg->front.iov_len;
416
417 monmap = ceph_monmap_decode(p, end);
418 if (IS_ERR(monmap)) {
419 pr_err("problem decoding monmap, %d\n",
420 (int)PTR_ERR(monmap));
421 return;
422 }
423 if (monc->have_fsid &&
424 ceph_fsid_compare(&monmap->fsid, &monc->monmap->fsid)) {
425 print_hex_dump(KERN_ERR, "monmap->fsid: ", DUMP_PREFIX_NONE, 16, 1,
426 (void *)&monmap->fsid, 16, 0);
427 print_hex_dump(KERN_ERR, "monc->monmap->fsid: ", DUMP_PREFIX_NONE, 16, 1,
428 (void *)&monc->monmap->fsid, 16, 0);
429
430 pr_err("fsid mismatch, got a previous map with different fsid");
431 kfree(monmap);
432 return;
433 }
434
435 client->monc.monmap = monmap;
436 client->monc.have_fsid = true;
437 kfree(old);
438
439 mutex_unlock(&monc->mutex);
440 wake_up(&client->mount_wq);
441}
442
375 443
444/*
445 * init client info after authentication
446 */
447static void __init_authenticated_client(struct ceph_mon_client *monc)
448{
449 struct ceph_client *client = monc->client;
376 450
451 client->signed_ticket = NULL;
452 client->signed_ticket_len = 0;
453 client->msgr->inst.name.type = CEPH_ENTITY_TYPE_CLIENT;
454 client->msgr->inst.name.num = monc->auth->global_id;
377 455
456 ceph_debugfs_client_init(client);
457}
378 458
379/* 459/*
380 * statfs 460 * statfs
@@ -414,12 +494,8 @@ static int send_statfs(struct ceph_mon_client *monc,
414{ 494{
415 struct ceph_msg *msg; 495 struct ceph_msg *msg;
416 struct ceph_mon_statfs *h; 496 struct ceph_mon_statfs *h;
417 int err;
418 497
419 dout("send_statfs tid %llu\n", req->tid); 498 dout("send_statfs tid %llu\n", req->tid);
420 err = __open_session(monc);
421 if (err)
422 return err;
423 msg = ceph_msg_new(CEPH_MSG_STATFS, sizeof(*h), 0, 0, NULL); 499 msg = ceph_msg_new(CEPH_MSG_STATFS, sizeof(*h), 0, 0, NULL);
424 if (IS_ERR(msg)) 500 if (IS_ERR(msg))
425 return PTR_ERR(msg); 501 return PTR_ERR(msg);
@@ -514,17 +590,14 @@ static void delayed_work(struct work_struct *work)
514 590
515 dout("monc delayed_work\n"); 591 dout("monc delayed_work\n");
516 mutex_lock(&monc->mutex); 592 mutex_lock(&monc->mutex);
517 if (monc->want_mount) { 593 if (monc->hunting) {
518 __request_mount(monc); 594 __close_session(monc);
595 __open_session(monc); /* continue hunting */
519 } else { 596 } else {
520 if (monc->hunting) { 597 ceph_con_keepalive(monc->con);
521 __close_session(monc); 598 if (monc->auth->ops->is_authenticated(monc->auth))
522 __open_session(monc); /* continue hunting */ 599 __send_subscribe(monc);
523 } else {
524 ceph_con_keepalive(monc->con);
525 }
526 } 600 }
527 __send_subscribe(monc);
528 __schedule_delayed(monc); 601 __schedule_delayed(monc);
529 mutex_unlock(&monc->mutex); 602 mutex_unlock(&monc->mutex);
530} 603}
@@ -555,6 +628,7 @@ static int build_initial_monmap(struct ceph_mon_client *monc)
555 monc->monmap->mon_inst[i].name.num = cpu_to_le64(i); 628 monc->monmap->mon_inst[i].name.num = cpu_to_le64(i);
556 } 629 }
557 monc->monmap->num_mon = num_mon; 630 monc->monmap->num_mon = num_mon;
631 monc->have_fsid = false;
558 632
559 /* release addr memory */ 633 /* release addr memory */
560 kfree(args->mon_addr); 634 kfree(args->mon_addr);
@@ -579,21 +653,37 @@ int ceph_monc_init(struct ceph_mon_client *monc, struct ceph_client *cl)
579 653
580 monc->con = NULL; 654 monc->con = NULL;
581 655
656 /* authentication */
657 monc->auth = ceph_auth_init(cl->mount_args->name,
658 cl->mount_args->secret);
659 if (IS_ERR(monc->auth))
660 return PTR_ERR(monc->auth);
661 monc->auth->want_keys =
662 CEPH_ENTITY_TYPE_AUTH | CEPH_ENTITY_TYPE_MON |
663 CEPH_ENTITY_TYPE_OSD | CEPH_ENTITY_TYPE_MDS;
664
582 /* msg pools */ 665 /* msg pools */
583 err = ceph_msgpool_init(&monc->msgpool_mount_ack, 4096, 1, false);
584 if (err < 0)
585 goto out;
586 err = ceph_msgpool_init(&monc->msgpool_subscribe_ack, 666 err = ceph_msgpool_init(&monc->msgpool_subscribe_ack,
587 sizeof(struct ceph_mon_subscribe_ack), 1, false); 667 sizeof(struct ceph_mon_subscribe_ack), 1, false);
588 if (err < 0) 668 if (err < 0)
589 goto out; 669 goto out_monmap;
590 err = ceph_msgpool_init(&monc->msgpool_statfs_reply, 670 err = ceph_msgpool_init(&monc->msgpool_statfs_reply,
591 sizeof(struct ceph_mon_statfs_reply), 0, false); 671 sizeof(struct ceph_mon_statfs_reply), 0, false);
592 if (err < 0) 672 if (err < 0)
593 goto out; 673 goto out_pool1;
674 err = ceph_msgpool_init(&monc->msgpool_auth_reply, 4096, 1, false);
675 if (err < 0)
676 goto out_pool2;
677
678 monc->m_auth = ceph_msg_new(CEPH_MSG_AUTH, 4096, 0, 0, NULL);
679 if (IS_ERR(monc->m_auth)) {
680 err = PTR_ERR(monc->m_auth);
681 monc->m_auth = NULL;
682 goto out_pool3;
683 }
594 684
595 monc->cur_mon = -1; 685 monc->cur_mon = -1;
596 monc->hunting = false; /* not really */ 686 monc->hunting = true;
597 monc->sub_renew_after = jiffies; 687 monc->sub_renew_after = jiffies;
598 monc->sub_sent = 0; 688 monc->sub_sent = 0;
599 689
@@ -605,7 +695,16 @@ int ceph_monc_init(struct ceph_mon_client *monc, struct ceph_client *cl)
605 monc->have_mdsmap = 0; 695 monc->have_mdsmap = 0;
606 monc->have_osdmap = 0; 696 monc->have_osdmap = 0;
607 monc->want_next_osdmap = 1; 697 monc->want_next_osdmap = 1;
608 monc->want_mount = true; 698 return 0;
699
700out_pool3:
701 ceph_msgpool_destroy(&monc->msgpool_auth_reply);
702out_pool2:
703 ceph_msgpool_destroy(&monc->msgpool_subscribe_ack);
704out_pool1:
705 ceph_msgpool_destroy(&monc->msgpool_statfs_reply);
706out_monmap:
707 kfree(monc->monmap);
609out: 708out:
610 return err; 709 return err;
611} 710}
@@ -624,14 +723,44 @@ void ceph_monc_stop(struct ceph_mon_client *monc)
624 } 723 }
625 mutex_unlock(&monc->mutex); 724 mutex_unlock(&monc->mutex);
626 725
627 ceph_msgpool_destroy(&monc->msgpool_mount_ack); 726 ceph_auth_destroy(monc->auth);
727
728 ceph_msg_put(monc->m_auth);
628 ceph_msgpool_destroy(&monc->msgpool_subscribe_ack); 729 ceph_msgpool_destroy(&monc->msgpool_subscribe_ack);
629 ceph_msgpool_destroy(&monc->msgpool_statfs_reply); 730 ceph_msgpool_destroy(&monc->msgpool_statfs_reply);
731 ceph_msgpool_destroy(&monc->msgpool_auth_reply);
630 732
631 kfree(monc->monmap); 733 kfree(monc->monmap);
632} 734}
633 735
634 736
737static void handle_auth_reply(struct ceph_mon_client *monc,
738 struct ceph_msg *msg)
739{
740 int ret;
741
742 mutex_lock(&monc->mutex);
743 ret = ceph_handle_auth_reply(monc->auth, msg->front.iov_base,
744 msg->front.iov_len,
745 monc->m_auth->front.iov_base,
746 monc->m_auth->front_max);
747 if (ret < 0) {
748 monc->client->mount_err = ret;
749 wake_up(&monc->client->mount_wq);
750 } else if (ret > 0) {
751 monc->m_auth->front.iov_len = ret;
752 monc->m_auth->hdr.front_len = cpu_to_le32(ret);
753 ceph_msg_get(monc->m_auth); /* keep our ref */
754 ceph_con_send(monc->con, monc->m_auth);
755 } else if (monc->auth->ops->is_authenticated(monc->auth)) {
756 dout("authenticated, starting session\n");
757 __init_authenticated_client(monc);
758 __send_subscribe(monc);
759 __resend_statfs(monc);
760 }
761 mutex_unlock(&monc->mutex);
762}
763
635/* 764/*
636 * handle incoming message 765 * handle incoming message
637 */ 766 */
@@ -644,8 +773,8 @@ static void dispatch(struct ceph_connection *con, struct ceph_msg *msg)
644 return; 773 return;
645 774
646 switch (type) { 775 switch (type) {
647 case CEPH_MSG_CLIENT_MOUNT_ACK: 776 case CEPH_MSG_AUTH_REPLY:
648 handle_mount_ack(monc, msg); 777 handle_auth_reply(monc, msg);
649 break; 778 break;
650 779
651 case CEPH_MSG_MON_SUBSCRIBE_ACK: 780 case CEPH_MSG_MON_SUBSCRIBE_ACK:
@@ -656,6 +785,10 @@ static void dispatch(struct ceph_connection *con, struct ceph_msg *msg)
656 handle_statfs_reply(monc, msg); 785 handle_statfs_reply(monc, msg);
657 break; 786 break;
658 787
788 case CEPH_MSG_MON_MAP:
789 ceph_monc_handle_map(monc, msg);
790 break;
791
659 case CEPH_MSG_MDS_MAP: 792 case CEPH_MSG_MDS_MAP:
660 ceph_mdsc_handle_map(&monc->client->mdsc, msg); 793 ceph_mdsc_handle_map(&monc->client->mdsc, msg);
661 break; 794 break;
@@ -682,12 +815,12 @@ static struct ceph_msg *mon_alloc_msg(struct ceph_connection *con,
682 int front = le32_to_cpu(hdr->front_len); 815 int front = le32_to_cpu(hdr->front_len);
683 816
684 switch (type) { 817 switch (type) {
685 case CEPH_MSG_CLIENT_MOUNT_ACK:
686 return ceph_msgpool_get(&monc->msgpool_mount_ack, front);
687 case CEPH_MSG_MON_SUBSCRIBE_ACK: 818 case CEPH_MSG_MON_SUBSCRIBE_ACK:
688 return ceph_msgpool_get(&monc->msgpool_subscribe_ack, front); 819 return ceph_msgpool_get(&monc->msgpool_subscribe_ack, front);
689 case CEPH_MSG_STATFS_REPLY: 820 case CEPH_MSG_STATFS_REPLY:
690 return ceph_msgpool_get(&monc->msgpool_statfs_reply, front); 821 return ceph_msgpool_get(&monc->msgpool_statfs_reply, front);
822 case CEPH_MSG_AUTH_REPLY:
823 return ceph_msgpool_get(&monc->msgpool_auth_reply, front);
691 } 824 }
692 return ceph_alloc_msg(con, hdr); 825 return ceph_alloc_msg(con, hdr);
693} 826}
@@ -717,10 +850,7 @@ static void mon_fault(struct ceph_connection *con)
717 if (!monc->hunting) { 850 if (!monc->hunting) {
718 /* start hunting */ 851 /* start hunting */
719 monc->hunting = true; 852 monc->hunting = true;
720 if (__open_session(monc) == 0) { 853 __open_session(monc);
721 __send_subscribe(monc);
722 __resend_statfs(monc);
723 }
724 } else { 854 } else {
725 /* already hunting, let's wait a bit */ 855 /* already hunting, let's wait a bit */
726 __schedule_delayed(monc); 856 __schedule_delayed(monc);
diff --git a/fs/ceph/mon_client.h b/fs/ceph/mon_client.h
index 9f6db45bf469..c75b53302ecc 100644
--- a/fs/ceph/mon_client.h
+++ b/fs/ceph/mon_client.h
@@ -9,6 +9,7 @@
9 9
10struct ceph_client; 10struct ceph_client;
11struct ceph_mount_args; 11struct ceph_mount_args;
12struct ceph_auth_client;
12 13
13/* 14/*
14 * The monitor map enumerates the set of all monitors. 15 * The monitor map enumerates the set of all monitors.
@@ -58,23 +59,26 @@ struct ceph_mon_client {
58 struct mutex mutex; 59 struct mutex mutex;
59 struct delayed_work delayed_work; 60 struct delayed_work delayed_work;
60 61
62 struct ceph_auth_client *auth;
63 struct ceph_msg *m_auth;
64
61 bool hunting; 65 bool hunting;
62 int cur_mon; /* last monitor i contacted */ 66 int cur_mon; /* last monitor i contacted */
63 unsigned long sub_sent, sub_renew_after; 67 unsigned long sub_sent, sub_renew_after;
64 struct ceph_connection *con; 68 struct ceph_connection *con;
69 bool have_fsid;
65 70
66 /* msg pools */ 71 /* msg pools */
67 struct ceph_msgpool msgpool_mount_ack;
68 struct ceph_msgpool msgpool_subscribe_ack; 72 struct ceph_msgpool msgpool_subscribe_ack;
69 struct ceph_msgpool msgpool_statfs_reply; 73 struct ceph_msgpool msgpool_statfs_reply;
74 struct ceph_msgpool msgpool_auth_reply;
70 75
71 /* pending statfs requests */ 76 /* pending statfs requests */
72 struct radix_tree_root statfs_request_tree; 77 struct radix_tree_root statfs_request_tree;
73 int num_statfs_requests; 78 int num_statfs_requests;
74 u64 last_tid; 79 u64 last_tid;
75 80
76 /* mds/osd map or mount requests */ 81 /* mds/osd map */
77 bool want_mount;
78 int want_next_osdmap; /* 1 = want, 2 = want+asked */ 82 int want_next_osdmap; /* 1 = want, 2 = want+asked */
79 u32 have_osdmap, have_mdsmap; 83 u32 have_osdmap, have_mdsmap;
80 84
@@ -101,11 +105,11 @@ extern int ceph_monc_got_osdmap(struct ceph_mon_client *monc, u32 have);
101 105
102extern void ceph_monc_request_next_osdmap(struct ceph_mon_client *monc); 106extern void ceph_monc_request_next_osdmap(struct ceph_mon_client *monc);
103 107
104extern int ceph_monc_request_mount(struct ceph_mon_client *monc);
105
106extern int ceph_monc_do_statfs(struct ceph_mon_client *monc, 108extern int ceph_monc_do_statfs(struct ceph_mon_client *monc,
107 struct ceph_statfs *buf); 109 struct ceph_statfs *buf);
108 110
111extern int ceph_monc_open_session(struct ceph_mon_client *monc);
112
109 113
110 114
111#endif 115#endif
diff --git a/fs/ceph/msgr.h b/fs/ceph/msgr.h
index 8e3ea2eb1bf5..c758e8f8f71b 100644
--- a/fs/ceph/msgr.h
+++ b/fs/ceph/msgr.h
@@ -21,7 +21,7 @@
21 * whenever the wire protocol changes. try to keep this string length 21 * whenever the wire protocol changes. try to keep this string length
22 * constant. 22 * constant.
23 */ 23 */
24#define CEPH_BANNER "ceph v023" 24#define CEPH_BANNER "ceph v024"
25#define CEPH_BANNER_MAX_LEN 30 25#define CEPH_BANNER_MAX_LEN 30
26 26
27 27
@@ -46,11 +46,16 @@ struct ceph_entity_name {
46 __le64 num; 46 __le64 num;
47} __attribute__ ((packed)); 47} __attribute__ ((packed));
48 48
49#define CEPH_ENTITY_TYPE_MON 1 49#define CEPH_ENTITY_TYPE_MON 0x01
50#define CEPH_ENTITY_TYPE_MDS 2 50#define CEPH_ENTITY_TYPE_MDS 0x02
51#define CEPH_ENTITY_TYPE_OSD 3 51#define CEPH_ENTITY_TYPE_OSD 0x04
52#define CEPH_ENTITY_TYPE_CLIENT 4 52#define CEPH_ENTITY_TYPE_CLIENT 0x08
53#define CEPH_ENTITY_TYPE_ADMIN 5 53#define CEPH_ENTITY_TYPE_ADMIN 0x10
54#define CEPH_ENTITY_TYPE_AUTH 0x20
55
56#define CEPH_ENTITY_TYPE_ANY 0xFF
57
58extern const char *ceph_entity_type_name(int type);
54 59
55/* 60/*
56 * entity_addr -- network address 61 * entity_addr -- network address
@@ -94,6 +99,7 @@ struct ceph_entity_inst {
94#define CEPH_MSGR_TAG_ACK 8 /* message ack */ 99#define CEPH_MSGR_TAG_ACK 8 /* message ack */
95#define CEPH_MSGR_TAG_KEEPALIVE 9 /* just a keepalive byte! */ 100#define CEPH_MSGR_TAG_KEEPALIVE 9 /* just a keepalive byte! */
96#define CEPH_MSGR_TAG_BADPROTOVER 10 /* bad protocol version */ 101#define CEPH_MSGR_TAG_BADPROTOVER 10 /* bad protocol version */
102#define CEPH_MSGR_TAG_BADAUTHORIZER 11 /* bad authorizer */
97 103
98 104
99/* 105/*
@@ -104,6 +110,8 @@ struct ceph_msg_connect {
104 __le32 global_seq; /* count connections initiated by this host */ 110 __le32 global_seq; /* count connections initiated by this host */
105 __le32 connect_seq; /* count connections initiated in this session */ 111 __le32 connect_seq; /* count connections initiated in this session */
106 __le32 protocol_version; 112 __le32 protocol_version;
113 __le32 authorizer_protocol;
114 __le32 authorizer_len;
107 __u8 flags; /* CEPH_MSG_CONNECT_* */ 115 __u8 flags; /* CEPH_MSG_CONNECT_* */
108} __attribute__ ((packed)); 116} __attribute__ ((packed));
109 117
@@ -112,6 +120,7 @@ struct ceph_msg_connect_reply {
112 __le32 global_seq; 120 __le32 global_seq;
113 __le32 connect_seq; 121 __le32 connect_seq;
114 __le32 protocol_version; 122 __le32 protocol_version;
123 __le32 authorizer_len;
115 __u8 flags; 124 __u8 flags;
116} __attribute__ ((packed)); 125} __attribute__ ((packed));
117 126
diff --git a/fs/ceph/osd_client.c b/fs/ceph/osd_client.c
index 0a16c4f951f9..ca0ee68c322a 100644
--- a/fs/ceph/osd_client.c
+++ b/fs/ceph/osd_client.c
@@ -11,6 +11,7 @@
11#include "osd_client.h" 11#include "osd_client.h"
12#include "messenger.h" 12#include "messenger.h"
13#include "decode.h" 13#include "decode.h"
14#include "auth.h"
14 15
15const static struct ceph_connection_operations osd_con_ops; 16const static struct ceph_connection_operations osd_con_ops;
16 17
@@ -331,6 +332,7 @@ static struct ceph_osd *create_osd(struct ceph_osd_client *osdc)
331 osd->o_con.private = osd; 332 osd->o_con.private = osd;
332 osd->o_con.ops = &osd_con_ops; 333 osd->o_con.ops = &osd_con_ops;
333 osd->o_con.peer_name.type = CEPH_ENTITY_TYPE_OSD; 334 osd->o_con.peer_name.type = CEPH_ENTITY_TYPE_OSD;
335
334 return osd; 336 return osd;
335} 337}
336 338
@@ -880,9 +882,15 @@ void ceph_osdc_handle_map(struct ceph_osd_client *osdc, struct ceph_msg *msg)
880 /* verify fsid */ 882 /* verify fsid */
881 ceph_decode_need(&p, end, sizeof(fsid), bad); 883 ceph_decode_need(&p, end, sizeof(fsid), bad);
882 ceph_decode_copy(&p, &fsid, sizeof(fsid)); 884 ceph_decode_copy(&p, &fsid, sizeof(fsid));
883 if (ceph_fsid_compare(&fsid, &osdc->client->monc.monmap->fsid)) { 885 if (osdc->client->monc.have_fsid) {
884 pr_err("got osdmap with wrong fsid, ignoring\n"); 886 if (ceph_fsid_compare(&fsid,
885 return; 887 &osdc->client->monc.monmap->fsid)) {
888 pr_err("got osdmap with wrong fsid, ignoring\n");
889 return;
890 }
891 } else {
892 ceph_fsid_set(&osdc->client->monc.monmap->fsid, &fsid);
893 osdc->client->monc.have_fsid = true;
886 } 894 }
887 895
888 down_write(&osdc->map_sem); 896 down_write(&osdc->map_sem);
@@ -1302,10 +1310,59 @@ static void put_osd_con(struct ceph_connection *con)
1302 put_osd(osd); 1310 put_osd(osd);
1303} 1311}
1304 1312
1313/*
1314 * authentication
1315 */
1316static int get_authorizer(struct ceph_connection *con,
1317 void **buf, int *len, int *proto,
1318 void **reply_buf, int *reply_len, int force_new)
1319{
1320 struct ceph_osd *o = con->private;
1321 struct ceph_osd_client *osdc = o->o_osdc;
1322 struct ceph_auth_client *ac = osdc->client->monc.auth;
1323 int ret = 0;
1324
1325 if (force_new && o->o_authorizer) {
1326 ac->ops->destroy_authorizer(ac, o->o_authorizer);
1327 o->o_authorizer = NULL;
1328 }
1329 if (o->o_authorizer == NULL) {
1330 ret = ac->ops->create_authorizer(
1331 ac, CEPH_ENTITY_TYPE_OSD,
1332 &o->o_authorizer,
1333 &o->o_authorizer_buf,
1334 &o->o_authorizer_buf_len,
1335 &o->o_authorizer_reply_buf,
1336 &o->o_authorizer_reply_buf_len);
1337 if (ret)
1338 return ret;
1339 }
1340
1341 *proto = ac->protocol;
1342 *buf = o->o_authorizer_buf;
1343 *len = o->o_authorizer_buf_len;
1344 *reply_buf = o->o_authorizer_reply_buf;
1345 *reply_len = o->o_authorizer_reply_buf_len;
1346 return 0;
1347}
1348
1349
1350static int verify_authorizer_reply(struct ceph_connection *con, int len)
1351{
1352 struct ceph_osd *o = con->private;
1353 struct ceph_osd_client *osdc = o->o_osdc;
1354 struct ceph_auth_client *ac = osdc->client->monc.auth;
1355
1356 return ac->ops->verify_authorizer_reply(ac, o->o_authorizer, len);
1357}
1358
1359
1305const static struct ceph_connection_operations osd_con_ops = { 1360const static struct ceph_connection_operations osd_con_ops = {
1306 .get = get_osd_con, 1361 .get = get_osd_con,
1307 .put = put_osd_con, 1362 .put = put_osd_con,
1308 .dispatch = dispatch, 1363 .dispatch = dispatch,
1364 .get_authorizer = get_authorizer,
1365 .verify_authorizer_reply = verify_authorizer_reply,
1309 .alloc_msg = alloc_msg, 1366 .alloc_msg = alloc_msg,
1310 .fault = osd_reset, 1367 .fault = osd_reset,
1311 .alloc_middle = ceph_alloc_middle, 1368 .alloc_middle = ceph_alloc_middle,
diff --git a/fs/ceph/osd_client.h b/fs/ceph/osd_client.h
index 766c8dc80aff..3d4ae6595aaa 100644
--- a/fs/ceph/osd_client.h
+++ b/fs/ceph/osd_client.h
@@ -13,6 +13,7 @@ struct ceph_msg;
13struct ceph_snap_context; 13struct ceph_snap_context;
14struct ceph_osd_request; 14struct ceph_osd_request;
15struct ceph_osd_client; 15struct ceph_osd_client;
16struct ceph_authorizer;
16 17
17/* 18/*
18 * completion callback for async writepages 19 * completion callback for async writepages
@@ -29,6 +30,9 @@ struct ceph_osd {
29 struct rb_node o_node; 30 struct rb_node o_node;
30 struct ceph_connection o_con; 31 struct ceph_connection o_con;
31 struct list_head o_requests; 32 struct list_head o_requests;
33 struct ceph_authorizer *o_authorizer;
34 void *o_authorizer_buf, *o_authorizer_reply_buf;
35 size_t o_authorizer_buf_len, o_authorizer_reply_buf_len;
32}; 36};
33 37
34/* an in-flight request */ 38/* an in-flight request */
diff --git a/fs/ceph/rados.h b/fs/ceph/rados.h
index fb23ff9297c9..12bfb2f7c275 100644
--- a/fs/ceph/rados.h
+++ b/fs/ceph/rados.h
@@ -157,7 +157,6 @@ struct ceph_eversion {
157#define CEPH_OSD_OP_MODE_WR 0x2000 157#define CEPH_OSD_OP_MODE_WR 0x2000
158#define CEPH_OSD_OP_MODE_RMW 0x3000 158#define CEPH_OSD_OP_MODE_RMW 0x3000
159#define CEPH_OSD_OP_MODE_SUB 0x4000 159#define CEPH_OSD_OP_MODE_SUB 0x4000
160#define CEPH_OSD_OP_MODE_EXEC 0x8000
161 160
162#define CEPH_OSD_OP_TYPE 0x0f00 161#define CEPH_OSD_OP_TYPE 0x0f00
163#define CEPH_OSD_OP_TYPE_LOCK 0x0100 162#define CEPH_OSD_OP_TYPE_LOCK 0x0100
@@ -285,6 +284,7 @@ enum {
285 CEPH_OSD_FLAG_BALANCE_READS = 256, 284 CEPH_OSD_FLAG_BALANCE_READS = 256,
286 CEPH_OSD_FLAG_PARALLELEXEC = 512, /* execute op in parallel */ 285 CEPH_OSD_FLAG_PARALLELEXEC = 512, /* execute op in parallel */
287 CEPH_OSD_FLAG_PGOP = 1024, /* pg op, no object */ 286 CEPH_OSD_FLAG_PGOP = 1024, /* pg op, no object */
287 CEPH_OSD_FLAG_EXEC = 2048, /* op may exec */
288}; 288};
289 289
290enum { 290enum {
diff --git a/fs/ceph/super.c b/fs/ceph/super.c
index fe0a5962a082..c901395ae8a1 100644
--- a/fs/ceph/super.c
+++ b/fs/ceph/super.c
@@ -128,6 +128,8 @@ static int ceph_show_options(struct seq_file *m, struct vfsmount *mnt)
128 seq_puts(m, ",noasyncreaddir"); 128 seq_puts(m, ",noasyncreaddir");
129 if (strcmp(args->snapdir_name, CEPH_SNAPDIRNAME_DEFAULT)) 129 if (strcmp(args->snapdir_name, CEPH_SNAPDIRNAME_DEFAULT))
130 seq_printf(m, ",snapdirname=%s", args->snapdir_name); 130 seq_printf(m, ",snapdirname=%s", args->snapdir_name);
131 if (args->name)
132 seq_printf(m, ",name=%s", args->name);
131 if (args->secret) 133 if (args->secret)
132 seq_puts(m, ",secret=<hidden>"); 134 seq_puts(m, ",secret=<hidden>");
133 return 0; 135 return 0;
@@ -224,12 +226,12 @@ const char *ceph_msg_type_name(int type)
224 switch (type) { 226 switch (type) {
225 case CEPH_MSG_SHUTDOWN: return "shutdown"; 227 case CEPH_MSG_SHUTDOWN: return "shutdown";
226 case CEPH_MSG_PING: return "ping"; 228 case CEPH_MSG_PING: return "ping";
229 case CEPH_MSG_AUTH: return "auth";
230 case CEPH_MSG_AUTH_REPLY: return "auth_reply";
227 case CEPH_MSG_MON_MAP: return "mon_map"; 231 case CEPH_MSG_MON_MAP: return "mon_map";
228 case CEPH_MSG_MON_GET_MAP: return "mon_get_map"; 232 case CEPH_MSG_MON_GET_MAP: return "mon_get_map";
229 case CEPH_MSG_MON_SUBSCRIBE: return "mon_subscribe"; 233 case CEPH_MSG_MON_SUBSCRIBE: return "mon_subscribe";
230 case CEPH_MSG_MON_SUBSCRIBE_ACK: return "mon_subscribe_ack"; 234 case CEPH_MSG_MON_SUBSCRIBE_ACK: return "mon_subscribe_ack";
231 case CEPH_MSG_CLIENT_MOUNT: return "client_mount";
232 case CEPH_MSG_CLIENT_MOUNT_ACK: return "client_mount_ack";
233 case CEPH_MSG_STATFS: return "statfs"; 235 case CEPH_MSG_STATFS: return "statfs";
234 case CEPH_MSG_STATFS_REPLY: return "statfs_reply"; 236 case CEPH_MSG_STATFS_REPLY: return "statfs_reply";
235 case CEPH_MSG_MDS_MAP: return "mds_map"; 237 case CEPH_MSG_MDS_MAP: return "mds_map";
@@ -267,6 +269,7 @@ enum {
267 Opt_last_int, 269 Opt_last_int,
268 /* int args above */ 270 /* int args above */
269 Opt_snapdirname, 271 Opt_snapdirname,
272 Opt_name,
270 Opt_secret, 273 Opt_secret,
271 Opt_last_string, 274 Opt_last_string,
272 /* string args above */ 275 /* string args above */
@@ -293,6 +296,7 @@ static match_table_t arg_tokens = {
293 {Opt_readdir_max_entries, "readdir_max_entries=%d"}, 296 {Opt_readdir_max_entries, "readdir_max_entries=%d"},
294 /* int args above */ 297 /* int args above */
295 {Opt_snapdirname, "snapdirname=%s"}, 298 {Opt_snapdirname, "snapdirname=%s"},
299 {Opt_name, "name=%s"},
296 {Opt_secret, "secret=%s"}, 300 {Opt_secret, "secret=%s"},
297 /* string args above */ 301 /* string args above */
298 {Opt_ip, "ip=%s"}, 302 {Opt_ip, "ip=%s"},
@@ -407,6 +411,11 @@ static struct ceph_mount_args *parse_mount_args(int flags, char *options,
407 argstr[0].to-argstr[0].from, 411 argstr[0].to-argstr[0].from,
408 GFP_KERNEL); 412 GFP_KERNEL);
409 break; 413 break;
414 case Opt_name:
415 args->name = kstrndup(argstr[0].from,
416 argstr[0].to-argstr[0].from,
417 GFP_KERNEL);
418 break;
410 case Opt_secret: 419 case Opt_secret:
411 args->secret = kstrndup(argstr[0].from, 420 args->secret = kstrndup(argstr[0].from,
412 argstr[0].to-argstr[0].from, 421 argstr[0].to-argstr[0].from,
@@ -476,6 +485,8 @@ static void destroy_mount_args(struct ceph_mount_args *args)
476 dout("destroy_mount_args %p\n", args); 485 dout("destroy_mount_args %p\n", args);
477 kfree(args->snapdir_name); 486 kfree(args->snapdir_name);
478 args->snapdir_name = NULL; 487 args->snapdir_name = NULL;
488 kfree(args->name);
489 args->name = NULL;
479 kfree(args->secret); 490 kfree(args->secret);
480 args->secret = NULL; 491 args->secret = NULL;
481 kfree(args); 492 kfree(args);
@@ -657,27 +668,23 @@ static int ceph_mount(struct ceph_client *client, struct vfsmount *mnt,
657 client->msgr->nocrc = ceph_test_opt(client, NOCRC); 668 client->msgr->nocrc = ceph_test_opt(client, NOCRC);
658 } 669 }
659 670
660 /* send mount request, and wait for mon, mds, and osd maps */ 671 /* open session, and wait for mon, mds, and osd maps */
661 err = ceph_monc_request_mount(&client->monc); 672 err = ceph_monc_open_session(&client->monc);
662 if (err < 0) 673 if (err < 0)
663 goto out; 674 goto out;
664 675
665 while (!have_mon_map(client) && !client->mount_err) { 676 while (!have_mon_map(client)) {
666 err = -EIO; 677 err = -EIO;
667 if (timeout && time_after_eq(jiffies, started + timeout)) 678 if (timeout && time_after_eq(jiffies, started + timeout))
668 goto out; 679 goto out;
669 680
670 /* wait */ 681 /* wait */
671 dout("mount waiting for mount\n"); 682 dout("mount waiting for mon_map\n");
672 err = wait_event_interruptible_timeout(client->mount_wq, 683 err = wait_event_interruptible_timeout(client->mount_wq, /* FIXME */
673 client->mount_err || have_mon_map(client), 684 have_mon_map(client),
674 timeout); 685 timeout);
675 if (err == -EINTR || err == -ERESTARTSYS) 686 if (err == -EINTR || err == -ERESTARTSYS)
676 goto out; 687 goto out;
677 if (client->mount_err) {
678 err = client->mount_err;
679 goto out;
680 }
681 } 688 }
682 689
683 dout("mount opening root\n"); 690 dout("mount opening root\n");
@@ -795,7 +802,6 @@ static int ceph_register_bdi(struct super_block *sb, struct ceph_client *client)
795 client->backing_dev_info.ra_pages = 802 client->backing_dev_info.ra_pages =
796 (client->mount_args->rsize + PAGE_CACHE_SIZE - 1) 803 (client->mount_args->rsize + PAGE_CACHE_SIZE - 1)
797 >> PAGE_SHIFT; 804 >> PAGE_SHIFT;
798
799 err = bdi_register_dev(&client->backing_dev_info, sb->s_dev); 805 err = bdi_register_dev(&client->backing_dev_info, sb->s_dev);
800 return err; 806 return err;
801} 807}
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index 8aa1ffba6c0d..e0e8130959b6 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -61,6 +61,7 @@ struct ceph_mount_args {
61 int max_readdir; /* max readdir size */ 61 int max_readdir; /* max readdir size */
62 int osd_timeout; 62 int osd_timeout;
63 char *snapdir_name; /* default ".snap" */ 63 char *snapdir_name; /* default ".snap" */
64 char *name;
64 char *secret; 65 char *secret;
65 int cap_release_safety; 66 int cap_release_safety;
66}; 67};
@@ -75,6 +76,7 @@ struct ceph_mount_args {
75#define CEPH_MSG_MAX_DATA_LEN (16*1024*1024) 76#define CEPH_MSG_MAX_DATA_LEN (16*1024*1024)
76 77
77#define CEPH_SNAPDIRNAME_DEFAULT ".snap" 78#define CEPH_SNAPDIRNAME_DEFAULT ".snap"
79#define CEPH_AUTH_NAME_DEFAULT "guest"
78 80
79/* 81/*
80 * Delay telling the MDS we no longer want caps, in case we reopen 82 * Delay telling the MDS we no longer want caps, in case we reopen