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