Whamcloud - gitweb
LU-1206: mdt: Fix error handling in mdt_mfd_open
[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  * Copyright (c) 2012, Whamcloud, Inc.
33  */
34 /*
35  * This file is part of Lustre, http://www.lustre.org/
36  * Lustre is a trademark of Sun Microsystems, Inc.
37  *
38  * lustre/mdt/mdt_capa.c
39  *
40  * Lustre Metadata Target (mdt) capability key read/write/update.
41  *
42  * Author: Lai Siyao <lsy@clusterfs.com>
43  */
44
45 #ifndef EXPORT_SYMTAB
46 # define EXPORT_SYMTAB
47 #endif
48 #define DEBUG_SUBSYSTEM S_MDS
49
50 #include "mdt_internal.h"
51
52 static inline void set_capa_key_expiry(struct mdt_device *mdt)
53 {
54         mdt->mdt_ck_expiry = jiffies + mdt->mdt_ck_timeout * CFS_HZ;
55 }
56
57 static void make_capa_key(struct lustre_capa_key *key,
58                           mdsno_t mdsnum, int keyid)
59 {
60         key->lk_seq = mdsnum;
61         key->lk_keyid = keyid + 1;
62         cfs_get_random_bytes(key->lk_key, sizeof(key->lk_key));
63 }
64
65 static inline void lck_cpu_to_le(struct lustre_capa_key *tgt,
66                                  struct lustre_capa_key *src)
67 {
68         tgt->lk_seq   = cpu_to_le64(src->lk_seq);
69         tgt->lk_keyid   = cpu_to_le32(src->lk_keyid);
70         tgt->lk_padding = cpu_to_le32(src->lk_padding);
71         memcpy(tgt->lk_key, src->lk_key, sizeof(src->lk_key));
72 }
73
74 static inline void lck_le_to_cpu(struct lustre_capa_key *tgt,
75                                  struct lustre_capa_key *src)
76 {
77         tgt->lk_seq   = le64_to_cpu(src->lk_seq);
78         tgt->lk_keyid   = le32_to_cpu(src->lk_keyid);
79         tgt->lk_padding = le32_to_cpu(src->lk_padding);
80         memcpy(tgt->lk_key, src->lk_key, sizeof(src->lk_key));
81 }
82
83 static int write_capa_keys(const struct lu_env *env,
84                            struct mdt_device *mdt,
85                            struct lustre_capa_key *keys)
86 {
87         struct mdt_thread_info *mti;
88         struct lustre_capa_key *tmp;
89         struct thandle *th;
90         loff_t off = 0;
91         int i, rc;
92
93         mti = lu_context_key_get(&env->le_ctx, &mdt_thread_key);
94         th = mdt_trans_create(env, mdt);
95         if (IS_ERR(th))
96                 RETURN(PTR_ERR(th));
97
98         rc = dt_declare_record_write(env, mdt->mdt_ck_obj,
99                                      sizeof(*tmp) * 3, 0, th);
100         if (rc)
101                 goto stop;
102
103         rc = mdt_trans_start(env, mdt, th);
104         if (rc)
105                 goto stop;
106
107         tmp = &mti->mti_capa_key;
108
109         for (i = 0; i < 2; i++) {
110                 lck_cpu_to_le(tmp, &keys[i]);
111
112                 rc = dt_record_write(env, mdt->mdt_ck_obj,
113                                      mdt_buf_const(env, tmp, sizeof(*tmp)),
114                                      &off, th);
115                 if (rc)
116                         break;
117         }
118
119 stop:
120         mdt_trans_stop(env, mdt, th);
121
122         CDEBUG(D_INFO, "write capability keys rc = %d:\n", rc);
123         return rc;
124 }
125
126 static int read_capa_keys(const struct lu_env *env,
127                           struct mdt_device *mdt,
128                           struct lustre_capa_key *keys)
129 {
130         struct mdt_thread_info *mti;
131         struct lustre_capa_key *tmp;
132         loff_t off = 0;
133         int i, rc;
134
135         mti = lu_context_key_get(&env->le_ctx, &mdt_thread_key);
136         tmp = &mti->mti_capa_key;
137
138         for (i = 0; i < 2; i++) {
139                 rc = dt_record_read(env, mdt->mdt_ck_obj,
140                                     mdt_buf(env, tmp, sizeof(*tmp)), &off);
141                 if (rc)
142                         return rc;
143
144                 lck_le_to_cpu(&keys[i], tmp);
145                 DEBUG_CAPA_KEY(D_SEC, &keys[i], "read");
146         }
147
148         return 0;
149 }
150
151 int mdt_capa_keys_init(const struct lu_env *env, struct mdt_device *mdt)
152 {
153         struct lustre_capa_key  *keys = mdt->mdt_capa_keys;
154         struct mdt_thread_info  *mti;
155         struct dt_object        *obj;
156         struct lu_attr          *la;
157         mdsno_t                  mdsnum;
158         unsigned long            size;
159         int                      rc;
160         ENTRY;
161
162         mdsnum = mdt_md_site(mdt)->ms_node_id;
163
164         mti = lu_context_key_get(&env->le_ctx, &mdt_thread_key);
165         LASSERT(mti != NULL);
166         la = &mti->mti_attr.ma_attr;
167
168         obj = mdt->mdt_ck_obj;
169         rc = obj->do_ops->do_attr_get(env, mdt->mdt_ck_obj, la, BYPASS_CAPA);
170         if (rc)
171                 RETURN(rc);
172
173         size = (unsigned long)la->la_size;
174         if (size == 0) {
175                 int i;
176
177                 for (i = 0; i < 2; i++) {
178                         make_capa_key(&keys[i], mdsnum, i);
179                         DEBUG_CAPA_KEY(D_SEC, &keys[i], "initializing");
180                 }
181
182                 rc = write_capa_keys(env, mdt, keys);
183                 if (rc) {
184                         CERROR("error writing MDS %s: rc %d\n", CAPA_KEYS, rc);
185                         RETURN(rc);
186                 }
187         } else {
188                 rc = read_capa_keys(env, mdt, keys);
189                 if (rc) {
190                         CERROR("error reading MDS %s: rc %d\n", CAPA_KEYS, rc);
191                         RETURN(rc);
192                 }
193         }
194         set_capa_key_expiry(mdt);
195         cfs_timer_arm(&mdt->mdt_ck_timer, mdt->mdt_ck_expiry);
196         CDEBUG(D_SEC, "mds_ck_timer %lu\n", mdt->mdt_ck_expiry);
197         RETURN(0);
198 }
199
200 void mdt_ck_timer_callback(unsigned long castmeharder)
201 {
202         struct mdt_device *mdt = (struct mdt_device *)castmeharder;
203         struct ptlrpc_thread *thread = &mdt->mdt_ck_thread;
204
205         ENTRY;
206         thread_add_flags(thread, SVC_EVENT);
207         cfs_waitq_signal(&thread->t_ctl_waitq);
208         EXIT;
209 }
210
211 static int mdt_ck_thread_main(void *args)
212 {
213         struct mdt_device      *mdt = args;
214         struct ptlrpc_thread   *thread = &mdt->mdt_ck_thread;
215         struct lustre_capa_key *bkey = &mdt->mdt_capa_keys[0],
216                                *rkey = &mdt->mdt_capa_keys[1];
217         struct lustre_capa_key *tmp;
218         struct lu_env           env;
219         struct mdt_thread_info *info;
220         struct md_device       *next;
221         struct l_wait_info      lwi = { 0 };
222         mdsno_t                 mdsnum;
223         int                     rc;
224         ENTRY;
225
226         cfs_daemonize_ctxt("mdt_ck");
227         cfs_block_allsigs();
228
229         thread_set_flags(thread, SVC_RUNNING);
230         cfs_waitq_signal(&thread->t_ctl_waitq);
231
232         rc = lu_env_init(&env, LCT_MD_THREAD|LCT_REMEMBER|LCT_NOREF);
233         if (rc)
234                 RETURN(rc);
235
236         thread->t_env = &env;
237         env.le_ctx.lc_thread = thread;
238         env.le_ctx.lc_cookie = 0x1;
239
240         info = lu_context_key_get(&env.le_ctx, &mdt_thread_key);
241         LASSERT(info != NULL);
242
243         tmp = &info->mti_capa_key;
244         mdsnum = mdt_md_site(mdt)->ms_node_id;
245         while (1) {
246                 l_wait_event(thread->t_ctl_waitq,
247                              thread_is_stopping(thread) ||
248                              thread_is_event(thread),
249                              &lwi);
250
251                 if (thread_is_stopping(thread))
252                         break;
253                 thread_clear_flags(thread, SVC_EVENT);
254
255                 if (cfs_time_before(cfs_time_current(), mdt->mdt_ck_expiry))
256                         break;
257
258                 *tmp = *rkey;
259                 make_capa_key(tmp, mdsnum, rkey->lk_keyid);
260
261                 next = mdt->mdt_child;
262                 rc = next->md_ops->mdo_update_capa_key(&env, next, tmp);
263                 if (!rc) {
264                         cfs_spin_lock(&capa_lock);
265                         *bkey = *rkey;
266                         *rkey = *tmp;
267                         cfs_spin_unlock(&capa_lock);
268
269                         rc = write_capa_keys(&env, mdt, mdt->mdt_capa_keys);
270                         if (rc) {
271                                 cfs_spin_lock(&capa_lock);
272                                 *rkey = *bkey;
273                                 memset(bkey, 0, sizeof(*bkey));
274                                 cfs_spin_unlock(&capa_lock);
275                         } else {
276                                 set_capa_key_expiry(mdt);
277                                 DEBUG_CAPA_KEY(D_SEC, rkey, "new");
278                         }
279                 }
280                 if (rc) {
281                         DEBUG_CAPA_KEY(D_ERROR, rkey, "update failed for");
282                         /* next retry is in 300 sec */
283                         mdt->mdt_ck_expiry = jiffies + 300 * CFS_HZ;
284                 }
285
286                 cfs_timer_arm(&mdt->mdt_ck_timer, mdt->mdt_ck_expiry);
287                 CDEBUG(D_SEC, "mdt_ck_timer %lu\n", mdt->mdt_ck_expiry);
288         }
289         lu_env_fini(&env);
290
291         thread_set_flags(thread, SVC_STOPPED);
292         cfs_waitq_signal(&thread->t_ctl_waitq);
293         RETURN(0);
294 }
295
296 int mdt_ck_thread_start(struct mdt_device *mdt)
297 {
298         struct ptlrpc_thread *thread = &mdt->mdt_ck_thread;
299         int rc;
300
301         cfs_waitq_init(&thread->t_ctl_waitq);
302         rc = cfs_create_thread(mdt_ck_thread_main, mdt, CFS_DAEMON_FLAGS);
303         if (rc < 0) {
304                 CERROR("cannot start mdt_ck thread, rc = %d\n", rc);
305                 return rc;
306         }
307
308         l_wait_condition(thread->t_ctl_waitq, thread_is_running(thread));
309         return 0;
310 }
311
312 void mdt_ck_thread_stop(struct mdt_device *mdt)
313 {
314         struct ptlrpc_thread *thread = &mdt->mdt_ck_thread;
315
316         if (!thread_is_running(thread))
317                 return;
318
319         thread_set_flags(thread, SVC_STOPPING);
320         cfs_waitq_signal(&thread->t_ctl_waitq);
321         l_wait_condition(thread->t_ctl_waitq, thread_is_stopped(thread));
322 }