Whamcloud - gitweb
Land b_smallfix onto HEAD (20040423_1603)
[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
31 #include <netinet/in.h>
32 #include <sys/socket.h>
33 #include <arpa/inet.h>
34
35 #include <sysio.h>
36 #include <fs.h>
37 #include <mount.h>
38 #include <inode.h>
39 #include <file.h>
40
41 /* both sys/queue.h (libsysio require it) and portals/lists.h have definition
42  * of 'LIST_HEAD'. undef it to suppress warnings
43  */
44 #undef LIST_HEAD
45
46 #include <portals/ptlctl.h>     /* needed for parse_dump */
47 #include <procbridge.h>
48
49 #include "llite_lib.h"
50
51 unsigned int portal_subsystem_debug = ~0 - (S_PORTALS | S_QSWNAL | S_SOCKNAL |
52                                             S_GMNAL | S_IBNAL);
53
54 ptl_handle_ni_t         tcpnal_ni;
55 struct task_struct     *current;
56
57 /* portals interfaces */
58
59 struct ldlm_namespace;
60 struct ldlm_res_id;
61 struct obd_import;
62
63 void *inter_module_get(char *arg)
64 {
65         if (!strcmp(arg, "tcpnal_ni"))
66                 return &tcpnal_ni;
67         else if (!strcmp(arg, "ldlm_cli_cancel_unused"))
68                 return ldlm_cli_cancel_unused;
69         else if (!strcmp(arg, "ldlm_namespace_cleanup"))
70                 return ldlm_namespace_cleanup;
71         else if (!strcmp(arg, "ldlm_replay_locks"))
72                 return ldlm_replay_locks;
73         else
74                 return NULL;
75 }
76
77 /* XXX move to proper place */
78 char *portals_nid2str(int nal, ptl_nid_t nid, char *str)
79 {
80         switch(nal){
81         case TCPNAL:
82                 /* userspace NAL */
83         case SOCKNAL:
84                 snprintf(str, PTL_NALFMT_SIZE - 1, "%u:%u.%u.%u.%u",
85                          (__u32)(nid >> 32), HIPQUAD(nid));
86                 break;
87         case QSWNAL:
88         case GMNAL:
89         case IBNAL:
90         case SCIMACNAL:
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 void init_current(char *comm)
103 {
104         current = malloc(sizeof(*current));
105         current->fs = malloc(sizeof(*current->fs));
106         current->fs->umask = umask(0777);
107         umask(current->fs->umask);
108         strncpy(current->comm, comm, sizeof(current->comm));
109         current->pid = getpid();
110         current->fsuid = 0;
111         current->fsgid = 0;
112         current->cap_effective = -1;
113         memset(&current->pending, 0, sizeof(current->pending));
114 }
115
116 /* FIXME */
117 void generate_random_uuid(unsigned char uuid_out[16])
118 {
119         int *arr = (int*)uuid_out;
120         int i;
121
122         for (i = 0; i < sizeof(uuid_out)/sizeof(int); i++)
123                 arr[i] = rand();
124 }
125
126 ptl_nid_t tcpnal_mynid;
127
128 int init_lib_portals()
129 {
130         int max_interfaces;
131         int rc;
132         ENTRY;
133
134         rc = PtlInit(&max_interfaces);
135         if (rc != PTL_OK) {
136                 CERROR("PtlInit failed: %d\n", rc);
137                 RETURN (-ENXIO);
138         }
139         RETURN(0);
140 }
141
142 int
143 libcfs_nal_cmd(struct portals_cfg *pcfg)
144 {
145         /* handle portals command if we want */
146         return 0;
147 }
148
149 extern int class_handle_ioctl(unsigned int cmd, unsigned long arg);
150
151 int lib_ioctl_nalcmd(int dev_id, unsigned int opc, void * ptr)
152 {
153         struct portal_ioctl_data *ptldata;
154
155         if (opc == IOC_PORTAL_NAL_CMD) {
156                 ptldata = (struct portal_ioctl_data *) ptr;
157
158                 if (ptldata->ioc_nal_cmd == NAL_CMD_REGISTER_MYNID) {
159                         tcpnal_mynid = ptldata->ioc_nid;
160                         printf("mynid: %u.%u.%u.%u\n",
161                                 (unsigned)(tcpnal_mynid>>24) & 0xFF,
162                                 (unsigned)(tcpnal_mynid>>16) & 0xFF,
163                                 (unsigned)(tcpnal_mynid>>8) & 0xFF,
164                                 (unsigned)(tcpnal_mynid) & 0xFF);
165                 }
166         }
167
168         return (0);
169 }
170
171 int lib_ioctl(int dev_id, unsigned int opc, void * ptr)
172 {
173         int rc;
174
175         if (dev_id == OBD_DEV_ID) {
176                 struct obd_ioctl_data *ioc = ptr;
177
178                 //XXX hack!!!
179                 ioc->ioc_plen1 = ioc->ioc_inllen1;
180                 ioc->ioc_pbuf1 = ioc->ioc_bulk;
181                 //XXX
182
183                 rc = class_handle_ioctl(opc, (unsigned long)ptr);
184
185                 printf ("proccssing ioctl cmd: %x, rc %d\n", opc,  rc);
186
187                 if (rc)
188                         return rc;
189         }
190         return (0);
191 }
192
193 int lllib_init(char *dumpfile)
194 {
195         if (!g_zconf) {
196                 /* this parse only get my nid from config file
197                  * before initialize portals
198                  */
199                 if (parse_dump(dumpfile, lib_ioctl_nalcmd))
200                         return -1;
201         } else {
202                 /* XXX need setup mynid before tcpnal initialize */
203                 tcpnal_mynid = ((uint64_t)getpid() << 32) | time(0);
204                 printf("LibLustre: TCPNAL NID: %016llx\n", tcpnal_mynid);
205         }
206
207         init_current("dummy");
208         if (init_obdclass() ||
209             init_lib_portals() ||
210             ptlrpc_init() ||
211             mdc_init() ||
212             lov_init() ||
213             osc_init())
214                 return -1;
215
216         if (!g_zconf && parse_dump(dumpfile, lib_ioctl))
217                 return -1;
218
219         return _sysio_fssw_register("llite", &llu_fssw_ops);
220 }
221  
222 #if 0
223 static void llu_check_request()
224 {
225         liblustre_wait_event(0);
226 }
227 #endif
228
229 int liblustre_process_log(struct config_llog_instance *cfg, int allow_recov)
230 {
231         struct lustre_cfg lcfg;
232         char  *peer = "MDS_PEER_UUID";
233         struct obd_device *obd;
234         struct lustre_handle mdc_conn = {0, };
235         struct obd_export *exp;
236         char  *name = "mdc_dev";
237         class_uuid_t uuid;
238         struct obd_uuid mdc_uuid;
239         struct llog_ctxt *ctxt;
240         ptl_nid_t nid = 0;
241         int nal, err, rc = 0;
242         ENTRY;
243
244         generate_random_uuid(uuid);
245         class_uuid_unparse(uuid, &mdc_uuid);
246
247         if (ptl_parse_nid(&nid, g_zconf_mdsnid)) {
248                 CERROR("Can't parse NID %s\n", g_zconf_mdsnid);
249                 RETURN(-EINVAL);
250         }
251
252         nal = ptl_name2nal("tcp");
253         if (nal <= 0) {
254                 CERROR("Can't parse NAL tcp\n");
255                 RETURN(-EINVAL);
256         }
257         LCFG_INIT(lcfg, LCFG_ADD_UUID, NULL);
258         lcfg.lcfg_nid = nid;
259         lcfg.lcfg_inllen1 = strlen(peer) + 1;
260         lcfg.lcfg_inlbuf1 = peer;
261         lcfg.lcfg_nal = nal;
262         err = class_process_config(&lcfg);
263         if (err < 0)
264                 GOTO(out, err);
265
266         LCFG_INIT(lcfg, LCFG_ATTACH, name);
267         lcfg.lcfg_inlbuf1 = "mdc";
268         lcfg.lcfg_inllen1 = strlen(lcfg.lcfg_inlbuf1) + 1;
269         lcfg.lcfg_inlbuf2 = mdc_uuid.uuid;
270         lcfg.lcfg_inllen2 = strlen(lcfg.lcfg_inlbuf2) + 1;
271         err = class_process_config(&lcfg);
272         if (err < 0)
273                 GOTO(out_del_uuid, err);
274
275         LCFG_INIT(lcfg, LCFG_SETUP, name);
276         lcfg.lcfg_inlbuf1 = g_zconf_mdsname;
277         lcfg.lcfg_inllen1 = strlen(lcfg.lcfg_inlbuf1) + 1;
278         lcfg.lcfg_inlbuf2 = peer;
279         lcfg.lcfg_inllen2 = strlen(lcfg.lcfg_inlbuf2) + 1;
280         err = class_process_config(&lcfg);
281         if (err < 0)
282                 GOTO(out_detach, err);
283         
284         obd = class_name2obd(name);
285         if (obd == NULL)
286                 GOTO(out_cleanup, err = -EINVAL);
287
288         /* Disable initial recovery on this import */
289         err = obd_set_info(obd->obd_self_export,
290                            strlen("initial_recov"), "initial_recov",
291                            sizeof(allow_recov), &allow_recov);
292
293         err = obd_connect(&mdc_conn, obd, &mdc_uuid);
294         if (err) {
295                 CERROR("cannot connect to %s: rc = %d\n",
296                         g_zconf_mdsname, err);
297                 GOTO(out_cleanup, err);
298         }
299         
300         exp = class_conn2export(&mdc_conn);
301         
302         ctxt = exp->exp_obd->obd_llog_ctxt[LLOG_CONFIG_REPL_CTXT];
303         rc = class_config_parse_llog(ctxt, g_zconf_profile, cfg);
304         if (rc) {
305                 CERROR("class_config_parse_llog failed: rc = %d\n", rc);
306         }
307
308         err = obd_disconnect(exp, 0);
309
310 out_cleanup:
311         LCFG_INIT(lcfg, LCFG_CLEANUP, name);
312         err = class_process_config(&lcfg);
313         if (err < 0)
314                 GOTO(out, err);
315
316 out_detach:
317         LCFG_INIT(lcfg, LCFG_DETACH, name);
318         err = class_process_config(&lcfg);
319         if (err < 0)
320                 GOTO(out, err);
321
322 out_del_uuid:
323         LCFG_INIT(lcfg, LCFG_DEL_UUID, name);
324         lcfg.lcfg_inllen1 = strlen(peer) + 1;
325         lcfg.lcfg_inlbuf1 = peer;
326         err = class_process_config(&lcfg);
327
328 out:
329         if (rc == 0)
330                 rc = err;
331         
332         RETURN(rc);
333 }
334
335 static void sighandler_USR1(int signum)
336 {
337         /* do nothing */
338 }
339
340 /* parse host:/mdsname/profile string */
341 int ll_parse_mount_target(const char *target, char **mdsnid,
342                           char **mdsname, char **profile)
343 {
344         static char buf[256];
345         char *s;
346
347         buf[255] = 0;
348         strncpy(buf, target, 255);
349
350         if ((s = strchr(buf, ':'))) {
351                 *mdsnid = buf;
352                 *s = '\0';
353                                                                                                                         
354                 while (*++s == '/')
355                         ;
356                 *mdsname = s;
357                 if ((s = strchr(*mdsname, '/'))) {
358                         *s = '\0';
359                         *profile = s + 1;
360                         return 0;
361                 }
362         }
363
364         return -1;
365 }
366
367 /* env variables */
368 #define ENV_LUSTRE_MNTPNT               "LIBLUSTRE_MOUNT_POINT"
369 #define ENV_LUSTRE_MNTTGT               "LIBLUSTRE_MOUNT_TARGET"
370 #define ENV_LUSTRE_TIMEOUT              "LIBLUSTRE_TIMEOUT"
371 #define ENV_LUSTRE_DUMPFILE             "LIBLUSTRE_DUMPFILE"
372
373 extern int _sysio_native_init();
374
375 extern unsigned int obd_timeout;
376
377 /* global variables */
378 int     g_zconf = 0;            /* zeroconf or dumpfile */
379 char   *g_zconf_mdsname = NULL; /* mdsname, for zeroconf */
380 char   *g_zconf_mdsnid = NULL;  /* mdsnid, for zeroconf */
381 char   *g_zconf_profile = NULL; /* profile, for zeroconf */
382
383
384 void __liblustre_setup_(void)
385 {
386         char *lustre_path = NULL;
387         char *target = NULL;
388         char *timeout = NULL;
389         char *dumpfile = NULL;
390         char *root_driver = "native";
391         char *lustre_driver = "llite";
392         char *root_path = "/";
393         unsigned mntflgs = 0;
394
395         int err;
396
397         /* consider tha case of starting multiple liblustre instances
398          * at a same time on single node.
399          */
400         srand(time(NULL) + getpid());
401
402         signal(SIGUSR1, sighandler_USR1);
403
404         lustre_path = getenv(ENV_LUSTRE_MNTPNT);
405         if (!lustre_path) {
406                 lustre_path = "/mnt/lustre";
407         }
408
409         target = getenv(ENV_LUSTRE_MNTTGT);
410         if (!target) {
411                 dumpfile = getenv(ENV_LUSTRE_DUMPFILE);
412                 if (!dumpfile) {
413                         CERROR("Neither mount target, nor dumpfile\n");
414                         exit(1);
415                 }
416                 g_zconf = 0;
417                 printf("LibLustre: mount point %s, dumpfile %s\n",
418                         lustre_path, dumpfile);
419         } else {
420                 if (ll_parse_mount_target(target,
421                                           &g_zconf_mdsnid,
422                                           &g_zconf_mdsname,
423                                           &g_zconf_profile)) {
424                         CERROR("mal-formed target %s \n", target);
425                         exit(1);
426                 }
427                 g_zconf = 1;
428                 printf("LibLustre: mount point %s, target %s\n",
429                         lustre_path, target);
430         }
431
432         timeout = getenv(ENV_LUSTRE_TIMEOUT);
433         if (timeout) {
434                 obd_timeout = (unsigned int) atoi(timeout);
435                 printf("LibLustre: set obd timeout as %u seconds\n",
436                         obd_timeout);
437         }
438
439         if (_sysio_init() != 0) {
440                 perror("init sysio");
441                 exit(1);
442         }
443
444         /* cygwin don't need native driver */
445 #ifndef __CYGWIN__
446         _sysio_native_init();
447 #endif
448
449         err = _sysio_mount_root(root_path, root_driver, mntflgs, NULL);
450         if (err) {
451                 perror(root_driver);
452                 exit(1);
453         }
454
455 #if 1
456         portal_debug = 0;
457         portal_subsystem_debug = 0;
458 #endif
459         err = lllib_init(dumpfile);
460         if (err) {
461                 perror("init llite driver");
462                 exit(1);
463         }       
464
465         err = mount("/", lustre_path, lustre_driver, mntflgs, NULL);
466         if (err) {
467                 errno = -err;
468                 perror(lustre_driver);
469                 exit(1);
470         }
471
472 #if 0
473         __sysio_hook_sys_enter = llu_check_request;
474         __sysio_hook_sys_leave = NULL;
475 #endif
476 }
477
478 void __liblustre_cleanup_(void)
479 {
480         _sysio_shutdown();
481         PtlFini();
482 }