From b182fa6bf5f8cb0dac2374e4fc6c95e76996544b Mon Sep 17 00:00:00 2001 From: rread Date: Wed, 8 Oct 2003 07:07:12 +0000 Subject: [PATCH] landing b_lcfg to b_devel - llog network api for processing the log from the client - config messages changed to use struct lustre_cfg and struct portals_cfg - lctl record options save config messages to log on the mds - ll_fill_super supports fetching the log and replaying to setup the devices needed for mount. - small changes to lctl interface to support new config protocol. - newdev is now a no-op. - cfg_device is used to set the target device for detach and cleanup. --- lustre/include/linux/lustre_cfg.h | 237 +++++++++++++++++++ lustre/obdclass/llog_test.c | 68 ++++-- lustre/obdclass/obd_config.c | 474 +++++++++++++++++++++++++++++++++++++ lustre/ptlrpc/llogd.c | 291 +++++++++++++++++++++++ lustre/ptlrpc/ptlrpc_module.c | 8 + lustre/utils/llmount.c | 111 +++++++++ lustre/utils/lustre_cfg.c | 477 ++++++++++++++++++++++++++++++++++++++ 7 files changed, 1653 insertions(+), 13 deletions(-) create mode 100644 lustre/include/linux/lustre_cfg.h create mode 100644 lustre/obdclass/obd_config.c create mode 100644 lustre/ptlrpc/llogd.c create mode 100644 lustre/utils/llmount.c create mode 100644 lustre/utils/lustre_cfg.c diff --git a/lustre/include/linux/lustre_cfg.h b/lustre/include/linux/lustre_cfg.h new file mode 100644 index 0000000..5403244 --- /dev/null +++ b/lustre/include/linux/lustre_cfg.h @@ -0,0 +1,237 @@ +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- + * vim:expandtab:shiftwidth=8:tabstop=8: + * + * Copyright (C) 2001 Cluster File Systems, Inc. + * + * This file is part of Lustre, http://www.lustre.org. + * + * 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. + * + * 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 + * along with Lustre; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef _LUSTRE_CFG_H +#define _LUSTRE_CFG_H + +#define LUSTRE_CFG_VERSION 0x00010001 + +enum lcfg_command_type { + LCFG_ATTACH = 0x00cf001, + LCFG_DETACH = 0x00cf002, + LCFG_SETUP = 0x00cf003, + LCFG_CLEANUP = 0x00cf004, + LCFG_LOV_SET_CONFIG = 0x00cf005, + LCFG_ADD_UUID = 0x00cf006, + LCFG_DEL_UUID = 0x00cf007, + LCFG_MOUNTOPT = 0x00cf008, + LCFG_DEL_MOUNTOPT = 0x00cf009, +}; + +struct lustre_cfg { + uint32_t lcfg_version; + uint32_t lcfg_command; + + uint32_t lcfg_dev; + uint32_t lcfg_flags; + uint64_t lcfg_nid; + uint32_t lcfg_nal; + + /* inline buffers for various arguments */ + uint32_t lcfg_dev_namelen; + char *lcfg_dev_name; + uint32_t lcfg_inllen1; + char *lcfg_inlbuf1; + uint32_t lcfg_inllen2; + char *lcfg_inlbuf2; + uint32_t lcfg_inllen3; + char *lcfg_inlbuf3; + uint32_t lcfg_inllen4; + char *lcfg_inlbuf4; + + char lcfg_bulk[0]; + +}; + +#ifndef __KERNEL__ +static inline int lustre_cfg_packlen(struct lustre_cfg *lcfg) +{ + int len = size_round(sizeof(struct lustre_cfg)); + len += size_round(lcfg->lcfg_dev_namelen); + len += size_round(lcfg->lcfg_inllen1); + len += size_round(lcfg->lcfg_inllen2); + len += size_round(lcfg->lcfg_inllen3); + len += size_round(lcfg->lcfg_inllen4); + return size_round16(len); + +} + +static inline int lustre_cfg_pack(struct lustre_cfg *data, char **pbuf, + int max, int *plen) +{ + char *ptr; + struct lustre_cfg *overlay; + int len; + + len = lustre_cfg_packlen(data); + + data->lcfg_version = LUSTRE_CFG_VERSION; + + if (*pbuf && len > max) + return 1; + if (*pbuf == NULL) { + *pbuf = malloc(len); + } + if (!*pbuf) + return 1; + overlay = (struct lustre_cfg *)*pbuf; + memcpy(*pbuf, data, sizeof(*data)); + + ptr = overlay->lcfg_bulk; + if (data->lcfg_dev_name) + LOGL(data->lcfg_dev_name, data->lcfg_dev_namelen, ptr); + if (data->lcfg_inlbuf1) + LOGL(data->lcfg_inlbuf1, data->lcfg_inllen1, ptr); + if (data->lcfg_inlbuf2) + LOGL(data->lcfg_inlbuf2, data->lcfg_inllen2, ptr); + if (data->lcfg_inlbuf3) + LOGL(data->lcfg_inlbuf3, data->lcfg_inllen3, ptr); + if (data->lcfg_inlbuf4) + LOGL(data->lcfg_inlbuf4, data->lcfg_inllen4, ptr); +// if (lustre_cfg_is_invalid(overlay)) +// return 1; + + *plen = len; + + return 0; +} + +static inline int lustre_cfg_unpack(struct lustre_cfg *data, char *pbuf, + int max) +{ + char *ptr; + struct lustre_cfg *overlay; + + if (!pbuf) + return 1; + overlay = (struct lustre_cfg *)pbuf; + + /* Preserve the caller's buffer pointers */ + overlay->lcfg_dev_name = data->lcfg_dev_name; + overlay->lcfg_inlbuf1 = data->lcfg_inlbuf1; + overlay->lcfg_inlbuf2 = data->lcfg_inlbuf2; + overlay->lcfg_inlbuf3 = data->lcfg_inlbuf3; + overlay->lcfg_inlbuf4 = data->lcfg_inlbuf4; + + memcpy(data, pbuf, sizeof(*data)); + + ptr = overlay->lcfg_bulk; + if (data->lcfg_dev_name) + LOGU(data->lcfg_dev_name, data->lcfg_dev_namelen, ptr); + if (data->lcfg_inlbuf1) + LOGU(data->lcfg_inlbuf1, data->lcfg_inllen1, ptr); + if (data->lcfg_inlbuf2) + LOGU(data->lcfg_inlbuf2, data->lcfg_inllen2, ptr); + if (data->lcfg_inlbuf3) + LOGU(data->lcfg_inlbuf3, data->lcfg_inllen3, ptr); + if (data->lcfg_inlbuf4) + LOGU(data->lcfg_inlbuf4, data->lcfg_inllen4, ptr); + + return 0; +} +#endif + +#include + +static inline int lustre_cfg_getdata(char **buf, int len, void *arg, int kernel) +{ + struct lustre_cfg *lcfg; + int err; + int offset = 0; + ENTRY; + if (len > OBD_MAX_IOCTL_BUFFER) { + CERROR("User buffer len %d exceeds %d max buffer\n", + len, OBD_MAX_IOCTL_BUFFER); + return -EINVAL; + } + + if (len < sizeof(struct lustre_cfg)) { + CERROR("OBD: user buffer too small for lustre_cfg\n"); + return -EINVAL; + } + + /* XXX allocate this more intelligently, using kmalloc when + * appropriate */ + OBD_ALLOC(*buf, len); + if (*buf == NULL) { + CERROR("Cannot allocate control buffer of len %d\n", len); + RETURN(-EINVAL); + } + + if (kernel) { + memcpy(*buf, (void *)arg, len); + } else { + err = copy_from_user(*buf, (void *)arg, len); + if (err) + RETURN(err); + } + + lcfg = (struct lustre_cfg *)*buf; + + if (lcfg->lcfg_version != LUSTRE_CFG_VERSION) { + CERROR("Version mismatch kernel vs application\n"); + return -EINVAL; + } + +// if (lustre_cfg_is_invalid(data)) { +// CERROR("ioctl not correctly formatted\n"); +// return -EINVAL; +// } + + if (lcfg->lcfg_dev_name) { + lcfg->lcfg_dev_name = &lcfg->lcfg_bulk[0]; + offset += size_round(lcfg->lcfg_dev_namelen); + } + + if (lcfg->lcfg_inllen1) { + lcfg->lcfg_inlbuf1 = &lcfg->lcfg_bulk[0] + offset; + offset += size_round(lcfg->lcfg_inllen1); + } + + if (lcfg->lcfg_inllen2) { + lcfg->lcfg_inlbuf2 = &lcfg->lcfg_bulk[0] + offset; + offset += size_round(lcfg->lcfg_inllen2); + } + + if (lcfg->lcfg_inllen3) { + lcfg->lcfg_inlbuf3 = &lcfg->lcfg_bulk[0] + offset; + offset += size_round(lcfg->lcfg_inllen3); + } + + if (lcfg->lcfg_inllen4) { + lcfg->lcfg_inlbuf4 = &lcfg->lcfg_bulk[0] + offset; + } + + EXIT; + return 0; +} + +static inline void lustre_cfg_freedata(char *buf, int len) +{ + ENTRY; + + OBD_FREE(buf, len); + EXIT; + return; +} + +#endif // _LUSTRE_CFG_H diff --git a/lustre/obdclass/llog_test.c b/lustre/obdclass/llog_test.c index ab37397..06a4ac0 100644 --- a/lustre/obdclass/llog_test.c +++ b/lustre/obdclass/llog_test.c @@ -72,15 +72,13 @@ static int verify_handle(char * test, struct llog_handle *llh, int num_recs) } /* Test named-log create/open, close */ -static int llog_test_1(struct obd_device *obd) +static int llog_test_1(struct obd_device *obd, char * name) { struct llog_handle *llh; - char name[10]; int rc; int rc2; ENTRY; - sprintf(name, "%x", llog_test_rand); CERROR("1a: create a log with name: %s\n", name); rc = llog_create(obd, &llh, NULL, name); @@ -105,13 +103,11 @@ static int llog_test_1(struct obd_device *obd) } /* Test named-log reopen; returns opened log on success */ -static int llog_test_2(struct obd_device *obd, struct llog_handle **llh) +static int llog_test_2(struct obd_device *obd, char * name, struct llog_handle **llh) { - char name[10]; int rc; ENTRY; - sprintf(name, "%x", llog_test_rand); CERROR("2: re-open a log with name: %s\n", name); rc = llog_create(obd, llh, NULL, name); if (rc) { @@ -338,6 +334,46 @@ static int llog_test_5(struct obd_device *obd) } +static int llog_test6_process_rec(struct llog_rec_hdr * rec, void * private) +{ + return 0; +} + +/* Test client api; open log by name and process */ +static int llog_test_6(struct obd_device *obd, char * name) +{ + struct obd_device *mdc_obd; + struct obd_uuid *mds_uuid = &obd->obd_log_exp->exp_obd->obd_uuid; + struct lustre_handle exph = {0, }; + struct obd_export * exp; + struct obd_uuid uuid = {"LLOG_TEST6_UUID"}; + int rc; + + CERROR("6a: re-open log %s using client API\n", name); + mdc_obd = class_find_client_obd(mds_uuid, LUSTRE_MDC_NAME, NULL); + if (mdc_obd == NULL) { + CERROR("No MDC devices connected to %s found.\n", + mds_uuid->uuid); + RETURN(-ENOENT); + } + + rc = obd_connect(&exph, mdc_obd, &uuid); + if (rc) { + CERROR("Failed to connect to MDC: %s\n", mdc_obd->obd_name); + RETURN(rc); + } + + exp = class_conn2export(&exph); + rc = mdc_llog_process(exp, name, NULL, llog_test6_process_rec); + if (rc) { + CERROR("mdc_llog_process failed: rc = %d\n", rc); + } + + rc = obd_disconnect(exp, 0); + + RETURN(rc); + +} /* ------------------------------------------------------------------------- * Tests above, boring obd functions below @@ -347,15 +383,17 @@ static int llog_run_tests(struct obd_device *obd) struct llog_handle *llh; struct obd_run_ctxt saved; int rc, err, cleanup_phase = 0; + char name[10]; ENTRY; + sprintf(name, "%x", llog_test_rand); push_ctxt(&saved, &obd->obd_log_exp->exp_obd->obd_ctxt, NULL); - rc = llog_test_1(obd); + rc = llog_test_1(obd, name); if (rc) GOTO(cleanup, rc); - rc = llog_test_2(obd, &llh); + rc = llog_test_2(obd, name, &llh); if (rc) GOTO(cleanup, rc); cleanup_phase = 1; /* close llh */ @@ -372,6 +410,10 @@ static int llog_run_tests(struct obd_device *obd) if (rc) GOTO(cleanup, rc); + rc = llog_test_6(obd, name); + if (rc) + GOTO(cleanup, rc); + GOTO(cleanup, rc); cleanup: switch (cleanup_phase) { @@ -398,28 +440,28 @@ static int llog_test_cleanup(struct obd_device *obd, int flags) static int llog_test_setup(struct obd_device *obd, obd_count len, void *buf) { - struct obd_ioctl_data *data = buf; + struct lustre_cfg *lcfg = buf; struct lustre_handle exph = {0, }; struct obd_device *tgt; struct obd_uuid fake_uuid = { "LLOG_TEST_UUID" }; int rc; ENTRY; - if (data->ioc_inllen1 < 1) { + if (lcfg->lcfg_inllen1 < 1) { CERROR("requires a TARGET OBD name\n"); RETURN(-EINVAL); } - tgt = class_name2obd(data->ioc_inlbuf1); + tgt = class_name2obd(lcfg->lcfg_inlbuf1); if (!tgt || !tgt->obd_attached || !tgt->obd_set_up) { CERROR("target device not attached or not set up (%d/%s)\n", - data->ioc_dev, data->ioc_inlbuf1); + lcfg->lcfg_dev, lcfg->lcfg_inlbuf1); RETURN(-EINVAL); } rc = obd_connect(&exph, tgt, &fake_uuid); if (rc) { - CERROR("fail to connect to target device %d\n", data->ioc_dev); + CERROR("fail to connect to target device %d\n", lcfg->lcfg_dev); RETURN(rc); } obd->obd_log_exp = class_conn2export(&exph); diff --git a/lustre/obdclass/obd_config.c b/lustre/obdclass/obd_config.c new file mode 100644 index 0000000..a66bdff --- /dev/null +++ b/lustre/obdclass/obd_config.c @@ -0,0 +1,474 @@ +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- + * vim:expandtab:shiftwidth=8:tabstop=8: + * + * Copyright (c) 2001-2003 Cluster File Systems, Inc. + * + * This file is part of Lustre, http://www.lustre.org. + * + * 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. + * + * 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 + * along with Lustre; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Config API + * + */ + +#define DEBUG_SUBSYSTEM S_CLASS +#ifdef __KERNEL__ +#include /* for request_module() */ +#include +#include +#include +#include +#include +#else +#include +#include +#include +#endif +#include +#include + + +/* Create a new device and set the type, name and uuid. If + * successful, the new device can be accessed by either name or uuid. + */ +int class_attach(struct lustre_cfg *lcfg) +{ + int minor; + struct obd_type *type; + int err = 0; + int len; + char *typename; + char *name; + char *uuid; + struct obd_device *obd; + int dev; + + if (!lcfg->lcfg_inllen1 || !lcfg->lcfg_inlbuf1) { + CERROR("No type passed!\n"); + RETURN(-EINVAL); + } + if (lcfg->lcfg_inlbuf1[lcfg->lcfg_inllen1 - 1] != 0) { + CERROR("Type not nul terminated!\n"); + RETURN(-EINVAL); + } + typename = lcfg->lcfg_inlbuf1; + + if (!lcfg->lcfg_dev_namelen || !lcfg->lcfg_dev_name) { + CERROR("No name passed!\n"); + RETURN(-EINVAL); + } + if (lcfg->lcfg_dev_name[lcfg->lcfg_dev_namelen - 1] != 0) { + CERROR("Name not nul terminated!\n"); + RETURN(-EINVAL); + } + name = lcfg->lcfg_dev_name; + + if (!lcfg->lcfg_inllen2 || !lcfg->lcfg_inlbuf2) { + CERROR("No UUID passed!\n"); + RETURN(-EINVAL); + } + if (lcfg->lcfg_inlbuf2[lcfg->lcfg_inllen2 - 1] != 0) { + CERROR("UUID not nul terminated!\n"); + RETURN(-EINVAL); + } + uuid = lcfg->lcfg_inlbuf2; + + CDEBUG(D_IOCTL, "attach type %s name: %s uuid: %s\n", + MKSTR(lcfg->lcfg_inlbuf1), + MKSTR(lcfg->lcfg_inlbuf2), MKSTR(lcfg->lcfg_inlbuf3)); + + /* find the type */ + type = class_get_type(typename); + if (!type) { + CERROR("OBD: unknown type: %s\n", typename); + RETURN(-EINVAL); + } + + obd = class_name2obd(name); + if (obd != NULL) { + CERROR("obd %s already attached\n", name); + RETURN(-EEXIST); + } + + obd = class_newdev(&dev); + if (dev == -1) + RETURN(-EINVAL); + + /* have we attached a type to this device */ + if (obd->obd_attached || obd->obd_type) { + CERROR("OBD: Device %d already typed as %s.\n", + obd->obd_minor, MKSTR(obd->obd_type->typ_name)); + RETURN(-EBUSY); + } + + minor = obd->obd_minor; + memset(obd, 0, sizeof(*obd)); + obd->obd_minor = minor; + obd->obd_type = type; + INIT_LIST_HEAD(&obd->obd_exports); + obd->obd_num_exports = 0; + spin_lock_init(&obd->obd_dev_lock); + init_waitqueue_head(&obd->obd_refcount_waitq); + + /* XXX belong ins setup not attach */ + /* recovery data */ + spin_lock_init(&obd->obd_processing_task_lock); + init_waitqueue_head(&obd->obd_next_transno_waitq); + INIT_LIST_HEAD(&obd->obd_recovery_queue); + INIT_LIST_HEAD(&obd->obd_delayed_reply_queue); + + init_waitqueue_head(&obd->obd_commit_waitq); + + len = strlen(name) + 1; + OBD_ALLOC(obd->obd_name, len); + if (!obd->obd_name) { + class_put_type(obd->obd_type); + obd->obd_type = NULL; + RETURN(-ENOMEM); + } + memcpy(obd->obd_name, name, len); + + len = strlen(uuid); + if (len >= sizeof(obd->obd_uuid)) { + CERROR("uuid must be < "LPSZ" bytes long\n", + sizeof(obd->obd_uuid)); + if (obd->obd_name) + OBD_FREE(obd->obd_name, + strlen(obd->obd_name) + 1); + class_put_type(obd->obd_type); + obd->obd_type = NULL; + RETURN(-EINVAL); + } + memcpy(obd->obd_uuid.uuid, uuid, len); + + /* do the attach */ + if (OBP(obd, attach)) + err = OBP(obd,attach)(obd, sizeof *lcfg, lcfg); + + if (err) { + if(name) + OBD_FREE(obd->obd_name, + strlen(obd->obd_name) + 1); + class_put_type(obd->obd_type); + obd->obd_type = NULL; + } else { + obd->obd_attached = 1; + + type->typ_refcnt++; + CDEBUG(D_IOCTL, "OBD: dev %d attached type %s\n", + obd->obd_minor, typename); + } + RETURN(err); +} + +int class_setup(struct obd_device *obd, struct lustre_cfg *lcfg) +{ + int err = 0; + ENTRY; + + /* have we attached a type to this device? */ + if (!obd->obd_attached) { + CERROR("Device %d not attached\n", obd->obd_minor); + RETURN(-ENODEV); + } + + /* has this been done already? */ + if (obd->obd_set_up) { + CERROR("Device %d already setup (type %s)\n", + obd->obd_minor, obd->obd_type->typ_name); + RETURN(-EBUSY); + } + + atomic_set(&obd->obd_refcount, 0); + + if (OBT(obd) && OBP(obd, setup)) + err = obd_setup(obd, sizeof(*lcfg), lcfg); + + if (!err) { + obd->obd_type->typ_refcnt++; + obd->obd_set_up = 1; + atomic_inc(&obd->obd_refcount); + } + RETURN(err); +} + +int class_detach(struct obd_device *obd, struct lustre_cfg *lcfg) +{ + int err = 0; + + ENTRY; + if (obd->obd_set_up) { + CERROR("OBD device %d still set up\n", obd->obd_minor); + RETURN(-EBUSY); + } + if (!obd->obd_attached) { + CERROR("OBD device %d not attached\n", obd->obd_minor); + RETURN(-ENODEV); + } + if (OBP(obd, detach)) + err = OBP(obd,detach)(obd); + + if (obd->obd_name) { + OBD_FREE(obd->obd_name, strlen(obd->obd_name)+1); + obd->obd_name = NULL; + } + + obd->obd_attached = 0; + obd->obd_type->typ_refcnt--; + class_put_type(obd->obd_type); + obd->obd_type = NULL; + memset(obd, 0, sizeof(*obd)); + RETURN(err); +} + +static void dump_exports(struct obd_device *obd) +{ + struct obd_export *exp, *n; + + list_for_each_entry_safe(exp, n, &obd->obd_exports, exp_obd_chain) { + CERROR("%s: %p %s %d %d %p\n", + obd->obd_name, exp, exp->exp_client_uuid.uuid, + atomic_read(&exp->exp_refcount), + exp->exp_failed, exp->exp_outstanding_reply ); + } +} + +int class_cleanup(struct obd_device *obd, struct lustre_cfg *lcfg) +{ + int flags = 0; + int err = 0; + char *flag; + + ENTRY; + if (!obd->obd_set_up) { + CERROR("Device %d not setup\n", obd->obd_minor); + RETURN(-ENODEV); + } + + if (lcfg->lcfg_inlbuf1) { + for (flag = lcfg->lcfg_inlbuf1; *flag != 0; flag++) + switch (*flag) { + case 'F': + flags |= OBD_OPT_FORCE; + break; + case 'A': + flags |= OBD_OPT_FAILOVER; + break; + default: + CERROR("unrecognised flag '%c'\n", + *flag); + } + } + + if (atomic_read(&obd->obd_refcount) == 1 || + flags & OBD_OPT_FORCE) { + /* this will stop new connections, and need to + do it before class_disconnect_exports() */ + obd->obd_stopping = 1; + } + + if (atomic_read(&obd->obd_refcount) > 1) { + struct l_wait_info lwi = LWI_TIMEOUT_INTR(1 * HZ, NULL, + NULL, NULL); + int rc; + + if (!(flags & OBD_OPT_FORCE)) { + CERROR("OBD device %d (%p) has refcount %d\n", + obd->obd_minor, obd, + atomic_read(&obd->obd_refcount)); + dump_exports(obd); + RETURN(-EBUSY); + } + class_disconnect_exports(obd, flags); + CDEBUG(D_IOCTL, + "%s: waiting for obd refs to go away: %d\n", + obd->obd_name, atomic_read(&obd->obd_refcount)); + + rc = l_wait_event(obd->obd_refcount_waitq, + atomic_read(&obd->obd_refcount) < 2, &lwi); + if (rc == 0) { + LASSERT(atomic_read(&obd->obd_refcount) == 1); + } else { + CERROR("wait cancelled cleaning anyway. " + "refcount: %d\n", + atomic_read(&obd->obd_refcount)); + dump_exports(obd); + } + CDEBUG(D_IOCTL, "%s: awake, now finishing cleanup\n", + obd->obd_name); + } + + if (OBT(obd) && OBP(obd, cleanup)) + err = obd_cleanup(obd, flags); + + if (!err) { + obd->obd_set_up = obd->obd_stopping = 0; + obd->obd_type->typ_refcnt--; + atomic_dec(&obd->obd_refcount); + /* XXX this should be an LASSERT */ + if (atomic_read(&obd->obd_refcount) > 0) + CERROR("%s still has refcount %d after " + "cleanup.\n", obd->obd_name, + atomic_read(&obd->obd_refcount)); + } + + RETURN(err); +} + +LIST_HEAD(lustre_profile_list); + +struct lustre_profile *class_get_profile(char * prof) +{ + struct lustre_profile *lprof; + + list_for_each_entry(lprof, &lustre_profile_list, lp_list) { + if (!strcmp(lprof->lp_profile, prof)) { + RETURN(lprof); + } + } + RETURN(NULL); +} + +int class_add_profile(int proflen, char *prof, + int osclen, char *osc, + int mdclen, char *mdc) +{ + struct lustre_profile *lprof; + int err = 0; + + OBD_ALLOC(lprof, sizeof(*lprof)); + if (lprof == NULL) + GOTO(out, err = -ENOMEM); + INIT_LIST_HEAD(&lprof->lp_list); + + LASSERT(proflen == (strlen(prof) + 1)); + OBD_ALLOC(lprof->lp_profile, proflen); + if (lprof->lp_profile == NULL) + GOTO(out, err = -ENOMEM); + memcpy(lprof->lp_profile, prof, proflen); + + LASSERT(osclen == (strlen(osc) + 1)); + OBD_ALLOC(lprof->lp_osc, osclen); + if (lprof->lp_profile == NULL) + GOTO(out, err = -ENOMEM); + memcpy(lprof->lp_osc, osc, osclen); + + LASSERT(mdclen == (strlen(mdc) + 1)); + OBD_ALLOC(lprof->lp_mdc, mdclen); + if (lprof->lp_mdc == NULL) + GOTO(out, err = -ENOMEM); + memcpy(lprof->lp_mdc, mdc, mdclen); + + list_add(&lprof->lp_list, &lustre_profile_list); + +out: + RETURN(err); +} + +void class_del_profile(char *prof) +{ + struct lustre_profile *lprof; + + lprof = class_get_profile(prof); + if (lprof) { + list_del(&lprof->lp_list); + OBD_FREE(lprof->lp_profile, strlen(lprof->lp_profile) + 1); + OBD_FREE(lprof->lp_osc, strlen(lprof->lp_osc) + 1); + OBD_FREE(lprof->lp_mdc, strlen(lprof->lp_mdc) + 1); + OBD_FREE(lprof, sizeof *lprof); + } +} + +int class_process_config(struct lustre_cfg *lcfg) +{ + struct obd_device *obd; + int err; + + LASSERT(lcfg && !IS_ERR(lcfg)); + + CDEBUG(D_IOCTL, "processing cmd: %x\n", lcfg->lcfg_command); + + /* Commands that don't need a device */ + switch(lcfg->lcfg_command) { + case LCFG_ATTACH: { + err = class_attach(lcfg); + GOTO(out, err); + } + case LCFG_ADD_UUID: { + CDEBUG(D_IOCTL, "adding mapping from uuid %s to nid "LPX64 + ", nal %d\n", lcfg->lcfg_inlbuf1, lcfg->lcfg_nid, + lcfg->lcfg_nal); + + err = class_add_uuid(lcfg->lcfg_inlbuf1, lcfg->lcfg_nid, + lcfg->lcfg_nal); + GOTO(out, err); + } + case LCFG_DEL_UUID: { + CDEBUG(D_IOCTL, "removing mappings for uuid %s\n", + lcfg->lcfg_inlbuf1 == NULL ? "" : + lcfg->lcfg_inlbuf1); + + err = class_del_uuid(lcfg->lcfg_inlbuf1); + GOTO(out, err); + } + case LCFG_MOUNTOPT: { + CDEBUG(D_IOCTL, "mountopt: profile %s osc %s mdc %s\n", + lcfg->lcfg_inlbuf1, lcfg->lcfg_inlbuf2, lcfg->lcfg_inlbuf3); + /* set these mount options somewhere, so ll_fill_super + * can find them. */ + err = class_add_profile(lcfg->lcfg_inllen1, lcfg->lcfg_inlbuf1, + lcfg->lcfg_inllen2, lcfg->lcfg_inlbuf2, + lcfg->lcfg_inllen3, lcfg->lcfg_inlbuf3); + GOTO(out, err); + } + case LCFG_DEL_MOUNTOPT: { + CDEBUG(D_IOCTL, "mountopt: profile %s\n", lcfg->lcfg_inlbuf1); + /* set these mount options somewhere, so ll_fill_super + * can find them. */ + class_del_profile(lcfg->lcfg_inlbuf1); + GOTO(out, err = 0); + } + } + + + /* Commands that require a device */ + obd = class_name2obd(lcfg->lcfg_dev_name); + if (obd == NULL) { + CERROR("no device\n"); + GOTO(out, err = -EINVAL); + } + + switch(lcfg->lcfg_command) { + case LCFG_SETUP: { + err = class_setup(obd, lcfg); + GOTO(out, err); + } + case LCFG_DETACH: { + err = class_detach(obd, lcfg); + GOTO(out, err = 0); + } + case LCFG_CLEANUP: { + err = class_cleanup(obd, lcfg); + GOTO(out, err = 0); + } + default: { + err = obd_config(obd, lcfg); + if (err) + GOTO(out, err); + } + } +out: + RETURN(err); +} + diff --git a/lustre/ptlrpc/llogd.c b/lustre/ptlrpc/llogd.c new file mode 100644 index 0000000..e5525c9 --- /dev/null +++ b/lustre/ptlrpc/llogd.c @@ -0,0 +1,291 @@ +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- + * vim:expandtab:shiftwidth=8:tabstop=8: + * + * Copyright (C) 2001-2003 Cluster File Systems, Inc. + * Author: Andreas Dilger + * + * This file is part of Lustre, http://www.lustre.org. + * + * 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. + * + * 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 + * along with Lustre; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * remote api for llog + * + */ + +#define DEBUG_SUBSYSTEM S_LOG + +#ifndef EXPORT_SYMTAB +#define EXPORT_SYMTAB +#endif + +#include +#include +#include +#include +#include + +int llogd_init(struct ptlrpc_request *req) +{ + struct obd_export *exp = req->rq_export; + struct obd_device *obd = exp->exp_obd; + struct llog_handle *loghandle; + struct llog_desc desc; + struct obd_run_ctxt saved; + void * ptr; + char * name; + int size[] = {sizeof (desc), + LLOG_BITMAP_BYTES}; + int rc, rc2; + ENTRY; + + LASSERT(obd->obd_log_exp == NULL); + + name = lustre_msg_string(req->rq_reqmsg, 0, 0); + if (name == NULL) { + CERROR("Can't unpack name\n"); + GOTO(out, rc = -EFAULT); + } + + memset(&desc, 0, sizeof(desc)); + + push_ctxt(&saved, &obd->obd_ctxt, NULL); + obd->obd_log_exp = class_export_get(exp); + + rc = llog_create(obd, &loghandle, NULL, name); + if (rc) + GOTO(out_pop, rc); + desc.lgd_logid = loghandle->lgh_id; + desc.lgd_cur_offset = LLOG_CHUNK_SIZE; /* skip header block */ + + rc = llog_init_handle(loghandle, LLOG_F_IS_PLAIN, + NULL); + if (rc) + GOTO(out_close, rc); + + rc = lustre_pack_msg(2, size, NULL, &req->rq_replen, &req->rq_repmsg); + if (rc) + GOTO(out_close, rc = -ENOMEM); + + ptr = lustre_msg_buf(req->rq_repmsg, 0, sizeof (desc)); + memcpy(ptr, &desc, sizeof(desc)); + + ptr = lustre_msg_buf(req->rq_repmsg, 1, LLOG_BITMAP_BYTES); + memcpy(ptr, loghandle->lgh_hdr->llh_bitmap, LLOG_BITMAP_BYTES); + +out_close: + rc2 = llog_close(loghandle); + class_export_put(obd->obd_log_exp); + obd->obd_log_exp = NULL; + if (!rc) + rc = rc2; +out_pop: + pop_ctxt(&saved, &obd->obd_ctxt, NULL); +out: + RETURN(rc); +} + +int llogd_next_block(struct ptlrpc_request *req) +{ + struct obd_export *exp = req->rq_export; + struct obd_device *obd = exp->exp_obd; + struct llog_handle *loghandle; + struct llog_desc *desc; + struct obd_run_ctxt saved; + __u8 *buf; + void * ptr; + int size[] = {sizeof (*desc), + LLOG_CHUNK_SIZE}; + int rc, rc2; + ENTRY; + + LASSERT(obd->obd_log_exp == NULL); + + desc = lustre_swab_reqbuf(req, 0, sizeof(*desc), + lustre_swab_llog_desc); + if (desc == NULL) { + CERROR ("Can't unpack llog_desc\n"); + GOTO(out, rc =-EFAULT); + } + + OBD_ALLOC(buf, LLOG_CHUNK_SIZE); + if (!buf) + GOTO(out, rc = -ENOMEM); + + push_ctxt(&saved, &obd->obd_ctxt, NULL); + obd->obd_log_exp = class_export_get(exp); + + rc = llog_create(obd, &loghandle, &desc->lgd_logid, NULL); + if (rc) + GOTO(out_pop, rc); + + rc = llog_init_handle(loghandle, LLOG_F_IS_PLAIN, NULL); + if (rc) + GOTO(out_close, rc); + + memset(buf, 0, LLOG_CHUNK_SIZE); + rc = llog_next_block(loghandle, &desc->lgd_saved_index, + desc->lgd_index, + &desc->lgd_cur_offset, buf, LLOG_CHUNK_SIZE); + if (rc) + GOTO(out_close, rc); + + + rc = lustre_pack_msg(2, size, NULL, &req->rq_replen, &req->rq_repmsg); + if (rc) + GOTO(out_close, rc = -ENOMEM); + + ptr = lustre_msg_buf(req->rq_repmsg, 0, sizeof (desc)); + memcpy(ptr, desc, sizeof(*desc)); + + ptr = lustre_msg_buf(req->rq_repmsg, 1, LLOG_CHUNK_SIZE); + memcpy(ptr, buf, LLOG_CHUNK_SIZE); + +out_close: + rc2 = llog_close(loghandle); + class_export_put(obd->obd_log_exp); + obd->obd_log_exp = NULL; + if (!rc) + rc = rc2; + +out_pop: + pop_ctxt(&saved, &obd->obd_ctxt, NULL); + OBD_FREE(buf, LLOG_CHUNK_SIZE); +out: + RETURN(rc); +} + +int llogd_close(struct ptlrpc_request *req) +{ + int rc; + + rc = 0; + + RETURN(rc); +} + + +int llogd_client_init(struct obd_export *exp, char * logname, + struct llog_desc **desc, __u32 **bitmap) +{ + struct obd_import *imp = class_exp2cliimp(exp); + struct ptlrpc_request *req = NULL; + void * ptr; + int size; + int repsize[] = {sizeof (**desc), + LLOG_BITMAP_BYTES}; + int rc; + ENTRY; + + LASSERT(*desc == NULL); + LASSERT(*bitmap == NULL); + + size = strlen(logname) + 1; + req = ptlrpc_prep_req(imp, LLOG_INIT, 1, &size, &logname); + if (!req) + GOTO(out, rc = -ENOMEM); + + req->rq_replen = lustre_msg_size(2, repsize); + rc = ptlrpc_queue_wait(req); + if (rc) + GOTO(out, rc); + + OBD_ALLOC(*desc, sizeof (**desc)); + if (*desc == NULL) + GOTO(out, rc = -ENOMEM); + + OBD_ALLOC(*bitmap, LLOG_BITMAP_BYTES); + if (*bitmap == NULL) + GOTO(err_free, rc = -ENOMEM); + + + ptr = lustre_swab_repbuf(req, 0, sizeof(**desc), + lustre_swab_llog_desc); + if (ptr == NULL) { + CERROR ("Can't unpack llog_desc\n"); + GOTO(err_free, rc =-EFAULT); + } + memcpy(*desc, ptr, sizeof(**desc)); + + ptr = lustre_msg_buf(req->rq_repmsg, 1, LLOG_BITMAP_BYTES); + if (ptr == NULL) { + CERROR ("Can't unpack bitmap\n"); + GOTO(err_free, rc =-EFAULT); + } + memcpy(*bitmap, ptr, LLOG_BITMAP_BYTES); + +out: + if (req) + ptlrpc_req_finished(req); + RETURN(rc); + +err_free: + if (*bitmap) + OBD_FREE(*bitmap, LLOG_BITMAP_BYTES); + if (*desc) + OBD_FREE(*desc, sizeof (**desc)); + goto out; +} + +int llogd_client_next_block(struct obd_export *exp, struct llog_desc *desc, + char * buf, int buf_size) +{ + struct obd_import *imp = class_exp2cliimp(exp); + struct ptlrpc_request *req = NULL; + void * ptr; + int size = sizeof(*desc); + int repsize[] = {sizeof (*desc), + LLOG_CHUNK_SIZE}; + int rc; + ENTRY; + + LASSERT (buf_size == LLOG_CHUNK_SIZE); + + req = ptlrpc_prep_req(imp, LLOG_NEXT_BLOCK, 1, &size, (char **) &desc); + if (!req) + GOTO(out, rc = -ENOMEM); + + req->rq_replen = lustre_msg_size(2, repsize); + rc = ptlrpc_queue_wait(req); + if (rc) + GOTO(out, rc); + + ptr = lustre_swab_repbuf(req, 0, sizeof(*desc), + lustre_swab_llog_desc); + if (ptr == NULL) { + CERROR ("Can't unpack llog_desc\n"); + GOTO(out, rc =-EFAULT); + } + memcpy(desc, ptr, sizeof(*desc)); + + ptr = lustre_msg_buf(req->rq_repmsg, 1, LLOG_CHUNK_SIZE); + if (ptr == NULL) { + CERROR ("Can't unpack bitmap\n"); + GOTO(out, rc =-EFAULT); + } + memcpy(buf, ptr, buf_size); + +out: + if (req) + ptlrpc_req_finished(req); + RETURN(rc); +} + + +int llogd_client_close(struct obd_export *exp, struct llog_desc **desc, + __u32 **bitmap) +{ + OBD_FREE(*desc, sizeof (**desc)); + OBD_FREE(*bitmap, LLOG_BITMAP_BYTES); + RETURN(0); +} diff --git a/lustre/ptlrpc/ptlrpc_module.c b/lustre/ptlrpc/ptlrpc_module.c index 3938a2b..8486b76 100644 --- a/lustre/ptlrpc/ptlrpc_module.c +++ b/lustre/ptlrpc/ptlrpc_module.c @@ -248,6 +248,14 @@ EXPORT_SYMBOL(ptlrpc_pinger_sending_on_import); EXPORT_SYMBOL(ptlrpc_lprocfs_register_obd); EXPORT_SYMBOL(ptlrpc_lprocfs_unregister_obd); +/* llogd.c */ +EXPORT_SYMBOL(llogd_init); +EXPORT_SYMBOL(llogd_next_block); +EXPORT_SYMBOL(llogd_close); +EXPORT_SYMBOL(llogd_client_init); +EXPORT_SYMBOL(llogd_client_next_block); +EXPORT_SYMBOL(llogd_client_close); + #ifdef __KERNEL__ MODULE_AUTHOR("Cluster File Systems, Inc. "); MODULE_DESCRIPTION("Lustre Request Processor"); diff --git a/lustre/utils/llmount.c b/lustre/utils/llmount.c new file mode 100644 index 0000000..1063886 --- /dev/null +++ b/lustre/utils/llmount.c @@ -0,0 +1,111 @@ +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- + * vim:expandtab:shiftwidth=8:tabstop=8: + * + * Copyright (C) 2002 Cluster File Systems, Inc. + * Author: Robert Read + * + * This file is part of Lustre, http://www.lustre.org. + * + * 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. + * + * 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 + * along with Lustre; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + + +#include +#include +#include +#include +#include +#include +#include + +int verbose = 0; +int nomtab = 0; + + +static void +update_mtab_entry(char *spec, char *node, char *type, char *opts, + int flags, int freq, int pass) +{ + FILE *fp; + struct mntent mnt; + + mnt.mnt_fsname = spec; + mnt.mnt_dir = node; + mnt.mnt_type = type; + mnt.mnt_opts = opts; + mnt.mnt_freq = freq; + mnt.mnt_passno = pass; + + if (!nomtab) { + fp = setmntent(MOUNTED, "a+"); + if (fp == NULL) { + fprintf(stderr, "setmntent(%s): %s:", MOUNTED, + strerror (errno)); + } else { + if ((addmntent (fp, &mnt)) == 1) { + fprintf(stderr, "addmntent: %s:", + strerror (errno)); + } + endmntent(fp); + } + } +} + +int +main(int argc, char * const argv[]) +{ + char * source = argv[1]; + char * target = argv[2]; + char * options = NULL; + int opt; + int i; + int rc; + + for (i = 0; i < argc; i++) { + printf("arg[%d] = %s\n", i, argv[i]); + } + while ((opt = getopt(argc, argv, "vno:")) != EOF) { + + switch (opt) { + case 'v': + verbose = 1; + break; + case 'n': + nomtab = 1; + break; + + case 'o': + options = optarg; + break; + default: + printf("default\n"); + } + } + + if (optind < argc) { + printf("optind %d\n", optind); +/* + while(optind < argc) +*/ + } + rc = mount(source, target, "lustre_lite", 0, options); + if (rc) { + perror("mount.lustre_lite:"); + } else { + update_mtab_entry(source, target, "lustre_lite", options, + 0, 0, 0); + } + return rc; +} diff --git a/lustre/utils/lustre_cfg.c b/lustre/utils/lustre_cfg.c new file mode 100644 index 0000000..ef64ed6 --- /dev/null +++ b/lustre/utils/lustre_cfg.c @@ -0,0 +1,477 @@ +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- + * vim:expandtab:shiftwidth=8:tabstop=8: + * + * Copyright (C) 2002 Cluster File Systems, Inc. + * Author: Peter J. Braam + * Author: Phil Schwan + * Author: Andreas Dilger + * Author: Robert Read + * + * This file is part of Lustre, http://www.lustre.org. + * + * 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. + * + * 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 + * along with Lustre; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + + +#include +#include +#include +#include + +#ifndef __KERNEL__ +#include +#endif +#include +#include +#include +#include +#include /* for struct lov_stripe_md */ +#include + +#include +#include +#include +#include +#include +#include + + +#include "obdctl.h" +#include +#include "parser.h" +#include + + +#define LCFG_INIT(lcfg, cmd) \ +do { \ + memset(&lcfg, 0, sizeof(lcfg)); \ + lcfg.lcfg_version = LUSTRE_CFG_VERSION; \ + lcfg.lcfg_command = (cmd); \ + if (lcfg_devname) { \ + lcfg.lcfg_dev_namelen = strlen(lcfg_devname) + 1; \ + lcfg.lcfg_dev_name = lcfg_devname; \ + } \ + \ +} while (0) + +static char * lcfg_devname; + +void lcfg_set_devname(char *name) +{ + if (lcfg_devname) + free(lcfg_devname); + lcfg_devname = strdup(name); +} + + +int jt_lcfg_device(int argc, char **argv) +{ + char *name; + + if (argc == 1) { + printf("current device is %s\n", lcfg_devname? : "not set"); + return 0; + } else if (argc != 2) { + return CMD_HELP; + } + + name = argv[1]; + + /* quietly strip the unnecessary '$' */ + if (*name == '$') + name++; + + lcfg_set_devname(name); + + return 0; +} + +/* NOOP */ +int jt_lcfg_newdev(int argc, char **argv) +{ + return 0; +} + +int jt_lcfg_attach(int argc, char **argv) +{ + struct lustre_cfg lcfg; + int rc; + + LCFG_INIT(lcfg, LCFG_ATTACH); + + if (argc != 2 && argc != 3 && argc != 4) + return CMD_HELP; + + lcfg.lcfg_inllen1 = strlen(argv[1]) + 1; + lcfg.lcfg_inlbuf1 = argv[1]; + if (argc >= 3) { + lcfg.lcfg_dev_namelen = strlen(argv[2]) + 1; + lcfg.lcfg_dev_name = argv[2]; + } else { + fprintf(stderr, "error: %s: LCFG_ATTACH requires a name\n", + jt_cmdname(argv[0])); + return -EINVAL; + } + + if (argc == 4) { + lcfg.lcfg_inllen2 = strlen(argv[3]) + 1; + lcfg.lcfg_inlbuf2 = argv[3]; + } + + rc = lcfg_ioctl(argv[0], OBD_DEV_ID, &lcfg); + if (rc < 0) { + fprintf(stderr, "error: %s: LCFG_ATTACH %s\n", + jt_cmdname(argv[0]), strerror(rc = errno)); + } else if (argc == 3) { + char name[1024]; + + lcfg_set_devname(argv[2]); + if (strlen(argv[2]) > 128) { + printf("Name too long to set environment\n"); + return -EINVAL; + } + snprintf(name, 512, "LUSTRE_DEV_%s", argv[2]); + rc = setenv(name, argv[1], 1); + if (rc) { + printf("error setting env variable %s\n", name); + } + } else { + lcfg_set_devname(argv[2]); + } + + return rc; +} + +int jt_lcfg_setup(int argc, char **argv) +{ + struct lustre_cfg lcfg; + int rc; + + LCFG_INIT(lcfg, LCFG_SETUP); + + if (argc > 5) + return CMD_HELP; + + if (argc > 1) { + lcfg.lcfg_inllen1 = strlen(argv[1]) + 1; + lcfg.lcfg_inlbuf1 = argv[1]; + } + if (argc > 2) { + lcfg.lcfg_inllen2 = strlen(argv[2]) + 1; + lcfg.lcfg_inlbuf2 = argv[2]; + } + if (argc > 3) { + lcfg.lcfg_inllen3 = strlen(argv[3]) + 1; + lcfg.lcfg_inlbuf3 = argv[3]; + } + if (argc > 4) { + lcfg.lcfg_inllen4 = strlen(argv[4]) + 1; + lcfg.lcfg_inlbuf4 = argv[4]; + } + + rc = lcfg_ioctl(argv[0], OBD_DEV_ID, &lcfg); + if (rc < 0) + fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]), + strerror(rc = errno)); + + return rc; +} + +int jt_obd_detach(int argc, char **argv) +{ + struct lustre_cfg lcfg; + int rc; + + LCFG_INIT(lcfg, LCFG_DETACH); + + if (argc != 1) + return CMD_HELP; + + rc = lcfg_ioctl(argv[0], OBD_DEV_ID, &lcfg); + if (rc < 0) + fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]), + strerror(rc = errno)); + + return rc; +} + +int jt_obd_cleanup(int argc, char **argv) +{ + struct lustre_cfg lcfg; + char force = 'F'; + char failover = 'A'; + char flags[3]; + int flag_cnt = 0, n; + int rc; + + LCFG_INIT(lcfg, LCFG_CLEANUP); + + if (argc < 1 || argc > 3) + return CMD_HELP; + + for (n = 1; n < argc; n++) + if (strcmp(argv[n], "force") == 0) { + flags[flag_cnt++] = force; + } else if (strcmp(argv[n], "failover") == 0) { + flags[flag_cnt++] = failover; + } else { + fprintf(stderr, "unknown option: %s", argv[n]); + return CMD_HELP; + } + + lcfg.lcfg_inllen1 = flag_cnt; + if (flag_cnt) + lcfg.lcfg_inlbuf1 = flags; + + rc = lcfg_ioctl(argv[0], OBD_DEV_ID, &lcfg); + if (rc < 0) + fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]), + strerror(rc = errno)); + + return rc; +} + +static +int do_add_uuid(char * func, char *uuid, ptl_nid_t nid, int nal) +{ + char tmp[64]; + int rc; + struct lustre_cfg lcfg; + + LCFG_INIT(lcfg, LCFG_ADD_UUID); + lcfg.lcfg_nid = nid; + lcfg.lcfg_inllen1 = strlen(uuid) + 1; + lcfg.lcfg_inlbuf1 = uuid; + lcfg.lcfg_nal = nal; + + rc = lcfg_ioctl(func, OBD_DEV_ID, &lcfg); + if (rc) { + fprintf(stderr, "IOC_PORTAL_ADD_UUID failed: %s\n", + strerror(errno)); + return -1; + } + + printf ("Added uuid %s: %s\n", uuid, ptl_nid2str (tmp, nid)); + return 0; +} + +int jt_lcfg_add_uuid(int argc, char **argv) +{ + ptl_nid_t nid = 0; + int nal; + + if (argc != 4) { + return CMD_HELP; + } + + if (ptl_parse_nid (&nid, argv[2]) != 0) { + fprintf (stderr, "Can't parse NID %s\n", argv[2]); + return (-1); + } + + nal = ptl_name2nal(argv[3]); + + if (nal <= 0) { + fprintf (stderr, "Can't parse NAL %s\n", argv[3]); + return -1; + } + + return do_add_uuid(argv[0], argv[1], nid, nal); +} + +int jt_lcfg_del_uuid(int argc, char **argv) +{ + int rc; + struct lustre_cfg lcfg; + + if (argc != 2) { + fprintf(stderr, "usage: %s \n", argv[0]); + return 0; + } + + LCFG_INIT(lcfg, LCFG_DEL_UUID); + + if (strcmp (argv[1], "_all_")) + { + lcfg.lcfg_inllen1 = strlen(argv[1]) + 1; + lcfg.lcfg_inlbuf1 = argv[1]; + } + + rc = lcfg_ioctl(argv[0], OBD_DEV_ID, &lcfg); + if (rc) { + fprintf(stderr, "IOC_PORTAL_DEL_UUID failed: %s\n", + strerror(errno)); + return -1; + } + return 0; +} + +int jt_lcfg_lov_setconfig(int argc, char **argv) +{ + struct lustre_cfg lcfg; + struct lov_desc desc; + struct obd_uuid *uuidarray, *ptr; + int rc, i; + char *end; + + LCFG_INIT(lcfg, LCFG_LOV_SET_CONFIG); + + if (argc <= 6) + return CMD_HELP; + + if (strlen(argv[1]) > sizeof(desc.ld_uuid) - 1) { + fprintf(stderr, + "error: %s: LOV uuid '%s' longer than "LPSZ" chars\n", + jt_cmdname(argv[0]), argv[1], sizeof(desc.ld_uuid) - 1); + return -EINVAL; + } + + memset(&desc, 0, sizeof(desc)); + obd_str2uuid(&desc.ld_uuid, argv[1]); + desc.ld_tgt_count = argc - 6; + desc.ld_default_stripe_count = strtoul(argv[2], &end, 0); + if (*end) { + fprintf(stderr, "error: %s: bad default stripe count '%s'\n", + jt_cmdname(argv[0]), argv[2]); + return CMD_HELP; + } + if (desc.ld_default_stripe_count > desc.ld_tgt_count) { + fprintf(stderr, + "error: %s: default stripe count %u > OST count %u\n", + jt_cmdname(argv[0]), desc.ld_default_stripe_count, + desc.ld_tgt_count); + return -EINVAL; + } + + desc.ld_default_stripe_size = strtoull(argv[3], &end, 0); + if (*end) { + fprintf(stderr, "error: %s: bad default stripe size '%s'\n", + jt_cmdname(argv[0]), argv[3]); + return CMD_HELP; + } + if (desc.ld_default_stripe_size < 4096) { + fprintf(stderr, + "error: %s: default stripe size "LPU64" too small\n", + jt_cmdname(argv[0]), desc.ld_default_stripe_size); + return -EINVAL; + } else if ((long)desc.ld_default_stripe_size < + desc.ld_default_stripe_size) { + fprintf(stderr, + "error: %s: default stripe size "LPU64" too large\n", + jt_cmdname(argv[0]), desc.ld_default_stripe_size); + return -EINVAL; + } + desc.ld_default_stripe_offset = strtoull(argv[4], &end, 0); + if (*end) { + fprintf(stderr, "error: %s: bad default stripe offset '%s'\n", + jt_cmdname(argv[0]), argv[4]); + return CMD_HELP; + } + desc.ld_pattern = strtoul(argv[5], &end, 0); + if (*end) { + fprintf(stderr, "error: %s: bad stripe pattern '%s'\n", + jt_cmdname(argv[0]), argv[5]); + return CMD_HELP; + } + + /* NOTE: it is possible to overwrite the default striping parameters, + * but EXTREME care must be taken when saving the OST UUID list. + * It must be EXACTLY the same, or have only additions at the + * end of the list, or only overwrite individual OST entries + * that are restored from backups of the previous OST. + */ + uuidarray = calloc(desc.ld_tgt_count, sizeof(*uuidarray)); + if (!uuidarray) { + fprintf(stderr, "error: %s: no memory for %d UUIDs\n", + jt_cmdname(argv[0]), desc.ld_tgt_count); + rc = -ENOMEM; + goto out; + } + for (i = 6, ptr = uuidarray; i < argc; i++, ptr++) { + if (strlen(argv[i]) >= sizeof(*ptr)) { + fprintf(stderr, "error: %s: arg %d (%s) too long\n", + jt_cmdname(argv[0]), i, argv[i]); + rc = -EINVAL; + goto out; + } + strcpy((char *)ptr, argv[i]); + } + + lcfg.lcfg_inllen1 = sizeof(desc); + lcfg.lcfg_inlbuf1 = (char *)&desc; + lcfg.lcfg_inllen2 = desc.ld_tgt_count * sizeof(*uuidarray); + lcfg.lcfg_inlbuf2 = (char *)uuidarray; + + rc = lcfg_ioctl(argv[0], OBD_DEV_ID, &lcfg); + if (rc) + fprintf(stderr, "error: %s: ioctl error: %s\n", + jt_cmdname(argv[0]), strerror(rc = errno)); +out: + free(uuidarray); + return rc; +} + +int jt_lcfg_mount_option(int argc, char **argv) +{ + int rc; + struct lustre_cfg lcfg; + + LCFG_INIT(lcfg, LCFG_MOUNTOPT); + + if (argc != 4) + return CMD_HELP; + + /* profile name */ + lcfg.lcfg_inllen1 = strlen(argv[1]) + 1; + lcfg.lcfg_inlbuf1 = argv[1]; + /* osc name */ + lcfg.lcfg_inllen2 = strlen(argv[2]) + 1; + lcfg.lcfg_inlbuf2 = argv[2]; + /* mdc name */ + lcfg.lcfg_inllen3 = strlen(argv[3]) + 1; + lcfg.lcfg_inlbuf3 = argv[3]; + + rc = lcfg_ioctl(argv[0], OBD_DEV_ID, &lcfg); + if (rc < 0) { + fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]), + strerror(rc = errno)); + } + + return rc; +} + +int jt_lcfg_del_mount_option(int argc, char **argv) +{ + int rc; + struct lustre_cfg lcfg; + + LCFG_INIT(lcfg, LCFG_DEL_MOUNTOPT); + + if (argc != 2) + return CMD_HELP; + + /* profile name */ + lcfg.lcfg_inllen1 = strlen(argv[1]) + 1; + lcfg.lcfg_inlbuf1 = argv[1]; + + rc = lcfg_ioctl(argv[0], OBD_DEV_ID, &lcfg); + if (rc < 0) { + fprintf(stderr, "error: %s: %s\n", jt_cmdname(argv[0]), + strerror(rc = errno)); + } + + return rc; +} + -- 1.8.3.1