Whamcloud - gitweb
Branch: HEAD
[fs/lustre-release.git] / lustre / llite / llite_gs.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  *   This file is part of Lustre, http://www.lustre.org.
7  *
8  *   Lustre is free software; you can redistribute it and/or
9  *   modify it under the terms of version 2 of the GNU General Public
10  *   License as published by the Free Software Foundation.
11  *
12  *   Lustre is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *   GNU General Public License for more details.
16  *
17  *   You should have received a copy of the GNU General Public License
18  *   along with Lustre; if not, write to the Free Software
19  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21
22 #define DEBUG_SUBSYSTEM S_LLITE
23
24 #include <linux/fs.h>
25 #include <linux/types.h>
26 #include <linux/version.h>
27 #include <asm/uaccess.h>
28 #include <linux/file.h>
29 #include <linux/kmod.h>
30 #include <linux/posix_acl.h>
31 #include <linux/xattr_acl.h>
32
33 #include <linux/lustre_acl.h>
34 #include <linux/lustre_lite.h>
35 #include <linux/lustre_gs.h>
36 #include "llite_internal.h"
37
38 int ll_gs_intent_init(struct lookup_intent *it)
39 {
40         struct lustre_intent_data *lustre_data;
41         
42         LASSERT(it->d.fs_data != NULL); 
43         lustre_data = (struct lustre_intent_data *)it->d.fs_data;
44         /*set lustre key size when there is gss server 
45          *or other configuration*/ 
46         lustre_data->it_key = NULL;
47         lustre_data->it_key_size = 0;
48         RETURN(0);
49 }
50
51 static int ll_get_acl_key(struct inode *inode, struct posix_acl **acl,
52                           struct lustre_key **lkey) 
53 {
54         struct lookup_intent it = { .it_op = IT_GETATTR };
55         struct dentry de = { .d_inode = inode };
56         struct ll_sb_info *sbi;
57         struct lustre_id id;
58         struct ptlrpc_request *req = NULL;
59         struct ll_inode_info *lli = ll_i2info(inode);
60         int rc = 0;
61         ENTRY;
62
63         if (lli->lli_posix_acl && lli->lli_key_info) {
64                 /*If they are in the local cache, just fetch them*/
65                 spin_lock(&lli->lli_lock);
66                 *acl = posix_acl_dup(lli->lli_posix_acl);
67                 *lkey =  lustre_key_get(lli->lli_key_info);
68                 spin_unlock(&lli->lli_lock);
69                 RETURN(rc);
70         }
71         sbi = ll_i2sbi(inode);
72         ll_inode2id(&id, inode);
73
74         if (ll_intent_alloc(&it))
75                 RETURN(-EACCES);
76
77         rc = md_intent_lock(sbi->ll_md_exp, &id, NULL, 0, NULL, 0, &id,
78                             &it, 0, &req, ll_mdc_blocking_ast);
79         if (rc < 0) {
80                 ll_intent_free(&it);
81                 GOTO(out, rc);
82         }
83
84         rc = revalidate_it_finish(req, 1, &it, &de);
85         if (rc) {
86                 ll_intent_release(&it);
87                 GOTO(out, rc);
88         }
89
90         ll_lookup_finish_locks(&it, &de);
91         ll_intent_free(&it);
92
93         spin_lock(&lli->lli_lock);
94         *acl = posix_acl_dup(lli->lli_posix_acl);
95         *lkey =  lustre_key_get(lli->lli_key_info);
96         spin_unlock(&lli->lli_lock);
97 out:
98         if (req)
99                 ptlrpc_req_finished(req);        
100         RETURN(rc);
101 }
102
103 static int ll_init_key_perm(struct key_perm *kperm, struct posix_acl *acl, 
104                             __u32 uid, __u32 gid, int mode) 
105 {
106         if (acl) {
107                 kperm->kp_acl_count = acl->a_count;
108                 memcpy(kperm->kp_acls, acl->a_entries, 
109                        acl->a_count * sizeof(struct posix_acl_entry));
110         }
111         kperm->kp_mode = mode;
112         kperm->kp_uid = uid;
113         kperm->kp_gid = gid;
114         RETURN(0);
115 }
116
117 static int ll_init_key_context(struct key_context *pkc, __u32 uid, 
118                                 __u32 gid, struct crypto_key *ck, 
119                                 struct posix_acl *acl,  int mode, 
120                                 int command, int valid)
121 {
122         struct key_perm *kperm;
123         ENTRY;
124
125         pkc->kc_command = command;
126         pkc->kc_valid = valid;
127
128         if (ck)
129                 memcpy(&pkc->kc_ck, ck, sizeof(*ck));
130
131         kperm = &pkc->kc_perm;      
132  
133         ll_init_key_perm(kperm, acl, uid, gid, mode);  
134         RETURN(0);
135 }
136 static int ll_get_default_acl(struct inode *inode, struct posix_acl **acl, 
137                               mode_t mode) 
138 {
139         int rc = 0, buf_size, ea_size;
140         char *buf = NULL;
141         ENTRY;
142
143         if (!S_ISDIR(inode->i_mode))
144                 RETURN(0);
145  
146         buf_size = xattr_acl_size(LL_ACL_MAX_ENTRIES);
147         OBD_ALLOC(buf, buf_size);
148         if (!buf)
149                 RETURN(-ENOMEM);
150
151         ea_size = ll_getxattr_internal(inode, XATTR_NAME_ACL_DEFAULT, 
152                                        buf, buf_size, OBD_MD_FLXATTR);
153         if (ea_size <= 0) {
154                 if (ea_size < 0 && ea_size != -ENODATA)
155                         CERROR("get default acl of ino %lu error rc %d \n",
156                                 inode->i_ino, ea_size);
157                 GOTO(out, rc = 0);       
158         }
159         *acl = posix_acl_from_xattr(buf, ea_size);
160         if (IS_ERR(*acl)) {
161                 rc = PTR_ERR(*acl);
162                 CERROR("convert xattr to acl failed: %d\n", rc);
163                 GOTO(out, rc);
164         } else if (*acl) {
165                 rc = posix_acl_valid(*acl);
166                 if (rc) {
167                         CERROR("acl valid error: %d\n", rc);
168                         posix_acl_release(*acl);
169                         GOTO(out, rc);
170                 }
171         }
172         
173         rc = posix_acl_create_masq(*acl, &mode); 
174 out:
175         if (buf) 
176                 OBD_FREE(buf, buf_size);
177         RETURN(rc);
178 }
179
180 int ll_gks_create_key(struct inode *dir, mode_t mode, void **key, 
181                       int* key_size)
182 {
183         struct obd_export *gs_exp = ll_i2gsexp(dir);
184         struct key_context *kcontext = NULL;
185         struct key_parms   kparms;
186         struct posix_acl *default_acl = NULL;       
187         int    rc = 0;  
188         ENTRY;
189  
190         OBD_ALLOC(kcontext, sizeof(struct key_context));
191         if (!kcontext)
192                 GOTO(out, rc = -ENOMEM);
193
194         rc = ll_get_default_acl(dir, &default_acl, mode);
195         if (rc)
196                 GOTO(out, rc);       
197  
198         ll_init_key_context(kcontext, current->fsuid, current->fsgid, 
199                             NULL, default_acl, mode, GKS_GET_KEY, 0);
200        
201         kparms.context = kcontext;
202         kparms.context_size = sizeof(struct key_context);
203         kparms.perm = NULL;
204        
205         *key_size = sizeof(struct crypto_key);
206         OBD_ALLOC(*key, *key_size);
207         if (!*key)
208                 GOTO(out, rc = -ENOMEM);
209  
210         /*GET an encrypt key from GS server*/
211         rc = obd_get_info(gs_exp, sizeof(struct key_parms), (void *)&kparms,
212                           key_size, *key);
213         if (rc) {
214                 CERROR("get key error rc %d \n", rc);
215                 GOTO(out, rc);
216         }
217         CDEBUG(D_INFO, "Get enkey %s MAC %s from exp %p \n", 
218                (char*)((struct crypto_key *)(*key))->ck_key, 
219                (char*)((struct crypto_key *)(*key))->ck_mac, 
220                gs_exp);
221 out:
222         if (kcontext)
223                 OBD_FREE(kcontext, sizeof(struct key_context));
224         if (default_acl)
225                 posix_acl_release(default_acl);
226         RETURN(rc);
227
228 }
229  
230 int ll_gks_init_it(struct inode *parent, struct lookup_intent *it)
231 {
232         struct obd_export *gs_exp = ll_i2gsexp(parent);
233         struct lustre_intent_data *lustre_data;
234         mode_t mode = (it->it_create_mode | S_IFREG) & (~current->fs->umask);
235         void *key = NULL;
236         int key_size = 0, rc = 0;
237         ENTRY;
238  
239         if (!gs_exp || !it)
240                 RETURN(rc);
241
242         ll_gs_intent_init(it);
243         if (!(it->it_op & IT_CREAT))
244                 RETURN(rc);
245
246         LASSERT(it->d.fs_data != NULL); 
247         lustre_data = (struct lustre_intent_data *)it->d.fs_data;
248           
249         if (lustre_data->it_key) {
250                 LASSERT(lustre_data->it_key_size == 
251                          sizeof(struct crypto_key));
252                 OBD_FREE(lustre_data->it_key, sizeof(struct crypto_key));
253         }
254
255         rc = ll_gks_create_key(parent, mode, &key, &key_size); 
256         if (rc)
257                 GOTO(out, rc);
258
259         lustre_data->it_key = key; 
260         lustre_data->it_key_size = key_size; 
261 out:
262         if (rc) {
263                 if (key && key_size)
264                         OBD_FREE(key, key_size);
265         }
266         RETURN(rc); 
267 }
268
269 int ll_gks_decrypt_key(struct inode *inode, struct lookup_intent *it)
270 {
271         struct obd_export *gs_exp = ll_i2gsexp(inode);
272         struct ll_inode_info *lli = ll_i2info(inode);
273         struct key_context *kcontext = NULL;
274         struct key_perm *kperm = NULL;
275         struct key_parms kparms;
276         struct lustre_key *lkey =  NULL;
277         struct crypto_key *ckey = NULL;
278         struct posix_acl *acl = NULL;
279         __u32 flags = 0; 
280         int rc = 0, ck_size = 0, kcontext_size = 0, acl_count;
281         
282         ENTRY;
283  
284         if (!gs_exp)
285                 RETURN(rc);
286        
287         rc = ll_get_acl_key(inode, &acl, &lkey);
288         if (rc)
289                 GOTO(out, rc);       
290         if (!lkey || IS_DECRYPTED(lkey->lk_flags))
291                 GOTO(out, rc = 0);
292        
293         acl_count = acl ? acl->a_count : 0;  
294         kcontext_size = crypto_kcontext_size(acl_count); 
295         OBD_ALLOC(kcontext, kcontext_size);
296         if (!kcontext)
297                 GOTO(out, rc = -ENOMEM);
298         
299         flags = mds_pack_open_flags(it->it_flags); 
300
301         spin_lock(&lli->lli_lock); 
302         ll_init_key_context(kcontext, inode->i_uid, inode->i_gid, &lkey->lk_ck, 
303                             acl, inode->i_mode, GKS_DECRYPT_KEY, flags);
304        
305         spin_unlock(&lli->lli_lock); 
306         
307         OBD_ALLOC(kperm, sizeof(struct key_perm));
308         ll_init_key_perm(kperm, NULL, current->uid, current->gid, 0);
309     
310         kparms.context = kcontext;
311         kparms.context_size = kcontext_size;
312         kparms.perm = kperm;       
313         kparms.perm_size = sizeof(struct key_perm); 
314
315         ck_size = sizeof(*ckey);
316         OBD_ALLOC(ckey, ck_size);
317         if (!ckey)
318                 GOTO(out, rc = -ENOMEM);
319  
320         /*GET an encrypt key from GS server*/
321         rc = obd_get_info(gs_exp, sizeof(struct key_parms), (void *)&kparms,
322                           &ck_size, ckey);
323         if (rc) {
324                 CERROR("decrypt key error rc %d \n", rc);
325                 GOTO(out, rc);
326         }
327         CDEBUG(D_INFO, "decrypt key %s MAC %s from exp %p \n", 
328                ckey->ck_mac, ckey->ck_mac, gs_exp);        
329       
330         /*copy the decrypt key from kcontext to the lustre key*/
331         
332         spin_lock(&lli->lli_lock); 
333         memcpy(&lkey->lk_ck, ckey, sizeof(*ckey));
334         SET_DECRYPTED(lkey->lk_flags);
335         spin_unlock(&lli->lli_lock); 
336 out:
337         if (acl)
338                 posix_acl_release(acl);
339         if (lkey)
340                 lustre_key_release(lkey); 
341         if (kperm)
342                 OBD_FREE(kperm, sizeof(struct key_perm));
343         if (kcontext)
344                 OBD_FREE(kcontext, kcontext_size);
345         if (ckey)
346                 OBD_FREE(ckey, ck_size);
347         RETURN(rc); 
348 }
349
350 int ll_gks_get_mac(struct inode *inode, struct iattr *iattr, void *value, 
351                    int size, void **key, int *key_size)
352 {
353         struct ll_inode_info *lli = ll_i2info(inode);
354         struct obd_export *gs_exp = ll_i2gsexp(inode);
355         struct key_context *kcontext = NULL;
356         struct key_perm *kperm = NULL;
357         struct key_parms kparms;
358         struct lustre_key *lkey =  NULL;
359         struct posix_acl *acl = NULL, *new_acl = NULL; 
360         int rc = 0,  kperm_size = 0, kcontext_size = 0; 
361         mode_t mac_mode;
362         int acl_count = 0;
363         
364         ENTRY;
365  
366         if (!gs_exp)
367                 RETURN(rc);
368        
369         rc = ll_get_acl_key(inode, &acl, &lkey);
370         if (rc)
371                 GOTO(out, rc);       
372         if (!lkey)
373                 RETURN(rc);
374         
375         acl_count = acl ? acl->a_count : 0;  
376         kcontext_size = crypto_kcontext_size(acl_count); 
377         OBD_ALLOC(kcontext, kcontext_size);
378         if (!kcontext)
379                 GOTO(out, rc = -ENOMEM);
380         spin_lock(&lli->lli_lock);
381         ll_init_key_context(kcontext, inode->i_uid, inode->i_gid, &lkey->lk_ck, 
382                             acl, inode->i_mode, GKS_GET_MAC, iattr->ia_valid);
383         spin_unlock(&lli->lli_lock);
384         if (value) {
385                 new_acl = posix_acl_from_xattr(value, size);
386                 if (IS_ERR(new_acl)) {
387                         rc = PTR_ERR(new_acl);
388                         CERROR("convert from xattr to acl error: %d",rc);
389                         new_acl = NULL;
390                         GOTO(out, rc);
391                 } else if (new_acl) {
392                         rc = posix_acl_valid(new_acl);
393                         if (rc) {
394                                 CERROR("acl valid error: %d", rc);
395                                 GOTO(out, rc);
396                         }
397                 }
398         } 
399         acl_count = acl ? acl->a_count : 0;  
400         kperm_size = crypto_kperm_size(acl_count);
401         OBD_ALLOC(kperm, kperm_size);
402         if (iattr->ia_valid & ATTR_MODE)
403                 mac_mode = iattr->ia_mode;
404         else
405                 mac_mode = inode->i_mode; 
406         ll_init_key_perm(kperm, new_acl, iattr->ia_uid, iattr->ia_gid, 
407                          mac_mode);
408         kparms.context = kcontext;
409         kparms.context_size = kcontext_size;
410         kparms.perm = kperm;       
411         kparms.perm_size = kperm_size; 
412
413         *key_size = sizeof(struct crypto_key);
414         OBD_ALLOC(*key, *key_size);
415         if (!*key)
416                 GOTO(out, rc = -ENOMEM);
417  
418         /*GET an encrypt key from GS server*/
419         rc = obd_get_info(gs_exp, sizeof(struct key_parms), (void *)&kparms,
420                           key_size, *key);
421         if (rc) {
422                 CERROR("decrypt key error rc %d \n", rc);
423                 GOTO(out, rc);
424         }
425         /*copy the decrypt key from kcontext to the lustre key*/
426         spin_lock(&lli->lli_lock);
427         memcpy(&lkey->lk_ck, *key, *key_size);
428         iattr->ia_valid |= ATTR_MAC;
429         spin_unlock(&lli->lli_lock);
430 out:
431         if (acl)
432                 posix_acl_release(acl);
433         if (new_acl)
434                 posix_acl_release(new_acl);
435         if (lkey)
436                 lustre_key_release(lkey); 
437         if (kperm)
438                 OBD_FREE(kperm, kperm_size);
439         if (kcontext)
440                 OBD_FREE(kcontext, kcontext_size);
441         RETURN(rc); 
442 }
443
444 /*key function for calculate the key for countermode method*/
445 static int ll_crypt_cb(struct page *page, __u64 offset, __u64 count,
446                        int flags)
447 {
448         struct inode *inode = page->mapping->host;
449         struct ll_inode_info *lli = ll_i2info(inode);
450         struct lustre_key *lkey = ll_i2info(inode)->lli_key_info;
451         unsigned char *ptr;
452         char *key_ptr;
453         int index = page->index;
454         __u64 data_key = 0; 
455         int i;
456         ENTRY;
457
458         if (!lkey)
459                 RETURN(0);
460         if (!IS_DECRYPTED(lkey->lk_flags))
461                 RETURN(-EFAULT);
462         if (flags == ENCRYPT_DATA && !IS_ENABLE_ENCRYPT(lkey->lk_flags))
463                 RETURN(-EFAULT);
464         if (flags == DECRYPT_DATA && !IS_ENABLE_DECRYPT(lkey->lk_flags))
465                 RETURN(-EFAULT);
466         
467         /*FIXME: tmp calculate method, should calculate 
468           the key according to KEY_TYPE*/
469         
470         spin_lock(&lli->lli_lock);
471         key_ptr = &lkey->lk_ck.ck_key[0];
472         for (i=0; i < KEY_SIZE; i++) 
473                 data_key += *key_ptr++; 
474         spin_unlock(&lli->lli_lock);
475         data_key += index;
476
477         CDEBUG(D_INFO, "data_key is "LPU64" \n", data_key);
478         /*encrypt the data*/
479         ptr = (char *)kmap(page);
480         ptr += offset; 
481         CDEBUG(D_INFO, "ptr is %s \n", ptr);
482         for (i = 0; i < count; i++) 
483                 *ptr++ ^= data_key; 
484         CDEBUG(D_INFO, "encrypted ptr is %s \n", ptr);
485         kunmap(page);
486         
487         RETURN(0); 
488
489
490 int ll_gs_init_inode_key(struct inode *inode, void  *mkey)
491 {
492         struct ll_inode_info *lli = ll_i2info(inode);
493         struct crypto_key *key = (struct crypto_key*)mkey;
494         struct lustre_key *lkey = NULL;
495         ENTRY;        
496
497         if (!key)
498                 RETURN(0);
499         
500         if (lli->lli_key_info == NULL) {
501                 OBD_ALLOC(lkey, sizeof(struct lustre_key));
502                 if (!lkey)
503                         RETURN(-ENOMEM); 
504                 memcpy(&lkey->lk_ck, key, sizeof(*key));
505                 atomic_set(&lkey->lk_refcount, 1);
506                 SET_UNDECRYPTED(lkey->lk_flags); 
507                 ENABLE_ENCRYPT(lkey->lk_flags);  
508                 ENABLE_DECRYPT(lkey->lk_flags); 
509                 spin_lock(&lli->lli_lock);
510                 lli->lli_key_info = lkey; 
511                 spin_unlock(&lli->lli_lock);
512         } else {
513                 lkey = lustre_key_get(lli->lli_key_info);
514                 if (!IS_DECRYPTED(lkey->lk_flags)) {
515                         if (memcmp(&lkey->lk_ck, key, sizeof(*key))) {
516                                 CWARN("already have key_info %p in ino %ld \n",
517                                       lli->lli_key_info, inode->i_ino);
518                         }
519                 } else {
520                         spin_lock(&lli->lli_lock);
521                         SET_UNDECRYPTED(lkey->lk_flags); 
522                         memcpy(&lkey->lk_ck, key, sizeof(*key));
523                         spin_unlock(&lli->lli_lock);
524                 }
525                 lustre_key_release(lkey);
526         }
527         CDEBUG(D_INFO, "set key %s mac %s in inode %lu \n", 
528                lli->lli_key_info->lk_ck.ck_mac, 
529                lli->lli_key_info->lk_ck.ck_key, 
530                inode->i_ino);
531         RETURN(0);
532 }
533
534 static int ll_gs_destroy_key(struct inode *inode)
535 {
536         struct ll_inode_info *lli = ll_i2info(inode);
537        
538         spin_lock(&lli->lli_lock);
539         if (lli->lli_key_info) {
540                 LASSERTF(atomic_read(&lli->lli_key_info->lk_refcount) == 1, 
541                          "lk_refcount %d != 1 when destory\n", 
542                          atomic_read(&lli->lli_key_info->lk_refcount));
543                 lustre_key_release(lli->lli_key_info);
544                 lli->lli_key_info = NULL;
545         }
546         spin_unlock(&lli->lli_lock);
547         RETURN(0);
548 }
549
550 struct crypto_helper_ops ll_cgs_ops = { 
551        .init_it_key     = ll_gks_init_it,
552        .create_key      = ll_gks_create_key,
553        .init_inode_key  = ll_gs_init_inode_key, 
554        .get_mac         = ll_gks_get_mac,
555        .decrypt_key     = ll_gks_decrypt_key, 
556        .destroy_key     = ll_gs_destroy_key,
557 };
558
559 int ll_mks_create_key(struct inode *inode, struct lookup_intent *it)
560 {
561         struct lustre_intent_data *lustre_data;
562         struct crypto_key         *crypto_key;
563         int    rc = 0;       
564         ENTRY;
565        
566         LASSERT(it->d.fs_data != NULL); 
567         lustre_data = (struct lustre_intent_data *)it->d.fs_data;
568        
569         if (lustre_data->it_key) {
570                 OBD_FREE(lustre_data->it_key, sizeof(struct crypto_key));
571         }
572         OBD_ALLOC(crypto_key, sizeof(struct crypto_key));
573         
574         lustre_data->it_key = crypto_key; 
575         lustre_data->it_key_size = sizeof(struct crypto_key); 
576         RETURN(rc);
577 }
578
579 int ll_mks_init_it(struct inode *parent, struct lookup_intent *it)
580 {
581         struct obd_export *gs_exp = ll_i2gsexp(parent);
582         int rc = 0;
583         ENTRY;
584  
585         if (!gs_exp || !it)
586                 RETURN(0);
587
588         ll_gs_intent_init(it);
589         if (it->it_op & IT_CREAT) {
590                 ll_mks_create_key(parent, it);
591         }
592         RETURN(rc); 
593 }
594
595 int ll_mks_decrypt_key(struct inode *inode, struct lookup_intent *it)
596 {
597         struct ll_inode_info *lli = ll_i2info(inode);
598         struct obd_export *gs_exp = ll_i2gsexp(inode);
599         struct lustre_key *lkey =  NULL;
600         struct posix_acl *acl = NULL;
601         int rc = 0;
602         
603         ENTRY;
604  
605         if (!gs_exp)
606                 RETURN(rc);
607        
608         rc = ll_get_acl_key(inode, &acl, &lkey);
609         if (rc || !lkey)
610                 RETURN(rc);      
611         spin_lock(&lli->lli_lock); 
612         SET_DECRYPTED(lkey->lk_flags); 
613         spin_unlock(&lli->lli_lock); 
614         RETURN(rc);
615 }
616 struct crypto_helper_ops ll_cmd_ops = { 
617        .init_it_key     = ll_mks_init_it,
618        .init_inode_key  = ll_gs_init_inode_key, 
619        .decrypt_key     = ll_mks_decrypt_key,
620        .destroy_key     = ll_gs_destroy_key,
621 };
622
623
624 static int ll_register_cops(struct ll_crypto_info *llci, char *type,
625                             struct crypto_helper_ops *cops)
626 {
627         struct list_head *list = &llci->ll_cops_list;
628         struct crypto_ops_item *opi = NULL, *tmp;
629         char   *opi_name = NULL;        
630         int rc = 0;
631         ENTRY;
632         
633         list_for_each_entry(tmp, list, clist) {
634                 if (!strcmp(type, tmp->ctype)) {
635                         CWARN("%s is already registered\n", type);
636                         rc = -EEXIST;
637                         GOTO(exit, rc); 
638                 }
639         }
640         
641         OBD_ALLOC(opi, sizeof(*opi));
642        
643         OBD_ALLOC(opi_name, strlen(type) + 1); 
644        
645         LASSERT(opi && opi_name);
646
647         memcpy(opi_name, type, strlen(type));
648
649         opi->ctype = opi_name;
650         opi->cops = cops;
651   
652         list_add_tail(&opi->clist, list);
653 exit:
654         RETURN(rc);
655 }
656
657 static int ll_init_sb_crypto(struct super_block *sb)
658 {
659         struct ll_crypto_info *llci = NULL;
660         int rc = 0;
661         ENTRY;
662
663         OBD_ALLOC(llci, sizeof(*llci));
664         
665         if (!llci)
666                 RETURN(-ENOMEM);
667
668         INIT_LIST_HEAD(&llci->ll_cops_list);
669         
670         ll_register_cops(llci, "gks", &ll_cgs_ops);
671         ll_register_cops(llci, "mks", &ll_cmd_ops);
672
673         ll_s2sbi(sb)->ll_crypto_info = llci;
674
675         RETURN(rc);
676 }         
677
678 static int ll_unregister_cops(struct ll_crypto_info *llci)
679 {
680         struct list_head *list = &llci->ll_cops_list;
681         struct crypto_ops_item *tmp, *item;
682
683         list_for_each_entry_safe(item, tmp, list, clist) {       
684                 list_del_init(&item->clist);       
685                 OBD_FREE(item->ctype, strlen(item->ctype) + 1);
686                 OBD_FREE(item, sizeof(*item));
687         }
688         RETURN(0);
689 }
690
691 int lustre_destroy_crypto(struct super_block *sb)
692 {
693         struct ll_crypto_info *llci = ll_s2crpi(sb);
694         ENTRY;       
695
696         if (!llci)
697                 RETURN(0);
698
699         if (llci->ll_gt_exp)
700                 obd_disconnect(llci->ll_gt_exp, 0);
701  
702         ll_unregister_cops(llci);
703         OBD_FREE(llci, sizeof(*llci)); 
704         RETURN(0);
705 }
706
707 int lustre_init_crypto(struct super_block *sb, char *gkc, 
708                        struct obd_connect_data *data,
709                        int async)
710 {
711         struct obd_device *obd = NULL;
712         struct ll_sb_info *sbi = ll_s2sbi(sb);
713         struct lustre_handle gt_conn;
714         int rc = 0;
715         ENTRY;
716
717         rc = ll_init_sb_crypto(sb);
718         if (rc)
719                 RETURN(rc);
720
721         if (!gkc || !strcmp(gkc, "null")) {
722                 CDEBUG(D_INFO, "No gks Server\n"); 
723                 RETURN(rc);
724         }
725         
726         obd = class_name2obd(gkc);
727         if (!obd) {
728                 CERROR("GSC %s: not setup or attached\n", gkc);
729                 GOTO(out, rc = -EINVAL);
730         }
731         
732         obd_set_info(obd->obd_self_export, strlen("async"), "async",
733                      sizeof(async), &async);
734         
735         rc = obd_connect(&gt_conn, obd, &sbi->ll_sb_uuid, data,
736                           OBD_OPT_REAL_CLIENT);
737         if (rc) {
738                 CERROR("cannot connect to %s: rc = %d\n", gkc, rc);
739                 GOTO(out, rc);
740         }
741         ll_s2crpi(sb)->ll_gt_exp = class_conn2export(&gt_conn);
742 out:
743         if (rc)
744                 lustre_destroy_crypto(sb); 
745         RETURN(rc);
746 }
747 struct crypto_helper_ops *
748 ll_gks_find_ops(struct ll_crypto_info *llc_info, char *type)
749 {
750         struct list_head *list = &llc_info->ll_cops_list;
751         struct crypto_ops_item *tmp;
752         ENTRY;
753
754         list_for_each_entry(tmp, list, clist) {
755                 if (!strcmp(type, tmp->ctype)) {
756                         EXIT;
757                         return (tmp->cops);            
758                 }
759         }
760         CERROR("can not find crypto api %s \n", type);
761         RETURN(NULL);
762 }
763
764 int ll_set_sb_gksinfo(struct super_block *sb, char *type)
765 {
766         struct ll_crypto_info *llci = ll_s2crpi(sb);
767         struct obd_export *md_exp = ll_s2mdexp(sb);
768         struct obd_export *dt_exp = ll_s2dtexp(sb);
769         struct crypto_helper_ops *ops;
770         int rc = 0;
771         ENTRY;
772         
773         /*try to find the helper ops according to the type*/
774         ops = ll_gks_find_ops(llci, type);
775         if (!ops) {
776                 CERROR("can not find the crypto ops by type %s \n", type);
777                 RETURN(-EINVAL);
778         }
779         llci->ll_cops = ops;
780         /*set crypto type */
781         rc = obd_set_info(md_exp, strlen("crypto_type"), "crypto_type",
782                           strlen(type), type);
783
784         /*set crypt call back func*/
785
786         rc = obd_set_info(dt_exp, strlen("crypto_cb"), "crypto_cb",
787                           sizeof(crypt_cb_t), &ll_crypt_cb);
788   
789         RETURN(rc);
790 }
791