Whamcloud - gitweb
26ea1869a2d41b304bdbf861262fa18b869cacf9
[fs/lustre-release.git] / lustre / mds / mds_capa.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * Copyright (C) 2004, 2005 Cluster File Systems, Inc.
5  *
6  * Author: Lai Siyao <lsy@clusterfs.com>
7  *
8  *   This file is part of Lustre, http://www.lustre.org.
9  *
10  *   Lustre is free software; you can redistribute it and/or
11  *   modify it under the terms of version 2 of the GNU General Public
12  *   License as published by the Free Software Foundation.
13  *
14  *   Lustre is distributed in the hope that it will be useful,
15  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *   GNU General Public License for more details.
18  *
19  *   You should have received a copy of the GNU General Public License
20  *   along with Lustre; if not, write to the Free Software
21  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  */
23
24 #define DEBUG_SUBSYSTEM S_MDS
25
26 #include <linux/fs.h>
27 #include <linux/version.h>
28 #include <asm/uaccess.h>
29 #include <linux/file.h>
30 #include <linux/kmod.h>
31 #include <linux/random.h>
32
33 #include <linux/obd.h>
34 #include <linux/lustre_mds.h>
35 #include <linux/lustre_fsfilt.h>
36 #include <linux/lustre_sec.h>
37
38 #include "mds_internal.h"
39
40 static struct ptlrpc_thread mds_eck_thread;
41
42 static struct thread_ctl {
43         struct completion ctl_starting;
44         struct completion ctl_finishing;
45 } mds_eck_ctl;
46
47 static LIST_HEAD(mds_capa_key_list);
48 static spinlock_t mds_capa_lock; /* protect capa and capa key */
49 struct timer_list mds_eck_timer;
50
51 #define CAPA_KEY_JIFFIES(key) \
52         expiry_to_jiffies(le64_to_cpu((key)->k_key->lk_expiry))
53
54 #define CUR_MDS_CAPA_KEY(mds) (mds)->mds_capa_keys[(mds)->mds_capa_key_idx]
55 #define CUR_CAPA_KEY(mds) CUR_MDS_CAPA_KEY(mds).k_key
56 #define CUR_CAPA_KEY_ID(mds) CUR_MDS_CAPA_KEY(mds).k_key->lk_keyid
57 #define CUR_CAPA_KEY_LIST(mds) CUR_MDS_CAPA_KEY(mds).k_list
58 #define CUR_CAPA_KEY_EXPIRY(mds) le64_to_cpu(CUR_CAPA_KEY(mds)->lk_expiry)
59 #define CUR_CAPA_KEY_JIFFIES(mds) CAPA_KEY_JIFFIES(&CUR_MDS_CAPA_KEY(mds))
60
61 static int mds_write_capa_key(struct obd_device *obd, int force_sync)
62 {
63         struct mds_obd *mds = &obd->u.mds;
64         struct mds_capa_key *keys = mds->mds_capa_keys;
65         struct file *filp = mds->mds_capa_keys_filp;
66         struct lvfs_run_ctxt saved;
67         loff_t off = 0;
68         int i, rc = 0;
69         ENTRY;
70
71         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
72         for (i = 0; i < 2 && keys[i].k_key; i++) {
73                 rc = fsfilt_write_record(obd, filp, keys[i].k_key,
74                                          sizeof(*keys[i].k_key),
75                                          &off, force_sync);
76                 if (rc) {
77                         CERROR("error writing MDS capa key: rc = %d\n", rc);
78                         break;
79                 }
80         }
81         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
82
83         RETURN(rc);
84 }
85
86 static inline int
87 mds_capa_key_cmp(struct mds_obd *mds)
88 {
89         return le32_to_cpu(mds->mds_capa_keys[0].k_key->lk_keyid) -
90                le32_to_cpu(mds->mds_capa_keys[1].k_key->lk_keyid);
91 }
92
93 static void
94 do_update_capa_key(struct mds_obd *mds, struct lustre_capa_key *key)
95 {
96         __u32 keyid = 1;
97         __u64 expiry_rounded;
98
99         if (CUR_CAPA_KEY(mds))
100                 keyid = le32_to_cpu(CUR_CAPA_KEY_ID(mds)) + 1;
101         spin_lock(&mds_capa_lock);
102         expiry_rounded = round_expiry(mds->mds_capa_key_timeout);
103         spin_unlock(&mds_capa_lock);
104
105         key->lk_mdsid = cpu_to_le32(mds->mds_num);
106         key->lk_keyid = cpu_to_le32(keyid);
107         key->lk_expiry = cpu_to_le64(expiry_rounded);
108         get_random_bytes(key->lk_key, sizeof(key->lk_key));
109 }
110
111 static void list_add_capa_key(struct mds_capa_key *key, struct list_head *head)
112 {
113         struct mds_capa_key *tmp;
114
115         list_for_each_entry_reverse(tmp, head, k_list) {
116                 if (le64_to_cpu(key->k_key->lk_expiry) <
117                     le64_to_cpu(tmp->k_key->lk_expiry)) {
118                         /* put key before tmp */
119                         list_add_tail(&key->k_list, &tmp->k_list);
120                         return;
121                 }
122         }
123
124         list_add_tail(&key->k_list, head);
125 }
126
127 int mds_read_capa_key(struct obd_device *obd, struct file *file)
128 {
129         loff_t off = 0;
130         struct mds_obd *mds = &obd->u.mds;
131         struct lustre_capa_key *key;
132         unsigned long capa_keys_size = file->f_dentry->d_inode->i_size;
133         unsigned long expiry;
134         int i = 0, rc = 0;
135         ENTRY;
136
137         if (capa_keys_size == 0) {
138                 CWARN("%s: initializing new %s\n", obd->obd_name,
139                       file->f_dentry->d_name.name);
140                  
141                 OBD_ALLOC(key, sizeof(*key));
142                 if (!key)
143                         RETURN(-ENOMEM);
144
145                 do_update_capa_key(mds, key);
146
147                 mds->mds_capa_keys[0].k_key = key;
148                 mds->mds_capa_keys[0].k_obd = obd;
149                 INIT_LIST_HEAD(&mds->mds_capa_keys[0].k_list);
150                 mds->mds_capa_key_idx = 0;
151
152                 rc = mds_write_capa_key(obd, 1);
153                 if (rc)
154                         GOTO(out, rc);
155         } else {
156                 LASSERT(capa_keys_size == sizeof(*key) ||
157                         capa_keys_size == 2 * sizeof(*key));
158
159                 while (capa_keys_size > i * sizeof(*key)) {
160                         OBD_ALLOC(key, sizeof(*key));
161                         if (!key)
162                                 RETURN(-ENOMEM);
163
164                         rc = fsfilt_read_record(obd, file, key, sizeof(*key),
165                                                 &off);
166                         if (rc) {
167                                 CERROR("error reading MDS %s capa key: %d\n",
168                                        file->f_dentry->d_name.name, rc);
169                                 OBD_FREE(key, sizeof(*key));
170                                 GOTO(out, rc);
171                         }
172
173                         mds->mds_capa_keys[i].k_key = key;
174                         mds->mds_capa_keys[i].k_obd = obd;
175                         INIT_LIST_HEAD(&mds->mds_capa_keys[i].k_list);
176                         i++;
177                 }
178
179                 mds->mds_capa_key_idx = 0;
180                 if (mds->mds_capa_keys[1].k_key && mds_capa_key_cmp(mds) < 0)
181                         mds->mds_capa_key_idx = 1;
182         }
183
184         expiry = CUR_CAPA_KEY_JIFFIES(mds);
185         spin_lock(&mds_capa_lock);
186         if (time_before(expiry, mds_eck_timer.expires) ||
187             !timer_pending(&mds_eck_timer)) {
188                 mod_timer(&mds_eck_timer, expiry);
189                 CDEBUG(D_INFO, "mds_eck_timer %lu", expiry);
190         }
191         list_add_capa_key(&CUR_MDS_CAPA_KEY(mds), &mds_capa_key_list);
192         spin_unlock(&mds_capa_lock);
193 out:
194         RETURN(rc);
195 }
196
197 void mds_capa_keys_cleanup(struct obd_device *obd)
198 {
199         struct mds_obd *mds = &obd->u.mds;
200         int i;
201
202         del_timer(&mds_eck_timer);
203         spin_lock(&mds_capa_lock);
204         if (CUR_CAPA_KEY(mds))
205                 list_del_init(&CUR_CAPA_KEY_LIST(mds));
206         spin_unlock(&mds_capa_lock);
207
208         for (i = 0; i < 2; i++)
209                 if (mds->mds_capa_keys[i].k_key)
210                         OBD_FREE(mds->mds_capa_keys[i].k_key,
211                                  sizeof(struct lustre_capa_key));
212 }
213
214 static int mds_set_capa_key(struct obd_device *obd, struct lustre_capa_key *key)
215 {
216         struct mds_obd *mds = &obd->u.mds;
217         int rc;
218         ENTRY;
219
220         rc = obd_set_info(mds->mds_dt_exp, strlen("capa_key"), "capa_key",
221                           sizeof(*key), key);
222         RETURN(rc);
223 }
224
225 static int
226 mds_update_capa_key(struct obd_device *obd, struct mds_capa_key *mkey,
227                     int force_sync)
228 {
229         struct mds_obd *mds = &obd->u.mds;
230         int to_update = !mds->mds_capa_key_idx;
231         struct lustre_capa_key *key = mds->mds_capa_keys[to_update].k_key;
232         __u32 keyid;
233         unsigned long expiry;
234         int rc, rc2;
235         ENTRY;
236
237         LASSERT(mkey != &mds->mds_capa_keys[to_update]);
238
239         if (key == NULL) {
240                 /* first update */
241                 OBD_ALLOC(key, sizeof(*key));
242                 if (!key)
243                         RETURN(-ENOMEM);
244                 mds->mds_capa_keys[to_update].k_key = key;
245                 mds->mds_capa_keys[to_update].k_obd = obd;
246         }
247
248         do_update_capa_key(mds, key);
249
250         keyid = le32_to_cpu(key->lk_keyid);
251
252         rc = mds_set_capa_key(obd, key);
253         if (rc)
254                 /* XXX: anyway, it will be replayed */
255                 CERROR("error set capa key(id %u), err = %d\n", keyid, rc);
256
257         rc2 = mds_write_capa_key(obd, 1);
258         if (rc2)
259                 GOTO(out, rc2);
260         
261         CDEBUG(D_INFO, "wrote capa keyid %u\n", keyid);
262
263         spin_lock(&mds_capa_lock);
264         list_del_init(&CUR_CAPA_KEY_LIST(mds));
265         mds->mds_capa_key_idx = to_update;
266         expiry = CUR_CAPA_KEY_JIFFIES(mds);
267         list_add_capa_key(&CUR_MDS_CAPA_KEY(mds), &mds_capa_key_list);
268
269         if (time_before(expiry, mds_eck_timer.expires) ||
270             !timer_pending(&mds_eck_timer)) {
271                 mod_timer(&mds_eck_timer, expiry);
272                 CDEBUG(D_INFO, "mds_eck_timer %lu", expiry);
273         }
274         spin_unlock(&mds_capa_lock);
275
276         DEBUG_MDS_CAPA_KEY(D_INFO, &CUR_MDS_CAPA_KEY(mds),
277                            "mds_update_capa_key");
278 out:
279         RETURN(rc2);
280 }
281
282 static inline int have_expired_capa_key(void)
283 {
284         struct mds_capa_key *key;
285         unsigned long expiry;
286         int expired = 0;
287         ENTRY;
288
289         spin_lock(&mds_capa_lock);
290         if (!list_empty(&mds_capa_key_list)) {
291                 key = list_entry(mds_capa_key_list.next, struct mds_capa_key,
292                                  k_list);
293                 /* expiry is in sec, so in case it misses, the result will
294                  * minus 5 sec and then compare with jiffies. (in case the
295                  * clock is innacurate) */
296                 expiry = CAPA_KEY_JIFFIES(key);
297                 expired = time_before(expiry - 5 * HZ, jiffies);
298                 if (!expired) {
299                         if (time_before(expiry, mds_eck_timer.expires) ||
300                             !timer_pending(&mds_eck_timer)) {
301                                 mod_timer(&mds_eck_timer, expiry);
302                                 CDEBUG(D_INFO, "mds_eck_timer %lu", expiry);
303                         }
304                 }
305         }
306         spin_unlock(&mds_capa_lock);
307
308         RETURN(expired);
309 }
310
311 static int inline mds_capa_key_check_stop(void)
312 {
313         return (mds_eck_thread.t_flags & SVC_STOPPING) ? 1: 0;
314 }
315
316 static int mds_capa_key_thread_main(void *arg)
317 {
318         struct thread_ctl *ctl = arg;
319         unsigned long flags;
320         int rc;
321         ENTRY;
322
323         lock_kernel();
324         ptlrpc_daemonize();
325
326         SIGNAL_MASK_LOCK(current, flags);
327         sigfillset(&current->blocked);
328         RECALC_SIGPENDING;
329         SIGNAL_MASK_UNLOCK(current, flags);
330         THREAD_NAME(current->comm, sizeof(current->comm), "mds_ck");
331         unlock_kernel();
332
333         /*
334          * letting starting function know, that we are ready and control may be
335          * returned.
336          */
337         mds_eck_thread.t_flags = SVC_RUNNING;
338         complete(&ctl->ctl_starting);
339
340         while (!mds_capa_key_check_stop()) {
341                 struct l_wait_info lwi = { 0 };
342                 unsigned long expiry;
343                 struct mds_capa_key *key, *tmp, *next = NULL;
344
345                 l_wait_event(mds_eck_thread.t_ctl_waitq,
346                              (have_expired_capa_key() ||
347                               mds_capa_key_check_stop()),
348                              &lwi);
349
350                 spin_lock(&mds_capa_lock);
351                 list_for_each_entry_safe(key, tmp, &mds_capa_key_list, k_list) {
352                         if (time_after(CAPA_KEY_JIFFIES(key), jiffies)) {
353                                 next = key;
354                                 break;
355                         }
356
357                         spin_unlock(&mds_capa_lock);
358
359                         CDEBUG(D_INFO, "mds capa key expired: "
360                                "mds #%u, key #%u\n",
361                                le32_to_cpu(key->k_key->lk_mdsid),
362                                le32_to_cpu(key->k_key->lk_keyid));
363
364                         rc = mds_update_capa_key(key->k_obd, key, 1);
365                         spin_lock(&mds_capa_lock);
366                 }
367
368                 if (next) {
369                         expiry = CAPA_KEY_JIFFIES(next);
370                         mod_timer(&mds_eck_timer, expiry);
371                         CDEBUG(D_INFO, "mds_eck_timer %lu", expiry);
372                 }
373                 spin_unlock(&mds_capa_lock);
374         }
375
376         mds_eck_thread.t_flags = SVC_STOPPED;
377
378         /* this is SMP-safe way to finish thread. */
379         complete_and_exit(&ctl->ctl_finishing, 0);
380         EXIT;
381 }
382
383 void mds_capa_key_timer_callback(unsigned long unused)
384 {
385         ENTRY;
386         wake_up(&mds_eck_thread.t_ctl_waitq);
387         EXIT;
388 }
389
390 int mds_capa_key_start_thread(void)
391 {
392         int rc;
393         ENTRY;
394
395         LASSERT(mds_eck_thread.t_flags == 0);
396         init_completion(&mds_eck_ctl.ctl_starting);
397         init_completion(&mds_eck_ctl.ctl_finishing);
398         init_waitqueue_head(&mds_eck_thread.t_ctl_waitq);
399         spin_lock_init(&mds_capa_lock);
400
401         rc = kernel_thread(mds_capa_key_thread_main, &mds_eck_ctl,
402                            (CLONE_VM | CLONE_FILES));
403         if (rc < 0) {
404                 CERROR("cannot start capa key thread, "
405                        "err = %d\n", rc);
406                 RETURN(rc);
407         }
408
409         wait_for_completion(&mds_eck_ctl.ctl_starting);
410         LASSERT(mds_eck_thread.t_flags == SVC_RUNNING);
411         RETURN(0);
412 }
413
414 void mds_capa_key_stop_thread(void)
415 {
416         ENTRY;
417         mds_eck_thread.t_flags = SVC_STOPPING;
418         wake_up(&mds_eck_thread.t_ctl_waitq);
419         wait_for_completion(&mds_eck_ctl.ctl_finishing);
420         LASSERT(mds_eck_thread.t_flags == SVC_STOPPED);
421         mds_eck_thread.t_flags = 0;
422         EXIT;
423 }
424
425 void mds_update_capa_stat(struct obd_device *obd, int stat)
426 {
427         struct mds_obd *mds = &obd->u.mds;
428
429         spin_lock(&mds_capa_lock);
430         mds->mds_capa_stat = stat;
431         spin_unlock(&mds_capa_lock);
432 }
433
434 void mds_update_capa_timeout(struct obd_device *obd, unsigned long timeout)
435 {
436         struct mds_obd *mds = &obd->u.mds;
437
438         spin_lock(&mds_capa_lock);
439         mds->mds_capa_timeout = timeout;
440         /* XXX: update all capabilities in cache if their expiry too long */
441         spin_unlock(&mds_capa_lock);
442 }
443
444 int mds_update_capa_key_timeout(struct obd_device *obd, unsigned long timeout)
445 {
446         struct mds_obd *mds = &obd->u.mds;
447         struct timeval tv;
448         int rc;
449         ENTRY;
450
451         do_gettimeofday(&tv);
452
453         spin_lock(&mds_capa_lock);
454         mds->mds_capa_key_timeout = timeout;
455         if (CUR_CAPA_KEY_EXPIRY(mds) < tv.tv_sec + timeout) {
456                 spin_unlock(&mds_capa_lock);
457                 RETURN(0);
458         }
459         spin_unlock(&mds_capa_lock);
460
461         rc = mds_update_capa_key(obd, &CUR_MDS_CAPA_KEY(mds), 1);
462
463         RETURN(rc);
464 }
465
466 static void mds_capa_reverse_map(struct mds_export_data *med,
467                                  struct lustre_capa *capa)
468 {
469         uid_t uid;
470
471         if (!med->med_remote) {
472                 /* when not remote uid, ruid == uid */
473                 capa->lc_ruid = capa->lc_uid;
474                 return;
475         }
476
477         ENTRY;
478         uid = mds_idmap_lookup_uid(med->med_idmap, 1, capa->lc_uid);
479         if (uid == MDS_IDMAP_NOTFOUND)
480                 uid = med->med_nllu;
481         capa->lc_ruid = uid;
482         capa->lc_flags |= CAPA_FL_REMUID;
483         EXIT;
484 }
485
486
487 int mds_pack_capa(struct obd_device *obd, struct mds_export_data *med,
488                   struct mds_body *req_body, struct lustre_capa *req_capa,
489                   struct ptlrpc_request *req, int *offset, struct mds_body *body)
490 {
491         struct mds_obd *mds = &obd->u.mds;
492         struct lustre_capa *capa;
493         struct lustre_msg *repmsg = req->rq_repmsg;
494         struct obd_capa *ocapa;
495         __u8 key[CAPA_KEY_LEN];  /* key */
496         int stat, expired, rc = 0;
497         ENTRY;
498
499         spin_lock(&mds_capa_lock);
500         stat = mds->mds_capa_stat;
501         spin_unlock(&mds_capa_lock);
502
503         if (stat == 0) {
504                 (*offset)++;
505                 RETURN(0); /* capability is disabled */
506         }
507
508         if (OBD_FAIL_CHECK(OBD_FAIL_MDS_PACK_CAPA))
509                 RETURN(-EINVAL);
510
511         if (req_body) {
512                 /* capa renewal, check capa op against open mode */
513                 struct mds_file_data *mfd;
514                 int mode;
515
516                 mfd = mds_handle2mfd(&req_body->handle);
517                 if (mfd == NULL) {
518                         DEBUG_CAPA(D_INFO, req_capa, "no handle "LPX64" for",
519                                    req_body->handle.cookie);
520                         RETURN(-ESTALE);
521                 }
522
523                 mode = accmode(mfd->mfd_mode);
524                 if (!(req_capa->lc_op & mode)) {
525                         DEBUG_CAPA(D_ERROR, req_capa, "accmode %d mismatch",
526                                    mode);
527                         RETURN(-EACCES);
528                 }
529
530                 mds_mfd_put(mfd);
531         }
532
533         LASSERT(repmsg->buflens[*offset] == sizeof(*capa));
534         capa = lustre_msg_buf(repmsg, (*offset)++, sizeof(*capa));
535         LASSERT(capa != NULL);
536
537         ocapa = capa_get(req_capa->lc_uid, req_capa->lc_op, req_capa->lc_mdsid,
538                          req_capa->lc_ino, MDS_CAPA);
539         if (ocapa) {
540                 expired = capa_is_to_expire(ocapa);
541                 if (!expired) {
542                         capa_dup(capa, ocapa);
543                         capa_put(ocapa);
544                         GOTO(out, rc);
545                 }
546                 capa_put(ocapa);
547         }
548
549         memcpy(capa, req_capa, sizeof(*capa));
550         mds_capa_reverse_map(med, capa);
551
552         spin_lock(&mds_capa_lock);
553         capa->lc_keyid = le32_to_cpu(CUR_CAPA_KEY_ID(mds));
554         capa->lc_expiry = round_expiry(mds->mds_capa_timeout);
555         if (mds->mds_capa_timeout < CAPA_EXPIRY)
556                 capa->lc_flags |= CAPA_FL_SHORT;
557         memcpy(key, CUR_CAPA_KEY(mds)->lk_key, sizeof(key));
558         spin_unlock(&mds_capa_lock);
559
560         capa_hmac(mds->mds_capa_hmac, key, capa);
561
562         ocapa = capa_renew(capa, MDS_CAPA);
563         if (!ocapa)
564                 rc = -ENOMEM;
565 out:
566         if (rc == 0)
567                 body->valid |= OBD_MD_CAPA;
568         RETURN(rc);
569 }