Whamcloud - gitweb
5e967b184370dfd018aca15d3dd4d5f5fae2ad77
[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  *  lustre/mdt/mdt_capa.c
5  *  Lustre Metadata Target (mdt) capability key read/write/update.
6  *
7  *  Copyright (C) 2005 Cluster File Systems, Inc.
8  *   Author: Lai Siyao <lsy@clusterfs.com>
9  *
10  *   This file is part of the Lustre file system, http://www.lustre.org
11  *   Lustre is a trademark of Cluster File Systems, Inc.
12  *
13  *   You may have signed or agreed to another license before downloading
14  *   this software.  If so, you are bound by the terms and conditions
15  *   of that agreement, and the following does not apply to you.  See the
16  *   LICENSE file included with this distribution for more information.
17  *
18  *   If you did not agree to a different license, then this copy of Lustre
19  *   is open source software; you can redistribute it and/or modify it
20  *   under the terms of version 2 of the GNU General Public License as
21  *   published by the Free Software Foundation.
22  *
23  *   In either case, Lustre is distributed in the hope that it will be
24  *   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
25  *   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26  *   license text for more details.
27  */
28
29 #ifndef EXPORT_SYMTAB
30 # define EXPORT_SYMTAB
31 #endif
32 #define DEBUG_SUBSYSTEM S_MDS
33
34 #include "mdt_internal.h"
35
36 static inline void set_capa_key_expiry(struct mdt_device *mdt)
37 {
38         mdt->mdt_ck_expiry = jiffies + mdt->mdt_ck_timeout * HZ;
39 }
40
41 static void make_capa_key(struct lustre_capa_key *key,
42                           mdsno_t mdsnum, int keyid)
43 {
44         key->lk_mdsid = mdsnum;
45         key->lk_keyid = keyid + 1;
46         get_random_bytes(key->lk_key, sizeof(key->lk_key));
47 }
48
49 enum {
50         MDT_TXN_CAPA_KEYS_WRITE_CREDITS = 1
51 };
52
53 static inline void lck_cpu_to_le(struct lustre_capa_key *tgt,
54                                  struct lustre_capa_key *src)
55 {
56         tgt->lk_mdsid   = cpu_to_le64(src->lk_mdsid);
57         tgt->lk_keyid   = cpu_to_le32(src->lk_keyid);
58         tgt->lk_padding = cpu_to_le32(src->lk_padding);
59         memcpy(tgt->lk_key, src->lk_key, sizeof(src->lk_key));
60 }
61
62 static inline void lck_le_to_cpu(struct lustre_capa_key *tgt,
63                                  struct lustre_capa_key *src)
64 {
65         tgt->lk_mdsid   = le64_to_cpu(src->lk_mdsid);
66         tgt->lk_keyid   = le32_to_cpu(src->lk_keyid);
67         tgt->lk_padding = le32_to_cpu(src->lk_padding);
68         memcpy(tgt->lk_key, src->lk_key, sizeof(src->lk_key));
69 }
70
71 static int write_capa_keys(const struct lu_env *env,
72                            struct mdt_device *mdt,
73                            struct lustre_capa_key *keys)
74 {
75         struct mdt_thread_info *mti;
76         struct lustre_capa_key *tmp;
77         struct thandle *th;
78         loff_t off = 0;
79         int i, rc;
80
81         mti = lu_context_key_get(&env->le_ctx, &mdt_thread_key);
82
83         th = mdt_trans_start(env, mdt, MDT_TXN_CAPA_KEYS_WRITE_CREDITS);
84         if (IS_ERR(th))
85                 RETURN(PTR_ERR(th));
86
87         tmp = &mti->mti_capa_key;
88
89         for (i = 0; i < 2; i++) {
90                 lck_cpu_to_le(tmp, &keys[i]);
91
92                 rc = mdt_record_write(env, mdt->mdt_ck_obj,
93                                       mdt_buf_const(env, tmp, sizeof(*tmp)),
94                                       &off, th);
95                 if (rc)
96                         break;
97         }
98
99         mdt_trans_stop(env, mdt, th);
100
101         CDEBUG(D_INFO, "write capability keys rc = %d:\n", rc);
102         return rc;
103 }
104
105 static int read_capa_keys(const struct lu_env *env,
106                           struct mdt_device *mdt,
107                           struct lustre_capa_key *keys)
108 {
109         struct mdt_thread_info *mti;
110         struct lustre_capa_key *tmp;
111         loff_t off = 0;
112         int i, rc;
113
114         mti = lu_context_key_get(&env->le_ctx, &mdt_thread_key);
115         tmp = &mti->mti_capa_key;
116
117         for (i = 0; i < 2; i++) {
118                 rc = mdt_record_read(env, mdt->mdt_ck_obj,
119                                      mdt_buf(env, tmp, sizeof(*tmp)), &off);
120                 if (rc)
121                         return rc;
122
123                 lck_le_to_cpu(&keys[i], tmp);
124                 DEBUG_CAPA_KEY(D_SEC, &keys[i], "read");
125         }
126
127         return 0;
128 }
129
130 int mdt_capa_keys_init(const struct lu_env *env, struct mdt_device *mdt)
131 {
132         struct lustre_capa_key  *keys = mdt->mdt_capa_keys;
133         struct mdt_thread_info  *mti;
134         struct dt_object        *obj;
135         struct lu_attr          *la;
136         mdsno_t                  mdsnum;
137         unsigned long            size;
138         int                      rc;
139         ENTRY;
140
141         mdsnum = mdt->mdt_md_dev.md_lu_dev.ld_site->ls_node_id;
142
143         mti = lu_context_key_get(&env->le_ctx, &mdt_thread_key);
144         LASSERT(mti != NULL);
145         la = &mti->mti_attr.ma_attr;
146
147         obj = mdt->mdt_ck_obj;
148         rc = obj->do_ops->do_attr_get(env, mdt->mdt_ck_obj, la, BYPASS_CAPA);
149         if (rc)
150                 RETURN(rc);
151
152         size = (unsigned long)la->la_size;
153         if (size == 0) {
154                 int i;
155
156                 for (i = 0; i < 2; i++) {
157                         make_capa_key(&keys[i], mdsnum, i);
158                         DEBUG_CAPA_KEY(D_SEC, &keys[i], "initializing");
159                 }
160
161                 rc = write_capa_keys(env, mdt, keys);
162                 if (rc) {
163                         CERROR("error writing MDS %s: rc %d\n", CAPA_KEYS, rc);
164                         RETURN(rc);
165                 }
166         } else {
167                 rc = read_capa_keys(env, mdt, keys);
168                 if (rc) {
169                         CERROR("error reading MDS %s: rc %d\n", CAPA_KEYS, rc);
170                         RETURN(rc);
171                 }
172         }
173         set_capa_key_expiry(mdt);
174         mod_timer(&mdt->mdt_ck_timer, mdt->mdt_ck_expiry);
175         CDEBUG(D_SEC, "mds_ck_timer %lu\n", mdt->mdt_ck_expiry);
176         RETURN(0);
177 }
178
179 void mdt_ck_timer_callback(unsigned long castmeharder)
180 {
181         struct mdt_device *mdt = (struct mdt_device *)castmeharder;
182         struct ptlrpc_thread *thread = &mdt->mdt_ck_thread;
183
184         ENTRY;
185         thread->t_flags |= SVC_EVENT;
186         wake_up(&thread->t_ctl_waitq);
187         EXIT;
188 }
189
190 static int mdt_ck_thread_main(void *args)
191 {
192         struct mdt_device      *mdt = args;
193         struct ptlrpc_thread   *thread = &mdt->mdt_ck_thread;
194         struct lustre_capa_key *bkey = &mdt->mdt_capa_keys[0],
195                                *rkey = &mdt->mdt_capa_keys[1];
196         struct lustre_capa_key *tmp;
197         struct lu_env           env;
198         struct mdt_thread_info *info;
199         struct md_device       *next;
200         struct l_wait_info      lwi = { 0 };
201         mdsno_t                 mdsnum;
202         int                     rc;
203         ENTRY;
204
205         ptlrpc_daemonize("mdt_ck");
206         cfs_block_allsigs();
207
208         thread->t_flags = SVC_RUNNING;
209         cfs_waitq_signal(&thread->t_ctl_waitq);
210
211         rc = lu_env_init(&env, NULL, LCT_MD_THREAD);
212         if (rc)
213                 RETURN(rc);
214
215         thread->t_env = &env;
216         env.le_ctx.lc_thread = thread;
217
218         info = lu_context_key_get(&env.le_ctx, &mdt_thread_key);
219         LASSERT(info != NULL);
220
221         tmp = &info->mti_capa_key;
222         mdsnum = mdt->mdt_md_dev.md_lu_dev.ld_site->ls_node_id;
223         while (1) {
224                 l_wait_event(thread->t_ctl_waitq,
225                              thread->t_flags & (SVC_STOPPING | SVC_EVENT),
226                              &lwi);
227
228                 if (thread->t_flags & SVC_STOPPING)
229                         break;
230                 thread->t_flags &= ~SVC_EVENT;
231
232                 if (time_after(mdt->mdt_ck_expiry, jiffies))
233                         break;
234
235                 *tmp = *rkey;
236                 make_capa_key(tmp, mdsnum, rkey->lk_keyid);
237
238                 next = mdt->mdt_child;
239                 rc = next->md_ops->mdo_update_capa_key(&env, next, tmp);
240                 if (!rc) {
241                         spin_lock(&capa_lock);
242                         *bkey = *rkey;
243                         *rkey = *tmp;
244                         spin_unlock(&capa_lock);
245
246                         rc = write_capa_keys(&env, mdt, mdt->mdt_capa_keys);
247                         if (rc) {
248                                 spin_lock(&capa_lock);
249                                 *rkey = *bkey;
250                                 memset(bkey, 0, sizeof(*bkey));
251                                 spin_unlock(&capa_lock);
252                         } else {
253                                 set_capa_key_expiry(mdt);
254                                 DEBUG_CAPA_KEY(D_SEC, rkey, "new");
255                         }
256                 }
257                 if (rc) {
258                         DEBUG_CAPA_KEY(D_ERROR, rkey, "update failed for");
259                         /* next retry is in 300 sec */
260                         mdt->mdt_ck_expiry = jiffies + 300 * HZ;
261                 }
262
263                 mod_timer(&mdt->mdt_ck_timer, mdt->mdt_ck_expiry);
264                 CDEBUG(D_SEC, "mdt_ck_timer %lu\n", mdt->mdt_ck_expiry);
265         }
266         lu_env_fini(&env);
267
268         thread->t_flags = SVC_STOPPED;
269         cfs_waitq_signal(&thread->t_ctl_waitq);
270         RETURN(0);
271 }
272
273 int mdt_ck_thread_start(struct mdt_device *mdt)
274 {
275         struct ptlrpc_thread *thread = &mdt->mdt_ck_thread;
276         int rc;
277
278         cfs_waitq_init(&thread->t_ctl_waitq);
279         rc = kernel_thread(mdt_ck_thread_main, mdt,
280                            (CLONE_VM | CLONE_FILES));
281         if (rc < 0) {
282                 CERROR("cannot start mdt_ck thread, rc = %d\n", rc);
283                 return rc;
284         }
285
286         wait_event(thread->t_ctl_waitq, thread->t_flags & SVC_RUNNING);
287         return 0;
288 }
289
290 void mdt_ck_thread_stop(struct mdt_device *mdt)
291 {
292         struct ptlrpc_thread *thread = &mdt->mdt_ck_thread;
293
294         if (!(thread->t_flags & SVC_RUNNING))
295                 return;
296
297         thread->t_flags = SVC_STOPPING;
298         cfs_waitq_signal(&thread->t_ctl_waitq);
299         wait_event(thread->t_ctl_waitq, thread->t_flags & SVC_STOPPED);
300 }
301
302