--- /dev/null
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ * Copyright (C) 2001 Cluster File Systems, Inc. <braam@clusterfs.com>
+ *
+ * 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 <linux/obd_support.h>
+
+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
}
/* 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);
}
/* 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) {
}
+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
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 */
if (rc)
GOTO(cleanup, rc);
+ rc = llog_test_6(obd, name);
+ if (rc)
+ GOTO(cleanup, rc);
+
GOTO(cleanup, rc);
cleanup:
switch (cleanup_phase) {
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);
--- /dev/null
+/* -*- 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 <linux/kmod.h> /* for request_module() */
+#include <linux/module.h>
+#include <linux/obd_class.h>
+#include <linux/random.h>
+#include <linux/slab.h>
+#include <linux/pagemap.h>
+#else
+#include <liblustre.h>
+#include <linux/obd_class.h>
+#include <linux/obd.h>
+#endif
+#include <linux/lprocfs_status.h>
+#include <portals/list.h>
+
+
+/* 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 ? "<all uuids>" :
+ 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);
+}
+
--- /dev/null
+/* -*- 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 <adilger@clusterfs.com>
+ *
+ * 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 <linux/fs.h>
+#include <linux/obd_class.h>
+#include <linux/lustre_log.h>
+#include <linux/lustre_net.h>
+#include <portals/list.h>
+
+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);
+}
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. <info@clusterfs.com>");
MODULE_DESCRIPTION("Lustre Request Processor");
--- /dev/null
+/* -*- 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 <rread@clusterfs.com>
+ *
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/mount.h>
+#include <mntent.h>
+
+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;
+}
--- /dev/null
+/* -*- 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 <braam@clusterfs.com>
+ * Author: Phil Schwan <phil@clusterfs.com>
+ * Author: Andreas Dilger <adilger@clusterfs.com>
+ * Author: Robert Read <rread@clusterfs.com>
+ *
+ * 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 <stdlib.h>
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#ifndef __KERNEL__
+#include <liblustre.h>
+#endif
+#include <linux/lustre_lib.h>
+#include <linux/lustre_cfg.h>
+#include <linux/lustre_idl.h>
+#include <linux/lustre_dlm.h>
+#include <linux/obd.h> /* for struct lov_stripe_md */
+#include <linux/lustre_build_version.h>
+
+#include <unistd.h>
+#include <sys/un.h>
+#include <time.h>
+#include <sys/time.h>
+#include <errno.h>
+#include <string.h>
+
+
+#include "obdctl.h"
+#include <portals/ptlctl.h>
+#include "parser.h"
+#include <stdio.h>
+
+
+#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 <uuid>\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;
+}
+