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