Whamcloud - gitweb
remove the scimac NAL
[fs/lustre-release.git] / lustre / liblustre / llite_lib.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * Lustre Light common routines
5  *
6  *  Copyright (c) 2002, 2003 Cluster File Systems, Inc.
7  *
8  *   This file is part of Lustre, http://www.lustre.org.
9  *
10  *   Lustre is free software; you can redistribute it and/or
11  *   modify it under the terms of version 2 of the GNU General Public
12  *   License as published by the Free Software Foundation.
13  *
14  *   Lustre is distributed in the hope that it will be useful,
15  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *   GNU General Public License for more details.
18  *
19  *   You should have received a copy of the GNU General Public License
20  *   along with Lustre; if not, write to the Free Software
21  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  */
23
24 #include <stdlib.h>
25 #include <string.h>
26 #include <assert.h>
27 #include <signal.h>
28 #include <sys/types.h>
29 #include <sys/queue.h>
30 #include <sys/capability.h>
31
32 #include <netinet/in.h>
33 #include <sys/socket.h>
34 #include <arpa/inet.h>
35
36 #include <sysio.h>
37 #include <fs.h>
38 #include <mount.h>
39 #include <inode.h>
40 #include <file.h>
41
42 /* both sys/queue.h (libsysio require it) and portals/lists.h have definition
43  * of 'LIST_HEAD'. undef it to suppress warnings
44  */
45 #undef LIST_HEAD
46
47 #include <portals/ptlctl.h>     /* needed for parse_dump */
48 #include <procbridge.h>
49
50 #include "llite_lib.h"
51
52 unsigned int portal_subsystem_debug = ~0 - (S_PORTALS | S_QSWNAL | S_SOCKNAL |
53                                             S_GMNAL | S_IBNAL);
54
55 ptl_handle_ni_t         tcpnal_ni;
56 struct task_struct     *current;
57
58 /* portals interfaces */
59
60 struct ldlm_namespace;
61 struct ldlm_res_id;
62 struct obd_import;
63
64 void *inter_module_get(char *arg)
65 {
66         if (!strcmp(arg, "tcpnal_ni"))
67                 return &tcpnal_ni;
68         else if (!strcmp(arg, "ldlm_cli_cancel_unused"))
69                 return ldlm_cli_cancel_unused;
70         else if (!strcmp(arg, "ldlm_namespace_cleanup"))
71                 return ldlm_namespace_cleanup;
72         else if (!strcmp(arg, "ldlm_replay_locks"))
73                 return ldlm_replay_locks;
74         else
75                 return NULL;
76 }
77
78 /* XXX move to proper place */
79 char *portals_nid2str(int nal, ptl_nid_t nid, char *str)
80 {
81         switch(nal){
82         case TCPNAL:
83                 /* userspace NAL */
84         case SOCKNAL:
85                 snprintf(str, PTL_NALFMT_SIZE - 1, "%u:%u.%u.%u.%u",
86                          (__u32)(nid >> 32), HIPQUAD(nid));
87                 break;
88         case QSWNAL:
89         case GMNAL:
90         case IBNAL:
91                 snprintf(str, PTL_NALFMT_SIZE - 1, "%u:%u",
92                          (__u32)(nid >> 32), (__u32)nid);
93                 break;
94         default:
95                 snprintf(str, PTL_NALFMT_SIZE - 1, "?%d? %llx",
96                          nal, (long long)nid);
97                 break;
98         }
99         return str;
100 }
101
102 int in_group_p(gid_t gid)
103 {
104         int i;
105
106         if (gid == current->fsgid)
107                 return 1;
108
109         for (i = 0; i < current->ngroups; i++) {
110                 if (gid == current->groups[i])
111                         return 1;
112         }
113
114         return 0;
115 }
116
117 static void init_capability(int *res)
118 {
119         cap_value_t cap_types[] = {
120                 CAP_CHOWN,
121                 CAP_DAC_OVERRIDE,
122                 CAP_DAC_READ_SEARCH,
123                 CAP_FOWNER,
124                 CAP_FSETID,
125                 CAP_KILL,
126                 CAP_SETGID,
127                 CAP_SETUID,
128                 /* following are linux specific, we could simply
129                  * remove them I think */
130                 CAP_SETPCAP,
131                 CAP_LINUX_IMMUTABLE,
132                 CAP_NET_BIND_SERVICE,
133                 CAP_NET_BROADCAST,
134                 CAP_NET_ADMIN,
135                 CAP_NET_RAW,
136                 CAP_IPC_LOCK,
137                 CAP_IPC_OWNER,
138                 CAP_SYS_MODULE,
139                 CAP_SYS_RAWIO,
140                 CAP_SYS_CHROOT,
141                 CAP_SYS_PTRACE,
142                 CAP_SYS_PACCT,
143                 CAP_SYS_ADMIN,
144                 CAP_SYS_BOOT,
145                 CAP_SYS_NICE,
146                 CAP_SYS_RESOURCE,
147                 CAP_SYS_TIME,
148                 CAP_SYS_TTY_CONFIG,
149                 CAP_MKNOD,
150                 CAP_LEASE,
151         };
152         cap_t syscap;
153         cap_flag_value_t capval;
154         int i;
155
156         *res = 0;
157
158         syscap = cap_get_proc();
159         if (!syscap) {
160                 printf("Liblustre: Warning: failed to get system capability, "
161                        "set to minimal\n");
162                 return;
163         }
164
165         for (i = 0; i < sizeof(cap_types)/sizeof(cap_t); i++) {
166                 LASSERT(cap_types[i] < 32);
167                 if (!cap_get_flag(syscap, cap_types[i],
168                      CAP_EFFECTIVE, &capval)) {
169                         if (capval == CAP_SET) {
170                                 *res |= 1 << cap_types[i];
171                         }
172                 }
173         }
174 }
175
176 static int init_current(char *comm)
177 {
178         current = malloc(sizeof(*current));
179         if (!current) {
180                 CERROR("Not enough memory\n");
181                 return -ENOMEM;
182         }
183         current->fs = &current->__fs;
184         current->fs->umask = umask(0777);
185         umask(current->fs->umask);
186
187         strncpy(current->comm, comm, sizeof(current->comm));
188         current->pid = getpid();
189         current->fsuid = geteuid();
190         current->fsgid = getegid();
191         memset(&current->pending, 0, sizeof(current->pending));
192
193         current->max_groups = sysconf(_SC_NGROUPS_MAX);
194         current->groups = malloc(sizeof(gid_t) * current->max_groups);
195         if (!current->groups) {
196                 CERROR("Not enough memory\n");
197                 return -ENOMEM;
198         }
199         current->ngroups = getgroups(current->max_groups, current->groqps);
200         if (current->ngroups < 0) {
201                 perror("Error getgroups");
202                 return -EINVAL;
203         }
204
205         init_capability(&current->cap_effective);
206
207         return 0;
208 }
209
210 /* FIXME */
211 void generate_random_uuid(unsigned char uuid_out[16])
212 {
213         int *arr = (int*)uuid_out;
214         int i;
215
216         for (i = 0; i < sizeof(uuid_out)/sizeof(int); i++)
217                 arr[i] = rand();
218 }
219
220 ptl_nid_t tcpnal_mynid;
221
222 int init_lib_portals()
223 {
224         int max_interfaces;
225         int rc;
226         ENTRY;
227
228         rc = PtlInit(&max_interfaces);
229         if (rc != PTL_OK) {
230                 CERROR("PtlInit failed: %d\n", rc);
231                 RETURN (-ENXIO);
232         }
233         RETURN(0);
234 }
235
236 int
237 libcfs_nal_cmd(struct portals_cfg *pcfg)
238 {
239         /* handle portals command if we want */
240         return 0;
241 }
242
243 extern int class_handle_ioctl(unsigned int cmd, unsigned long arg);
244
245 int lib_ioctl_nalcmd(int dev_id, unsigned int opc, void * ptr)
246 {
247         struct portal_ioctl_data *ptldata;
248
249         if (opc == IOC_PORTAL_NAL_CMD) {
250                 ptldata = (struct portal_ioctl_data *) ptr;
251
252                 if (ptldata->ioc_nal_cmd == NAL_CMD_REGISTER_MYNID) {
253                         tcpnal_mynid = ptldata->ioc_nid;
254                         printf("mynid: %u.%u.%u.%u\n",
255                                 (unsigned)(tcpnal_mynid>>24) & 0xFF,
256                                 (unsigned)(tcpnal_mynid>>16) & 0xFF,
257                                 (unsigned)(tcpnal_mynid>>8) & 0xFF,
258                                 (unsigned)(tcpnal_mynid) & 0xFF);
259                 }
260         }
261
262         return (0);
263 }
264
265 int lib_ioctl(int dev_id, unsigned int opc, void * ptr)
266 {
267         int rc;
268
269         if (dev_id == OBD_DEV_ID) {
270                 struct obd_ioctl_data *ioc = ptr;
271
272                 //XXX hack!!!
273                 ioc->ioc_plen1 = ioc->ioc_inllen1;
274                 ioc->ioc_pbuf1 = ioc->ioc_bulk;
275                 //XXX
276
277                 rc = class_handle_ioctl(opc, (unsigned long)ptr);
278
279                 printf ("proccssing ioctl cmd: %x, rc %d\n", opc,  rc);
280
281                 if (rc)
282                         return rc;
283         }
284         return (0);
285 }
286
287 int lllib_init(char *dumpfile)
288 {
289         if (!g_zconf) {
290                 /* this parse only get my nid from config file
291                  * before initialize portals
292                  */
293                 if (parse_dump(dumpfile, lib_ioctl_nalcmd))
294                         return -1;
295         } else {
296                 /* XXX need setup mynid before tcpnal initialize */
297                 tcpnal_mynid = ((uint64_t)getpid() << 32) | time(0);
298                 printf("LibLustre: TCPNAL NID: %016llx\n", tcpnal_mynid);
299         }
300
301         if (init_current("dummy") ||
302             init_obdclass() ||
303             init_lib_portals() ||
304             ptlrpc_init() ||
305             mdc_init() ||
306             lov_init() ||
307             osc_init())
308                 return -1;
309
310         if (!g_zconf && parse_dump(dumpfile, lib_ioctl))
311                 return -1;
312
313         return _sysio_fssw_register("llite", &llu_fssw_ops);
314 }
315  
316 #if 0
317 static void llu_check_request()
318 {
319         liblustre_wait_event(0);
320 }
321 #endif
322
323 int liblustre_process_log(struct config_llog_instance *cfg, int allow_recov)
324 {
325         struct lustre_cfg lcfg;
326         char  *peer = "MDS_PEER_UUID";
327         struct obd_device *obd;
328         struct lustre_handle mdc_conn = {0, };
329         struct obd_export *exp;
330         char  *name = "mdc_dev";
331         class_uuid_t uuid;
332         struct obd_uuid mdc_uuid;
333         struct llog_ctxt *ctxt;
334         ptl_nid_t nid = 0;
335         int nal, err, rc = 0;
336         ENTRY;
337
338         generate_random_uuid(uuid);
339         class_uuid_unparse(uuid, &mdc_uuid);
340
341         if (ptl_parse_nid(&nid, g_zconf_mdsnid)) {
342                 CERROR("Can't parse NID %s\n", g_zconf_mdsnid);
343                 RETURN(-EINVAL);
344         }
345
346         nal = ptl_name2nal("tcp");
347         if (nal <= 0) {
348                 CERROR("Can't parse NAL tcp\n");
349                 RETURN(-EINVAL);
350         }
351         LCFG_INIT(lcfg, LCFG_ADD_UUID, NULL);
352         lcfg.lcfg_nid = nid;
353         lcfg.lcfg_inllen1 = strlen(peer) + 1;
354         lcfg.lcfg_inlbuf1 = peer;
355         lcfg.lcfg_nal = nal;
356         err = class_process_config(&lcfg);
357         if (err < 0)
358                 GOTO(out, err);
359
360         LCFG_INIT(lcfg, LCFG_ATTACH, name);
361         lcfg.lcfg_inlbuf1 = "mdc";
362         lcfg.lcfg_inllen1 = strlen(lcfg.lcfg_inlbuf1) + 1;
363         lcfg.lcfg_inlbuf2 = mdc_uuid.uuid;
364         lcfg.lcfg_inllen2 = strlen(lcfg.lcfg_inlbuf2) + 1;
365         err = class_process_config(&lcfg);
366         if (err < 0)
367                 GOTO(out_del_uuid, err);
368
369         LCFG_INIT(lcfg, LCFG_SETUP, name);
370         lcfg.lcfg_inlbuf1 = g_zconf_mdsname;
371         lcfg.lcfg_inllen1 = strlen(lcfg.lcfg_inlbuf1) + 1;
372         lcfg.lcfg_inlbuf2 = peer;
373         lcfg.lcfg_inllen2 = strlen(lcfg.lcfg_inlbuf2) + 1;
374         err = class_process_config(&lcfg);
375         if (err < 0)
376                 GOTO(out_detach, err);
377         
378         obd = class_name2obd(name);
379         if (obd == NULL)
380                 GOTO(out_cleanup, err = -EINVAL);
381
382         /* Disable initial recovery on this import */
383         err = obd_set_info(obd->obd_self_export,
384                            strlen("initial_recov"), "initial_recov",
385                            sizeof(allow_recov), &allow_recov);
386
387         err = obd_connect(&mdc_conn, obd, &mdc_uuid);
388         if (err) {
389                 CERROR("cannot connect to %s: rc = %d\n",
390                         g_zconf_mdsname, err);
391                 GOTO(out_cleanup, err);
392         }
393         
394         exp = class_conn2export(&mdc_conn);
395         
396         ctxt = exp->exp_obd->obd_llog_ctxt[LLOG_CONFIG_REPL_CTXT];
397         rc = class_config_parse_llog(ctxt, g_zconf_profile, cfg);
398         if (rc) {
399                 CERROR("class_config_parse_llog failed: rc = %d\n", rc);
400         }
401
402         err = obd_disconnect(exp, 0);
403
404 out_cleanup:
405         LCFG_INIT(lcfg, LCFG_CLEANUP, name);
406         err = class_process_config(&lcfg);
407         if (err < 0)
408                 GOTO(out, err);
409
410 out_detach:
411         LCFG_INIT(lcfg, LCFG_DETACH, name);
412         err = class_process_config(&lcfg);
413         if (err < 0)
414                 GOTO(out, err);
415
416 out_del_uuid:
417         LCFG_INIT(lcfg, LCFG_DEL_UUID, name);
418         lcfg.lcfg_inllen1 = strlen(peer) + 1;
419         lcfg.lcfg_inlbuf1 = peer;
420         err = class_process_config(&lcfg);
421
422 out:
423         if (rc == 0)
424                 rc = err;
425         
426         RETURN(rc);
427 }
428
429 /* parse host:/mdsname/profile string */
430 int ll_parse_mount_target(const char *target, char **mdsnid,
431                           char **mdsname, char **profile)
432 {
433         static char buf[256];
434         char *s;
435
436         buf[255] = 0;
437         strncpy(buf, target, 255);
438
439         if ((s = strchr(buf, ':'))) {
440                 *mdsnid = buf;
441                 *s = '\0';
442                                                                                                                         
443                 while (*++s == '/')
444                         ;
445                 *mdsname = s;
446                 if ((s = strchr(*mdsname, '/'))) {
447                         *s = '\0';
448                         *profile = s + 1;
449                         return 0;
450                 }
451         }
452
453         return -1;
454 }
455
456 /* env variables */
457 #define ENV_LUSTRE_MNTPNT               "LIBLUSTRE_MOUNT_POINT"
458 #define ENV_LUSTRE_MNTTGT               "LIBLUSTRE_MOUNT_TARGET"
459 #define ENV_LUSTRE_TIMEOUT              "LIBLUSTRE_TIMEOUT"
460 #define ENV_LUSTRE_DUMPFILE             "LIBLUSTRE_DUMPFILE"
461
462 extern int _sysio_native_init();
463
464 extern unsigned int obd_timeout;
465
466 /* global variables */
467 int     g_zconf = 0;            /* zeroconf or dumpfile */
468 char   *g_zconf_mdsname = NULL; /* mdsname, for zeroconf */
469 char   *g_zconf_mdsnid = NULL;  /* mdsnid, for zeroconf */
470 char   *g_zconf_profile = NULL; /* profile, for zeroconf */
471
472
473 void __liblustre_setup_(void)
474 {
475         char *lustre_path = NULL;
476         char *target = NULL;
477         char *timeout = NULL;
478         char *dumpfile = NULL;
479         char *root_driver = "native";
480         char *lustre_driver = "llite";
481         char *root_path = "/";
482         unsigned mntflgs = 0;
483
484         int err;
485
486         /* consider tha case of starting multiple liblustre instances
487          * at a same time on single node.
488          */
489         srand(time(NULL) + getpid());
490
491         lustre_path = getenv(ENV_LUSTRE_MNTPNT);
492         if (!lustre_path) {
493                 lustre_path = "/mnt/lustre";
494         }
495
496         target = getenv(ENV_LUSTRE_MNTTGT);
497         if (!target) {
498                 dumpfile = getenv(ENV_LUSTRE_DUMPFILE);
499                 if (!dumpfile) {
500                         CERROR("Neither mount target, nor dumpfile\n");
501                         exit(1);
502                 }
503                 g_zconf = 0;
504                 printf("LibLustre: mount point %s, dumpfile %s\n",
505                         lustre_path, dumpfile);
506         } else {
507                 if (ll_parse_mount_target(target,
508                                           &g_zconf_mdsnid,
509                                           &g_zconf_mdsname,
510                                           &g_zconf_profile)) {
511                         CERROR("mal-formed target %s \n", target);
512                         exit(1);
513                 }
514                 g_zconf = 1;
515                 printf("LibLustre: mount point %s, target %s\n",
516                         lustre_path, target);
517         }
518
519         timeout = getenv(ENV_LUSTRE_TIMEOUT);
520         if (timeout) {
521                 obd_timeout = (unsigned int) atoi(timeout);
522                 printf("LibLustre: set obd timeout as %u seconds\n",
523                         obd_timeout);
524         }
525
526         if (_sysio_init() != 0) {
527                 perror("init sysio");
528                 exit(1);
529         }
530
531         /* cygwin don't need native driver */
532 #ifndef __CYGWIN__
533         _sysio_native_init();
534 #endif
535
536         err = _sysio_mount_root(root_path, root_driver, mntflgs, NULL);
537         if (err) {
538                 perror(root_driver);
539                 exit(1);
540         }
541
542 #if 1
543         portal_debug = 0;
544         portal_subsystem_debug = 0;
545 #endif
546         err = lllib_init(dumpfile);
547         if (err) {
548                 perror("init llite driver");
549                 exit(1);
550         }       
551
552         err = mount("/", lustre_path, lustre_driver, mntflgs, NULL);
553         if (err) {
554                 errno = -err;
555                 perror(lustre_driver);
556                 exit(1);
557         }
558
559 #if 0
560         __sysio_hook_sys_enter = llu_check_request;
561         __sysio_hook_sys_leave = NULL;
562 #endif
563 }
564
565 void __liblustre_cleanup_(void)
566 {
567         _sysio_shutdown();
568         PtlFini();
569 }