AUTOMAKE_OPTIONS = foreign
# NOTE: keep extN before mds
-SUBDIRS = utils obdclass ldlm ptlrpc llite lib obdecho mdc osc extN mds ost
-SUBDIRS+= tests obdfilter obdfs demos doc scripts
+SUBDIRS = lov utils obdclass ldlm ptlrpc llite lib obdecho mdc osc extN
+SUBDIRS+= mds ost tests obdfilter obdfs demos doc scripts
EXTRA_DIST = BUGS FDL Rules include patches
# We get the version from the spec file.
#
# Check for required packages
-*
AC_PATH_PROG([XML2_CONFIG], [xml2-config], [],)
if test -z "$XML2_CONFIG"; then
demodir='$(docdir)/demo'
AC_SUBST(demodir)
-AC_OUTPUT(Makefile lib/Makefile ldlm/Makefile obdecho/Makefile ptlrpc/Makefile \
+AC_OUTPUT(Makefile lov/Makefile lib/Makefile ldlm/Makefile \
+ obdecho/Makefile ptlrpc/Makefile \
osc/Makefile mdc/Makefile mds/Makefile ost/Makefile utils/Makefile \
tests/Makefile obdfilter/Makefile obdclass/Makefile \
llite/Makefile obdfs/Makefile demos/Makefile \
* - ioctl's
*/
+/*
+ * GENERAL STUFF
+ */
+typedef __u8 uuid_t[37];
+
+
+
#define PTL_RPC_MSG_REQUEST 4711
#define PTL_RPC_MSG_ERR 4712
#define MDS_DISCONNECT 8
#define MDS_GETSTATUS 9
#define MDS_STATFS 10
+#define MDS_LOVINFO 11
#define REINT_SETATTR 1
#define REINT_CREATE 2
__u32 f_type;
};
+
+#define MDS_STATUS_CONN 1
+#define MDS_STATUS_LOV 2
+
+struct mds_status_req {
+ __u32 flags;
+ __u32 repbuf;
+};
+
+struct mds_conn_status {
+ struct ll_fid rootfid;
+ __u64 xid;
+ __u64 last_committed;
+ __u64 last_rcvd;
+ /* XXX preallocated quota & obj fields here */
+};
+
struct mds_body {
struct ll_fid fid1;
struct ll_fid fid2;
};
+/*
+ * LOV data structures
+ */
+
+#define LOV_RAID0 0
+struct lov_desc {
+ __u32 ld_tgt_count; /* how many OBD's */
+ __u32 ld_default_stripecount;
+ __u32 ld_default_stripesize; /* in bytes */
+ __u32 ld_pattern; /* RAID 0,1 etc */
+ uuid_t ld_uuid;
+};
+
/*
* LDLM requests:
*/
return len;
}
+
static inline int obd_ioctl_is_invalid(struct obd_ioctl_data *data)
{
if (data->ioc_len > (1<<30)) {
printk("OBD ioctl: packlen exceeds ioc_len\n");
return 1;
}
+#if 0
if (data->ioc_inllen1 &&
data->ioc_bulk[data->ioc_inllen1 - 1] != '\0') {
printk("OBD ioctl: inlbuf1 not 0 terminated\n");
printk("OBD ioctl: inlbuf3 not 0 terminated\n");
return 1;
}
+#endif
return 0;
}
/* buffer MUST be at least the size of obd_ioctl_hdr */
-static inline int obd_ioctl_getdata(char *buf, int *len, void *arg)
+static inline int obd_ioctl_getdata(char **buf, int *len, void *arg)
{
- struct obd_ioctl_hdr *hdr;
+ struct obd_ioctl_hdr hdr;
struct obd_ioctl_data *data;
int err;
ENTRY;
- hdr = (struct obd_ioctl_hdr *)buf;
- data = (struct obd_ioctl_data *)buf;
- err = copy_from_user(buf, (void *)arg, sizeof(*hdr));
+ err = copy_from_user(&hdr, (void *)arg, sizeof(hdr));
if ( err ) {
EXIT;
return err;
}
- if (hdr->ioc_version != OBD_IOCTL_VERSION) {
+ if (hdr.ioc_version != OBD_IOCTL_VERSION) {
printk("OBD: version mismatch kernel vs application\n");
return -EINVAL;
}
- if (hdr->ioc_len > *len) {
+ if (hdr.ioc_len > *len) {
printk("OBD: user buffer exceeds kernel buffer\n");
return -EINVAL;
}
-
- if (hdr->ioc_len < sizeof(struct obd_ioctl_data)) {
+ if (hdr.ioc_len < sizeof(struct obd_ioctl_data)) {
printk("OBD: user buffer too small for ioctl\n");
return -EINVAL;
}
- err = copy_from_user(buf, (void *)arg, hdr->ioc_len);
+ OBD_ALLOC(*buf, hdr.ioc_len);
+ if (!*buf) {
+ CERROR("Cannot allocate control buffer of len %d\n",
+ hdr.ioc_len);
+ RETURN(-EINVAL);
+ }
+ *len = hdr.ioc_len;
+ data = (struct obd_ioctl_data *)*buf;
+
+ err = copy_from_user(*buf, (void *)arg, hdr.ioc_len);
if ( err ) {
EXIT;
return err;
#define OBD_IOC_UUID2DEV _IOWR('f', 130, long)
#define OBD_IOC_RECOVD_NEWCONN _IOWR('f', 131, long)
+#define OBD_IOC_LOV_CONFIG _IOWR('f', 132, long)
-#define OBD_IOC_DEC_FS_USE_COUNT _IO ('f', 132 )
+#define OBD_IOC_DEC_FS_USE_COUNT _IO ('f', 133 )
#endif
};
-typedef __u8 uuid_t[37];
+struct lov_tgt_desc {
+ uuid_t uuid;
+ struct lustre_handle conn;
+};
-#define MAX_MULTI 16
struct lov_obd {
- __u32 lov_default_count;
- __u32 lov_default_pattern;
- __u32 lov_default_size;
- uuid_t lov_service_uuids[MAX_MULTI];
-
-#if 0
- int lov_count;
- struct lustre_handle *lov_targets;
-#endif
+ struct obd_device *mdcobd;
+ struct lov_desc desc;
+ int bufsize;
+ struct lov_tgt_desc *tgts;
};
/* corresponds to one of the obd's */
int obd_minor;
int obd_flags;
struct proc_dir_entry *obd_proc_entry;
- int obd_multi_count;
- struct lustre_handle obd_multi_conn[MAX_MULTI];
- unsigned int obd_gen_last_id;
- unsigned long obd_gen_prealloc_quota;
- // struct obd_device *obd_target; /* for anything that simply layers */
struct list_head obd_exports;
struct list_head obd_imports;
struct ldlm_namespace *obd_namespace;
struct list_head export_chain;
struct obd_device *export_obd;
struct ptlrpc_connection *export_connection;
- unsigned int export_id;
void *export_data; /* device specific data */
+ int export_desclen;
+ char *export_desc;
};
struct obd_import {
int class_unregister_type(char *nm);
int class_name2dev(char *name);
int class_uuid2dev(char *name);
+struct obd_device *class_uuid2obd(char *name);
int class_connect (struct lustre_handle *conn, struct obd_device *obd);
int class_disconnect(struct lustre_handle *conn);
struct obd_export *class_conn2export(struct lustre_handle *);
#define OBD_LOV_DEVICENAME "lov"
+void lov_unpackdesc(struct lov_desc *ld);
+void lov_packdesc(struct lov_desc *ld);
+
struct lov_object_id { /* per-child structure */
__u64 l_object_id;
__u32 l_device_id;
ldlm_SOURCES = l_lock.c ldlm_lock.c ldlm_resource.c ldlm_test.c ldlm_lockd.c \
ldlm_extent.c ldlm_request.c
-
include $(top_srcdir)/Rules
--- /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. <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.
+ *
+ * (Un)packing of OST/MDS requests
+ *
+ */
+
+#define DEBUG_SUBSYSTEM S_LLITE
+
+#include <linux/lustre_net.h>
+#include <linux/obd_support.h>
+
+void lov_packdesc(struct lov_desc *ld)
+{
+ ld->ld_tgt_count = HTON__u32(ld->ld_tgt_count);
+ ld->ld_default_stripecount = HTON__u32(ld->ld_default_stripecount);
+ ld->ld_default_stripesize = HTON__u32(ld->ld_default_stripesize);
+ ld->ld_pattern = HTON__u32(ld->ld_pattern);
+}
+
+void lov_unpackdesc(struct lov_desc *ld)
+{
+ ld->ld_tgt_count = NTOH__u32(ld->ld_tgt_count);
+ ld->ld_default_stripecount = HTON__u32(ld->ld_default_stripecount);
+ ld->ld_default_stripesize = HTON__u32(ld->ld_default_stripesize);
+ ld->ld_pattern = HTON__u32(ld->ld_pattern);
+}
GOTO(out_free, sb = NULL);
}
- devno = simple_strtoul(ost, NULL, 0);
- if (devno >= MAX_OBD_DEVICES) {
- CERROR("devno of %s too high\n", ost);
- GOTO(out_free, sb = NULL);
- }
-
- err = obd_connect(&sbi->ll_osc_conn, &obd_dev[devno]);
- if (err) {
- CERROR("cannot connect to %s: rc = %d\n", ost, err);
- GOTO(out_free, sb = NULL);
- }
-
devno = simple_strtoul(mds, NULL, 0);
if (devno >= MAX_OBD_DEVICES) {
CERROR("devno of %s too high\n", mds);
GOTO(out_free, sb = NULL);
}
- err = obd_connect(&sbi->ll_mdc_conn, &obd_dev[devno]);
- if (err) {
- CERROR("cannot connect to %s: rc = %d\n", mds, err);
- GOTO(out_free, sb = NULL);
- }
-
+ /* First the MDS since an LOV requires an the MDC connection
+ to find its descriptor */
#if 0
err = connmgr_connect(ptlrpc_connmgr, sbi->ll_mds_conn);
if (err) {
}
#endif
+ err = obd_connect(&sbi->ll_mdc_conn, &obd_dev[devno]);
+ if (err) {
+ CERROR("cannot connect to %s: rc = %d\n", mds, err);
+ GOTO(out_free, sb = NULL);
+ }
sbi2mdc(sbi)->mdc_conn->c_level = LUSTRE_CONN_FULL;
+ /* now the OST, which could be an LOV */
+ devno = simple_strtoul(ost, NULL, 0);
+ if (devno >= MAX_OBD_DEVICES) {
+ CERROR("devno of %s too high\n", ost);
+ GOTO(out_free, sb = NULL);
+ }
+ err = obd_connect(&sbi->ll_osc_conn, &obd_dev[devno]);
+ if (err) {
+ CERROR("cannot connect to %s: rc = %d\n", ost, err);
+ GOTO(out_free, sb = NULL);
+ }
+
/* XXX: need to store the last_* values somewhere */
err = mdc_getstatus(&sbi->ll_mdc_conn,
&rootfid, &last_committed,
MODULE = lov
modulefs_DATA = lov.o
EXTRA_PROGRAMS = lov
+LINX= lov_pack.c
-lov_SOURCES = lov_obd.c
+lov_SOURCES = lov_obd.c $(LINX)
+
+lov_pack.c:
+ test -e lov_pack.c || ln -sf $(top_srcdir)/lib/lov_pack.c
include $(top_srcdir)/Rules
#define EXPORT_SYMTAB
#define DEBUG_SUBSYSTEM S_LOV
+#include <linux/slab.h>
#include <linux/module.h>
+#include <linux/obd_support.h>
+#include <linux/lustre_lib.h>
+#include <linux/lustre_net.h>
+#include <linux/lustre_idl.h>
#include <linux/obd_class.h>
#include <linux/obd_lov.h>
extern struct obd_device obd_dev[MAX_OBD_DEVICES];
/* obd methods */
-static int lov_connect(struct lustre_handle *conn)
+
+static int lov_getinfo(struct obd_device *obd,
+ struct lov_desc *desc,
+ uuid_t **uuids,
+ struct ptlrpc_request **request)
+{
+ struct ptlrpc_request *req;
+ struct mds_status_req *streq;
+ struct lov_obd *lov = &obd->u.lov;
+ struct mdc_obd *mdc = &lov->mdcobd->u.mdc;
+ int rc, size[2] = {sizeof(*streq)};
+ ENTRY;
+
+ req = ptlrpc_prep_req2(mdc->mdc_client, mdc->mdc_conn, &mdc->mdc_connh,
+ MDS_LOVINFO, 1, size, NULL);
+ if (!req)
+ GOTO(out, rc = -ENOMEM);
+
+ *request = req;
+ streq = lustre_msg_buf(req->rq_reqmsg, 0);
+ streq->flags = HTON__u32(MDS_STATUS_LOV);
+ streq->repbuf = HTON__u32(8000);
+
+ /* prepare for reply */
+ req->rq_level = LUSTRE_CONN_CON;
+ size[0] = sizeof(*desc);
+ size[1] = 8000;
+ req->rq_replen = lustre_msg_size(2, size);
+
+ rc = ptlrpc_queue_wait(req);
+ rc = ptlrpc_check_status(req, rc);
+
+ if (!rc) {
+ memcpy(desc, lustre_msg_buf(req->rq_repmsg, 0), sizeof(*desc));
+ *uuids = lustre_msg_buf(req->rq_repmsg, 1);
+ lov_unpackdesc(desc);
+ }
+ EXIT;
+ out:
+ return rc;
+}
+
+static int lov_connect(struct lustre_handle *conn, struct obd_device *obd)
{
int rc;
+ int i;
+ struct ptlrpc_request *req;
+ struct lov_obd *lov = &obd->u.lov;
+ uuid_t *uuidarray;
MOD_INC_USE_COUNT;
- rc = class_connect(conn);
-
- if (rc)
+ rc = class_connect(conn, obd);
+ if (rc) {
MOD_DEC_USE_COUNT;
+ RETURN(rc);
+ }
+
+ rc = lov_getinfo(obd, &lov->desc, &uuidarray, &req);
+ if (rc) {
+ CERROR("cannot get lov info %d\n", rc);
+ GOTO(out, rc);
+ }
+
+ if (lov->desc.ld_tgt_count > 1000) {
+ CERROR("configuration error: target count > 1000 (%d)\n",
+ lov->desc.ld_tgt_count);
+ GOTO(out, rc = -EINVAL);
+ }
+
+ if (strcmp(obd->obd_uuid, lov->desc.ld_uuid)) {
+ CERROR("lov uuid %s not on mds device (%s)\n",
+ obd->obd_uuid, lov->desc.ld_uuid);
+ GOTO(out, rc = -EINVAL);
+ }
+
+ if (req->rq_repmsg->bufcount < 2 || req->rq_repmsg->buflens[1] <
+ sizeof(uuid_t) * lov->desc.ld_tgt_count) {
+ CERROR("invalid uuid array returned\n");
+ GOTO(out, rc = -EINVAL);
+ }
+
+ lov->bufsize = sizeof(struct lov_tgt_desc) * lov->desc.ld_tgt_count;
+ OBD_ALLOC(lov->tgts, lov->bufsize);
+ if (!lov->tgts) {
+ CERROR("Out of memory\n");
+ GOTO(out, rc = -ENOMEM);
+ }
+
+ uuidarray = lustre_msg_buf(req->rq_repmsg, 1);
+ for (i = 0 ; i < lov->desc.ld_tgt_count; i++) {
+ memcpy(lov->tgts[i].uuid, uuidarray[i], sizeof(uuid_t));
+ }
+
+ for (i = 0 ; i < lov->desc.ld_tgt_count; i++) {
+ struct obd_device *tgt = class_uuid2obd(uuidarray[i]);
+ if (!tgt) {
+ CERROR("Target %s not configured\n", uuidarray[i]);
+ GOTO(out_mem, rc = -EINVAL);
+ }
+ rc = obd_connect(&lov->tgts[i].conn, tgt);
+ if (rc) {
+ CERROR("Target %s connect error %d\n",
+ uuidarray[i], rc);
+ GOTO(out_mem, rc);
+ }
+ }
+ out_mem:
+ if (rc) {
+ for (i = 0 ; i < lov->desc.ld_tgt_count; i++) {
+ rc = obd_disconnect(&lov->tgts[i].conn);
+ if (rc)
+ CERROR("Target %s disconnect error %d\n",
+ uuidarray[i], rc);
+ }
+ OBD_FREE(lov->tgts, lov->bufsize);
+ }
+ out:
+ if (rc) {
+ class_disconnect(conn);
+ }
+ if (req)
+ ptlrpc_free_req(req);
return rc;
+
}
static int lov_disconnect(struct lustre_handle *conn)
{
+ struct obd_device *obd = class_conn2obd(conn);
+ struct lov_obd *lov = &obd->u.lov;
int rc;
+ int i;
+
+ if (!lov->tgts)
+ goto out_local;
+
+ for (i = 0 ; i < lov->desc.ld_tgt_count; i++) {
+ rc = obd_disconnect(&lov->tgts[i].conn);
+ if (rc)
+ CERROR("Target %s disconnect error %d\n",
+ lov->tgts[i].uuid, rc);
+ }
+ OBD_FREE(lov->tgts, lov->bufsize);
+ lov->bufsize = 0;
+ lov->tgts = NULL;
+
+ out_local:
rc = class_disconnect(conn);
if (!rc)
MOD_DEC_USE_COUNT;
- /* XXX cleanup preallocated inodes */
return rc;
}
+static int lov_setup(struct obd_device *obd, obd_count len, void *buf)
+{
+ struct obd_ioctl_data* data = buf;
+ struct lov_obd *lov = &obd->u.lov;
+ int rc = 0;
+ ENTRY;
+
+ if (data->ioc_inllen1 < 1) {
+ CERROR("osc setup requires an MDC UUID\n");
+ RETURN(-EINVAL);
+ }
+
+ if (data->ioc_inllen1 > 37) {
+ CERROR("mdc UUID must be less than 38 characters\n");
+ RETURN(-EINVAL);
+ }
+
+ /* FIXME: we should make a connection instead perhaps to avoid
+ the mdc from walking away? The fs guarantees this. */
+ lov->mdcobd = class_uuid2obd(data->ioc_inlbuf1);
+ if (!lov->mdcobd) {
+ CERROR("LOV %s cannot locate MDC %s\n", obd->obd_uuid,
+ data->ioc_inlbuf1);
+ rc = -EINVAL;
+ }
+ RETURN(rc);
+}
+
+#if 0
static int lov_getattr(struct lustre_handle *conn, struct obdo *oa)
{
int rc;
#endif
struct obd_ops lov_obd_ops = {
- o_setup: class_multi_setup,
- o_cleanup: class_multi_cleanup,
- o_create: lov_create,
+ o_setup: lov_setup,
o_connect: lov_connect,
o_disconnect: lov_disconnect,
+#if 0
+ o_create: lov_create,
o_getattr: lov_getattr,
o_setattr: lov_setattr,
o_open: lov_open,
o_close: lov_close,
-#if 0
o_destroy: lov_destroy,
o_brw: lov_pgcache_brw,
o_punch: lov_punch,
modulefs_DATA = mds.o mds_extN.o # mds_ext2.o mds_ext3.o
EXTRA_PROGRAMS = mds mds_extN # mds_ext2 mds_ext3
-LINX=mds_updates.c simple.c ll_pack.c l_net.c
+LINX= mds_updates.c simple.c ll_pack.c l_net.c lov_pack.c
+
ll_pack.c:
test -e ll_pack.c || ln -sf $(top_srcdir)/lib/ll_pack.c
-
mds_updates.c:
test -e mds_updates.c || ln -sf $(top_srcdir)/lib/mds_updates.c
-
simple.c:
test -e simple.c || ln -sf $(top_srcdir)/lib/simple.c
-
l_net.c:
test -e l_net.c || ln -sf $(top_srcdir)/lib/l_net.c
+lov_pack.c:
+ test -e lov_pack.c || ln -sf $(top_srcdir)/lib/lov_pack.c
-mds_SOURCES = handler.c mds_reint.c mds_fs.c $(LINX)
+mds_SOURCES = mds_lov.c handler.c mds_reint.c mds_fs.c $(LINX)
include $(top_srcdir)/Rules
#include <linux/module.h>
#include <linux/lustre_mds.h>
#include <linux/lustre_dlm.h>
+extern int mds_get_lovtgts(struct obd_device *obd, uuid_t *uuidarray);
+extern int mds_get_lovdesc(struct obd_device *obd, struct lov_desc *desc);
extern int mds_update_last_rcvd(struct mds_obd *mds, void *handle,
struct ptlrpc_request *req);
static int mds_cleanup(struct obd_device * obddev);
body = lustre_msg_buf(req->rq_reqmsg, 0);
mds_unpack_body(body);
- /* Anything we need to do here with the client's trans no or so? */
+ /* Anything we need to do here with the client's trans no or so? */
body = lustre_msg_buf(req->rq_repmsg, 0);
memcpy(&body->fid1, &mds->mds_rootfid, sizeof(body->fid1));
RETURN(0);
}
+static int mds_lovinfo(struct ptlrpc_request *req)
+{
+ struct mds_status_req *streq;
+ struct lov_desc *desc;
+ int rc, size[2] = {sizeof(*desc)};
+ ENTRY;
+
+ streq = lustre_msg_buf(req->rq_reqmsg, 0);
+ streq->flags = NTOH__u32(streq->flags);
+ streq->repbuf = NTOH__u32(streq->repbuf);
+ size[1] = streq->repbuf;
+
+ rc = lustre_pack_msg(2, size, NULL, &req->rq_replen, &req->rq_repmsg);
+ if (rc) {
+ CERROR("mds: out of memory for message: size=%d\n", size[1]);
+ req->rq_status = -ENOMEM;
+ RETURN(0);
+ }
+
+ desc = lustre_msg_buf(req->rq_repmsg, 0);
+ rc = mds_get_lovdesc(req->rq_obd, desc);
+ if (rc != 0 ) {
+ CERROR("get_lovdesc error %d", rc);
+ req->rq_status = rc;
+ RETURN(0);
+ }
+
+ if (desc->ld_tgt_count * sizeof(uuid_t) > streq->repbuf) {
+ CERROR("too many targets, enlarge client buffers\n");
+ req->rq_status = -ENOSPC;
+ RETURN(0);
+ }
+
+ rc = mds_get_lovtgts(req->rq_obd, lustre_msg_buf(req->rq_repmsg, 1));
+ if (rc) {
+ CERROR("get_lovtgts error %d", rc);
+ req->rq_status = rc;
+ RETURN(0);
+ }
+ RETURN(0);
+}
+
int mds_lock_callback(struct lustre_handle *lockh, struct ldlm_lock_desc *desc,
void *data, int data_len, struct ptlrpc_request **reqp)
{
rc = mds_getstatus(req);
break;
+ case MDS_LOVINFO:
+ CDEBUG(D_INODE, "lovinfo\n");
+ rc = mds_lovinfo(req);
+ break;
+
case MDS_GETATTR:
CDEBUG(D_INODE, "getattr\n");
OBD_FAIL_RETURN(OBD_FAIL_MDS_GETATTR_NET, 0);
RETURN(0);
}
+extern int mds_iocontrol(long cmd, struct lustre_handle *conn,
+ int len, void *karg, void *uarg);
+
/* use obd ops to offer management infrastructure */
static struct obd_ops mds_obd_ops = {
o_connect: mds_connect,
o_disconnect: mds_disconnect,
o_setup: mds_setup,
o_cleanup: mds_cleanup,
+ o_iocontrol: mds_iocontrol
};
static int __init mds_init(void)
--- /dev/null
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+ * linux/mds/mds_lov.c
+ *
+ * Lustre Metadata Server (mds) handling of striped file data
+ *
+ * Copyright (C) 2001, 2002 Cluster File Systems, Inc.
+ *
+ * This code is issued under the GNU General Public License.
+ * See the file COPYING in this distribution
+ *
+ * by Peter Braam <braam@clusterfs.com> &
+ *
+ */
+
+#define EXPORT_SYMTAB
+#define DEBUG_SUBSYSTEM S_MDS
+
+#include <linux/module.h>
+#include <linux/lustre_mds.h>
+#include <linux/lustre_idl.h>
+#include <linux/obd_lov.h>
+
+int mds_configure_lov(struct obd_device *obd, struct lov_desc *desc,
+ uuid_t *uuidarray)
+{
+ struct mds_obd *mds = &obd->u.mds;
+ struct obd_run_ctxt saved;
+ struct file *f;
+ loff_t off = 0;
+ int count;
+ int rc;
+ int i;
+
+ count = desc->ld_tgt_count;
+ lov_packdesc(desc);
+
+ push_ctxt(&saved, &mds->mds_ctxt);
+ f = filp_open("LOVDESC", O_CREAT|O_RDWR, 0644);
+ if (!f || IS_ERR(f)) {
+ pop_ctxt(&saved);
+ CERROR("Cannot open/create LOVDESC file\n");
+ RETURN(-EIO);
+ }
+
+ rc = lustre_fwrite(f, (char *)desc, sizeof(*desc), &off);
+ filp_close(f, 0);
+ if (rc != sizeof(*desc)) {
+ pop_ctxt(&saved);
+ CERROR("Cannot open/create LOVDESC file\n");
+ RETURN(-EIO);
+ }
+
+ off = 0;
+ f = filp_open("LOVTGTS", O_CREAT|O_RDWR, 0644);
+ if (!f || IS_ERR(f)) {
+ pop_ctxt(&saved);
+ CERROR("Cannot open/create LOVDESC file\n");
+ RETURN(-EIO);
+ }
+
+ for (i=0 ; i < count ; i++) {
+ rc = lustre_fwrite(f, uuidarray[i],
+ sizeof(uuidarray[i]), &off);
+ if (rc != sizeof(uuidarray[i])) {
+ CERROR("cannot write LOV UUID %s (%d)\n",
+ uuidarray[i], i);
+ break;
+ }
+ rc = 0;
+ }
+ filp_close(f, 0);
+ pop_ctxt(&saved);
+
+ RETURN(rc);
+}
+
+int mds_get_lovdesc(struct obd_device *obd, struct lov_desc *desc)
+{
+ struct mds_obd *mds = &obd->u.mds;
+ struct obd_run_ctxt saved;
+ struct file *f;
+ loff_t off = 0;
+ int rc, rc2;
+
+ push_ctxt(&saved, &mds->mds_ctxt);
+ f = filp_open("LOVDESC", O_RDONLY, 0644);
+ if (!f || IS_ERR(f)) {
+ CERROR("Cannot open LOVDESC file\n");
+ pop_ctxt(&saved);
+ RETURN(-EIO);
+ }
+
+ rc = lustre_fread(f, (char *)desc, sizeof(*desc), &off);
+ rc2 = filp_close(f, 0);
+ if (rc2) {
+ CERROR("Error closing LOVDESC file %d\n", rc);
+ }
+ if (rc != sizeof(*desc)) {
+ CERROR("Cannot read LOVDESC file\n");
+ pop_ctxt(&saved);
+ RETURN(-EIO);
+ }
+ pop_ctxt(&saved);
+
+ RETURN(0);
+}
+
+int mds_get_lovtgts(struct obd_device *obd, uuid_t *uuidarray)
+{
+ struct mds_obd *mds = &obd->u.mds;
+ struct obd_run_ctxt saved;
+ struct lov_desc desc;
+ struct file *f;
+ loff_t off = 0;
+ int rc;
+ int rc2;
+ int count;
+
+ rc = mds_get_lovdesc(obd, &desc);
+ if (rc) {
+ CERROR("cannot get descriptor\n");
+ RETURN(-EIO);
+ }
+
+ push_ctxt(&saved, &mds->mds_ctxt);
+ f = filp_open("LOVTGTS", O_RDONLY, 0644);
+ if (!f || IS_ERR(f)) {
+ CERROR("Cannot open LOVTGTS file\n");
+ pop_ctxt(&saved);
+ RETURN(-EIO);
+ }
+
+ lov_unpackdesc(&desc);
+ count = desc.ld_tgt_count;
+
+ off = 0;
+ rc = lustre_fread(f, (char *)uuidarray, count * sizeof(uuid_t),
+ &off);
+ rc2 = filp_close(f, 0);
+ if (rc2) {
+ CERROR("Error closing LOVTGTS file %d\n", rc);
+ }
+ if (rc != count * sizeof(uuid_t)) {
+ CERROR("Error reading LOVTGTS file\n");
+ pop_ctxt(&saved);
+ RETURN(-EIO);
+ }
+ pop_ctxt(&saved);
+
+ RETURN(0);
+}
+
+int mds_iocontrol(long cmd, struct lustre_handle *conn,
+ int len, void *karg, void *uarg)
+{
+ struct obd_device *obd = class_conn2obd(conn);
+ struct obd_ioctl_data *data = karg;
+ struct lov_desc *desc;
+ int count;
+ int rc;
+
+
+ switch (cmd) {
+ case OBD_IOC_LOV_CONFIG:
+ desc = (struct lov_desc *)data->ioc_inlbuf1;
+ if (sizeof(*desc) > data->ioc_inllen1) {
+ CERROR("descriptor size wrong\n");
+ RETURN(-EINVAL);
+ }
+
+ count = desc->ld_tgt_count;
+ if (sizeof(uuid_t) * count != data->ioc_inllen2) {
+ CERROR("UUID array size wrong\n");
+ RETURN(-EINVAL);
+ }
+ rc = mds_configure_lov(obd, desc, (uuid_t *)data->ioc_inlbuf2);
+
+ RETURN(rc);
+ default:
+ RETURN(-EINVAL);
+ }
+
+ RETURN(0);
+}
#include <linux/obd_support.h>
#include <linux/obd_class.h>
+#include <linux/smp_lock.h>
+struct semaphore obd_conf_sem; /* serialize configuration commands */
struct obd_device obd_dev[MAX_OBD_DEVICES];
-extern struct obd_type *class_nm_to_type(char *nm);
struct list_head obd_types;
-
unsigned long obd_memory = 0;
unsigned long obd_fail_loc = 0;
+extern struct obd_type *class_nm_to_type(char *nm);
/* opening /dev/obd */
static int obd_class_open(struct inode * inode, struct file * file)
data->ioc_cookie = conn->cookie;
}
+
/* to control /dev/obd */
static int obd_class_ioctl (struct inode * inode, struct file * filp,
unsigned int cmd, unsigned long arg)
{
- /* NOTE this must be larger than any of the ioctl data structs */
- char buf[1024];
- int len = 1024;
+ char *buf;
+ int len;
struct obd_ioctl_data *data;
struct obd_device *obd = filp->private_data;
struct lustre_handle conn;
int err = 0;
ENTRY;
- memset(buf, 0, sizeof(buf));
+ down(&obd_conf_sem);
if (!obd && cmd != OBD_IOC_DEVICE && cmd != TCGETS &&
cmd != OBD_IOC_LIST &&
cmd != OBD_IOC_NAME2DEV && cmd != OBD_IOC_NEWDEV) {
CERROR("OBD ioctl: No device\n");
- RETURN(-EINVAL);
+ GOTO(out, err=-EINVAL);
}
- if (obd_ioctl_getdata(buf, &len, (void *)arg)) {
+ if (obd_ioctl_getdata(&buf, &len, (void *)arg)) {
CERROR("OBD ioctl: data error\n");
- RETURN(-EINVAL);
+ GOTO(out, err=-EINVAL);
}
data = (struct obd_ioctl_data *)buf;
switch (cmd) {
case TCGETS:
- RETURN(-EINVAL);
+ GOTO(out, err=-EINVAL);
case OBD_IOC_DEVICE: {
CDEBUG(D_IOCTL, "\n");
if (data->ioc_dev >= MAX_OBD_DEVICES || data->ioc_dev < 0) {
CERROR("OBD ioctl: DEVICE insufficient devices\n");
- RETURN(-EINVAL);
+ GOTO(out, err=-EINVAL);
}
CDEBUG(D_IOCTL, "device %d\n", data->ioc_dev);
filp->private_data = &obd_dev[data->ioc_dev];
- RETURN(0);
+ GOTO(out, err=0);
}
case OBD_IOC_LIST: {
int i;
- char *buf = data->ioc_bulk;
+ char *buf2 = data->ioc_bulk;
int remains = data->ioc_inllen1;
if (!data->ioc_inlbuf1) {
CERROR("No buffer passed!\n");
- RETURN(-EINVAL);
+ GOTO(out, err=-EINVAL);
}
struct obd_device *obd = &obd_dev[i];
if (!obd->obd_type)
continue;
- l = snprintf(buf, remains, "%2d %s %s %s\n",
+ l = snprintf(buf2, remains, "%2d %s %s %s\n",
i, obd->obd_type->typ_name,
obd->obd_name, obd->obd_uuid);
- buf +=l;
+ buf2 +=l;
remains -=l;
if (remains <= 0) {
CERROR("not enough space for device listing\n");
}
err = copy_to_user((int *)arg, data, len);
- RETURN(err);
+ GOTO(out, err);
}
*/
int dev;
- if (!data->ioc_inlbuf1) {
- CERROR("No name passed!\n");
- RETURN(-EINVAL);
+ if (!data->ioc_inllen1 || !data->ioc_inlbuf1 ) {
+ CERROR("No name passed,!\n");
+ GOTO(out, err=-EINVAL);
}
+ if (data->ioc_inlbuf1[data->ioc_inllen1-1] !=0) {
+ CERROR("Name not nul terminated!\n");
+ GOTO(out, err=-EINVAL);
+ }
+
CDEBUG(D_IOCTL, "device name %s\n", data->ioc_inlbuf1);
dev = class_name2dev(data->ioc_inlbuf1);
data->ioc_dev = dev;
if (dev == -1) {
CDEBUG(D_IOCTL, "No device for name %s!\n",
data->ioc_inlbuf1);
- RETURN(-EINVAL);
+ GOTO(out, err=-EINVAL);
}
CDEBUG(D_IOCTL, "device name %s, dev %d\n", data->ioc_inlbuf1,
dev);
err = copy_to_user((int *)arg, data, sizeof(*data));
- RETURN(err);
+ GOTO(out, err);
}
case OBD_IOC_UUID2DEV: {
*/
int dev;
- if (!data->ioc_inlbuf1) {
+ if (!data->ioc_inllen1 || !data->ioc_inlbuf1) {
CERROR("No UUID passed!\n");
- RETURN(-EINVAL);
+ GOTO(out, err=-EINVAL);
}
+ if (data->ioc_inlbuf1[data->ioc_inllen1-1] !=0) {
+ CERROR("Name not nul terminated!\n");
+ GOTO(out, err=-EINVAL);
+ }
+
CDEBUG(D_IOCTL, "device name %s\n", data->ioc_inlbuf1);
dev = class_uuid2dev(data->ioc_inlbuf1);
data->ioc_dev = dev;
if (dev == -1) {
CDEBUG(D_IOCTL, "No device for name %s!\n",
data->ioc_inlbuf1);
- RETURN(-EINVAL);
+ GOTO(out, err=-EINVAL);
}
CDEBUG(D_IOCTL, "device name %s, dev %d\n", data->ioc_inlbuf1,
dev);
err = copy_to_user((int *)arg, data, sizeof(*data));
- RETURN(err);
+ GOTO(out, err);
}
case OBD_IOC_NEWDEV: {
data->ioc_dev = dev;
if (dev == -1)
- RETURN(-EINVAL);
+ GOTO(out, err=-EINVAL);
err = copy_to_user((int *)arg, data, sizeof(*data));
- RETURN(err);
+ GOTO(out, err);
}
case OBD_IOC_ATTACH: {
if (obd->obd_flags & OBD_ATTACHED) {
CERROR("OBD: Device %d already typed as %s.\n",
obd->obd_minor, MKSTR(obd->obd_type->typ_name));
- RETURN(-EBUSY);
+ GOTO(out, err=-EBUSY);
+ }
+
+ if (!data->ioc_inllen1 || !data->ioc_inlbuf1) {
+ CERROR("No type passed!\n");
+ GOTO(out, err=-EINVAL);
+ }
+ if (data->ioc_inlbuf1[data->ioc_inllen1-1] !=0) {
+ CERROR("Type not nul terminated!\n");
+ GOTO(out, err=-EINVAL);
}
CDEBUG(D_IOCTL, "attach type %s name: %s uuid: %s\n",
MKSTR(data->ioc_inlbuf2), MKSTR(data->ioc_inlbuf3));
/* find the type */
+
type = class_nm_to_type(data->ioc_inlbuf1);
if (!type) {
CERROR("OBD: unknown type dev %d\n", obd->obd_minor);
- RETURN(-EINVAL);
+ GOTO(out, err=-EINVAL);
}
obd->obd_type = type;
- obd->obd_multi_count = 0;
INIT_LIST_HEAD(&obd->obd_exports);
/* do the attach */
type->typ_refcnt++;
CDEBUG(D_IOCTL, "OBD: dev %d attached type %s\n",
obd->obd_minor, data->ioc_inlbuf1);
- obd->obd_proc_entry =
- proc_lustre_register_obd_device(obd);
if (data->ioc_inlbuf2) {
int len = strlen(data->ioc_inlbuf2) + 1;
OBD_ALLOC(obd->obd_name, len + 1);
LBUG();
}
memcpy(obd->obd_name, data->ioc_inlbuf2, len + 1);
+ obd->obd_proc_entry =
+ proc_lustre_register_obd_device(obd);
+ } else {
+ CERROR("WARNING: unnamed obd device\n");
+ obd->obd_proc_entry = NULL;
}
+
if (data->ioc_inlbuf3) {
int len = strlen(data->ioc_inlbuf3);
if (len > 37) {
if (obd->obd_name)
OBD_FREE(obd->obd_name,
strlen(obd->obd_name) + 1);
- RETURN(-EINVAL);
+ GOTO(out, err=-EINVAL);
}
memcpy(obd->obd_uuid, data->ioc_inlbuf3,
sizeof(obd->obd_uuid));
MOD_INC_USE_COUNT;
}
- RETURN(err);
+ GOTO(out, err);
}
case OBD_IOC_DETACH: {
ENTRY;
if (obd->obd_flags & OBD_SET_UP) {
CERROR("OBD device %d still set up\n", obd->obd_minor);
- RETURN(-EBUSY);
+ GOTO(out, err=-EBUSY);
}
if (! (obd->obd_flags & OBD_ATTACHED) ) {
CERROR("OBD device %d not attached\n", obd->obd_minor);
- RETURN(-ENODEV);
+ GOTO(out, err=-ENODEV);
}
if ( !list_empty(&obd->obd_exports) ) {
CERROR("OBD device %d has exports\n",
obd->obd_minor);
- RETURN(-EBUSY);
+ GOTO(out, err=-EBUSY);
}
if (obd->obd_name) {
obd->obd_type->typ_refcnt--;
obd->obd_type = NULL;
MOD_DEC_USE_COUNT;
- RETURN(0);
+ GOTO(out, err=0);
}
case OBD_IOC_SETUP: {
/* have we attached a type to this device? */
if (!(obd->obd_flags & OBD_ATTACHED)) {
CERROR("Device %d not attached\n", obd->obd_minor);
- RETURN(-ENODEV);
+ GOTO(out, err=-ENODEV);
}
/* has this been done already? */
if ( obd->obd_flags & OBD_SET_UP ) {
CERROR("Device %d already setup (type %s)\n",
obd->obd_minor, obd->obd_type->typ_name);
- RETURN(-EBUSY);
+ GOTO(out, err=-EBUSY);
}
if ( OBT(obd) && OBP(obd, setup) )
obd->obd_flags |= OBD_SET_UP;
}
- RETURN(err);
+ GOTO(out, err);
}
case OBD_IOC_CLEANUP: {
/* have we attached a type to this device? */
if (!(obd->obd_flags & OBD_ATTACHED)) {
CERROR("Device %d not attached\n", obd->obd_minor);
- RETURN(-ENODEV);
+ GOTO(out, err=-ENODEV);
}
if ( OBT(obd) && OBP(obd, cleanup) )
obd->obd_flags &= ~OBD_SET_UP;
obd->obd_type->typ_refcnt--;
}
- RETURN(err);
+ GOTO(out, err);
}
case OBD_IOC_CONNECT: {
CDEBUG(D_IOCTL, "assigned export %Lx\n", conn.addr);
obd_conn2data(data, &conn);
if (err)
- RETURN(err);
+ GOTO(out, err);
err = copy_to_user((int *)arg, data, sizeof(*data));
- RETURN(err);
+ GOTO(out, err);
}
case OBD_IOC_DISCONNECT: {
obd_data2conn(&conn, data);
err = obd_disconnect(&conn);
- RETURN(err);
+ GOTO(out, err);
}
case OBD_IOC_DEC_USE_COUNT: {
MOD_DEC_USE_COUNT;
- RETURN(0);
+ GOTO(out, err=0);
}
case OBD_IOC_CREATE: {
err = obd_create(&conn, &data->ioc_obdo1);
if (err)
- RETURN(err);
+ GOTO(out, err);
err = copy_to_user((int *)arg, data, sizeof(*data));
- RETURN(err);
+ GOTO(out, err);
}
case OBD_IOC_GETATTR: {
obd_data2conn(&conn, data);
err = obd_getattr(&conn, &data->ioc_obdo1);
if (err)
- RETURN(err);
+ GOTO(out, err);
err = copy_to_user((int *)arg, data, sizeof(*data));
- RETURN(err);
+ GOTO(out, err);
}
case OBD_IOC_SETATTR: {
obd_data2conn(&conn, data);
err = obd_setattr(&conn, &data->ioc_obdo1);
if (err)
- RETURN(err);
+ GOTO(out, err);
err = copy_to_user((int *)arg, data, sizeof(*data));
- RETURN(err);
+ GOTO(out, err);
}
case OBD_IOC_DESTROY: {
err = obd_destroy(&conn, &data->ioc_obdo1);
if (err)
- RETURN(err);
+ GOTO(out, err);
err = copy_to_user((int *)arg, data, sizeof(*data));
- RETURN(err);
+ GOTO(out, err);
}
case OBD_IOC_BRW_WRITE:
OBD_FREE(counts, pages * sizeof(*counts));
OBD_FREE(offsets, pages * sizeof(*offsets));
OBD_FREE(flags, pages * sizeof(*flags));
- return err;
+ GOTO(out, err);
}
- default: {
+ default:
obd_data2conn(&conn, data);
- err = obd_iocontrol(cmd, &conn, sizeof(*data), data, NULL);
+ err = obd_iocontrol(cmd, &conn, len, data, NULL);
if (err)
- RETURN(err);
+ GOTO(out, err);
- err = copy_to_user((int *)arg, data, sizeof(*data));
- RETURN(err);
- }
+ err = copy_to_user((int *)arg, data, len);
+ GOTO(out, err);
}
+
+ out:
+ OBD_FREE(buf, len);
+ up(&obd_conf_sem);
+ RETURN(err);
} /* obd_class_ioctl */
EXPORT_SYMBOL(class_unregister_type);
EXPORT_SYMBOL(class_name2dev);
EXPORT_SYMBOL(class_uuid2dev);
+EXPORT_SYMBOL(class_uuid2obd);
EXPORT_SYMBOL(class_connect);
EXPORT_SYMBOL(class_conn2export);
EXPORT_SYMBOL(class_conn2obd);
EXPORT_SYMBOL(class_disconnect);
-EXPORT_SYMBOL(class_multi_setup);
-EXPORT_SYMBOL(class_multi_cleanup);
+//EXPORT_SYMBOL(class_multi_setup);
+//EXPORT_SYMBOL(class_multi_cleanup);
static int __init init_obdclass(void)
{
printk(KERN_INFO "OBD class driver v0.9, info@clusterfs.com\n");
+ sema_init(&obd_conf_sem, 1);
INIT_LIST_HEAD(&obd_types);
if ((err = misc_register(&obd_psdev))) {
return res;
}
+
+struct obd_device *class_uuid2obd(char *name)
+{
+ int i;
+
+ for (i=0; i < MAX_OBD_DEVICES; i++) {
+ struct obd_device *obd = &obd_dev[i];
+ if (obd->obd_name && strncmp(name, obd->obd_uuid, 37) == 0) {
+ return obd;
+ }
+ }
+
+ return NULL;
+}
+
void obd_cleanup_caches(void)
{
int rc;
memset(export, 0, sizeof(*export));
get_random_bytes(&export->export_cookie, sizeof(__u64));
- /* XXX this should probably spinlocked? */
- export->export_id = ++obd->obd_gen_last_id;
export->export_obd = obd;
export->export_import.addr = conn->addr;
export->export_import.cookie = conn->cookie;
list_add(&(export->export_chain), export->export_obd->obd_exports.prev);
-
- CDEBUG(D_INFO, "connect: new ID %u\n", export->export_id);
conn->addr = (__u64) (unsigned long)export;
conn->cookie = export->export_cookie;
return 0;
-} /* class_connect */
+}
int class_disconnect(struct lustre_handle *conn)
{
kmem_cache_free(export_cachep, export);
RETURN(0);
-} /* gen_obd_disconnect */
+}
+
+#if 0
/* FIXME: Data is a space- or comma-separated list of device IDs. This will
* have to change. */
}
return 0;
}
-
+#endif
* the obdtrace driver creates /proc/lustre/obd/<obdid>/stats entry.
*
* This file defines three functions
- * proc_lustre_register_obd_device()
- * proc_lustre_release_obd_device()
+ * proc_lustre_register_obd_device() - called at device attach time
+ * proc_lustre_release_obd_device() - called at detach
* proc_lustre_remove_obd_entry()
* that dynamically create/delete /proc/lustre/obd entries:
*
struct obd_device * obddev = (struct obd_device *) data;
int p;
- p = sprintf(&page[0], "device %d: ", obddev->obd_minor);
+ p = sprintf(&page[0], "device=%d\n", obddev->obd_minor);
+ p += sprintf(&page[0], "name=%s\n", MKSTR(obddev->obd_name));
+ p += sprintf(&page[0], "uuid=%s\n", obddev->obd_uuid);
+ p += sprintf(&page[p], "attached=1\n");
+ p += sprintf(&page[0], "type=%s\n", MKSTR(obddev->obd_type->typ_name));
- if (obddev->obd_flags & OBD_ATTACHED) {
- p += sprintf(&page[p], ", attached(%s)",
- obddev->obd_type->typ_name);
- }
-
if (obddev->obd_flags & OBD_SET_UP) {
- struct dentry *my_dentry;
- struct vfsmount *root_mnt;
- char *path;
- char *pathpage;
-
- if (!(pathpage = (char*) __get_free_page(GFP_KERNEL)))
- return -ENOMEM;
-
- my_dentry = NULL;
- root_mnt = mntget(current->fs->rootmnt);
- path = d_path(my_dentry,root_mnt,pathpage,PAGE_SIZE);
-
- p += sprintf(&page[p], ", setup(%s)", path);
-
- free_page((unsigned long) pathpage);
+ p += sprintf(&page[p], "setup=1\n");
}
/* print exports */
p += sprintf(&page[p], "\n");
/* Compute eof and return value */
-
if (offset + count >= p) {
*eof=1;
return (p - offset);
return 0;
proc_lustre_obd_dir_entry =
- proc_mkdir("obd", proc_lustre_dir_entry);
+ proc_mkdir("devices", proc_lustre_dir_entry);
if (IS_ERR(proc_lustre_obd_dir_entry))
return 0;
}
-
- sprintf(obdname, "%d", obd->obd_minor);
-
-
+ sprintf(obdname, "%s", obd->obd_name);
obd_dir = proc_mkdir(obdname, proc_lustre_obd_dir_entry);
+
if (obd_dir)
- obd_status = create_proc_entry("status", S_IRUSR | S_IFREG, obd_dir);
+ obd_status = create_proc_entry("status", S_IRUSR | S_IFREG,
+ obd_dir);
if (obd_status) {
obd_status->read_proc = read_lustre_status;
do_insmod $LUSTRE/ost/ost.o || exit -1
do_insmod $LUSTRE/osc/osc.o || exit -1
do_insmod $LUSTRE/mdc/mdc.o || exit -1
+ do_insmod $LUSTRE/lov/lov.o || exit -1
do_insmod $LUSTRE/llite/llite.o || exit -1
echo "$R/tmp/lustre-log" > /proc/sys/portals/debug_path
EOF
}
+setup_mds_lov() {
+
+ [ "$SETUP_MDS" = "y" ] || return 0
+
+ if [ -z "$LOVUUID" ]; then
+ echo "No LOV configured"
+ return
+ fi
+
+ $OBDCTL <<- EOF || return $?
+ name2dev MDSDEV
+ connect
+ lovconfig ${LOVUUID} 1 4096 0 OSCUUID
+ disconnect
+ quit
+ EOF
+}
+
+
setup_ost() {
[ "$SETUP_OST" = "y" ] || return 0
}
setup_server() {
- setup_mds $1 && setup_ost $1
+ setup_mds $1 && setup_mds_lov $1 && setup_ost $1
}
setup_osc() {
$OBDCTL <<- EOF || return $rc
newdev
- attach osc $THEOSC
+ attach osc $THEOSC ${THEOSC}-UUID
setup OBDUUID $OSTNODE
quit
EOF
$OBDCTL <<- EOF || return $?
newdev
- attach mdc $THEMDC
+ attach mdc $THEMDC ${THEMDC}-UUID
setup MDSUUID $MDSNODE
quit
EOF
done
}
+setup_lov () {
+ [ "$SETUP_MDC" != "y" ] && return 0
+
+ if [ -z "$LOVUUID" ]; then
+ echo "No LOV configured"
+ return
+ fi
+
+ $OBDCTL <<- EOF || return $?
+ newdev
+ attach lov LOVNAME ${LOVUUID}
+ setup MDCDEV-UUID
+ quit
+ EOF
+}
+
setup_mount() {
set -vx
}
setup_client() {
- setup_osc && setup_mdc && setup_mount
+ setup_osc && setup_mdc && setup_lov && setup_mount
}
DEBUG_ON="echo 0xffffffff > /proc/sys/portals/debug"
losetup -d ${LOOP}2
do_rmmod llite
+ do_rmmod lov
do_rmmod mdc
do_rmmod mds_extN
quit
EOF
+rmmod lov
rmmod obdecho
rmmod mds_extN
rmmod mds_ext3
MDSDEV=/tmp/mds
MDSSIZE=25000
SETUP_MDS=y
+# LOVUUID=LovUUID
return rc;
}
+static int jt_lov_config(int argc, char **argv)
+{
+ struct obd_ioctl_data data;
+ struct lov_desc desc;
+ uuid_t *uuidarray;
+ int size, i;
+ IOCINIT(data);
+
+ if (argc <= 5 ){
+ Parser_printhelp("lovconfig");
+ return -1;
+ }
+
+ if (strlen(argv[1]) > sizeof(uuid_t) - 1) {
+ fprintf(stderr, "lov_config: no %dB memory for uuid's\n",
+ size);
+ return -ENOMEM;
+ }
+
+ memset(&desc, 0, sizeof(desc));
+ strcpy(desc.ld_uuid, argv[1]);
+ desc.ld_default_stripecount = strtoul(argv[2], NULL, 0);
+ desc.ld_default_stripesize = strtoul(argv[3], NULL, 0);
+ desc.ld_pattern = strtoul(argv[4], NULL, 0);
+ desc.ld_tgt_count = argc - 5;
+
+
+ size = sizeof(uuid_t) * desc.ld_tgt_count;
+ uuidarray = malloc(size);
+ if (!uuidarray) {
+ fprintf(stderr, "lov_config: no %dB memory for uuid's\n",
+ size);
+ return -ENOMEM;
+ }
+ memset(uuidarray, 0, size);
+ for (i=5 ; i < argc ; i++) {
+ char *buf = (char *) (uuidarray + i -5 );
+ if (strlen(argv[i]) >= sizeof(uuid_t)) {
+ fprintf(stderr, "lov_config: arg %d (%s) too long\n",
+ i, argv[i]);
+ free(uuidarray);
+ return -EINVAL;
+ }
+ strcpy(buf, argv[i]);
+ }
+
+ data.ioc_inllen1 = sizeof(desc);
+ data.ioc_inlbuf1 = (char *)&desc;
+ data.ioc_inllen2 = size;
+ data.ioc_inlbuf2 = (char *)uuidarray;
+
+ if (obd_ioctl_pack(&data, &buf, max)) {
+ fprintf(stderr, "error: %s: invalid ioctl\n", cmdname(argv[0]));
+ return -EINVAL;
+ }
+
+ rc = ioctl(fd, OBD_IOC_LOV_CONFIG , buf);
+ if (rc < 0)
+ fprintf(stderr, "lov_config: error: %s: %s\n",
+ cmdname(argv[0]),strerror(rc = errno));
+ free(uuidarray);
+ return rc;
+}
+
+
static int jt_test_ldlm(int argc, char **argv)
{
struct obd_ioctl_data data;
"--threads <threads> <devno> <command [args ...]>"},
/* Device configuration commands */
+ {"lovconfig", jt_lov_config, 0, "configure lov data on MDS "
+ "(usage: lov-uuid stripecount, stripesize, pattern, UUID1, [UUID2, ...])"},
{"list", jt_list, 0, "list the devices (no args)"},
{"newdev", jt_newdev, 0, "set device to a new unused obd (no args)"},
{"device", jt_device, 0, "set current device (args device_no name)"},
return 0;
}
+
+void Parser_printhelp(char *cmd)
+{
+ char *argv[] = { "help", cmd };
+ Parser_help(2, argv);
+}
+
+
/*************************************************************************
* COMMANDS *
*************************************************************************/
int Parser_commands(void); /* Start the command parser */
void Parser_qhelp(int, char **); /* Quick help routine */
int Parser_help(int, char **); /* Detailed help routine */
+void Parser_printhelp(char *); /* Detailed help routine */
void Parser_exit(int, char **); /* Shuts down command parser */
int Parser_execarg(int argc, char **argv, command_t cmds[]);
int execute_line(char * line);