X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lustre%2Fobdclass%2Fcapa.c;h=29c40c17bbffcd016f96d5c686440806995c3ac5;hp=406342699dea1602b0210567e8eeb997e1eb7beb;hb=a32a2faaa95e4e3379511dd2e8d5493496437867;hpb=510d22a03bb13d48c0e4d8b811b9c5e0f94c3225 diff --git a/lustre/obdclass/capa.c b/lustre/obdclass/capa.c index 4063426..29c40c1 100644 --- a/lustre/obdclass/capa.c +++ b/lustre/obdclass/capa.c @@ -1,30 +1,44 @@ -/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- - * vim:expandtab:shiftwidth=8:tabstop=8: +/* + * GPL HEADER START * - * lustre/obdclass/capa.c - * Lustre Capability Cache Management + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * - * Copyright (c) 2001-2003 Cluster File Systems, Inc. - * Author: Lai Siyao + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 only, + * as published by the Free Software Foundation. * - * This file is part of Lustre, http://www.lustre.org. + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License version 2 for more details (a copy is included + * in the LICENSE file that accompanied this code). * - * Lustre is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. + * You should have received a copy of the GNU General Public License + * version 2 along with this program; If not, see + * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf * - * Lustre is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. * - * You should have received a copy of the GNU General Public License - * along with Lustre; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * GPL HEADER END + */ +/* + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Use is subject to license terms. + * + * Copyright (c) 2012, Intel Corporation. + */ +/* + * This file is part of Lustre, http://www.lustre.org/ + * Lustre is a trademark of Sun Microsystems, Inc. + * + * lustre/obdclass/capa.c + * + * Lustre Capability Hash Management + * + * Author: Lai Siyao */ -#ifndef EXPORT_SYMTAB -# define EXPORT_SYMTAB -#endif #define DEBUG_SUBSYSTEM S_SEC @@ -36,457 +50,402 @@ #include #include -#include -#include -#include -#include +#include +#include +#include #else #include #endif #include -#include - -kmem_cache_t *capa_cachep = NULL; - -/* capa_lock protect capa hash, list and content. */ -spinlock_t capa_lock = SPIN_LOCK_UNLOCKED; -struct hlist_head *capa_hash; -struct list_head capa_list[3]; -static int capa_count[3] = { 0 }; - -static char *capa_type_name[] = { "client", "mds", "filter" }; - -/* TODO: mdc and llite all need this, so define it here. - * in the future it will be moved to ll_sb_info to support multi- - * mount point */ -struct timer_list ll_capa_timer; -atomic_t ll_capa_stat = ATOMIC_INIT(0); - -EXPORT_SYMBOL(capa_lock); -EXPORT_SYMBOL(capa_hash); -EXPORT_SYMBOL(capa_list); -EXPORT_SYMBOL(ll_capa_timer); -EXPORT_SYMBOL(ll_capa_stat); +#include -static inline int const -capa_hashfn(unsigned int uid, __u64 mdsid, unsigned long ino) -{ - return (ino ^ uid) * (unsigned long)(mdsid + 1) % NR_CAPAHASH; -} - -int capa_op(int flags) -{ - if (flags & (FMODE_WRITE|MDS_OPEN_TRUNC)) - return CAPA_WRITE; - else if (flags & FMODE_READ) - return CAPA_READ; - - LBUG(); /* should be either MAY_READ or MAY_WRITE */ - return 0; -} - -static struct obd_capa * -find_capa(struct hlist_head *head, uid_t uid, int capa_op, __u64 mdsid, - unsigned long ino, __u32 igen, int type) -{ - struct hlist_node *pos; - struct obd_capa *ocapa; - uid_t ouid; - - hlist_for_each_entry(ocapa, pos, head, c_hash) { - if (ocapa->c_capa.lc_ino != ino) - continue; - if (ocapa->c_capa.lc_igen != igen) - continue; - if (ocapa->c_capa.lc_mdsid != mdsid) - continue; - if ((ocapa->c_capa.lc_op & capa_op) != ocapa->c_capa.lc_op) - continue; - if (ocapa->c_type != type) - continue; +#define NR_CAPAHASH 32 +#define CAPA_HASH_SIZE 3000 /* for MDS & OSS */ - if (ocapa->c_type == CLIENT_CAPA) - ouid = ocapa->c_capa.lc_ruid; - else - ouid = ocapa->c_capa.lc_uid; +struct kmem_cache *capa_cachep; - if (ouid != uid) - continue; +#ifdef __KERNEL__ +/* lock for capa hash/capa_list/fo_capa_keys */ +DEFINE_SPINLOCK(capa_lock); - DEBUG_CAPA(D_INODE, &ocapa->c_capa, "found %s", - capa_type_name[ocapa->c_type]); +cfs_list_t capa_list[CAPA_SITE_MAX]; - return ocapa; - } +static struct capa_hmac_alg capa_hmac_algs[] = { + DEF_CAPA_HMAC_ALG("sha1", SHA1, 20, 20), +}; +#endif +/* capa count */ +int capa_count[CAPA_SITE_MAX] = { 0, }; - return NULL; -} +EXPORT_SYMBOL(capa_cachep); +EXPORT_SYMBOL(capa_list); +EXPORT_SYMBOL(capa_lock); +EXPORT_SYMBOL(capa_count); -static struct obd_capa * -filter_find_capa(struct hlist_head *head, struct lustre_capa *capa) +cfs_hlist_head_t *init_capa_hash(void) { - struct hlist_node *pos; - struct obd_capa *ocapa; + cfs_hlist_head_t *hash; + int nr_hash, i; - hlist_for_each_entry(ocapa, pos, head, c_hash) { - if (ocapa->c_type != FILTER_CAPA) - continue; - if (!memcmp(&ocapa->c_capa, capa, - sizeof(struct lustre_capa_data))) { + OBD_ALLOC(hash, PAGE_CACHE_SIZE); + if (!hash) + return NULL; - DEBUG_CAPA(D_INODE, &ocapa->c_capa, "found %s", - capa_type_name[ocapa->c_type]); - return ocapa; - } - } + nr_hash = PAGE_CACHE_SIZE / sizeof(cfs_hlist_head_t); + LASSERT(nr_hash > NR_CAPAHASH); - return NULL; + for (i = 0; i < NR_CAPAHASH; i++) + CFS_INIT_HLIST_HEAD(hash + i); + return hash; } +EXPORT_SYMBOL(init_capa_hash); -inline void __capa_get(struct obd_capa *ocapa) +#ifdef __KERNEL__ +static inline int capa_on_server(struct obd_capa *ocapa) { - if (ocapa->c_type != CLIENT_CAPA) - atomic_inc(&ocapa->c_refc); + return ocapa->c_site == CAPA_SITE_SERVER; } -static struct obd_capa * -find_capa_locked(struct hlist_head *head, uid_t uid, int capa_op, __u64 mdsid, - unsigned long ino, __u32 igen, int type) +static inline void capa_delete(struct obd_capa *ocapa) { - struct obd_capa *ocapa; - - spin_lock(&capa_lock); - ocapa = find_capa(head, uid, capa_op, mdsid, ino, igen, type); - if (ocapa) - __capa_get(ocapa); - spin_unlock(&capa_lock); - - return ocapa; + LASSERT(capa_on_server(ocapa)); + cfs_hlist_del_init(&ocapa->u.tgt.c_hash); + cfs_list_del_init(&ocapa->c_list); + capa_count[ocapa->c_site]--; + /* release the ref when alloc */ + capa_put(ocapa); } -static struct obd_capa *alloc_capa(void) +void cleanup_capa_hash(cfs_hlist_head_t *hash) { - struct obd_capa *ocapa; - - OBD_SLAB_ALLOC(ocapa, capa_cachep, SLAB_NOFS, sizeof(*ocapa)); - if (ocapa) { - INIT_HLIST_NODE(&ocapa->c_hash); - INIT_LIST_HEAD(&ocapa->c_list); - } - - return ocapa; + int i; + cfs_hlist_node_t *pos, *next; + struct obd_capa *oc; + + spin_lock(&capa_lock); + for (i = 0; i < NR_CAPAHASH; i++) { + cfs_hlist_for_each_entry_safe(oc, pos, next, hash + i, + u.tgt.c_hash) + capa_delete(oc); + } + spin_unlock(&capa_lock); + + OBD_FREE(hash, PAGE_CACHE_SIZE); } +EXPORT_SYMBOL(cleanup_capa_hash); -static void __capa_put(struct obd_capa *ocapa) +static inline int capa_hashfn(struct lu_fid *fid) { - hlist_del_init(&ocapa->c_hash); - list_del_init(&ocapa->c_list); - capa_count[ocapa->c_type]--; + return (fid_oid(fid) ^ fid_ver(fid)) * + (unsigned long)(fid_seq(fid) + 1) % NR_CAPAHASH; } -static void destroy_capa(struct obd_capa *ocapa) +/* capa renewal time check is earlier than that on client, which is to prevent + * client renew right after obtaining it. */ +static inline int capa_is_to_expire(struct obd_capa *oc) { - OBD_SLAB_FREE(ocapa, capa_cachep, sizeof(*ocapa)); + return cfs_time_before(cfs_time_sub(oc->c_expiry, + cfs_time_seconds(oc->c_capa.lc_timeout)*2/3), + cfs_time_current()); } -int capa_cache_init(void) +static struct obd_capa *find_capa(struct lustre_capa *capa, + cfs_hlist_head_t *head, int alive) { - int nr_hash, i; - - OBD_ALLOC(capa_hash, PAGE_SIZE); - if (!capa_hash) - return -ENOMEM; + cfs_hlist_node_t *pos; + struct obd_capa *ocapa; + int len = alive ? offsetof(struct lustre_capa, lc_keyid):sizeof(*capa); - nr_hash = PAGE_SIZE / sizeof(struct hlist_head); - LASSERT(nr_hash > NR_CAPAHASH); + cfs_hlist_for_each_entry(ocapa, pos, head, u.tgt.c_hash) { + if (memcmp(&ocapa->c_capa, capa, len)) + continue; + /* don't return one that will expire soon in this case */ + if (alive && capa_is_to_expire(ocapa)) + continue; - for (i = 0; i < NR_CAPAHASH; i++) - INIT_HLIST_HEAD(capa_hash + i); + LASSERT(capa_on_server(ocapa)); - for (i = 0; i < 3; i++) - INIT_LIST_HEAD(&capa_list[i]); + DEBUG_CAPA(D_SEC, &ocapa->c_capa, "found"); + return ocapa; + } - return 0; + return NULL; } -void capa_cache_cleanup(void) +#define LRU_CAPA_DELETE_COUNT 12 +static inline void capa_delete_lru(cfs_list_t *head) { - struct obd_capa *ocapa, *tmp; - int i; - - for (i = MDS_CAPA; i <= FILTER_CAPA; i++) { - list_for_each_entry_safe(ocapa, tmp, &capa_list[i], c_list) { - __capa_put(ocapa); - destroy_capa(ocapa); - } - } + struct obd_capa *ocapa; + cfs_list_t *node = head->next; + int count = 0; + + /* free LRU_CAPA_DELETE_COUNT unused capa from head */ + while (count++ < LRU_CAPA_DELETE_COUNT) { + ocapa = cfs_list_entry(node, struct obd_capa, c_list); + node = node->next; + if (atomic_read(&ocapa->c_refc)) + continue; - OBD_FREE(capa_hash, PAGE_SIZE); + DEBUG_CAPA(D_SEC, &ocapa->c_capa, "free lru"); + capa_delete(ocapa); + } } - -static inline void list_add_capa(struct obd_capa *ocapa, struct list_head *head) +/* add or update */ +struct obd_capa *capa_add(cfs_hlist_head_t *hash, struct lustre_capa *capa) { - struct obd_capa *tmp; - - /* XXX: capa is sorted in client, this could be optimized */ - if (ocapa->c_type == CLIENT_CAPA) { - list_for_each_entry_reverse(tmp, head, c_list) { - if (ocapa->c_capa.lc_expiry > tmp->c_capa.lc_expiry) { - list_add(&ocapa->c_list, &tmp->c_list); - return; - } - } - list_add(&ocapa->c_list, head); - return; - } + cfs_hlist_head_t *head = hash + capa_hashfn(&capa->lc_fid); + struct obd_capa *ocapa, *old = NULL; + cfs_list_t *list = &capa_list[CAPA_SITE_SERVER]; + + ocapa = alloc_capa(CAPA_SITE_SERVER); + if (IS_ERR(ocapa)) + return NULL; - list_add_tail(&ocapa->c_list, head); + spin_lock(&capa_lock); + old = find_capa(capa, head, 0); + if (!old) { + ocapa->c_capa = *capa; + set_capa_expiry(ocapa); + cfs_hlist_add_head(&ocapa->u.tgt.c_hash, head); + cfs_list_add_tail(&ocapa->c_list, list); + capa_get(ocapa); + capa_count[CAPA_SITE_SERVER]++; + if (capa_count[CAPA_SITE_SERVER] > CAPA_HASH_SIZE) + capa_delete_lru(list); + spin_unlock(&capa_lock); + return ocapa; + } else { + capa_get(old); + spin_unlock(&capa_lock); + capa_put(ocapa); + return old; + } } +EXPORT_SYMBOL(capa_add); -static inline void do_update_capa(struct obd_capa *ocapa, struct lustre_capa *capa) +struct obd_capa *capa_lookup(cfs_hlist_head_t *hash, struct lustre_capa *capa, + int alive) { - memcpy(&ocapa->c_capa, capa, sizeof(*capa)); + struct obd_capa *ocapa; + + spin_lock(&capa_lock); + ocapa = find_capa(capa, hash + capa_hashfn(&capa->lc_fid), alive); + if (ocapa) { + cfs_list_move_tail(&ocapa->c_list, + &capa_list[CAPA_SITE_SERVER]); + capa_get(ocapa); + } + spin_unlock(&capa_lock); + + return ocapa; } +EXPORT_SYMBOL(capa_lookup); -static struct obd_capa * -get_new_capa_locked(struct hlist_head *head, int type, struct lustre_capa *capa) +int capa_hmac(__u8 *hmac, struct lustre_capa *capa, __u8 *key) { - uid_t uid = capa->lc_uid; - int capa_op = capa->lc_op; - __u64 mdsid = capa->lc_mdsid; - unsigned long ino = capa->lc_ino; - struct obd_capa *ocapa, *old; - - ocapa = alloc_capa(); - if (!ocapa) - return NULL; - - spin_lock(&capa_lock); + struct crypto_hash *tfm; + struct capa_hmac_alg *alg; + int keylen; + struct scatterlist sl; + + if (capa_alg(capa) != CAPA_HMAC_ALG_SHA1) { + CERROR("unknown capability hmac algorithm!\n"); + return -EFAULT; + } - if (type == FILTER_CAPA) - old = filter_find_capa(head, capa); - else - old = find_capa(head, uid, capa_op, mdsid, ino, - capa->lc_igen, type); + alg = &capa_hmac_algs[capa_alg(capa)]; - if (!old) { - do_update_capa(ocapa, capa); - ocapa->c_type = type; - list_add_capa(ocapa, &capa_list[type]); - hlist_add_head(&ocapa->c_hash, head); - if (type == CLIENT_CAPA) - INIT_LIST_HEAD(&ocapa->c_lli_list); - __capa_get(ocapa); - - capa_count[type]++; - - DEBUG_CAPA(D_INODE, &ocapa->c_capa, "new %s", - capa_type_name[type]); - - if (type != CLIENT_CAPA && capa_count[type] > CAPA_CACHE_SIZE) { - struct list_head *node = capa_list[type].next; - struct obd_capa *tcapa; - int count = 0; - - /* free 12 unused capa from head */ - while (node->next != &capa_list[type] && count < 12) { - tcapa = list_entry(node, struct obd_capa, - c_list); - node = node->next; - if (atomic_read(&tcapa->c_refc) > 0) - continue; - DEBUG_CAPA(D_INODE, &tcapa->c_capa, - "free unused %s", - capa_type_name[type]); - __capa_put(tcapa); - destroy_capa(tcapa); - count++; - } - } - - spin_unlock(&capa_lock); - return ocapa; + tfm = crypto_alloc_hash(alg->ha_name, 0, 0); + if (IS_ERR(tfm)) { + CERROR("crypto_alloc_tfm failed, check whether your kernel" + "has crypto support!\n"); + return PTR_ERR(tfm); } - spin_unlock(&capa_lock); + keylen = alg->ha_keylen; - destroy_capa(ocapa); - return old; -} - -struct obd_capa * -capa_get(uid_t uid, int capa_op,__u64 mdsid, unsigned long ino, - __u32 igen, int type) -{ - struct hlist_head *head = capa_hash + capa_hashfn(uid, mdsid, ino); - struct obd_capa *ocapa; + sg_set_page(&sl, virt_to_page(capa), + offsetof(struct lustre_capa, lc_hmac), + (unsigned long)(capa) % PAGE_CACHE_SIZE); - ocapa = find_capa_locked(head, uid, capa_op, mdsid, ino, igen, type); - - if (type == CLIENT_CAPA && !ocapa && atomic_read(&ll_capa_stat)) { - CDEBUG(D_ERROR, "can't find capa for (uid %u, op %d, mdsid " - LPU64", ino %lu igen %u, type %d)\n", - (unsigned) uid, capa_op, mdsid, ino, igen, type); - atomic_set(&ll_capa_stat, 0); - } + ll_crypto_hmac(tfm, key, &keylen, &sl, sl.length, hmac); + crypto_free_hash(tfm); - return ocapa; + return 0; } +EXPORT_SYMBOL(capa_hmac); -struct obd_capa * filter_capa_get(struct lustre_capa *capa) +int capa_encrypt_id(__u32 *d, __u32 *s, __u8 *key, int keylen) { - struct hlist_head *head = capa_hash + - capa_hashfn(capa->lc_uid, capa->lc_mdsid, capa->lc_ino); - struct obd_capa *ocapa; + struct crypto_blkcipher *tfm; + struct scatterlist sd; + struct scatterlist ss; + struct blkcipher_desc desc; + unsigned int min; + int rc; + char alg[CRYPTO_MAX_ALG_NAME+1] = "aes"; + ENTRY; + + /* passing "aes" in a variable instead of a constant string keeps gcc + * 4.3.2 happy */ + tfm = crypto_alloc_blkcipher(alg, 0, 0 ); + if (IS_ERR(tfm)) { + CERROR("failed to load transform for aes\n"); + RETURN(PTR_ERR(tfm)); + } + + min = ll_crypto_tfm_alg_min_keysize(tfm); + if (keylen < min) { + CERROR("keylen at least %d bits for aes\n", min * 8); + GOTO(out, rc = -EINVAL); + } - spin_lock(&capa_lock); - ocapa = filter_find_capa(head, capa); - if (ocapa) - __capa_get(ocapa); - spin_unlock(&capa_lock); - return ocapa; -} + rc = crypto_blkcipher_setkey(tfm, key, min); + if (rc) { + CERROR("failed to setting key for aes\n"); + GOTO(out, rc); + } -void capa_put_nolock(struct obd_capa *ocapa) -{ - DEBUG_CAPA(D_INODE, &ocapa->c_capa, "put %s", - capa_type_name[ocapa->c_type]); - - if (ocapa->c_type == CLIENT_CAPA) { - list_del_init(&ocapa->c_lli_list); - __capa_put(ocapa); - destroy_capa(ocapa); - } else { - atomic_dec(&ocapa->c_refc); + sg_set_page(&sd, virt_to_page(d), 16, + (unsigned long)(d) % PAGE_CACHE_SIZE); + + sg_set_page(&ss, virt_to_page(s), 16, + (unsigned long)(s) % PAGE_CACHE_SIZE); + desc.tfm = tfm; + desc.info = NULL; + desc.flags = 0; + rc = crypto_blkcipher_encrypt(&desc, &sd, &ss, 16); + if (rc) { + CERROR("failed to encrypt for aes\n"); + GOTO(out, rc); } -} -void capa_put(struct obd_capa *ocapa) -{ - if (!ocapa) - return; + EXIT; - spin_lock(&capa_lock); - capa_put_nolock(ocapa); - spin_unlock(&capa_lock); +out: + crypto_free_blkcipher(tfm); + return rc; } +EXPORT_SYMBOL(capa_encrypt_id); -struct obd_capa *capa_renew(struct lustre_capa *capa, int type) +int capa_decrypt_id(__u32 *d, __u32 *s, __u8 *key, int keylen) { - uid_t uid = capa->lc_uid; - int capa_op = capa->lc_op; - __u64 mdsid = capa->lc_mdsid; - unsigned long ino = capa->lc_ino; - struct hlist_head *head = capa_hash + - capa_hashfn(uid, mdsid, ino); - struct obd_capa *ocapa; - - spin_lock(&capa_lock); + struct crypto_blkcipher *tfm; + struct scatterlist sd; + struct scatterlist ss; + struct blkcipher_desc desc; + unsigned int min; + int rc; + char alg[CRYPTO_MAX_ALG_NAME+1] = "aes"; + ENTRY; + + /* passing "aes" in a variable instead of a constant string keeps gcc + * 4.3.2 happy */ + tfm = crypto_alloc_blkcipher(alg, 0, 0 ); + if (IS_ERR(tfm)) { + CERROR("failed to load transform for aes\n"); + RETURN(PTR_ERR(tfm)); + } + + min = ll_crypto_tfm_alg_min_keysize(tfm); + if (keylen < min) { + CERROR("keylen at least %d bits for aes\n", min * 8); + GOTO(out, rc = -EINVAL); + } - if (type == FILTER_CAPA) - ocapa = filter_find_capa(head, capa); - else - ocapa = find_capa(head, uid, capa_op, mdsid, ino, - capa->lc_igen, type); - if (ocapa) { - DEBUG_CAPA(D_INFO, capa, "renew %s", capa_type_name[type]); - do_update_capa(ocapa, capa); + rc = crypto_blkcipher_setkey(tfm, key, min); + if (rc) { + CERROR("failed to setting key for aes\n"); + GOTO(out, rc); } - spin_unlock(&capa_lock); + sg_set_page(&sd, virt_to_page(d), 16, + (unsigned long)(d) % PAGE_CACHE_SIZE); - if (!ocapa) - ocapa = get_new_capa_locked(head, type, capa); + sg_set_page(&ss, virt_to_page(s), 16, + (unsigned long)(s) % PAGE_CACHE_SIZE); - if (type == CLIENT_CAPA) - atomic_set(&ll_capa_stat, 1); + desc.tfm = tfm; + desc.info = NULL; + desc.flags = 0; + rc = crypto_blkcipher_decrypt(&desc, &sd, &ss, 16); + if (rc) { + CERROR("failed to decrypt for aes\n"); + GOTO(out, rc); + } - return ocapa; -} + EXIT; -void capa_hmac(__u8 *key, struct lustre_capa *capa) -{ - struct crypto_tfm *tfm; - int keylen = CAPA_KEY_LEN; - struct scatterlist sl = { - .page = virt_to_page(capa), - .offset = (unsigned long)(capa) % PAGE_SIZE, - .length = sizeof(struct lustre_capa_data), - }; - - tfm = crypto_alloc_tfm(CAPA_HMAC_ALG, 0); - LASSERT(tfm); - crypto_hmac(tfm, key, &keylen, &sl, 1, capa->lc_hmac); - crypto_free_tfm(tfm); +out: + crypto_free_blkcipher(tfm); + return rc; } +EXPORT_SYMBOL(capa_decrypt_id); +#endif -void capa_dup(void *dst, struct obd_capa *ocapa) +void capa_cpy(void *capa, struct obd_capa *ocapa) { - spin_lock(&capa_lock); - memcpy(dst, &ocapa->c_capa, sizeof(ocapa->c_capa)); - spin_unlock(&capa_lock); + spin_lock(&ocapa->c_lock); + *(struct lustre_capa *)capa = ocapa->c_capa; + spin_unlock(&ocapa->c_lock); } +EXPORT_SYMBOL(capa_cpy); -void capa_dup2(void *dst, struct lustre_capa *capa) +void _debug_capa(struct lustre_capa *c, + struct libcfs_debug_msg_data *msgdata, + const char *fmt, ... ) { - spin_lock(&capa_lock); - memcpy(dst, capa, sizeof(*capa)); - spin_unlock(&capa_lock); + va_list args; + va_start(args, fmt); + libcfs_debug_vmsg2(msgdata, fmt, args, + " capability@%p fid "DFID" opc "LPX64" uid "LPU64 + " gid "LPU64" flags %u alg %d keyid %u timeout %u " + "expiry %u\n", c, PFID(capa_fid(c)), capa_opc(c), + capa_uid(c), capa_gid(c), capa_flags(c), + capa_alg(c), capa_keyid(c), capa_timeout(c), + capa_expiry(c)); + va_end(args); } +EXPORT_SYMBOL(_debug_capa); -int capa_expired(struct lustre_capa *capa) -{ - struct timeval tv; +/* + * context key constructor/destructor: + * lu_capainfo_key_init, lu_capainfo_key_fini + */ +LU_KEY_INIT_FINI(lu_capainfo, struct lu_capainfo); - do_gettimeofday(&tv); - return ((unsigned long )capa->lc_expiry <= tv.tv_sec) ? 1 : 0; -} +struct lu_context_key lu_capainfo_key = { + .lct_tags = LCT_SERVER_SESSION, + .lct_init = lu_capainfo_key_init, + .lct_fini = lu_capainfo_key_fini +}; -int __capa_is_to_expire(struct obd_capa *ocapa, struct timeval *tv) +struct lu_capainfo *lu_capainfo_get(const struct lu_env *env) { - int pre_expiry = capa_pre_expiry(&ocapa->c_capa); - - /* XXX: in case the clock is inaccurate, minus one more - * pre_expiry to make sure the expiry won't miss */ - return ((unsigned long)ocapa->c_capa.lc_expiry - - 2 * pre_expiry <= tv->tv_sec)? 1 : 0; + /* NB, in mdt_init0 */ + if (env->le_ses == NULL) + return NULL; + return lu_context_key_get(env->le_ses, &lu_capainfo_key); } +EXPORT_SYMBOL(lu_capainfo_get); -int capa_is_to_expire(struct obd_capa *ocapa) +/** + * Initialization of lu_capainfo_key data. + */ +int lu_capainfo_init(void) { - struct timeval tv; - int rc; - - do_gettimeofday(&tv); - spin_lock(&capa_lock); - rc = __capa_is_to_expire(ocapa, &tv); - spin_unlock(&capa_lock); + int rc; - return rc; + LU_CONTEXT_KEY_INIT(&lu_capainfo_key); + rc = lu_context_key_register(&lu_capainfo_key); + return rc; } -void dump_capa_hmac(char *buf, char *key) +/** + * Dual to lu_capainfo_init(). + */ +void lu_capainfo_fini(void) { - int i, n = 0; - - for (i = 0; i < CAPA_DIGEST_SIZE; i++) - n += sprintf(buf + n, "%02x", (unsigned char) key[i]); + lu_context_key_degister(&lu_capainfo_key); } - - -EXPORT_SYMBOL(capa_op); -EXPORT_SYMBOL(capa_get); -EXPORT_SYMBOL(__capa_get); -EXPORT_SYMBOL(filter_capa_get); -EXPORT_SYMBOL(capa_put); -EXPORT_SYMBOL(capa_put_nolock); -EXPORT_SYMBOL(capa_renew); -EXPORT_SYMBOL(capa_hmac); -EXPORT_SYMBOL(capa_dup); -EXPORT_SYMBOL(capa_dup2); -EXPORT_SYMBOL(capa_expired); -EXPORT_SYMBOL(__capa_is_to_expire); -EXPORT_SYMBOL(capa_is_to_expire); -EXPORT_SYMBOL(dump_capa_hmac); -