Whamcloud - gitweb
2dddb2f0be1050000fb9b46bc27f174cced4420f
[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         case SCIMACNAL:
92                 snprintf(str, PTL_NALFMT_SIZE - 1, "%u:%u",
93                          (__u32)(nid >> 32), (__u32)nid);
94                 break;
95         default:
96                 snprintf(str, PTL_NALFMT_SIZE - 1, "?%d? %llx",
97                          nal, (long long)nid);
98                 break;
99         }
100         return str;
101 }
102
103 int in_group_p(gid_t gid)
104 {
105         int i;
106
107         if (gid == current->fsgid)
108                 return 1;
109
110         for (i = 0; i < current->ngroups; i++) {
111                 if (gid == current->groups[i])
112                         return 1;
113         }
114
115         return 0;
116 }
117
118 static void init_capability(int *res)
119 {
120         cap_value_t cap_types[] = {
121                 CAP_CHOWN,
122                 CAP_DAC_OVERRIDE,
123                 CAP_DAC_READ_SEARCH,
124                 CAP_FOWNER,
125                 CAP_FSETID,
126                 CAP_KILL,
127                 CAP_SETGID,
128                 CAP_SETUID,
129                 /* following are linux specific, we could simply
130                  * remove them I think */
131                 CAP_SETPCAP,
132                 CAP_LINUX_IMMUTABLE,
133                 CAP_NET_BIND_SERVICE,
134                 CAP_NET_BROADCAST,
135                 CAP_NET_ADMIN,
136                 CAP_NET_RAW,
137                 CAP_IPC_LOCK,
138                 CAP_IPC_OWNER,
139                 CAP_SYS_MODULE,
140                 CAP_SYS_RAWIO,
141                 CAP_SYS_CHROOT,
142                 CAP_SYS_PTRACE,
143                 CAP_SYS_PACCT,
144                 CAP_SYS_ADMIN,
145                 CAP_SYS_BOOT,
146                 CAP_SYS_NICE,
147                 CAP_SYS_RESOURCE,
148                 CAP_SYS_TIME,
149                 CAP_SYS_TTY_CONFIG,
150                 CAP_MKNOD,
151                 CAP_LEASE,
152         };
153         cap_t syscap;
154         cap_flag_value_t capval;
155         int i;
156
157         *res = 0;
158
159         syscap = cap_get_proc();
160         if (!syscap) {
161                 printf("Liblustre: Warning: failed to get system capability, "
162                        "set to minimal\n");
163                 return;
164         }
165
166         for (i = 0; i < sizeof(cap_types)/sizeof(cap_t); i++) {
167                 LASSERT(cap_types[i] < 32);
168                 if (!cap_get_flag(syscap, cap_types[i],
169                      CAP_EFFECTIVE, &capval)) {
170                         if (capval == CAP_SET) {
171                                 *res |= 1 << cap_types[i];
172                         }
173                 }
174         }
175 }
176
177 static int init_current(char *comm)
178 {
179         current = malloc(sizeof(*current));
180         if (!current) {
181                 CERROR("Not enough memory\n");
182                 return -ENOMEM;
183         }
184         current->fs = &current->__fs;
185         current->fs->umask = umask(0777);
186         umask(current->fs->umask);
187
188         strncpy(current->comm, comm, sizeof(current->comm));
189         current->pid = getpid();
190         current->fsuid = geteuid();
191         current->fsgid = getegid();
192         memset(&current->pending, 0, sizeof(current->pending));
193
194         current->max_groups = sysconf(_SC_NGROUPS_MAX);
195         current->groups = malloc(sizeof(gid_t) * current->max_groups);
196         if (!current->groups) {
197                 CERROR("Not enough memory\n");
198                 return -ENOMEM;
199         }
200         current->ngroups = getgroups(current->max_groups, current->groqps);
201         if (current->ngroups < 0) {
202                 perror("Error getgroups");
203                 return -EINVAL;
204         }
205
206         init_capability(&current->cap_effective);
207
208         return 0;
209 }
210
211 /* FIXME */
212 void generate_random_uuid(unsigned char uuid_out[16])
213 {
214         int *arr = (int*)uuid_out;
215         int i;
216
217         for (i = 0; i < sizeof(uuid_out)/sizeof(int); i++)
218                 arr[i] = rand();
219 }
220
221 ptl_nid_t tcpnal_mynid;
222
223 int init_lib_portals()
224 {
225         int max_interfaces;
226         int rc;
227         ENTRY;
228
229         rc = PtlInit(&max_interfaces);
230         if (rc != PTL_OK) {
231                 CERROR("PtlInit failed: %d\n", rc);
232                 RETURN (-ENXIO);
233         }
234         RETURN(0);
235 }
236
237 int
238 libcfs_nal_cmd(struct portals_cfg *pcfg)
239 {
240         /* handle portals command if we want */
241         return 0;
242 }
243
244 extern int class_handle_ioctl(unsigned int cmd, unsigned long arg);
245
246 int lib_ioctl_nalcmd(int dev_id, unsigned int opc, void * ptr)
247 {
248         struct portal_ioctl_data *ptldata;
249
250         if (opc == IOC_PORTAL_NAL_CMD) {
251                 ptldata = (struct portal_ioctl_data *) ptr;
252
253                 if (ptldata->ioc_nal_cmd == NAL_CMD_REGISTER_MYNID) {
254                         tcpnal_mynid = ptldata->ioc_nid;
255                         printf("mynid: %u.%u.%u.%u\n",
256                                 (unsigned)(tcpnal_mynid>>24) & 0xFF,
257                                 (unsigned)(tcpnal_mynid>>16) & 0xFF,
258                                 (unsigned)(tcpnal_mynid>>8) & 0xFF,
259                                 (unsigned)(tcpnal_mynid) & 0xFF);
260                 }
261         }
262
263         return (0);
264 }
265
266 int lib_ioctl(int dev_id, unsigned int opc, void * ptr)
267 {
268         int rc;
269
270         if (dev_id == OBD_DEV_ID) {
271                 struct obd_ioctl_data *ioc = ptr;
272
273                 //XXX hack!!!
274                 ioc->ioc_plen1 = ioc->ioc_inllen1;
275                 ioc->ioc_pbuf1 = ioc->ioc_bulk;
276                 //XXX
277
278                 rc = class_handle_ioctl(opc, (unsigned long)ptr);
279
280                 printf ("proccssing ioctl cmd: %x, rc %d\n", opc,  rc);
281
282                 if (rc)
283                         return rc;
284         }
285         return (0);
286 }
287
288 int lllib_init(char *dumpfile)
289 {
290         if (!g_zconf) {
291                 /* this parse only get my nid from config file
292                  * before initialize portals
293                  */
294                 if (parse_dump(dumpfile, lib_ioctl_nalcmd))
295                         return -1;
296         } else {
297                 /* XXX need setup mynid before tcpnal initialize */
298                 tcpnal_mynid = ((uint64_t)getpid() << 32) | time(0);
299                 printf("LibLustre: TCPNAL NID: %016llx\n", tcpnal_mynid);
300         }
301
302         if (init_current("dummy") ||
303             init_obdclass() ||
304             init_lib_portals() ||
305             ptlrpc_init() ||
306             mdc_init() ||
307             lov_init() ||
308             osc_init())
309                 return -1;
310
311         if (!g_zconf && parse_dump(dumpfile, lib_ioctl))
312                 return -1;
313
314         return _sysio_fssw_register("llite", &llu_fssw_ops);
315 }
316  
317 #if 0
318 static void llu_check_request()
319 {
320         liblustre_wait_event(0);
321 }
322 #endif
323
324 int liblustre_process_log(struct config_llog_instance *cfg, int allow_recov)
325 {
326         struct lustre_cfg lcfg;
327         char  *peer = "MDS_PEER_UUID";
328         struct obd_device *obd;
329         struct lustre_handle mdc_conn = {0, };
330         struct obd_export *exp;
331         char  *name = "mdc_dev";
332         class_uuid_t uuid;
333         struct obd_uuid mdc_uuid;
334         struct llog_ctxt *ctxt;
335         ptl_nid_t nid = 0;
336         int nal, err, rc = 0;
337         ENTRY;
338
339         generate_random_uuid(uuid);
340         class_uuid_unparse(uuid, &mdc_uuid);
341
342         if (ptl_parse_nid(&nid, g_zconf_mdsnid)) {
343                 CERROR("Can't parse NID %s\n", g_zconf_mdsnid);
344                 RETURN(-EINVAL);
345         }
346
347         nal = ptl_name2nal("tcp");
348         if (nal <= 0) {
349                 CERROR("Can't parse NAL tcp\n");
350                 RETURN(-EINVAL);
351         }
352         LCFG_INIT(lcfg, LCFG_ADD_UUID, NULL);
353         lcfg.lcfg_nid = nid;
354         lcfg.lcfg_inllen1 = strlen(peer) + 1;
355         lcfg.lcfg_inlbuf1 = peer;
356         lcfg.lcfg_nal = nal;
357         err = class_process_config(&lcfg);
358         if (err < 0)
359                 GOTO(out, err);
360
361         LCFG_INIT(lcfg, LCFG_ATTACH, name);
362         lcfg.lcfg_inlbuf1 = "mdc";
363         lcfg.lcfg_inllen1 = strlen(lcfg.lcfg_inlbuf1) + 1;
364         lcfg.lcfg_inlbuf2 = mdc_uuid.uuid;
365         lcfg.lcfg_inllen2 = strlen(lcfg.lcfg_inlbuf2) + 1;
366         err = class_process_config(&lcfg);
367         if (err < 0)
368                 GOTO(out_del_uuid, err);
369
370         LCFG_INIT(lcfg, LCFG_SETUP, name);
371         lcfg.lcfg_inlbuf1 = g_zconf_mdsname;
372         lcfg.lcfg_inllen1 = strlen(lcfg.lcfg_inlbuf1) + 1;
373         lcfg.lcfg_inlbuf2 = peer;
374         lcfg.lcfg_inllen2 = strlen(lcfg.lcfg_inlbuf2) + 1;
375         err = class_process_config(&lcfg);
376         if (err < 0)
377                 GOTO(out_detach, err);
378         
379         obd = class_name2obd(name);
380         if (obd == NULL)
381                 GOTO(out_cleanup, err = -EINVAL);
382
383         /* Disable initial recovery on this import */
384         err = obd_set_info(obd->obd_self_export,
385                            strlen("initial_recov"), "initial_recov",
386                            sizeof(allow_recov), &allow_recov);
387
388         err = obd_connect(&mdc_conn, obd, &mdc_uuid);
389         if (err) {
390                 CERROR("cannot connect to %s: rc = %d\n",
391                         g_zconf_mdsname, err);
392                 GOTO(out_cleanup, err);
393         }
394         
395         exp = class_conn2export(&mdc_conn);
396         
397         ctxt = exp->exp_obd->obd_llog_ctxt[LLOG_CONFIG_REPL_CTXT];
398         rc = class_config_parse_llog(ctxt, g_zconf_profile, cfg);
399         if (rc) {
400                 CERROR("class_config_parse_llog failed: rc = %d\n", rc);
401         }
402
403         err = obd_disconnect(exp, 0);
404
405 out_cleanup:
406         LCFG_INIT(lcfg, LCFG_CLEANUP, name);
407         err = class_process_config(&lcfg);
408         if (err < 0)
409                 GOTO(out, err);
410
411 out_detach:
412         LCFG_INIT(lcfg, LCFG_DETACH, name);
413         err = class_process_config(&lcfg);
414         if (err < 0)
415                 GOTO(out, err);
416
417 out_del_uuid:
418         LCFG_INIT(lcfg, LCFG_DEL_UUID, name);
419         lcfg.lcfg_inllen1 = strlen(peer) + 1;
420         lcfg.lcfg_inlbuf1 = peer;
421         err = class_process_config(&lcfg);
422
423 out:
424         if (rc == 0)
425                 rc = err;
426         
427         RETURN(rc);
428 }
429
430 /* parse host:/mdsname/profile string */
431 int ll_parse_mount_target(const char *target, char **mdsnid,
432                           char **mdsname, char **profile)
433 {
434         static char buf[256];
435         char *s;
436
437         buf[255] = 0;
438         strncpy(buf, target, 255);
439
440         if ((s = strchr(buf, ':'))) {
441                 *mdsnid = buf;
442                 *s = '\0';
443                                                                                                                         
444                 while (*++s == '/')
445                         ;
446                 *mdsname = s;
447                 if ((s = strchr(*mdsname, '/'))) {
448                         *s = '\0';
449                         *profile = s + 1;
450                         return 0;
451                 }
452         }
453
454         return -1;
455 }
456
457 /* env variables */
458 #define ENV_LUSTRE_MNTPNT               "LIBLUSTRE_MOUNT_POINT"
459 #define ENV_LUSTRE_MNTTGT               "LIBLUSTRE_MOUNT_TARGET"
460 #define ENV_LUSTRE_TIMEOUT              "LIBLUSTRE_TIMEOUT"
461 #define ENV_LUSTRE_DUMPFILE             "LIBLUSTRE_DUMPFILE"
462
463 extern int _sysio_native_init();
464
465 extern unsigned int obd_timeout;
466
467 /* global variables */
468 int     g_zconf = 0;            /* zeroconf or dumpfile */
469 char   *g_zconf_mdsname = NULL; /* mdsname, for zeroconf */
470 char   *g_zconf_mdsnid = NULL;  /* mdsnid, for zeroconf */
471 char   *g_zconf_profile = NULL; /* profile, for zeroconf */
472
473
474 void __liblustre_setup_(void)
475 {
476         char *lustre_path = NULL;
477         char *target = NULL;
478         char *timeout = NULL;
479         char *dumpfile = NULL;
480         char *root_driver = "native";
481         char *lustre_driver = "llite";
482         char *root_path = "/";
483         unsigned mntflgs = 0;
484
485         int err;
486
487         /* consider tha case of starting multiple liblustre instances
488          * at a same time on single node.
489          */
490         srand(time(NULL) + getpid());
491
492         lustre_path = getenv(ENV_LUSTRE_MNTPNT);
493         if (!lustre_path) {
494                 lustre_path = "/mnt/lustre";
495         }
496
497         target = getenv(ENV_LUSTRE_MNTTGT);
498         if (!target) {
499                 dumpfile = getenv(ENV_LUSTRE_DUMPFILE);
500                 if (!dumpfile) {
501                         CERROR("Neither mount target, nor dumpfile\n");
502                         exit(1);
503                 }
504                 g_zconf = 0;
505                 printf("LibLustre: mount point %s, dumpfile %s\n",
506                         lustre_path, dumpfile);
507         } else {
508                 if (ll_parse_mount_target(target,
509                                           &g_zconf_mdsnid,
510                                           &g_zconf_mdsname,
511                                           &g_zconf_profile)) {
512                         CERROR("mal-formed target %s \n", target);
513                         exit(1);
514                 }
515                 g_zconf = 1;
516                 printf("LibLustre: mount point %s, target %s\n",
517                         lustre_path, target);
518         }
519
520         timeout = getenv(ENV_LUSTRE_TIMEOUT);
521         if (timeout) {
522                 obd_timeout = (unsigned int) atoi(timeout);
523                 printf("LibLustre: set obd timeout as %u seconds\n",
524                         obd_timeout);
525         }
526
527         if (_sysio_init() != 0) {
528                 perror("init sysio");
529                 exit(1);
530         }
531
532         /* cygwin don't need native driver */
533 #ifndef __CYGWIN__
534         _sysio_native_init();
535 #endif
536
537         err = _sysio_mount_root(root_path, root_driver, mntflgs, NULL);
538         if (err) {
539                 perror(root_driver);
540                 exit(1);
541         }
542
543 #if 1
544         portal_debug = 0;
545         portal_subsystem_debug = 0;
546 #endif
547         err = lllib_init(dumpfile);
548         if (err) {
549                 perror("init llite driver");
550                 exit(1);
551         }       
552
553         err = mount("/", lustre_path, lustre_driver, mntflgs, NULL);
554         if (err) {
555                 errno = -err;
556                 perror(lustre_driver);
557                 exit(1);
558         }
559
560 #if 0
561         __sysio_hook_sys_enter = llu_check_request;
562         __sysio_hook_sys_leave = NULL;
563 #endif
564 }
565
566 void __liblustre_cleanup_(void)
567 {
568         _sysio_shutdown();
569         PtlFini();
570 }