diff --git a/lustre/Makefile.am b/lustre/Makefile.am index d9a6945bd0635a3f4fa7729bd66d51e8374358a5..a43ae233db5bc214c90da80acfd202aa69429880 100644 --- a/lustre/Makefile.am +++ b/lustre/Makefile.am @@ -6,8 +6,8 @@ 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. diff --git a/lustre/configure.in b/lustre/configure.in index 2afd890e039d8e3d140a9a00679d2ad0218ff5cc..41c5502d1ac0fab4cea7a8464342f0170a35d353 100644 --- a/lustre/configure.in +++ b/lustre/configure.in @@ -14,7 +14,6 @@ AC_PROG_RANLIB # # Check for required packages -* AC_PATH_PROG([XML2_CONFIG], [xml2-config], [],) if test -z "$XML2_CONFIG"; then @@ -89,7 +88,8 @@ AC_SUBST(docdir) 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 \ diff --git a/lustre/include/linux/lustre_idl.h b/lustre/include/linux/lustre_idl.h index 50c8c5b7a2230e25a6355f4ce7615b43ac788f34..94c8f4f9932ee3f12a2bcbd70ba42f7ac5b815b1 100644 --- a/lustre/include/linux/lustre_idl.h +++ b/lustre/include/linux/lustre_idl.h @@ -43,6 +43,13 @@ * - ioctl's */ +/* + * GENERAL STUFF + */ +typedef __u8 uuid_t[37]; + + + #define PTL_RPC_MSG_REQUEST 4711 #define PTL_RPC_MSG_ERR 4712 @@ -217,6 +224,7 @@ struct ost_body { #define MDS_DISCONNECT 8 #define MDS_GETSTATUS 9 #define MDS_STATFS 10 +#define MDS_LOVINFO 11 #define REINT_SETATTR 1 #define REINT_CREATE 2 @@ -232,6 +240,23 @@ struct ll_fid { __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; @@ -301,6 +326,19 @@ struct mds_rec_rename { }; +/* + * 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: */ @@ -416,6 +454,7 @@ static inline int obd_ioctl_packlen(struct obd_ioctl_data *data) return len; } + static inline int obd_ioctl_is_invalid(struct obd_ioctl_data *data) { if (data->ioc_len > (1<<30)) { @@ -481,6 +520,7 @@ static inline int obd_ioctl_is_invalid(struct obd_ioctl_data *data) 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"); @@ -497,6 +537,7 @@ static inline int obd_ioctl_is_invalid(struct obd_ioctl_data *data) printk("OBD ioctl: inlbuf3 not 0 terminated\n"); return 1; } +#endif return 0; } @@ -535,39 +576,45 @@ static inline int obd_ioctl_pack(struct obd_ioctl_data *data, char **pbuf, /* 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; @@ -629,7 +676,8 @@ static inline int obd_ioctl_getdata(char *buf, int *len, void *arg) #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 diff --git a/lustre/include/linux/obd.h b/lustre/include/linux/obd.h index aab618d89fe0bd90049bca12b562947048dbb466..f45ef0651aaeee4ab8bd586613872e3e019aa0a5 100644 --- a/lustre/include/linux/obd.h +++ b/lustre/include/linux/obd.h @@ -152,19 +152,16 @@ struct ost_obd { }; -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 */ @@ -178,11 +175,6 @@ struct obd_device { 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; diff --git a/lustre/include/linux/obd_class.h b/lustre/include/linux/obd_class.h index 3c93a8e40229a92403d895cc9a206d2874b0907f..48939073ad5ef15480295347068df1a4dffe8a10 100644 --- a/lustre/include/linux/obd_class.h +++ b/lustre/include/linux/obd_class.h @@ -76,8 +76,9 @@ struct obd_export { 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 { @@ -687,6 +688,7 @@ int class_register_type(struct obd_ops *ops, char *nm); 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 *); diff --git a/lustre/include/linux/obd_lov.h b/lustre/include/linux/obd_lov.h index 9cfbd85d3a4d1b10e4169c89ca23083165f40c83..ea6ddedf2de10791e97d3049e4940b630ba3bec1 100644 --- a/lustre/include/linux/obd_lov.h +++ b/lustre/include/linux/obd_lov.h @@ -9,6 +9,9 @@ #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; diff --git a/lustre/ldlm/Makefile.am b/lustre/ldlm/Makefile.am index f9bfc2a579f77ed6b33a0ad8ed9054332166c26f..bfc45d2d8bc30d27b9309bcbd9df43c910e1b1fb 100644 --- a/lustre/ldlm/Makefile.am +++ b/lustre/ldlm/Makefile.am @@ -16,6 +16,5 @@ LINX=l_lock.c 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 diff --git a/lustre/lib/lov_pack.c b/lustre/lib/lov_pack.c new file mode 100644 index 0000000000000000000000000000000000000000..ad51941389153bea900a7600743a4188a198c1ad --- /dev/null +++ b/lustre/lib/lov_pack.c @@ -0,0 +1,44 @@ +/* -*- 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); +} diff --git a/lustre/llite/super.c b/lustre/llite/super.c index 8c82b9e0d3e067dcf6695c62403a718f681ada83..fd2aa8bf622e6ab4f224eef9dacbe0a8044daafd 100644 --- a/lustre/llite/super.c +++ b/lustre/llite/super.c @@ -113,30 +113,14 @@ static struct super_block * ll_read_super(struct super_block *sb, 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) { @@ -145,8 +129,25 @@ static struct super_block * ll_read_super(struct super_block *sb, } #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, diff --git a/lustre/lov/Makefile.am b/lustre/lov/Makefile.am index 90d38d4afe72f6a7c6d747f009aa9c63357428c9..5d24fc4e5114e0bb1d49a12fd4101932899e18b5 100644 --- a/lustre/lov/Makefile.am +++ b/lustre/lov/Makefile.am @@ -8,7 +8,11 @@ DEFS := 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 diff --git a/lustre/lov/lov_obd.c b/lustre/lov/lov_obd.c index b5d1054881db786cd27102f6152f1b9542e6ae14..7f56413186cdd6b4be8e95badedd1e6c9267f2aa 100644 --- a/lustre/lov/lov_obd.c +++ b/lustre/lov/lov_obd.c @@ -13,38 +13,203 @@ #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; @@ -389,16 +554,15 @@ static int lov_cancel(struct lustre_handle *conn, __u32 mode, #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, diff --git a/lustre/mds/Makefile.am b/lustre/mds/Makefile.am index f5fb93201fba1736e24ecda753d641541940a372..8d5a48633101d2241f0ae2ddf6250cb64cddc34f 100644 --- a/lustre/mds/Makefile.am +++ b/lustre/mds/Makefile.am @@ -9,20 +9,20 @@ MODULE = mds 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 diff --git a/lustre/mds/handler.c b/lustre/mds/handler.c index 48ba352971d811d62fbba83177e8a62ef102b296..81a3a310ecbd9fffd1df9550ad3d49c31cf3d05e 100644 --- a/lustre/mds/handler.c +++ b/lustre/mds/handler.c @@ -23,6 +23,8 @@ #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); @@ -194,8 +196,8 @@ static int mds_getstatus(struct ptlrpc_request *req) 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)); @@ -233,6 +235,48 @@ static int mds_getstatus(struct ptlrpc_request *req) 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) { @@ -709,6 +753,11 @@ int mds_handle(struct ptlrpc_request *req) 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); @@ -1012,12 +1061,16 @@ static int mds_cleanup(struct obd_device * obddev) 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) diff --git a/lustre/mds/mds_lov.c b/lustre/mds/mds_lov.c new file mode 100644 index 0000000000000000000000000000000000000000..42fac105a412beee4c7ff84a260f9708f6fbeb9c --- /dev/null +++ b/lustre/mds/mds_lov.c @@ -0,0 +1,186 @@ +/* -*- 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); +} diff --git a/lustre/obdclass/class_obd.c b/lustre/obdclass/class_obd.c index 5cbacde86c2180522b3810e064aec3d03fcbedf5..66e830b656044f958f746990ec35e0fe01f4f3eb 100644 --- a/lustre/obdclass/class_obd.c +++ b/lustre/obdclass/class_obd.c @@ -42,14 +42,15 @@ #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) @@ -87,13 +88,13 @@ inline void obd_conn2data(struct obd_ioctl_data *data, struct lustre_handle *con 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; @@ -101,43 +102,43 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, 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); } @@ -146,10 +147,10 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, 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"); @@ -158,7 +159,7 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, } err = copy_to_user((int *)arg, data, len); - RETURN(err); + GOTO(out, err); } @@ -168,23 +169,28 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, */ 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: { @@ -193,23 +199,28 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, */ 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: { @@ -229,10 +240,10 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, 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: { @@ -242,7 +253,16 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, 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", @@ -250,14 +270,14 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, 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 */ @@ -270,8 +290,6 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, 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); @@ -280,7 +298,13 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, 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) { @@ -288,7 +312,7 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, 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)); @@ -297,23 +321,23 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, 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) { @@ -328,21 +352,21 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, 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) ) @@ -353,13 +377,13 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, 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) ) @@ -369,7 +393,7 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, obd->obd_flags &= ~OBD_SET_UP; obd->obd_type->typ_refcnt--; } - RETURN(err); + GOTO(out, err); } case OBD_IOC_CONNECT: { @@ -380,21 +404,21 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, 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: { @@ -402,10 +426,10 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, 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: { @@ -413,20 +437,20 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, 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: { @@ -434,10 +458,10 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, 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: @@ -524,19 +548,23 @@ static int obd_class_ioctl (struct inode * inode, struct file * filp, 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 */ @@ -566,12 +594,13 @@ EXPORT_SYMBOL(class_register_type); 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) { @@ -580,6 +609,7 @@ 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))) { diff --git a/lustre/obdclass/genops.c b/lustre/obdclass/genops.c index 34e63eb98979abfe82c2ca50d2792a14e335e9bb..3a272455c72285c53288bff2e96e4f9556e7479d 100644 --- a/lustre/obdclass/genops.c +++ b/lustre/obdclass/genops.c @@ -139,6 +139,21 @@ int class_uuid2dev(char *name) 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; @@ -246,19 +261,15 @@ int class_connect (struct lustre_handle *conn, struct obd_device *obd) 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) { @@ -275,7 +286,9 @@ 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. */ @@ -347,4 +360,4 @@ int class_multi_cleanup(struct obd_device *obddev) } return 0; } - +#endif diff --git a/lustre/obdclass/proc_lustre.c b/lustre/obdclass/proc_lustre.c index 66ff9021f97085c4b715616b064afea4ccd7bca0..5c351c20c48db3d3ae4d197ca8ffbff004bb45c2 100644 --- a/lustre/obdclass/proc_lustre.c +++ b/lustre/obdclass/proc_lustre.c @@ -19,8 +19,8 @@ * 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: * @@ -59,29 +59,14 @@ static int read_lustre_status(char *page, char **start, off_t offset, 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 */ @@ -104,7 +89,6 @@ static int read_lustre_status(char *page, char **start, off_t offset, p += sprintf(&page[p], "\n"); /* Compute eof and return value */ - if (offset + count >= p) { *eof=1; return (p - offset); @@ -125,17 +109,16 @@ proc_lustre_register_obd_device(struct obd_device *obd) 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; diff --git a/lustre/tests/common.sh b/lustre/tests/common.sh index 2b536296a5ef8ac1dab7e8d44951a3cc986b8431..fe77905c538dfb4c950847bf796ef40ec66d684c 100644 --- a/lustre/tests/common.sh +++ b/lustre/tests/common.sh @@ -221,6 +221,7 @@ setup_lustre() { 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 @@ -294,6 +295,25 @@ setup_mds() { 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 @@ -354,7 +374,7 @@ setup_ost() { } setup_server() { - setup_mds $1 && setup_ost $1 + setup_mds $1 && setup_mds_lov $1 && setup_ost $1 } setup_osc() { @@ -371,7 +391,7 @@ setup_osc() { $OBDCTL <<- EOF || return $rc newdev - attach osc $THEOSC + attach osc $THEOSC ${THEOSC}-UUID setup OBDUUID $OSTNODE quit EOF @@ -392,13 +412,29 @@ setup_mdc() { $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 @@ -424,7 +460,7 @@ setup_mount() { } setup_client() { - setup_osc && setup_mdc && setup_mount + setup_osc && setup_mdc && setup_lov && setup_mount } DEBUG_ON="echo 0xffffffff > /proc/sys/portals/debug" @@ -476,6 +512,7 @@ cleanup_lustre() { losetup -d ${LOOP}2 do_rmmod llite + do_rmmod lov do_rmmod mdc do_rmmod mds_extN diff --git a/lustre/tests/llmountcleanup.sh b/lustre/tests/llmountcleanup.sh index 0448d31a16574f4aa82ec8a6d319b7e08bfb9892..298d01d53fa62b100c462ed62c0ec6b9fc435414 100755 --- a/lustre/tests/llmountcleanup.sh +++ b/lustre/tests/llmountcleanup.sh @@ -39,6 +39,7 @@ detach quit EOF +rmmod lov rmmod obdecho rmmod mds_extN rmmod mds_ext3 diff --git a/lustre/tests/mds.cfg b/lustre/tests/mds.cfg index bfea75b3e05f487ef00af9b594e976b70abee53e..b9b9f780bec94a5fd82bdc19c6bd770f8e33e5dd 100644 --- a/lustre/tests/mds.cfg +++ b/lustre/tests/mds.cfg @@ -4,3 +4,4 @@ MDSFS=extN MDSDEV=/tmp/mds MDSSIZE=25000 SETUP_MDS=y +# LOVUUID=LovUUID diff --git a/lustre/utils/obdctl.c b/lustre/utils/obdctl.c index dd2a24f9d60914bdaa9a96afa342e916f43b0209..5552116e7064aea02b59ffe97af1a0ab85dae39f 100644 --- a/lustre/utils/obdctl.c +++ b/lustre/utils/obdctl.c @@ -1420,6 +1420,71 @@ static int jt_test_brw(int argc, char **argv) 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; @@ -1470,6 +1535,8 @@ command_t cmdlist[] = { "--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)"}, diff --git a/lustre/utils/parser.c b/lustre/utils/parser.c index fc22ba7f4ab347f39ff04313d872c1869ac7f7ea..b06f624b4c221684180e65c47205a2b362361a39 100644 --- a/lustre/utils/parser.c +++ b/lustre/utils/parser.c @@ -389,6 +389,14 @@ int Parser_help(int argc, char **argv) return 0; } + +void Parser_printhelp(char *cmd) +{ + char *argv[] = { "help", cmd }; + Parser_help(2, argv); +} + + /************************************************************************* * COMMANDS * *************************************************************************/ diff --git a/lustre/utils/parser.h b/lustre/utils/parser.h index 65dedaab537531d86e3ed242755c59de12d73d4f..8f225051bab7cb7aa7496c7266c8edbb7c5027f2 100644 --- a/lustre/utils/parser.h +++ b/lustre/utils/parser.h @@ -28,6 +28,7 @@ void Parser_init(char *, command_t *); /* Set prompt and load command list */ 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);