diff options
-rw-r--r-- | fs/ceph/Makefile | 1 | ||||
-rw-r--r-- | fs/ceph/auth.c | 220 | ||||
-rw-r--r-- | fs/ceph/auth.h | 77 | ||||
-rw-r--r-- | fs/ceph/auth_none.c | 120 | ||||
-rw-r--r-- | fs/ceph/auth_none.h | 28 | ||||
-rw-r--r-- | fs/ceph/ceph_fs.h | 14 | ||||
-rw-r--r-- | fs/ceph/ceph_strings.c | 13 | ||||
-rw-r--r-- | fs/ceph/decode.h | 6 | ||||
-rw-r--r-- | fs/ceph/mds_client.c | 69 | ||||
-rw-r--r-- | fs/ceph/mds_client.h | 4 | ||||
-rw-r--r-- | fs/ceph/messenger.c | 54 | ||||
-rw-r--r-- | fs/ceph/messenger.h | 10 | ||||
-rw-r--r-- | fs/ceph/mon_client.c | 210 | ||||
-rw-r--r-- | fs/ceph/mon_client.h | 14 | ||||
-rw-r--r-- | fs/ceph/msgr.h | 21 | ||||
-rw-r--r-- | fs/ceph/osd_client.c | 63 | ||||
-rw-r--r-- | fs/ceph/osd_client.h | 4 | ||||
-rw-r--r-- | fs/ceph/rados.h | 2 | ||||
-rw-r--r-- | fs/ceph/super.c | 32 | ||||
-rw-r--r-- | fs/ceph/super.h | 2 |
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 | ||
18 | else | 19 | else |
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 | */ | ||
16 | static u32 supported_protocols[] = { | ||
17 | CEPH_AUTH_NONE | ||
18 | }; | ||
19 | |||
20 | int 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 | */ | ||
33 | struct 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 | |||
54 | out: | ||
55 | return ERR_PTR(ret); | ||
56 | } | ||
57 | |||
58 | void 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 | */ | ||
69 | void 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 | |||
77 | int 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 | */ | ||
93 | int 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 | |||
124 | bad: | ||
125 | return -ERANGE; | ||
126 | } | ||
127 | |||
128 | /* | ||
129 | * Handle auth message from monitor. | ||
130 | */ | ||
131 | int 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 | |||
214 | bad: | ||
215 | pr_err("failed to decode auth msg\n"); | ||
216 | out: | ||
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 | |||
14 | struct ceph_auth_client; | ||
15 | struct ceph_authorizer; | ||
16 | |||
17 | struct 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 | |||
52 | struct 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 | |||
64 | extern struct ceph_auth_client *ceph_auth_init(const char *name, | ||
65 | const char *secret); | ||
66 | extern void ceph_auth_destroy(struct ceph_auth_client *ac); | ||
67 | |||
68 | extern void ceph_auth_reset(struct ceph_auth_client *ac); | ||
69 | |||
70 | extern int ceph_auth_build_hello(struct ceph_auth_client *ac, | ||
71 | void *buf, size_t len); | ||
72 | extern int ceph_handle_auth_reply(struct ceph_auth_client *ac, | ||
73 | void *buf, size_t len, | ||
74 | void *reply_buf, size_t reply_len); | ||
75 | extern 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 | |||
12 | static 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 | |||
20 | static void destroy(struct ceph_auth_client *ac) | ||
21 | { | ||
22 | kfree(ac->private); | ||
23 | ac->private = NULL; | ||
24 | } | ||
25 | |||
26 | static 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 | */ | ||
37 | static 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 | */ | ||
51 | static 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 | |||
82 | bad2: | ||
83 | ret = -ERANGE; | ||
84 | bad: | ||
85 | return ret; | ||
86 | } | ||
87 | |||
88 | static void ceph_auth_none_destroy_authorizer(struct ceph_auth_client *ac, | ||
89 | struct ceph_authorizer *a) | ||
90 | { | ||
91 | /* nothing to do */ | ||
92 | } | ||
93 | |||
94 | static 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 | |||
103 | int 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 | |||
13 | struct ceph_none_authorizer { | ||
14 | char buf[128]; | ||
15 | int buf_len; | ||
16 | char reply_buf[0]; | ||
17 | }; | ||
18 | |||
19 | struct 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 | |||
25 | extern 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 { | |||
75 | int ceph_file_layout_is_valid(const struct ceph_file_layout *layout); | 75 | int 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 | ||
6 | const 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 | |||
6 | const char *ceph_osd_op_name(int op) | 19 | const 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) | |||
98 | static inline void ceph_decode_addr(struct ceph_entity_addr *a) | 98 | static 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 | } |
127 | static 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 | */ | ||
2912 | static 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 | |||
2948 | static 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 | |||
2898 | const static struct ceph_connection_operations mds_con_ops = { | 2957 | const 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 | ||
553 | static 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 | ||
804 | static 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 | |||
780 | static void prepare_read_ack(struct ceph_connection *con) | 811 | static 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)); |
860 | out: | 896 | out: |
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) | |||
106 | static int __open_session(struct ceph_mon_client *monc) | 113 | static 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 | ||
283 | int ceph_monc_request_mount(struct ceph_mon_client *monc) | 302 | /* |
303 | * | ||
304 | */ | ||
305 | int 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 | */ | ||
405 | static 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 | */ | ||
447 | static 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 | |||
700 | out_pool3: | ||
701 | ceph_msgpool_destroy(&monc->msgpool_auth_reply); | ||
702 | out_pool2: | ||
703 | ceph_msgpool_destroy(&monc->msgpool_subscribe_ack); | ||
704 | out_pool1: | ||
705 | ceph_msgpool_destroy(&monc->msgpool_statfs_reply); | ||
706 | out_monmap: | ||
707 | kfree(monc->monmap); | ||
609 | out: | 708 | out: |
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 | ||
737 | static 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 | ||
10 | struct ceph_client; | 10 | struct ceph_client; |
11 | struct ceph_mount_args; | 11 | struct ceph_mount_args; |
12 | struct 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 | ||
102 | extern void ceph_monc_request_next_osdmap(struct ceph_mon_client *monc); | 106 | extern void ceph_monc_request_next_osdmap(struct ceph_mon_client *monc); |
103 | 107 | ||
104 | extern int ceph_monc_request_mount(struct ceph_mon_client *monc); | ||
105 | |||
106 | extern int ceph_monc_do_statfs(struct ceph_mon_client *monc, | 108 | extern int ceph_monc_do_statfs(struct ceph_mon_client *monc, |
107 | struct ceph_statfs *buf); | 109 | struct ceph_statfs *buf); |
108 | 110 | ||
111 | extern 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 | |||
58 | extern 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 | ||
15 | const static struct ceph_connection_operations osd_con_ops; | 16 | const 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 | */ | ||
1316 | static 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 | |||
1350 | static 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 | |||
1305 | const static struct ceph_connection_operations osd_con_ops = { | 1360 | const 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; | |||
13 | struct ceph_snap_context; | 13 | struct ceph_snap_context; |
14 | struct ceph_osd_request; | 14 | struct ceph_osd_request; |
15 | struct ceph_osd_client; | 15 | struct ceph_osd_client; |
16 | struct 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 | ||
290 | enum { | 290 | enum { |
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 |