#ifndef __LINUX_SEC_H_
#define __LINUX_SEC_H_
+enum ptlrpcs_major_flavors {
+ PTLRPCS_FLVR_MAJOR_NULL = 0,
+ PTLRPCS_FLVR_MAJOR_GSS = 1,
+ PTLRPCS_FLVR_MAJOR_MAX,
+};
+
+enum ptlrpcs_null_minor_flavors {
+ PTLRPCS_FLVR_MINOR_NULL = 0,
+ PTLRPCS_FLVR_MINOR_NULL_MAX,
+};
+
+enum ptlrpcs_gss_minor_flavors {
+ PTLRPCS_FLVR_MINOR_GSS_NONE = 0,
+ PTLRPCS_FLVR_MINOR_GSS_KRB5 = 1,
+ PTLRPCS_FLVR_MINOR_GSS_MAX,
+};
+
+enum ptlrpcs_security_type {
+ PTLRPCS_SVC_NONE = 0, /* no security */
+ PTLRPCS_SVC_AUTH = 1, /* authentication */
+ PTLRPCS_SVC_PRIV = 2, /* privacy */
+ PTLRPCS_SVC_MAX,
+};
+
+/*
+ * flavor compose/extract
+ */
+#define SEC_FLAVOR_MAJOR_OFFSET (24)
+#define SEC_FLAVOR_RESERVE_OFFSET (16)
+#define SEC_FLAVOR_SVC_OFFSET (8)
+#define SEC_FLAVOR_MINOR_OFFSET (0)
+
+#define SEC_MAKE_FLAVOR(major, minor, svc) \
+ (((__u32)(major) << SEC_FLAVOR_MAJOR_OFFSET) | \
+ ((__u32)(svc) << SEC_FLAVOR_SVC_OFFSET) | \
+ ((__u32)(minor) << SEC_FLAVOR_MINOR_OFFSET))
+
+#define SEC_MAKE_SUBFLAVOR(minor, svc) \
+ (((__u32)(svc) << SEC_FLAVOR_SVC_OFFSET) | \
+ ((__u32)(minor) << SEC_FLAVOR_MINOR_OFFSET))
+
+#define SEC_FLAVOR_MAJOR(flavor) \
+ ((((__u32)(flavor)) >> SEC_FLAVOR_MAJOR_OFFSET) & 0xFF)
+#define SEC_FLAVOR_MINOR(flavor) \
+ ((((__u32)(flavor)) >> SEC_FLAVOR_MINOR_OFFSET) & 0xFF)
+#define SEC_FLAVOR_SVC(flavor) \
+ ((((__u32)(flavor)) >> SEC_FLAVOR_SVC_OFFSET) & 0xFF)
+#define SEC_FLAVOR_SUB(flavor) \
+ ((((__u32)(flavor)) >> SEC_FLAVOR_MINOR_OFFSET) & 0xFFFF)
+
+/*
+ * general gss flavors
+ */
+#define PTLRPCS_FLVR_GSS_NONE \
+ SEC_MAKE_FLAVOR(PTLRPCS_FLVR_MAJOR_GSS, \
+ PTLRPCS_FLVR_MINOR_GSS_NONE, \
+ PTLRPCS_SVC_NONE)
+#define PTLRPCS_FLVR_GSS_AUTH \
+ SEC_MAKE_FLAVOR(PTLRPCS_FLVR_MAJOR_GSS, \
+ PTLRPCS_FLVR_MINOR_GSS_NONE, \
+ PTLRPCS_SVC_AUTH)
+#define PTLRPCS_FLVR_GSS_PRIV \
+ SEC_MAKE_FLAVOR(PTLRPCS_FLVR_MAJOR_GSS, \
+ PTLRPCS_FLVR_MINOR_GSS_NONE, \
+ PTLRPCS_SVC_PRIV)
+
+/*
+ * gss subflavors
+ */
+#define PTLRPCS_SUBFLVR_KRB5 \
+ SEC_MAKE_SUBFLAVOR(PTLRPCS_FLVR_MINOR_GSS_KRB5, \
+ PTLRPCS_SVC_NONE)
+#define PTLRPCS_SUBFLVR_KRB5I \
+ SEC_MAKE_SUBFLAVOR(PTLRPCS_FLVR_MINOR_GSS_KRB5, \
+ PTLRPCS_SVC_AUTH)
+#define PTLRPCS_SUBFLVR_KRB5P \
+ SEC_MAKE_SUBFLAVOR(PTLRPCS_FLVR_MINOR_GSS_KRB5, \
+ PTLRPCS_SVC_PRIV)
+
+/*
+ * "end user" flavors
+ */
+#define PTLRPCS_FLVR_NULL \
+ SEC_MAKE_FLAVOR(PTLRPCS_FLVR_MAJOR_NULL, \
+ PTLRPCS_FLVR_MINOR_NULL, \
+ PTLRPCS_SVC_NONE)
+#define PTLRPCS_FLVR_KRB5 \
+ SEC_MAKE_FLAVOR(PTLRPCS_FLVR_MAJOR_GSS, \
+ PTLRPCS_FLVR_MINOR_GSS_KRB5, \
+ PTLRPCS_SVC_NONE)
+#define PTLRPCS_FLVR_KRB5I \
+ SEC_MAKE_FLAVOR(PTLRPCS_FLVR_MAJOR_GSS, \
+ PTLRPCS_FLVR_MINOR_GSS_KRB5, \
+ PTLRPCS_SVC_AUTH)
+#define PTLRPCS_FLVR_KRB5P \
+ SEC_MAKE_FLAVOR(PTLRPCS_FLVR_MAJOR_GSS, \
+ PTLRPCS_FLVR_MINOR_GSS_KRB5, \
+ PTLRPCS_SVC_PRIV)
+
+#define PTLRPCS_FLVR_INVALID (-1)
+
+__u32 ptlrpcs_name2flavor(const char *name);
+char *ptlrpcs_flavor2name(__u32 flavor);
+
+
/* forward declaration */
struct obd_import;
struct ptlrpc_request;
struct ptlrpc_sec;
struct ptlrpc_secops;
-#define PTLRPC_SEC_MAX_FLAVORS (4)
-
-typedef struct ptlrpcs_flavor_s {
- __u32 flavor;
- __u32 subflavor;
-} ptlrpcs_flavor_t;
-
-enum ptlrpcs_security_type {
- PTLRPC_SEC_TYPE_NONE = 0, /* no security */
- PTLRPC_SEC_TYPE_AUTH = 1, /* authentication */
- PTLRPC_SEC_TYPE_PRIV = 2, /* privacy */
-};
+typedef struct {
+ struct list_head list;
+ __u32 flavor;
+} deny_sec_t;
/*
* This header is prepended at any on-wire ptlrpc packets
*/
struct ptlrpcs_wire_hdr {
__u32 flavor;
- __u32 sectype;
+ __u32 unused;
__u32 msg_len;
__u32 sec_len;
};
return (__u8 *) (buf + sizeof(*hdr) + hdr->msg_len);
}
-enum ptlrpcs_flavors {
- PTLRPC_SEC_NULL = 0,
- PTLRPC_SEC_GSS = 1,
-};
-
#define PTLRPC_SEC_GSS_VERSION (1)
-enum ptlrpcs_gss_subflavors {
- PTLRPC_SEC_GSS_KRB5 = 0,
- PTLRPC_SEC_GSS_KRB5I = 1,
- PTLRPC_SEC_GSS_KRB5P = 2,
-};
-
enum ptlrpcs_gss_proc {
- PTLRPC_GSS_PROC_DATA = 0,
- PTLRPC_GSS_PROC_INIT = 1,
- PTLRPC_GSS_PROC_CONTINUE_INIT = 2,
- PTLRPC_GSS_PROC_DESTROY = 3,
- PTLRPC_GSS_PROC_ERR = 4,
+ PTLRPCS_GSS_PROC_DATA = 0,
+ PTLRPCS_GSS_PROC_INIT = 1,
+ PTLRPCS_GSS_PROC_CONTINUE_INIT = 2,
+ PTLRPCS_GSS_PROC_DESTROY = 3,
+ PTLRPCS_GSS_PROC_ERR = 4,
};
enum ptlrpcs_gss_svc {
- PTLRPC_GSS_SVC_NONE = 1,
- PTLRPC_GSS_SVC_INTEGRITY = 2,
- PTLRPC_GSS_SVC_PRIVACY = 3,
+ PTLRPCS_GSS_SVC_NONE = 1,
+ PTLRPCS_GSS_SVC_INTEGRITY = 2,
+ PTLRPCS_GSS_SVC_PRIVACY = 3,
};
enum ptlrpcs_error {
- PTLRPCS_OK = 0,
- PTLRPCS_BADCRED = 1,
- PTLRPCS_REJECTEDCRED = 2,
- PTLRPCS_BADVERF = 3,
- PTLRPCS_REJECTEDVERF = 4,
- PTLRPCS_TOOWEAK = 5,
+ PTLRPCS_OK = 0,
+ PTLRPCS_BADCRED = 1,
+ PTLRPCS_REJECTEDCRED = 2,
+ PTLRPCS_BADVERF = 3,
+ PTLRPCS_REJECTEDVERF = 4,
+ PTLRPCS_TOOWEAK = 5,
/* GSS errors */
- PTLRPCS_GSS_CREDPROBLEM = 13,
- PTLRPCS_GSS_CTXPROBLEM = 14,
+ PTLRPCS_GSS_CREDPROBLEM = 13,
+ PTLRPCS_GSS_CTXPROBLEM = 14,
};
struct vfs_cred {
- __u64 vc_pag;
- uid_t vc_uid;
- gid_t vc_gid;
- struct group_info *vc_ginfo;
+ __u64 vc_pag;
+ uid_t vc_uid;
+ gid_t vc_gid;
+ struct group_info *vc_ginfo;
};
struct ptlrpc_credops {
+ int (*match) (struct ptlrpc_cred *cred, struct vfs_cred *vcred);
int (*refresh)(struct ptlrpc_cred *cred);
- int (*match) (struct ptlrpc_cred *cred,
- struct ptlrpc_request *req,
- struct vfs_cred *vcred);
- int (*sign) (struct ptlrpc_cred *cred, struct ptlrpc_request *req);
- int (*verify) (struct ptlrpc_cred *cred, struct ptlrpc_request *req);
- int (*seal) (struct ptlrpc_cred *cred, struct ptlrpc_request *req);
- int (*unseal) (struct ptlrpc_cred *cred, struct ptlrpc_request *req);
void (*destroy)(struct ptlrpc_cred *cred);
+ int (*sign) (struct ptlrpc_cred *cred,
+ struct ptlrpc_request *req);
+ int (*verify) (struct ptlrpc_cred *cred,
+ struct ptlrpc_request *req);
+ int (*seal) (struct ptlrpc_cred *cred,
+ struct ptlrpc_request *req);
+ int (*unseal) (struct ptlrpc_cred *cred,
+ struct ptlrpc_request *req);
};
-#define PTLRPC_CRED_UPTODATE 0x00000001
-#define PTLRPC_CRED_DEAD 0x00000002
+#define PTLRPC_CRED_UPTODATE_BIT 0 /* uptodate */
+#define PTLRPC_CRED_DEAD_BIT 1 /* mark expired gracefully */
+#define PTLRPC_CRED_ERROR_BIT 2 /* fatal error (refresh, etc.) */
+
+#define PTLRPC_CRED_UPTODATE (1 << PTLRPC_CRED_UPTODATE_BIT)
+#define PTLRPC_CRED_DEAD (1 << PTLRPC_CRED_DEAD_BIT)
+#define PTLRPC_CRED_ERROR (1 << PTLRPC_CRED_ERROR_BIT)
+
+#define PTLRPC_CRED_FLAGS_MASK (PTLRPC_CRED_UPTODATE | \
+ PTLRPC_CRED_DEAD | \
+ PTLRPC_CRED_ERROR)
struct ptlrpc_cred {
struct list_head pc_hash; /* linked into hash table */
atomic_t pc_refcount;
struct ptlrpc_sec *pc_sec;
struct ptlrpc_credops *pc_ops;
- struct ptlrpc_request *pc_req;
unsigned long pc_expire;
- int pc_flags;
+ unsigned long pc_flags;
/* XXX maybe should not be here */
__u64 pc_pag;
uid_t pc_uid;
};
struct ptlrpc_secops {
- struct ptlrpc_sec * (*create_sec) (ptlrpcs_flavor_t *flavor,
+ struct ptlrpc_sec * (*create_sec) (__u32 flavor,
const char *pipe_dir,
void *pipe_data);
void (*destroy_sec) (struct ptlrpc_sec *sec);
struct ptlrpc_cred * (*create_cred) (struct ptlrpc_sec *sec,
- struct ptlrpc_request *req,
struct vfs_cred *vcred);
/* buffer manipulation */
int (*alloc_reqbuf) (struct ptlrpc_sec *sec,
struct ptlrpc_request *req);
/* security payload size estimation */
int (*est_req_payload)(struct ptlrpc_sec *sec,
+ struct ptlrpc_request *req,
int msgsize);
int (*est_rep_payload)(struct ptlrpc_sec *sec,
+ struct ptlrpc_request *req,
int msgsize);
};
struct module *pst_owner;
char *pst_name;
atomic_t pst_inst; /* instance, debug only */
- ptlrpcs_flavor_t pst_flavor;
+ __u32 pst_flavor; /* major flavor */
struct ptlrpc_secops *pst_ops;
};
+#define PTLRPC_SEC_FL_MDS 0x0001 /* outgoing from MDS */
+#define PTLRPC_SEC_FL_REVERSE 0x0002 /* reverse sec */
+#define PTLRPC_SEC_FL_PAG 0x0004 /* enable PAG */
+
#define PTLRPC_CREDCACHE_NR 8
#define PTLRPC_CREDCACHE_MASK (PTLRPC_CREDCACHE_NR - 1)
struct ptlrpc_sec_type *ps_type;
struct list_head ps_credcache[PTLRPC_CREDCACHE_NR];
spinlock_t ps_lock; /* protect cred cache */
- __u32 ps_sectype;
- ptlrpcs_flavor_t ps_flavor;
+ __u32 ps_flavor;
atomic_t ps_refcount;
atomic_t ps_credcount;
struct obd_import *ps_import;
/* actual security model need initialize following fields */
unsigned long ps_expire; /* cache expire interval */
unsigned long ps_nextgc; /* next gc time */
- unsigned int ps_flags;
+ unsigned long ps_flags;
};
/* sec.c */
int ptlrpcs_register(struct ptlrpc_sec_type *type);
int ptlrpcs_unregister(struct ptlrpc_sec_type *type);
-struct ptlrpc_sec * ptlrpcs_sec_create(ptlrpcs_flavor_t *flavor,
+struct ptlrpc_sec * ptlrpcs_sec_create(__u32 flavor,
+ unsigned long flags,
struct obd_import *import,
const char *pipe_dir,
void *pipe_data);
atomic_inc(&cred->pc_refcount);
}
-static inline int ptlrpcs_cred_is_uptodate(struct ptlrpc_cred *cred)
-{
- LASSERT(cred);
- LASSERT(atomic_read(&cred->pc_refcount));
- return (cred->pc_flags & PTLRPC_CRED_UPTODATE);
-}
static inline int ptlrpcs_cred_refresh(struct ptlrpc_cred *cred)
{
LASSERT(cred);
LASSERT(cred->pc_ops->refresh);
return cred->pc_ops->refresh(cred);
}
-static inline void ptlrpcs_cred_die(struct ptlrpc_cred *cred)
+
+static inline int ptlrpcs_cred_is_uptodate(struct ptlrpc_cred *cred)
{
- LASSERT(atomic_read(&cred->pc_refcount));
- LASSERT(cred->pc_sec);
- if (!(cred->pc_flags & PTLRPC_CRED_DEAD)) {
- spin_lock(&cred->pc_sec->ps_lock);
- cred->pc_flags |= PTLRPC_CRED_DEAD;
- cred->pc_flags &= ~PTLRPC_CRED_UPTODATE;
- list_del_init(&cred->pc_hash);
- spin_unlock(&cred->pc_sec->ps_lock);
- }
+ smp_mb();
+ return ((cred->pc_flags & PTLRPC_CRED_FLAGS_MASK) ==
+ PTLRPC_CRED_UPTODATE);
}
+
static inline int ptlrpcs_cred_is_dead(struct ptlrpc_cred *cred)
{
- return(cred->pc_flags & PTLRPC_CRED_DEAD);
+ smp_mb();
+ return ((cred->pc_flags & (PTLRPC_CRED_DEAD | PTLRPC_CRED_ERROR)) != 0);
+}
+
+#define ptlrpcs_cred_expire(cred) \
+ if (!test_and_set_bit(PTLRPC_CRED_DEAD_BIT, &cred->pc_flags)) { \
+ CWARN("cred %p: get expired\n", cred); \
+ clear_bit(PTLRPC_CRED_UPTODATE_BIT, &cred->pc_flags); \
+ }
+
+static inline int ptlrpcs_cred_check_uptodate(struct ptlrpc_cred *cred)
+{
+ LASSERT(atomic_read(&cred->pc_refcount));
+
+ if (!ptlrpcs_cred_is_uptodate(cred))
+ return 1;
+
+ if (cred->pc_expire == 0)
+ return 0;
+ if (time_after(cred->pc_expire, get_seconds()))
+ return 0;
+ ptlrpcs_cred_expire(cred);
+ return 1;
}
-static inline int ptlrpcs_est_req_payload(struct ptlrpc_sec *sec,
+static inline int ptlrpcs_est_req_payload(struct ptlrpc_request *req,
int datasize)
{
+ struct ptlrpc_sec *sec = req->rq_cred->pc_sec;
struct ptlrpc_secops *ops;
LASSERT(sec);
ops = sec->ps_type->pst_ops;
if (ops->est_req_payload)
- return ops->est_req_payload(sec, datasize);
+ return ops->est_req_payload(sec, req, datasize);
else
return 0;
}
-static inline int ptlrpcs_est_rep_payload(struct ptlrpc_sec *sec,
+static inline int ptlrpcs_est_rep_payload(struct ptlrpc_request *req,
int datasize)
{
+ struct ptlrpc_sec *sec = req->rq_cred->pc_sec;
struct ptlrpc_secops *ops;
LASSERT(sec);
ops = sec->ps_type->pst_ops;
if (ops->est_rep_payload)
- return ops->est_rep_payload(sec, datasize);
+ return ops->est_rep_payload(sec, req, datasize);
else
return 0;
}
+static inline int add_deny_security(char *sec, struct list_head *head)
+{
+ deny_sec_t *p_deny_sec = NULL;
+ int rc = 0;
+
+ LASSERT(sec != NULL);
+
+ OBD_ALLOC(p_deny_sec, sizeof(*p_deny_sec));
+ if (p_deny_sec == NULL)
+ return -ENOMEM;
+
+ p_deny_sec->flavor = ptlrpcs_name2flavor(sec);
+ if (p_deny_sec->flavor == PTLRPCS_FLVR_INVALID) {
+ CERROR("unrecognized security type %s\n", (char*) sec);
+ rc = -EINVAL;
+ goto out;
+ }
+
+ list_add_tail(&p_deny_sec->list, head);
+out:
+ if (rc) {
+ if (p_deny_sec)
+ OBD_FREE(p_deny_sec, sizeof(*p_deny_sec));
+ }
+ return rc;
+}
+
int ptlrpcs_cli_wrap_request(struct ptlrpc_request *req);
int ptlrpcs_cli_unwrap_reply(struct ptlrpc_request *req);
int ptlrpcs_cli_alloc_reqbuf(struct ptlrpc_request *req, int msgsize);
/* higher interface */
int ptlrpcs_import_get_sec(struct obd_import *imp);
void ptlrpcs_import_drop_sec(struct obd_import *imp);
+void ptlrpcs_import_flush_current_creds(struct obd_import *imp);
int ptlrpcs_req_get_cred(struct ptlrpc_request *req);
void ptlrpcs_req_drop_cred(struct ptlrpc_request *req);
int ptlrpcs_req_replace_dead_cred(struct ptlrpc_request *req);
int ptlrpcs_req_refresh_cred(struct ptlrpc_request *req);
+int ptlrpcs_check_cred(struct obd_import *imp);
/* internal helpers */
int sec_alloc_reqbuf(struct ptlrpc_sec *sec, struct ptlrpc_request *req,
struct ptlrpc_svcsec {
struct module *pss_owner;
char *pss_name;
- ptlrpcs_flavor_t pss_flavor;
+ __u32 pss_flavor; /* major flavor */
int pss_sec_size;
int (*accept) (struct ptlrpc_request *req,
int svcsec_null_init(void);
int svcsec_null_exit(void);
+/* capability */
+#ifdef __KERNEL__
+#include <linux/crypto.h>
+#endif
+
+#define NR_CAPAHASH 32
+#define CAPA_TIMEOUT 1800 /* sec, == 30 min */
+#define CAPA_KEY_TIMEOUT (24 * 60 * 60) /* sec, == 1 day */
+#define CAPA_CACHE_SIZE 1000 /* for MDS & OST */
+#define CAPA_HMAC_ALG "sha1"
+
+struct lustre_capa_data {
+ __u32 lc_uid; /* uid */
+ __u32 lc_op; /* operations allowed */
+ __u64 lc_ino; /* inode# */
+ __u32 lc_mdsid; /* mds# */
+ __u32 lc_keyid; /* key used for the capability */
+ __u64 lc_expiry; /* expiry time: servers have clocks */
+ __u32 lc_flags; /* security features for capability */
+} __attribute__((packed));
+
+struct client_capa {
+ struct inode *inode; /* this should be always valid
+ * if c_refc > 0 */
+ struct lustre_handle handle; /* handle of mds_file_data */
+#if 0 /* TODO: support multi mount point */
+ struct list_head *list; /* the capa list belong to this client */
+ struct timer_list *timer; /* timer belong to this client */
+#endif
+};
+
+struct filter_capa {
+ int bvalid; /* black key here valid or not */
+ __u32 bkeyid; /* black key id */
+ __u8 bhmac[CAPA_DIGEST_SIZE]; /* black key */
+};
+
+struct obd_capa {
+ struct hlist_node c_hash;
+ struct list_head c_list;
+
+ struct lustre_capa c_capa; /* capa */
+ int c_type;
+ atomic_t c_refc;
+
+ union {
+ struct client_capa client;
+ struct filter_capa filter;
+ } u;
+};
+
+#define c_inode u.client.inode
+#define c_handle u.client.handle
+#define c_bvalid u.filter.bvalid
+#define c_bkeyid u.filter.bkeyid
+#define c_bhmac u.filter.bhmac
+
+enum lustre_capa_type {
+ CLIENT_CAPA = 0,
+ MDS_CAPA = 1,
+ FILTER_CAPA = 2,
+};
+
+#define DEBUG_CAPA(level, capa, fmt, args...) \
+do { \
+CDEBUG(level, fmt " capa@%p uid %u op %u ino "LPU64" mdsid %d keyid %d " \
+ "expiry "LPU64" flags %u\n", \
+ ##args, capa, (capa)->lc_uid, (capa)->lc_op, (capa)->lc_ino, \
+ (capa)->lc_mdsid, (capa)->lc_keyid, (capa)->lc_expiry, \
+ (capa)->lc_flags); \
+} while (0)
+
+#define DEBUG_CAPA_KEY(level, key, fmt, args...) \
+do { \
+CDEBUG(level, fmt " capa key@%p mdsid %d keyid %d expiry "LPU64"\n", \
+ ##args, key, (key)->lk_mdsid, (key)->lk_keyid, (key)->lk_expiry); \
+} while (0)
+
+#define DEBUG_MDS_CAPA_KEY(level, mkey, fmt, args...) \
+do { \
+CDEBUG(level, fmt " capa key@%p mdsid %d keyid %d expiry "LPU64"\n", \
+ ##args, mkey, le32_to_cpu((mkey)->k_key->lk_mdsid), \
+ le32_to_cpu((mkey)->k_key->lk_keyid), \
+ le64_to_cpu((mkey)->k_key->lk_expiry)); \
+} while (0)
+
+extern spinlock_t capa_lock;
+extern struct hlist_head *capa_hash;
+extern struct list_head capa_list[];
+extern struct timer_list ll_capa_timer;
+
+/* obdclass/capa.c */
+int capa_op(int flags);
+void __capa_get(struct obd_capa *ocapa);
+struct obd_capa *capa_get(uid_t uid, int capa_op, __u64 mdsid,
+ unsigned long ino, int type,
+ struct lustre_capa *capa, struct inode *inode,
+ struct lustre_handle *handle);
+void capa_put(struct obd_capa *ocapa, int type);
+int capa_renew(struct lustre_capa *capa, int type);
+void capa_hmac(struct crypto_tfm *tfm, __u8 *key, struct lustre_capa *capa);
+void capa_dup(void *dst, struct obd_capa *ocapa);
+void capa_dup2(void *dst, struct lustre_capa *capa);
+int capa_expired(struct lustre_capa *capa);
+int __capa_is_to_expire(struct obd_capa *ocapa);
+int capa_is_to_expire(struct obd_capa *ocapa);
+
+#define CAPA_EXPIRY_SHIFT 10 /* 1024 sec */
+#define CAPA_EXPIRY (1UL << PAGE_SHIFT)
+#define CAPA_EXPIRY_MASK (~(CAPA_EXPIRY-1))
+
+#define CAPA_PRE_EXPIRY_NOROUND 3 /* sec */
+#define CAPA_PRE_EXPIRY 300 /* sec */
+
+/* struct lustre_capa.lc_flags */
+#define CAPA_FL_NOROUND 0x001 /* capa expiry not rounded */
+#define CAPA_FL_REMUID 0x002 /* remote uid */
+
+static inline unsigned long capa_pre_expiry(struct lustre_capa *capa)
+{
+ return (capa->lc_flags & CAPA_FL_NOROUND) ?
+ CAPA_PRE_EXPIRY_NOROUND : CAPA_PRE_EXPIRY;
+}
+
+static inline __u64
+round_expiry(__u32 timeout)
+{
+ struct timeval tv;
+ __u64 expiry;
+
+ do_gettimeofday(&tv);
+ expiry = tv.tv_sec + timeout;
+
+ if (timeout > CAPA_EXPIRY)
+ expiry = (expiry + CAPA_EXPIRY - 1) & CAPA_EXPIRY_MASK;
+
+ return expiry;
+}
+
+static inline int
+capa_key_cmp(struct lustre_capa_key *k1, struct lustre_capa_key *k2)
+{
+ return k1->lk_keyid - k2->lk_keyid;
+}
+
+static inline unsigned long
+expiry_to_jiffies(__u64 expiry)
+{
+ /* sec -> jiffies */
+ struct timeval tv;
+ unsigned long timeout;
+
+ do_gettimeofday(&tv);
+ timeout = jiffies + ((unsigned long)expiry - tv.tv_sec) * HZ;
+ return timeout;
+}
+
+struct mds_capa_key {
+ struct list_head k_list;
+
+ struct lustre_capa_key *k_key;
+ struct obd_device *k_obd;
+};
+
+struct filter_capa_key {
+ struct list_head k_list;
+ struct lustre_capa_key k_key;
+};
+
#endif /* __LINUX_SEC_H_ */