Whamcloud - gitweb
- added more debug in osc. Currently two ideas are working for checks why osc does...
[fs/lustre-release.git] / lustre / include / linux / lustre_sec.h
index 4426178..723f76a 100644 (file)
 #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;
@@ -30,30 +135,17 @@ struct ptlrpc_credops;
 struct ptlrpc_sec;
 struct ptlrpc_secops;
 
-#define PTLRPC_SEC_MAX_FLAVORS   (4)
-
-typedef struct ptlrpcs_flavor_s {
-        __u32   flavor;
-        __u32   subflavor;
-} ptlrpcs_flavor_t;
-
 typedef struct {
         struct list_head        list;
-        ptlrpcs_flavor_t        sec;
+        __u32                   flavor;
 } deny_sec_t;
 
-enum ptlrpcs_security_type {
-        PTLRPC_SEC_TYPE_NONE    = 0,    /* no security */
-        PTLRPC_SEC_TYPE_AUTH    = 1,    /* authentication */
-        PTLRPC_SEC_TYPE_PRIV    = 2,    /* privacy */
-};
-
 /*
  * 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;
 };
@@ -78,50 +170,39 @@ __u8 *buf_to_sec_data(void *buf)
         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 {
@@ -138,10 +219,17 @@ struct ptlrpc_credops {
                            struct ptlrpc_request *req);
 };
 
-#define PTLRPC_CRED_UPTODATE    0x00000001 /* uptodate */
-#define PTLRPC_CRED_DEAD        0x00000002 /* mark expired gracefully */
-#define PTLRPC_CRED_ERROR       0x00000004 /* fatal error (refresh, etc.) */
-#define PTLRPC_CRED_FLAGS_MASK  0x00000007
+#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 */
@@ -149,14 +237,14 @@ struct ptlrpc_cred {
         struct ptlrpc_sec      *pc_sec;
         struct ptlrpc_credops  *pc_ops;
         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);
@@ -175,8 +263,10 @@ struct ptlrpc_secops {
                                                 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);
 };
 
@@ -184,10 +274,14 @@ struct ptlrpc_sec_type {
         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)
 
@@ -195,22 +289,22 @@ struct ptlrpc_sec {
         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);
@@ -227,14 +321,6 @@ static inline void ptlrpcs_cred_get(struct ptlrpc_cred *cred)
         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_FLAGS_MASK) ==
-                PTLRPC_CRED_UPTODATE);
-}
-
 static inline int ptlrpcs_cred_refresh(struct ptlrpc_cred *cred)
 {
         LASSERT(cred);
@@ -244,25 +330,32 @@ static inline int ptlrpcs_cred_refresh(struct ptlrpc_cred *cred)
         return cred->pc_ops->refresh(cred);
 }
 
-/* we set the cred flags is safe since cred cache code don't
- * touch cred with refcount > 0
- */
-static inline void ptlrpcs_cred_expire(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);
+        smp_mb();
+        return ((cred->pc_flags & PTLRPC_CRED_FLAGS_MASK) ==
+                PTLRPC_CRED_UPTODATE);
+}
 
-        if (cred->pc_flags & PTLRPC_CRED_DEAD)
-                return;
-        cred->pc_flags |= PTLRPC_CRED_DEAD;
-        cred->pc_flags &= ~PTLRPC_CRED_UPTODATE;
-        CWARN("cred %p: get expired\n", cred);
+static inline int ptlrpcs_cred_is_dead(struct ptlrpc_cred *cred)
+{
+        smp_mb();
+        return ((cred->pc_flags & (PTLRPC_CRED_DEAD | PTLRPC_CRED_ERROR)) != 0);
 }
 
-/* usually called upon an UPTODATE cred */
-static inline int ptlrpcs_cred_check_expire(struct ptlrpc_cred *cred)
+#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()))
@@ -271,9 +364,10 @@ static inline int ptlrpcs_cred_check_expire(struct ptlrpc_cred *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);
@@ -282,14 +376,15 @@ static inline int ptlrpcs_est_req_payload(struct ptlrpc_sec *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);
@@ -298,33 +393,27 @@ static inline int ptlrpcs_est_rep_payload(struct ptlrpc_sec *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)
 {
-        int rc = 0;
-        deny_sec_t      *p_deny_sec = NULL;
+        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;
-
-        if (strcmp(sec, "null") == 0) {
-                p_deny_sec->sec.flavor = PTLRPC_SEC_NULL;
-                p_deny_sec->sec.subflavor = PTLRPC_SEC_NULL;
-        }else if (strcmp(sec, "krb5i") == 0) {
-               p_deny_sec->sec.flavor = PTLRPC_SEC_GSS;
-               p_deny_sec->sec.subflavor = PTLRPC_SEC_GSS_KRB5I;
-        }else if (strcmp(sec, "krb5p") == 0) {
-               p_deny_sec->sec.flavor = PTLRPC_SEC_GSS;
-               p_deny_sec->sec.subflavor = PTLRPC_SEC_GSS_KRB5P;
-        }else{
-               CERROR("unrecognized security type %s\n", (char*) sec);
-               GOTO(out, rc = -EINVAL);
+        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);
@@ -346,6 +435,7 @@ void ptlrpcs_cli_free_repbuf(struct ptlrpc_request *req);
 /* 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);
@@ -370,7 +460,7 @@ struct ptlrpc_reply_state;
 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,
@@ -391,37 +481,6 @@ struct ptlrpc_svcsec {
 #define SVC_LOGIN       4
 #define SVC_LOGOUT      5
 
-/* FIXME
- * this should be a gss internal structure. fix these when we
- * sort out the flavor issues.
- */
-
-typedef struct rawobj_s {
-        __u32           len;
-        __u8           *data;
-} rawobj_t;
-
-/* on-the-wire gss cred: */
-struct rpc_gss_wire_cred {
-        __u32                   gc_v;           /* version */
-        __u32                   gc_proc;        /* control procedure */
-        __u32                   gc_seq;         /* sequence number */
-        __u32                   gc_svc;         /* service */
-        rawobj_t                gc_ctx;         /* context handle */
-};
-
-struct gss_svc_data {
-        __u32                           subflavor; /* XXX */
-        /* decoded gss client cred: */
-        struct rpc_gss_wire_cred        clcred;
-        /* internal used status */
-        unsigned int                    is_init:1,
-                                        is_init_continue:1,
-                                        is_err_notify:1,
-                                        is_fini:1;
-        int                             reserve_len;
-};
-
 int svcsec_register(struct ptlrpc_svcsec *ss);
 int svcsec_unregister(struct ptlrpc_svcsec *ss);
 int svcsec_accept(struct ptlrpc_request *req, enum ptlrpcs_error *res);
@@ -442,4 +501,173 @@ void svcsec_free_reply_state(struct ptlrpc_reply_state *rs);
 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_ */