From 84095d5ad1b51cfe24e140bc2ca94622f51a8600 Mon Sep 17 00:00:00 2001 From: nikita Date: Thu, 18 May 2006 21:02:05 +0000 Subject: [PATCH] add prototype of req-layout interface (more details to follow) --- lustre/include/linux/Makefile.am | 2 +- lustre/include/linux/lustre_req_layout.h | 86 ++++++++ lustre/ptlrpc/Makefile.in | 2 +- lustre/ptlrpc/autoMakefile.am | 2 +- lustre/ptlrpc/layout.c | 345 +++++++++++++++++++++++++++++++ lustre/ptlrpc/ptlrpc_module.c | 20 +- 6 files changed, 448 insertions(+), 9 deletions(-) create mode 100644 lustre/include/linux/lustre_req_layout.h create mode 100644 lustre/ptlrpc/layout.c diff --git a/lustre/include/linux/Makefile.am b/lustre/include/linux/Makefile.am index 13f1389..e9068bb 100644 --- a/lustre/include/linux/Makefile.am +++ b/lustre/include/linux/Makefile.am @@ -15,4 +15,4 @@ EXTRA_DIST = lprocfs_status.h lustre_debug.h lustre_ha.h lustre_lib.h \ lustre_export.h lustre_log.h obd_echo.h \ lustre_compat25.h lustre_fsfilt.h lustre_import.h lustre_mds.h lustre_mdc.h \ lustre_acl.h obd.h lvfs.h lvfs_linux.h lustre_cfg.h lustre_lite.h lustre_idl.h \ - lustre_quota.h lustre_ucache.h lustre_ver.h.in lustre_param.h lu_object.h lustre_fid.h md_object.h + lustre_quota.h lustre_ucache.h lustre_ver.h.in lustre_param.h lu_object.h lustre_fid.h md_object.h lustre_req_layout.h diff --git a/lustre/include/linux/lustre_req_layout.h b/lustre/include/linux/lustre_req_layout.h new file mode 100644 index 0000000..e0e5eeb --- /dev/null +++ b/lustre/include/linux/lustre_req_layout.h @@ -0,0 +1,86 @@ +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- + * vim:expandtab:shiftwidth=8:tabstop=8: + * + * lustre/include/linux/lustre_req_layout.h + * Lustre Metadata Target (mdt) request handler + * + * Copyright (c) 2006 Cluster File Systems, Inc. + * Author: Nikita Danilov + * + * This file is part of the Lustre file system, http://www.lustre.org + * Lustre is a trademark of Cluster File Systems, Inc. + * + * You may have signed or agreed to another license before downloading + * this software. If so, you are bound by the terms and conditions + * of that agreement, and the following does not apply to you. See the + * LICENSE file included with this distribution for more information. + * + * If you did not agree to a different license, then this copy of Lustre + * is open source 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. + * + * In either case, 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 + * license text for more details. + */ + +#ifndef _LINUX_LUSTRE_REQ_LAYOUT_H__ +#define _LINUX_LUSTRE_REQ_LAYOUT_H__ + +/* struct ptlrpc_request, lustre_msg* */ +#include + +struct req_msg_field; +struct req_format; +struct req_capsule; + +struct ptlrpc_request; + +enum req_location { + RCL_CLIENT, + RCL_SERVER, + RCL_NR +}; + +struct req_capsule { + struct ptlrpc_request *rc_req; + const struct req_format *rc_fmt[RCL_NR]; + __u32 rc_swabbed; + enum req_location rc_loc; +}; + +void req_capsule_init(struct req_capsule *pill, + struct ptlrpc_request *req, + enum req_location location); +void req_capsule_fini(struct req_capsule *pill); + +void req_capsule_client_init(struct req_capsule *pill, + const struct req_format *fmt); +void req_capsule_server_init(struct req_capsule *pill, + const struct req_format *fmt); +int req_capsule_start(struct req_capsule *pill, + const struct req_format *fmt, int *area); + +const void *req_capsule_client_get(const struct req_capsule *pill, + const struct req_msg_field *field); +void *req_capsule_server_get(const struct req_capsule *pill, + const struct req_msg_field *field); + +int req_layout_init(void); +void req_layout_fini(void); + +extern const struct req_format RQF_MDS_GETSTATUS; +extern const struct req_format RQF_MDS_STATFS; +extern const struct req_format RQF_MDS_GETATTR; +extern const struct req_format RQF_MDS_GETATTR_NAME; +extern const struct req_format RQF_MDS_REINT_CREATE; + +extern const struct req_msg_field RMF_MDT_BODY; +extern const struct req_msg_field RMF_OBD_STATFS; +extern const struct req_msg_field RMF_NAME; +extern const struct req_msg_field RMF_REC_CREATE; + + +#endif /* _LINUX_LUSTRE_REQ_LAYOUT_H__ */ diff --git a/lustre/ptlrpc/Makefile.in b/lustre/ptlrpc/Makefile.in index 244925b..2003051 100644 --- a/lustre/ptlrpc/Makefile.in +++ b/lustre/ptlrpc/Makefile.in @@ -12,7 +12,7 @@ ldlm_objs += $(LDLM)ldlm_flock.o $(LDLM)ldlm_inodebits.o ptlrpc_objs := client.o recover.o connection.o niobuf.o pack_generic.o ptlrpc_objs += events.o ptlrpc_module.o service.o pinger.o recov_thread.o ptlrpc_objs += llog_net.o llog_client.o llog_server.o import.o ptlrpcd.o -ptlrpc_objs += pers.o lproc_ptlrpc.o +ptlrpc_objs += pers.o lproc_ptlrpc.o layout.o ptlrpc-objs := $(ldlm_objs) $(ptlrpc_objs) diff --git a/lustre/ptlrpc/autoMakefile.am b/lustre/ptlrpc/autoMakefile.am index ee2c7d9..09dc09b 100644 --- a/lustre/ptlrpc/autoMakefile.am +++ b/lustre/ptlrpc/autoMakefile.am @@ -18,7 +18,7 @@ LDLM_COMM_SOURCES= $(top_srcdir)/lustre/ldlm/l_lock.c \ COMMON_SOURCES = client.c recover.c connection.c niobuf.c pack_generic.c \ events.c ptlrpc_module.c service.c pinger.c recov_thread.c llog_net.c \ llog_client.c llog_server.c import.c ptlrpcd.c pers.c \ - ptlrpc_internal.h $(LDLM_COMM_SOURCES) + ptlrpc_internal.h layout.c $(LDLM_COMM_SOURCES) if LIBLUSTRE diff --git a/lustre/ptlrpc/layout.c b/lustre/ptlrpc/layout.c new file mode 100644 index 0000000..5f2186c --- /dev/null +++ b/lustre/ptlrpc/layout.c @@ -0,0 +1,345 @@ +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- + * vim:expandtab:shiftwidth=8:tabstop=8: + * + * lustre/ptlrpc/layout.c + * Lustre Metadata Target (mdt) request handler + * + * Copyright (c) 2006 Cluster File Systems, Inc. + * Author: Nikita Danilov + * + * This file is part of the Lustre file system, http://www.lustre.org + * Lustre is a trademark of Cluster File Systems, Inc. + * + * You may have signed or agreed to another license before downloading + * this software. If so, you are bound by the terms and conditions + * of that agreement, and the following does not apply to you. See the + * LICENSE file included with this distribution for more information. + * + * If you did not agree to a different license, then this copy of Lustre + * is open source 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. + * + * In either case, 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 + * license text for more details. + */ + +#ifndef EXPORT_SYMTAB +# define EXPORT_SYMTAB +#endif +#define DEBUG_SUBSYSTEM S_RPC + +#ifdef __KERNEL__ +#include +#else +# include +#endif + +/* LUSTRE_VERSION_CODE */ +#include + +#include +/* lustre_swab_mdt_body */ +#include +/* obd2cli_tgt() (required by DEBUG_REQ()) */ +#include + +/* struct ptlrpc_request, lustre_msg* */ +#include + +static const struct req_msg_field *empty[] = {}; /* none */ + +static const struct req_msg_field *mdt_body_only[] = { + &RMF_MDT_BODY +}; + +static const struct req_msg_field *mds_statfs_server[] = { + &RMF_OBD_STATFS +}; + +static const struct req_msg_field *mds_getattr_name_client[] = { + &RMF_MDT_BODY, + &RMF_NAME +}; + +static const struct req_msg_field *mds_reint_create_client[] = { + &RMF_REC_CREATE, + &RMF_NAME +}; + +static const struct req_format *req_formats[] = { + &RQF_MDS_GETSTATUS, + &RQF_MDS_STATFS, + &RQF_MDS_GETATTR, + &RQF_MDS_GETATTR_NAME, + &RQF_MDS_REINT_CREATE +}; + +struct req_msg_field { + __u32 rmf_flags; + const char *rmf_name; + int rmf_size; + void (*rmf_swabber)(void *); + int rmf_offset[ARRAY_SIZE(req_formats)][RCL_NR]; +}; + +enum rmf_flags { + RMF_F_STRING = 1 << 0 +}; + +struct req_capsule; + +/* + * Request fields. + */ +#define DEFINE_MSGF(name, flags, size, swabber) { \ + .rmf_name = (name), \ + .rmf_flags = (flags), \ + .rmf_size = (size), \ + .rmf_swabber = (void (*)(void*))(swabber) \ +} + +const struct req_msg_field RMF_MDT_BODY = + DEFINE_MSGF("mdt_body", 0, + sizeof(struct mdt_body), lustre_swab_mdt_body); +EXPORT_SYMBOL(RMF_MDT_BODY); + +const struct req_msg_field RMF_OBD_STATFS = + DEFINE_MSGF("obd_statfs", 0, + sizeof(struct obd_statfs), lustre_swab_obd_statfs); +EXPORT_SYMBOL(RMF_OBD_STATFS); + +const struct req_msg_field RMF_NAME = + DEFINE_MSGF("name", RMF_F_STRING, 0, NULL); +EXPORT_SYMBOL(RMF_NAME); + +const struct req_msg_field RMF_REC_CREATE = + DEFINE_MSGF("rec_create", 0, + sizeof(struct mdt_rec_create), lustre_swab_mdt_rec_create); +EXPORT_SYMBOL(RMF_REC_CREATE); + +/* + * Request formats. + */ + +struct req_format { + const char *rf_name; + int rf_idx; + struct { + int nr; + const struct req_msg_field **d; + } rf_fields[RCL_NR]; +}; + +#define DEFINE_REQ_FMT(name, client, client_nr, server, server_nr) { \ + .rf_name = name, \ + .rf_fields = { \ + [RCL_CLIENT] = { \ + .nr = client_nr, \ + .d = client \ + }, \ + [RCL_SERVER] = { \ + .nr = server_nr, \ + .d = server \ + } \ + } \ +} + +#define DEFINE_REQ_FMT0(name, client, server) \ +DEFINE_REQ_FMT(name, client, ARRAY_SIZE(client), server, ARRAY_SIZE(server)) + +const struct req_format RQF_MDS_GETSTATUS = + DEFINE_REQ_FMT0("MDS_GETSTATUS", empty, mdt_body_only); +EXPORT_SYMBOL(RQF_MDS_GETSTATUS); + +const struct req_format RQF_MDS_STATFS = + DEFINE_REQ_FMT0("MDS_STATFS", empty, mds_statfs_server); +EXPORT_SYMBOL(RQF_MDS_STATFS); + +const struct req_format RQF_MDS_GETATTR = + DEFINE_REQ_FMT0("MDS_GETATTR", mdt_body_only, mdt_body_only); +EXPORT_SYMBOL(RQF_MDS_GETATTR); + +const struct req_format RQF_MDS_GETATTR_NAME = + DEFINE_REQ_FMT0("MDS_GETATTR_NAME", + mds_getattr_name_client, mdt_body_only); +EXPORT_SYMBOL(RQF_MDS_GETATTR_NAME); + +const struct req_format RQF_MDS_REINT_CREATE = + DEFINE_REQ_FMT0("MDS_REINT_CREATE", + mds_reint_create_client, mdt_body_only); +EXPORT_SYMBOL(RQF_MDS_REINT_CREATE); + +int req_layout_init(void) +{ + int i; + int j; + int k; + + for (i = 0; i < ARRAY_SIZE(req_formats); ++i) { + struct req_format *rf; + + rf = (struct req_format *)req_formats[i]; + rf->rf_idx = i; + for (j = 0; j < RCL_NR; ++j) { + for (k = 0; k < rf->rf_fields[j].nr; ++k) { + struct req_msg_field *field; + + field = (typeof(field))rf->rf_fields[j].d[k]; + LASSERT(field->rmf_offset[i][j] == 0); + /* + * k + 1 to detect unused format/field + * combinations. + */ + field->rmf_offset[i][j] = k + 1; + } + } + } + return 0; +} +EXPORT_SYMBOL(req_layout_init); + +void req_layout_fini(void) +{ +} +EXPORT_SYMBOL(req_layout_fini); + +void req_capsule_init(struct req_capsule *pill, + struct ptlrpc_request *req, enum req_location location) +{ + LASSERT(location == RCL_SERVER || location == RCL_CLIENT); + + memset(pill, 0, sizeof *pill); + pill->rc_req = req; + pill->rc_loc = location; +} +EXPORT_SYMBOL(req_capsule_init); + +void req_capsule_fini(struct req_capsule *pill) +{ +} +EXPORT_SYMBOL(req_capsule_fini); + +static int __req_format_is_sane(const struct req_format *fmt) +{ + return + 0 <= fmt->rf_idx && fmt->rf_idx < ARRAY_SIZE(req_formats) && + req_formats[fmt->rf_idx] == fmt; +} + +static void __req_capsule_init(struct req_capsule *pill, + const struct req_format *fmt, + enum req_location loc) +{ + LASSERT(0 <= loc && loc < ARRAY_SIZE(pill->rc_fmt)); + LASSERT(pill->rc_fmt[loc] == NULL); + LASSERT(ergo(loc != pill->rc_loc, pill->rc_swabbed == 0)); + LASSERT(__req_format_is_sane(fmt)); + + pill->rc_fmt[loc] = fmt; +} + +void req_capsule_server_init(struct req_capsule *pill, + const struct req_format *fmt) +{ + __req_capsule_init(pill, fmt, RCL_SERVER); +} +EXPORT_SYMBOL(req_capsule_server_init); + +void req_capsule_client_init(struct req_capsule *pill, + const struct req_format *fmt) +{ + __req_capsule_init(pill, fmt, RCL_CLIENT); +} +EXPORT_SYMBOL(req_capsule_client_init); + +int req_capsule_start(struct req_capsule *pill, + const struct req_format *fmt, int *area) +{ + int i; + int nr; + int result; + + LASSERT(pill->rc_loc == RCL_SERVER); + + nr = fmt->rf_fields[RCL_SERVER].nr; + for (i = 0; i < nr; ++i) + area[i] = fmt->rf_fields[RCL_SERVER].d[i]->rmf_size; + req_capsule_server_init(pill, fmt); + result = lustre_pack_reply(pill->rc_req, nr, area, NULL); + if (result != 0) { + DEBUG_REQ(D_ERROR, pill->rc_req, + "Failed to pack %d fields in format `%s': ", + nr, fmt->rf_name); + } + return result; +} +EXPORT_SYMBOL(req_capsule_start); + +static void *__req_capsule_get(const struct req_capsule *pill, + const struct req_msg_field *field, + enum req_location loc) +{ + const struct req_format *fmt; + const struct ptlrpc_request *req; + struct lustre_msg *msg; + void *value; + int offset; + + void *(*getter)(struct lustre_msg *m, int n, int minlen); + + static const char *rcl_names[RCL_NR] = { + [RCL_CLIENT] = "client", + [RCL_SERVER] = "server" + }; + + LASSERT(0 <= loc && loc < ARRAY_SIZE(pill->rc_fmt)); + CLASSERT(ARRAY_SIZE(pill->rc_fmt) == ARRAY_SIZE(field->rmf_offset[0])); + + fmt = pill->rc_fmt[loc]; + LASSERT(fmt != NULL); + LASSERT(__req_format_is_sane(fmt)); + + offset = field->rmf_offset[fmt->rf_idx][loc]; + LASSERT(offset > 0); + -- offset; + LASSERT(0 <= offset && offset < (sizeof(pill->rc_swabbed) << 3)); + + req = pill->rc_req; + msg = loc == RCL_CLIENT ? req->rq_reqmsg : req->rq_repmsg; + + getter = (field->rmf_flags & RMF_F_STRING) ? + (typeof(getter))lustre_msg_string : lustre_msg_buf; + + value = getter(msg, offset, field->rmf_size); + + if (!(pill->rc_swabbed & (1 << offset)) && loc != pill->rc_loc && + field->rmf_swabber != NULL && value != NULL && + lustre_msg_swabbed(msg)) + field->rmf_swabber(value); + if (value == NULL) + DEBUG_REQ(D_ERROR, pill->rc_req, + "Wrong buffer for field `%s' (%d) in format `%s': " + "%d < %d (%s)\n", + field->rmf_name, offset, fmt->rf_name, + lustre_msg_buflen(msg, offset), field->rmf_size, + rcl_names[loc]); + return value; +} + +const void *req_capsule_client_get(const struct req_capsule *pill, + const struct req_msg_field *field) +{ + return (const void *)__req_capsule_get(pill, field, RCL_CLIENT); +} +EXPORT_SYMBOL(req_capsule_client_get); + +void *req_capsule_server_get(const struct req_capsule *pill, + const struct req_msg_field *field) +{ + return __req_capsule_get(pill, field, RCL_SERVER); +} +EXPORT_SYMBOL(req_capsule_server_get); + diff --git a/lustre/ptlrpc/ptlrpc_module.c b/lustre/ptlrpc/ptlrpc_module.c index c2d3e36..408ec6c 100644 --- a/lustre/ptlrpc/ptlrpc_module.c +++ b/lustre/ptlrpc/ptlrpc_module.c @@ -38,6 +38,7 @@ #include #include #include +#include #include "ptlrpc_internal.h" @@ -51,23 +52,28 @@ __init int ptlrpc_init(void) lustre_assert_wire_constants(); - rc = ptlrpc_init_portals(); + rc = req_layout_init(); if (rc) RETURN(rc); cleanup_phase = 1; + rc = ptlrpc_init_portals(); + if (rc) + RETURN(rc); + cleanup_phase = 2; + ptlrpc_init_connection(); rc = llog_init_commit_master(); if (rc) GOTO(cleanup, rc); - cleanup_phase = 2; + cleanup_phase = 3; ptlrpc_put_connection_superhack = ptlrpc_put_connection; rc = ptlrpc_start_pinger(); if (rc) GOTO(cleanup, rc); - cleanup_phase = 3; + cleanup_phase = 4; rc = ldlm_init(); if (rc) @@ -76,13 +82,15 @@ __init int ptlrpc_init(void) cleanup: switch(cleanup_phase) { - case 3: + case 4: ptlrpc_stop_pinger(); - case 2: + case 3: llog_cleanup_commit_master(1); ptlrpc_cleanup_connection(); - case 1: + case 2: ptlrpc_exit_portals(); + case 1: + req_layout_fini(); default: ; } -- 1.8.3.1