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