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