Whamcloud - gitweb
e2b863e84177f54c82fcc762c188d6784b28deac
[fs/lustre-release.git] / lustre / mdt / mdt_capa.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
19  *
20  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21  * CA 95054 USA or visit www.sun.com if you need additional information or
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  *
30  * Copyright (c) 2012, Whamcloud, Inc.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  *
36  * lustre/mdt/mdt_capa.c
37  *
38  * Lustre Metadata Target (mdt) capability key read/write/update.
39  *
40  * Author: Lai Siyao <lsy@clusterfs.com>
41  */
42
43 #ifndef EXPORT_SYMTAB
44 # define EXPORT_SYMTAB
45 #endif
46 #define DEBUG_SUBSYSTEM S_MDS
47
48 #include "mdt_internal.h"
49
50 static inline void set_capa_key_expiry(struct mdt_device *mdt)
51 {
52         mdt->mdt_ck_expiry = jiffies + mdt->mdt_ck_timeout * CFS_HZ;
53 }
54
55 static void make_capa_key(struct lustre_capa_key *key,
56                           mdsno_t mdsnum, int keyid)
57 {
58         key->lk_seq = mdsnum;
59         key->lk_keyid = keyid + 1;
60         cfs_get_random_bytes(key->lk_key, sizeof(key->lk_key));
61 }
62
63 static inline void lck_cpu_to_le(struct lustre_capa_key *tgt,
64                                  struct lustre_capa_key *src)
65 {
66         tgt->lk_seq   = cpu_to_le64(src->lk_seq);
67         tgt->lk_keyid   = cpu_to_le32(src->lk_keyid);
68         tgt->lk_padding = cpu_to_le32(src->lk_padding);
69         memcpy(tgt->lk_key, src->lk_key, sizeof(src->lk_key));
70 }
71
72 static inline void lck_le_to_cpu(struct lustre_capa_key *tgt,
73                                  struct lustre_capa_key *src)
74 {
75         tgt->lk_seq   = le64_to_cpu(src->lk_seq);
76         tgt->lk_keyid   = le32_to_cpu(src->lk_keyid);
77         tgt->lk_padding = le32_to_cpu(src->lk_padding);
78         memcpy(tgt->lk_key, src->lk_key, sizeof(src->lk_key));
79 }
80
81 static int write_capa_keys(const struct lu_env *env,
82                            struct mdt_device *mdt,
83                            struct lustre_capa_key *keys)
84 {
85         struct mdt_thread_info *mti;
86         struct lustre_capa_key *tmp;
87         struct thandle *th;
88         loff_t off = 0;
89         int i, rc;
90
91         mti = lu_context_key_get(&env->le_ctx, &mdt_thread_key);
92         th = mdt_trans_create(env, mdt);
93         if (IS_ERR(th))
94                 RETURN(PTR_ERR(th));
95
96         rc = dt_declare_record_write(env, mdt->mdt_ck_obj,
97                                      sizeof(*tmp) * 3, 0, th);
98         if (rc)
99                 goto stop;
100
101         rc = mdt_trans_start(env, mdt, th);
102         if (rc)
103                 goto stop;
104
105         tmp = &mti->mti_capa_key;
106
107         for (i = 0; i < 2; i++) {
108                 lck_cpu_to_le(tmp, &keys[i]);
109
110                 rc = dt_record_write(env, mdt->mdt_ck_obj,
111                                      mdt_buf_const(env, tmp, sizeof(*tmp)),
112                                      &off, th);
113                 if (rc)
114                         break;
115         }
116
117 stop:
118         mdt_trans_stop(env, mdt, th);
119
120         CDEBUG(D_INFO, "write capability keys rc = %d:\n", rc);
121         return rc;
122 }
123
124 static int read_capa_keys(const struct lu_env *env,
125                           struct mdt_device *mdt,
126                           struct lustre_capa_key *keys)
127 {
128         struct mdt_thread_info *mti;
129         struct lustre_capa_key *tmp;
130         loff_t off = 0;
131         int i, rc;
132
133         mti = lu_context_key_get(&env->le_ctx, &mdt_thread_key);
134         tmp = &mti->mti_capa_key;
135
136         for (i = 0; i < 2; i++) {
137                 rc = dt_record_read(env, mdt->mdt_ck_obj,
138                                     mdt_buf(env, tmp, sizeof(*tmp)), &off);
139                 if (rc)
140                         return rc;
141
142                 lck_le_to_cpu(&keys[i], tmp);
143                 DEBUG_CAPA_KEY(D_SEC, &keys[i], "read");
144         }
145
146         return 0;
147 }
148
149 int mdt_capa_keys_init(const struct lu_env *env, struct mdt_device *mdt)
150 {
151         struct lustre_capa_key  *keys = mdt->mdt_capa_keys;
152         struct mdt_thread_info  *mti;
153         struct dt_object        *obj;
154         struct lu_attr          *la;
155         mdsno_t                  mdsnum;
156         unsigned long            size;
157         int                      rc;
158         ENTRY;
159
160         mdsnum = mdt_md_site(mdt)->ms_node_id;
161
162         mti = lu_context_key_get(&env->le_ctx, &mdt_thread_key);
163         LASSERT(mti != NULL);
164         la = &mti->mti_attr.ma_attr;
165
166         obj = mdt->mdt_ck_obj;
167         rc = obj->do_ops->do_attr_get(env, mdt->mdt_ck_obj, la, BYPASS_CAPA);
168         if (rc)
169                 RETURN(rc);
170
171         size = (unsigned long)la->la_size;
172         if (size == 0) {
173                 int i;
174
175                 for (i = 0; i < 2; i++) {
176                         make_capa_key(&keys[i], mdsnum, i);
177                         DEBUG_CAPA_KEY(D_SEC, &keys[i], "initializing");
178                 }
179
180                 rc = write_capa_keys(env, mdt, keys);
181                 if (rc) {
182                         CERROR("error writing MDS %s: rc %d\n", CAPA_KEYS, rc);
183                         RETURN(rc);
184                 }
185         } else {
186                 rc = read_capa_keys(env, mdt, keys);
187                 if (rc) {
188                         CERROR("error reading MDS %s: rc %d\n", CAPA_KEYS, rc);
189                         RETURN(rc);
190                 }
191         }
192         set_capa_key_expiry(mdt);
193         cfs_timer_arm(&mdt->mdt_ck_timer, mdt->mdt_ck_expiry);
194         CDEBUG(D_SEC, "mds_ck_timer %lu\n", mdt->mdt_ck_expiry);
195         RETURN(0);
196 }
197
198 void mdt_ck_timer_callback(unsigned long castmeharder)
199 {
200         struct mdt_device *mdt = (struct mdt_device *)castmeharder;
201         struct ptlrpc_thread *thread = &mdt->mdt_ck_thread;
202
203         ENTRY;
204         thread_add_flags(thread, SVC_EVENT);
205         cfs_waitq_signal(&thread->t_ctl_waitq);
206         EXIT;
207 }
208
209 static int mdt_ck_thread_main(void *args)
210 {
211         struct mdt_device      *mdt = args;
212         struct ptlrpc_thread   *thread = &mdt->mdt_ck_thread;
213         struct lustre_capa_key *bkey = &mdt->mdt_capa_keys[0],
214                                *rkey = &mdt->mdt_capa_keys[1];
215         struct lustre_capa_key *tmp;
216         struct lu_env           env;
217         struct mdt_thread_info *info;
218         struct md_device       *next;
219         struct l_wait_info      lwi = { 0 };
220         mdsno_t                 mdsnum;
221         int                     rc;
222         ENTRY;
223
224         cfs_daemonize_ctxt("mdt_ck");
225         cfs_block_allsigs();
226
227         thread_set_flags(thread, SVC_RUNNING);
228         cfs_waitq_signal(&thread->t_ctl_waitq);
229
230         rc = lu_env_init(&env, LCT_MD_THREAD|LCT_REMEMBER|LCT_NOREF);
231         if (rc)
232                 RETURN(rc);
233
234         thread->t_env = &env;
235         env.le_ctx.lc_thread = thread;
236         env.le_ctx.lc_cookie = 0x1;
237
238         info = lu_context_key_get(&env.le_ctx, &mdt_thread_key);
239         LASSERT(info != NULL);
240
241         tmp = &info->mti_capa_key;
242         mdsnum = mdt_md_site(mdt)->ms_node_id;
243         while (1) {
244                 l_wait_event(thread->t_ctl_waitq,
245                              thread_is_stopping(thread) ||
246                              thread_is_event(thread),
247                              &lwi);
248
249                 if (thread_is_stopping(thread))
250                         break;
251                 thread_clear_flags(thread, SVC_EVENT);
252
253                 if (cfs_time_before(cfs_time_current(), mdt->mdt_ck_expiry))
254                         break;
255
256                 *tmp = *rkey;
257                 make_capa_key(tmp, mdsnum, rkey->lk_keyid);
258
259                 next = mdt->mdt_child;
260                 rc = next->md_ops->mdo_update_capa_key(&env, next, tmp);
261                 if (!rc) {
262                         cfs_spin_lock(&capa_lock);
263                         *bkey = *rkey;
264                         *rkey = *tmp;
265                         cfs_spin_unlock(&capa_lock);
266
267                         rc = write_capa_keys(&env, mdt, mdt->mdt_capa_keys);
268                         if (rc) {
269                                 cfs_spin_lock(&capa_lock);
270                                 *rkey = *bkey;
271                                 memset(bkey, 0, sizeof(*bkey));
272                                 cfs_spin_unlock(&capa_lock);
273                         } else {
274                                 set_capa_key_expiry(mdt);
275                                 DEBUG_CAPA_KEY(D_SEC, rkey, "new");
276                         }
277                 }
278                 if (rc) {
279                         DEBUG_CAPA_KEY(D_ERROR, rkey, "update failed for");
280                         /* next retry is in 300 sec */
281                         mdt->mdt_ck_expiry = jiffies + 300 * CFS_HZ;
282                 }
283
284                 cfs_timer_arm(&mdt->mdt_ck_timer, mdt->mdt_ck_expiry);
285                 CDEBUG(D_SEC, "mdt_ck_timer %lu\n", mdt->mdt_ck_expiry);
286         }
287         lu_env_fini(&env);
288
289         thread_set_flags(thread, SVC_STOPPED);
290         cfs_waitq_signal(&thread->t_ctl_waitq);
291         RETURN(0);
292 }
293
294 int mdt_ck_thread_start(struct mdt_device *mdt)
295 {
296         struct ptlrpc_thread *thread = &mdt->mdt_ck_thread;
297         int rc;
298
299         cfs_waitq_init(&thread->t_ctl_waitq);
300         rc = cfs_create_thread(mdt_ck_thread_main, mdt, CFS_DAEMON_FLAGS);
301         if (rc < 0) {
302                 CERROR("cannot start mdt_ck thread, rc = %d\n", rc);
303                 return rc;
304         }
305
306         l_wait_condition(thread->t_ctl_waitq, thread_is_running(thread));
307         return 0;
308 }
309
310 void mdt_ck_thread_stop(struct mdt_device *mdt)
311 {
312         struct ptlrpc_thread *thread = &mdt->mdt_ck_thread;
313
314         if (!thread_is_running(thread))
315                 return;
316
317         thread_set_flags(thread, SVC_STOPPING);
318         cfs_waitq_signal(&thread->t_ctl_waitq);
319         l_wait_condition(thread->t_ctl_waitq, thread_is_stopped(thread));
320 }