X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fliblustre%2Fllite_lib.c;h=7baec8c65702b79302bdb1b4c8490fff7700e43b;hb=2d673ba8fa43267bc51b754ade41684d30256bc1;hp=b11de88ef96aa57c1cbd30add7b139a11dfbab36;hpb=96ec6856f91f7f9031cfce4273c714d72cfe59ae;p=fs%2Flustre-release.git diff --git a/lustre/liblustre/llite_lib.c b/lustre/liblustre/llite_lib.c index b11de88..7baec8c 100644 --- a/lustre/liblustre/llite_lib.c +++ b/lustre/liblustre/llite_lib.c @@ -1,226 +1,427 @@ /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- * vim:expandtab:shiftwidth=8:tabstop=8: * - * Lustre Light Super operations + * GPL HEADER START * - * Copyright (c) 2002, 2003 Cluster File Systems, Inc. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * - * This file is part of Lustre, http://www.lustre.org. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 only, + * as published by the Free Software Foundation. * - * Lustre is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License version 2 for more details (a copy is included + * in the LICENSE file that accompanied this code). * - * Lustre is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * version 2 along with this program; If not, see + * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf * - * You should have received a copy of the GNU General Public License - * along with Lustre; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + * GPL HEADER END + */ +/* + * Copyright 2008 Sun Microsystems, Inc. All rights reserved + * Use is subject to license terms. + */ +/* + * This file is part of Lustre, http://www.lustre.org/ + * Lustre is a trademark of Sun Microsystems, Inc. + * + * lustre/liblustre/llite_lib.c + * + * Lustre Light common routines */ - -#define DEBUG_SUBSYSTEM S_LLITE #include #include -#include #include +#include #include +#include #include #include +#ifdef HAVE_XTIO_H +#include +#endif #include #include #include +#ifdef HAVE_FILE_H #include +#endif -#include -#include -#include - -#include /* needed for ptpctl.h */ -#include /* needed for parse_dump */ +/* both sys/queue.h (libsysio require it) and portals/lists.h have definition + * of 'LIST_HEAD'. undef it to suppress warnings + */ +#undef LIST_HEAD +#include +#include /* needed for parse_dump */ +#include "lutil.h" #include "llite_lib.h" +int slp_global_init(void); -ptl_handle_ni_t tcpnal_ni; -struct task_struct *current; -struct obd_class_user_state ocus; - -/* portals interfaces */ -ptl_handle_ni_t * -kportal_get_ni (int nal) +static int lllib_init(void) { - return &tcpnal_ni; -} + if (liblustre_init_current("liblustre") || + init_lib_portals() || + init_obdclass() || + ptlrpc_init() || + mgc_init() || + lmv_init() || + mdc_init() || + lov_init() || + osc_init() || + slp_global_init()) + return -1; -inline void -kportal_put_ni (int nal) -{ - return; + return _sysio_fssw_register("lustre", &llu_fssw_ops); } -struct ldlm_namespace; -struct ldlm_res_id; -struct obd_import; - -extern int ldlm_cli_cancel_unused(struct ldlm_namespace *ns, struct ldlm_res_id *res_id, int flags); -extern int ldlm_namespace_cleanup(struct ldlm_namespace *ns, int local_only); -extern int ldlm_replay_locks(struct obd_import *imp); - -void *inter_module_get(char *arg) +int liblustre_process_log(struct config_llog_instance *cfg, + char *mgsnid, char *profile, + int allow_recov) { - if (!strcmp(arg, "tcpnal_ni")) - return &tcpnal_ni; - else if (!strcmp(arg, "ldlm_cli_cancel_unused")) - return ldlm_cli_cancel_unused; - else if (!strcmp(arg, "ldlm_namespace_cleanup")) - return ldlm_namespace_cleanup; - else if (!strcmp(arg, "ldlm_replay_locks")) - return ldlm_replay_locks; - else - return NULL; -} + struct lustre_cfg_bufs bufs; + struct lustre_cfg *lcfg; + char *peer = "MGS_UUID"; + struct obd_device *obd; + struct obd_export *exp; + char *name = "mgc_dev"; + class_uuid_t uuid; + struct obd_uuid mgc_uuid; + struct llog_ctxt *ctxt; + lnet_nid_t nid = 0; + char *mdsnid; + int err, rc = 0; + struct obd_connect_data *ocd = NULL; + ENTRY; + + ll_generate_random_uuid(uuid); + class_uuid_unparse(uuid, &mgc_uuid); + + nid = libcfs_str2nid(mgsnid); + if (nid == LNET_NID_ANY) { + CERROR("Can't parse NID %s\n", mgsnid); + RETURN(-EINVAL); + } -void init_current(char *comm) -{ - current = malloc(sizeof(*current)); - current->fs = malloc(sizeof(*current->fs)); - current->fs->umask = umask(0777); - umask(current->fs->umask); - strncpy(current->comm, comm, sizeof(current->comm)); - current->pid = getpid(); - current->fsuid = 0; - current->fsgid = 0; - current->cap_effective = 0; - memset(¤t->pending, 0, sizeof(current->pending)); -} + lustre_cfg_bufs_reset(&bufs, NULL); + lustre_cfg_bufs_set_string(&bufs, 1, peer); + lcfg = lustre_cfg_new(LCFG_ADD_UUID, &bufs); + lcfg->lcfg_nid = nid; + rc = class_process_config(lcfg); + lustre_cfg_free(lcfg); + if (rc < 0) + GOTO(out, rc); + + lustre_cfg_bufs_reset(&bufs, name); + lustre_cfg_bufs_set_string(&bufs, 1, LUSTRE_MGC_NAME); + lustre_cfg_bufs_set_string(&bufs, 2, mgc_uuid.uuid); + lcfg = lustre_cfg_new(LCFG_ATTACH, &bufs); + rc = class_process_config(lcfg); + lustre_cfg_free(lcfg); + if (rc < 0) + GOTO(out_del_uuid, rc); + + lustre_cfg_bufs_reset(&bufs, name); + lustre_cfg_bufs_set_string(&bufs, 1, LUSTRE_MGS_OBDNAME); + lustre_cfg_bufs_set_string(&bufs, 2, peer); + lcfg = lustre_cfg_new(LCFG_SETUP, &bufs); + rc = class_process_config(lcfg); + lustre_cfg_free(lcfg); + if (rc < 0) + GOTO(out_detach, rc); + + while ((mdsnid = strsep(&mgsnid, ","))) { + nid = libcfs_str2nid(mdsnid); + lustre_cfg_bufs_reset(&bufs, NULL); + lustre_cfg_bufs_set_string(&bufs, 1, libcfs_nid2str(nid)); + lcfg = lustre_cfg_new(LCFG_ADD_UUID, &bufs); + lcfg->lcfg_nid = nid; + rc = class_process_config(lcfg); + lustre_cfg_free(lcfg); + if (rc) { + CERROR("Add uuid for %s failed %d\n", + libcfs_nid2str(nid), rc); + continue; + } -ptl_nid_t tcpnal_mynid; + lustre_cfg_bufs_reset(&bufs, name); + lustre_cfg_bufs_set_string(&bufs, 1, libcfs_nid2str(nid)); + lcfg = lustre_cfg_new(LCFG_ADD_CONN, &bufs); + lcfg->lcfg_nid = nid; + rc = class_process_config(lcfg); + lustre_cfg_free(lcfg); + if (rc) { + CERROR("Add conn for %s failed %d\n", + libcfs_nid2str(nid), rc); + continue; + } + } -int init_lib_portals() -{ - int rc; - - PtlInit(); - rc = PtlNIInit(procbridge_interface, 0, 0, 0, &tcpnal_ni); - if (rc != 0) { - CERROR("ksocknal: PtlNIInit failed: error %d\n", rc); - PtlFini(); - RETURN (rc); + obd = class_name2obd(name); + if (obd == NULL) + GOTO(out_cleanup, rc = -EINVAL); + + OBD_ALLOC(ocd, sizeof(*ocd)); + if (ocd == NULL) + GOTO(out_cleanup, rc = -ENOMEM); + + ocd->ocd_connect_flags = OBD_CONNECT_VERSION | OBD_CONNECT_FID | + OBD_CONNECT_AT | OBD_CONNECT_VBR; +#ifdef LIBLUSTRE_POSIX_ACL + ocd->ocd_connect_flags |= OBD_CONNECT_ACL; +#endif + ocd->ocd_version = LUSTRE_VERSION_CODE; + + rc = obd_connect(NULL, &exp, obd, &mgc_uuid, ocd, NULL); + if (rc) { + CERROR("cannot connect to %s at %s: rc = %d\n", + LUSTRE_MGS_OBDNAME, mgsnid, rc); + GOTO(out_cleanup, rc); } - PtlNIDebug(tcpnal_ni, ~0); - return rc; -} -extern int class_handle_ioctl(struct obd_class_user_state *ocus, unsigned int cmd, unsigned long arg); + ctxt = llog_get_context(exp->exp_obd, LLOG_CONFIG_REPL_CTXT); + cfg->cfg_flags |= CFG_F_COMPAT146; + rc = class_config_parse_llog(ctxt, profile, cfg); + llog_ctxt_put(ctxt); + if (rc) { + CERROR("class_config_parse_llog failed: rc = %d\n", rc); + } -struct mount_option_s mount_option = {NULL, NULL}; + /* We don't so much care about errors in cleaning up the config llog + * connection, as we have already read the config by this point. */ + err = obd_disconnect(exp); + if (err) + CERROR("obd_disconnect failed: rc = %d\n", err); + +out_cleanup: + if (ocd) + OBD_FREE(ocd, sizeof(*ocd)); + + lustre_cfg_bufs_reset(&bufs, name); + lcfg = lustre_cfg_new(LCFG_CLEANUP, &bufs); + err = class_process_config(lcfg); + lustre_cfg_free(lcfg); + if (err) + CERROR("md_cleanup failed: rc = %d\n", err); + +out_detach: + lustre_cfg_bufs_reset(&bufs, name); + lcfg = lustre_cfg_new(LCFG_DETACH, &bufs); + err = class_process_config(lcfg); + lustre_cfg_free(lcfg); + if (err) + CERROR("md_detach failed: rc = %d\n", err); + +out_del_uuid: + lustre_cfg_bufs_reset(&bufs, name); + lustre_cfg_bufs_set_string(&bufs, 1, peer); + lcfg = lustre_cfg_new(LCFG_DEL_UUID, &bufs); + err = class_process_config(lcfg); + if (err) + CERROR("del MDC UUID failed: rc = %d\n", err); + lustre_cfg_free(lcfg); +out: + + RETURN(rc); +} -/* FIXME simple arg parser FIXME */ -void parse_mount_options(void *arg) +/* parse host:/fsname string */ +int ll_parse_mount_target(const char *target, char **mgsnid, + char **fsname) { - char *buf = NULL; - struct obd_ioctl_data *data; - char *ptr, *comma, *eq, **tgt, *v; - int len; + static char buf[256]; + char *s; - if (obd_ioctl_getdata(&buf, &len, arg)) { - CERROR("OBD ioctl: data error\n"); - return; - } - data = (struct obd_ioctl_data *)buf; - ptr = data->ioc_inlbuf1; - printf("mount option: %s\n", ptr); - - while (ptr) { - eq = strchr(ptr, '='); - if (!eq) - return; - - *eq = 0; - if (!strcmp("osc", ptr)) - tgt = &mount_option.osc_uuid; - else if (!strcmp("mdc", ptr)) - tgt = &mount_option.mdc_uuid; - else { - printf("Unknown mount option %s\n", ptr); - return; - } + buf[255] = 0; + strncpy(buf, target, 255); - v = eq + 1; - comma = strchr(v, ','); - if (comma) { - *comma = 0; - ptr = comma + 1; - } else - ptr = NULL; + if ((s = strchr(buf, ':'))) { + *mgsnid = buf; + *s = '\0'; - *tgt = malloc(strlen(v)+1); - strcpy(*tgt, v); + while (*++s == '/') + ; + sprintf(s + strlen(s), "-client"); + *fsname = s; + + return 0; } - if (buf) - obd_ioctl_freedata(buf, len); + return -1; } -int lib_ioctl(int dev_id, int opc, void * ptr) +/* + * early liblustre init + * called from C startup in catamount apps, before main() + * + * The following is a skeleton sysio startup sequence, + * as implemented in C startup (skipping error handling). + * In this framework none of these calls need be made here + * or in the apps themselves. The NAMESPACE_STRING specifying + * the initial set of fs ops (creates, mounts, etc.) is passed + * as an environment variable. + * + * _sysio_init(); + * _sysio_incore_init(); + * _sysio_native_init(); + * _sysio_lustre_init(); + * _sysio_boot(NAMESPACE_STRING); + * + * the name _sysio_lustre_init() follows the naming convention + * established in other fs drivers from libsysio: + * _sysio_incore_init(), _sysio_native_init() + * + * _sysio_lustre_init() must be called before _sysio_boot() + * to enable libsysio's processing of namespace init strings containing + * lustre filesystem operations + */ +int _sysio_lustre_init(void) { - int rc; + int err; + char *envstr; +#ifndef INIT_SYSIO + extern void __liblustre_cleanup_(void); +#endif + + liblustre_init_random(); + + err = lllib_init(); + if (err) { + perror("init llite driver"); + return err; + } + + envstr = getenv("LIBLUSTRE_TIMEOUT"); + if (envstr != NULL) { + obd_timeout = (unsigned int)strtol(envstr, NULL, 0); + printf("LibLustre: obd timeout=%u seconds\n", + obd_timeout); + } - if (dev_id == OBD_DEV_ID) { - struct obd_ioctl_data *ioc = ptr; + /* debug peer on timeout? */ + envstr = getenv("LIBLUSTRE_DEBUG_PEER_ON_TIMEOUT"); + if (envstr != NULL) { + obd_debug_peer_on_timeout = + (unsigned int)strtol(envstr, NULL, 0); + printf("LibLustre: debug peer on timeout=%d\n", + obd_debug_peer_on_timeout ? 0 : 1); + } - if (opc == OBD_IOC_MOUNTOPT) { - parse_mount_options(ptr); - return 0; - } +#ifndef INIT_SYSIO + (void)atexit(__liblustre_cleanup_); +#endif + return err; +} - rc = class_handle_ioctl(&ocus, opc, (unsigned long)ptr); +extern int _sysio_native_init(); - /* you _may_ need to call obd_ioctl_unpack or some - other verification function if you want to use ioc - directly here */ - printf ("processing ioctl cmd: %x buf len: %d, rc %d\n", - opc, ioc->ioc_len, rc); +static int mnt_retry = 0; - if (rc) - return rc; - } - return (0); -} +char *lustre_path = NULL; -int lllib_init(char *arg) +void __liblustre_setup_(void) { - tcpnal_mynid = ntohl(inet_addr(arg)); - INIT_LIST_HEAD(&ocus.ocus_conns); + char *target = NULL; + char *lustre_driver = "lustre"; + unsigned mntflgs = 0; + int err, count; + + lustre_path = getenv("LIBLUSTRE_MOUNT_POINT"); + if (!lustre_path) { + lustre_path = "/mnt/lustre"; + } - init_current("dummy"); - if (init_obdclass() || - init_lib_portals() || - ptlrpc_init() || - ldlm_init() || - mdc_init() || - lov_init() || - osc_init()) - return -1; + target = getenv("LIBLUSTRE_MOUNT_RETRY"); + if (target) { + mnt_retry = atoi(target); + if (mnt_retry < 0) + mnt_retry = 0; + } - if (parse_dump("/tmp/DUMP_FILE", lib_ioctl)) - return -1; + /* mount target */ + target = getenv("LIBLUSTRE_MOUNT_TARGET"); + if (!target) { + printf("LibLustre: no mount target specified\n"); + exit(1); + } - return _sysio_fssw_register("llite", &llu_fssw_ops); + CDEBUG(D_CONFIG, "LibLustre: mount point %s, target %s\n", + lustre_path, target); + +#ifdef INIT_SYSIO + /* initialize libsysio & mount rootfs */ + if (_sysio_init()) { + perror("init sysio"); + exit(1); + } + _sysio_native_init(); + + err = _sysio_mount_root("/", "native", mntflgs, NULL); + if (err) { + fprintf(stderr, "sysio mount failed: %s\n", strerror(errno)); + exit(1); + } + + if (_sysio_lustre_init()) + exit(1); +#endif /* INIT_SYSIO */ + + count = mnt_retry; + do { + err = mount(target, lustre_path, lustre_driver, mntflgs, NULL); + if (err && mnt_retry && (-- count)) { + fprintf(stderr, "Lustre mount failed: %s. " + "Will retry %d more times\n", + strerror(errno), mnt_retry - count ); + sleep(2); + } + } while (err && count > 0); + if (err) { + fprintf(stderr, "Lustre mount failed: %s\n", strerror(errno)); + exit(1); + } } -/* FIXME */ -void generate_random_uuid(unsigned char uuid_out[16]) +void __liblustre_cleanup_(void) { - int *arr = (int*)uuid_out; - int i; +#ifndef INIT_SYSIO + /* guard against being called multiple times */ + static int cleaned = 0; - for (i = 0; i < sizeof(uuid_out)/sizeof(int); i++) - arr[i] = rand(); + if (cleaned) + return; + cleaned++; +#endif + + /* user app might chdir to a lustre directory, and leave busy pnode + * during finaly libsysio cleanup. here we chdir back to "/". + * but it can't fix the situation that liblustre is mounted + * at "/". + */ + chdir("/"); +#if 0 + umount(lustre_path); +#endif + /* we can't call umount here, because libsysio will not cleanup + * opening files for us. _sysio_shutdown() will cleanup fds at + * first but which will also close the sockets we need for umount + * liblutre. this dilema lead to another hack in + * libsysio/src/file_hack.c FIXME + */ +#ifdef INIT_SYSIO + _sysio_shutdown(); + cleanup_lib_portals(); + LNetFini(); +#endif } -