aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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