#include <lnet/lnet.h>
#include <lnet/lib-types.h>
+#define LST_FEAT_NONE (0)
+#define LST_FEAT_BULK_LEN (1 << 0) /* enable variable page size */
+
+#define LST_FEATS_EMPTY (LST_FEAT_NONE)
+#define LST_FEATS_MASK (LST_FEAT_NONE | LST_FEAT_BULK_LEN)
+
#define LST_NAME_SIZE 32 /* max name buffer length */
#define LSTIO_DEBUG 0xC00 /* debug */
int lstio_ses_key; /* IN: local key */
int lstio_ses_timeout; /* IN: session timeout */
int lstio_ses_force; /* IN: force create ? */
+ /** IN: session features */
+ unsigned lstio_ses_feats;
lst_sid_t *lstio_ses_idp; /* OUT: session id */
int lstio_ses_nmlen; /* IN: name length */
char *lstio_ses_namep; /* IN: session name */
typedef struct {
lst_sid_t *lstio_ses_idp; /* OUT: session id */
int *lstio_ses_keyp; /* OUT: local key */
+ /** OUT: session features */
+ unsigned *lstio_ses_featp;
lstcon_ndlist_ent_t *lstio_ses_ndinfo; /* OUT: */
int lstio_ses_nmlen; /* IN: name length */
char *lstio_ses_namep; /* OUT: session name */
int lstio_grp_nmlen; /* IN: name length */
char *lstio_grp_namep; /* IN: group name */
int lstio_grp_count; /* IN: # of nodes */
+ /** OUT: session features */
+ unsigned *lstio_grp_featp;
lnet_process_id_t *lstio_grp_idsp; /* IN: nodes */
cfs_list_t *lstio_grp_resultp; /* OUT: list head of result buffer */
} lstio_group_nodes_args_t;
int
brw_client_init (sfw_test_instance_t *tsi)
{
- test_bulk_req_t *breq = &tsi->tsi_u.bulk;
- int flags = breq->blk_flags;
- int npg = breq->blk_npg;
- srpc_bulk_t *bulk;
- sfw_test_unit_t *tsu;
-
- LASSERT (tsi->tsi_is_client);
-
- if (npg > LNET_MAX_IOV || npg <= 0)
- return -EINVAL;
-
- if (breq->blk_opc != LST_BRW_READ && breq->blk_opc != LST_BRW_WRITE)
- return -EINVAL;
-
- if (flags != LST_BRW_CHECK_NONE &&
- flags != LST_BRW_CHECK_FULL && flags != LST_BRW_CHECK_SIMPLE)
- return -EINVAL;
+ sfw_session_t *sn = tsi->tsi_batch->bat_session;
+ int flags;
+ int npg;
+ int len;
+ int opc;
+ srpc_bulk_t *bulk;
+ sfw_test_unit_t *tsu;
+
+ LASSERT(sn != NULL);
+ LASSERT(tsi->tsi_is_client);
+
+ if ((sn->sn_features & LST_FEAT_BULK_LEN) == 0) {
+ test_bulk_req_t *breq = &tsi->tsi_u.bulk_v0;
+
+ opc = breq->blk_opc;
+ flags = breq->blk_flags;
+ npg = breq->blk_npg;
+ /* NB: this is not going to work for variable page size,
+ * but we have to keep it for compatibility */
+ len = npg * CFS_PAGE_SIZE;
+
+ } else {
+ test_bulk_req_v1_t *breq = &tsi->tsi_u.bulk_v1;
+
+ /* I should never get this step if it's unknown feature
+ * because make_session will reject unknown feature */
+ LASSERT((sn->sn_features & ~LST_FEATS_MASK) == 0);
+
+ opc = breq->blk_opc;
+ flags = breq->blk_flags;
+ len = breq->blk_len;
+ npg = (len + CFS_PAGE_SIZE - 1) >> CFS_PAGE_SHIFT;
+ }
+
+ if (npg > LNET_MAX_IOV || npg <= 0)
+ return -EINVAL;
+
+ if (opc != LST_BRW_READ && opc != LST_BRW_WRITE)
+ return -EINVAL;
+
+ if (flags != LST_BRW_CHECK_NONE &&
+ flags != LST_BRW_CHECK_FULL && flags != LST_BRW_CHECK_SIMPLE)
+ return -EINVAL;
cfs_list_for_each_entry_typed(tsu, &tsi->tsi_units,
sfw_test_unit_t, tsu_list) {
bulk = srpc_alloc_bulk(lnet_cpt_of_nid(tsu->tsu_dest.nid),
- npg, breq->blk_opc == LST_BRW_READ);
+ npg, len, opc == LST_BRW_READ);
if (bulk == NULL) {
brw_client_fini(tsi);
return -ENOMEM;
tsu->tsu_private = bulk;
}
- return 0;
+ return 0;
}
#define BRW_POISON 0xbeefbeefbeefbeefULL
{
srpc_bulk_t *bulk = tsu->tsu_private;
sfw_test_instance_t *tsi = tsu->tsu_instance;
- test_bulk_req_t *breq = &tsi->tsi_u.bulk;
- int npg = breq->blk_npg;
- int flags = breq->blk_flags;
- srpc_client_rpc_t *rpc;
- srpc_brw_reqst_t *req;
- int rc;
-
- LASSERT (bulk != NULL);
- LASSERT (bulk->bk_niov == npg);
-
- rc = sfw_create_test_rpc(tsu, dest, npg, npg * CFS_PAGE_SIZE, &rpc);
- if (rc != 0) return rc;
-
- memcpy(&rpc->crpc_bulk, bulk, offsetof(srpc_bulk_t, bk_iovs[npg]));
- if (breq->blk_opc == LST_BRW_WRITE)
- brw_fill_bulk(&rpc->crpc_bulk, flags, BRW_MAGIC);
- else
- brw_fill_bulk(&rpc->crpc_bulk, flags, BRW_POISON);
+ sfw_session_t *sn = tsi->tsi_batch->bat_session;
+ srpc_client_rpc_t *rpc;
+ srpc_brw_reqst_t *req;
+ int flags;
+ int npg;
+ int len;
+ int opc;
+ int rc;
+
+ LASSERT(sn != NULL);
+ LASSERT(bulk != NULL);
+
+ if ((sn->sn_features & LST_FEAT_BULK_LEN) == 0) {
+ test_bulk_req_t *breq = &tsi->tsi_u.bulk_v0;
+
+ opc = breq->blk_opc;
+ flags = breq->blk_flags;
+ npg = breq->blk_npg;
+ len = npg * CFS_PAGE_SIZE;
+
+ } else {
+ test_bulk_req_v1_t *breq = &tsi->tsi_u.bulk_v1;
+
+ /* I should never get this step if it's unknown feature
+ * because make_session will reject unknown feature */
+ LASSERT((sn->sn_features & ~LST_FEATS_MASK) == 0);
+
+ opc = breq->blk_opc;
+ flags = breq->blk_flags;
+ len = breq->blk_len;
+ npg = (len + CFS_PAGE_SIZE - 1) >> CFS_PAGE_SHIFT;
+ }
+
+ rc = sfw_create_test_rpc(tsu, dest, sn->sn_features, npg, len, &rpc);
+ if (rc != 0)
+ return rc;
- req = &rpc->crpc_reqstmsg.msg_body.brw_reqst;
- req->brw_flags = flags;
- req->brw_rw = breq->blk_opc;
- req->brw_len = npg * CFS_PAGE_SIZE;
+ memcpy(&rpc->crpc_bulk, bulk, offsetof(srpc_bulk_t, bk_iovs[npg]));
+ if (opc == LST_BRW_WRITE)
+ brw_fill_bulk(&rpc->crpc_bulk, flags, BRW_MAGIC);
+ else
+ brw_fill_bulk(&rpc->crpc_bulk, flags, BRW_POISON);
- *rpcpp = rpc;
- return 0;
+ req = &rpc->crpc_reqstmsg.msg_body.brw_reqst;
+ req->brw_flags = flags;
+ req->brw_rw = opc;
+ req->brw_len = len;
+
+ *rpcpp = rpc;
+ return 0;
}
static void
srpc_msg_t *reqstmsg = &rpc->srpc_reqstbuf->buf_msg;
srpc_brw_reply_t *reply = &replymsg->msg_body.brw_reply;
srpc_brw_reqst_t *reqst = &reqstmsg->msg_body.brw_reqst;
+ int npg;
int rc;
LASSERT (sv->sv_id == SRPC_SERVICE_BRW);
if (reqstmsg->msg_magic != SRPC_MSG_MAGIC) {
LASSERT (reqstmsg->msg_magic == __swab32(SRPC_MSG_MAGIC));
- __swab32s(&reqstmsg->msg_type);
__swab32s(&reqst->brw_rw);
__swab32s(&reqst->brw_len);
__swab32s(&reqst->brw_flags);
}
LASSERT (reqstmsg->msg_type == (__u32)srpc_service2request(sv->sv_id));
+ reply->brw_status = 0;
rpc->srpc_done = brw_server_rpc_done;
if ((reqst->brw_rw != LST_BRW_READ && reqst->brw_rw != LST_BRW_WRITE) ||
- reqst->brw_len == 0 || (reqst->brw_len & ~CFS_PAGE_MASK) != 0 ||
- reqst->brw_len / CFS_PAGE_SIZE > LNET_MAX_IOV ||
(reqst->brw_flags != LST_BRW_CHECK_NONE &&
reqst->brw_flags != LST_BRW_CHECK_FULL &&
reqst->brw_flags != LST_BRW_CHECK_SIMPLE)) {
return 0;
}
- reply->brw_status = 0;
- /* allocate from "local" node */
- rc = sfw_alloc_pages(rpc, rpc->srpc_scd->scd_cpt,
- reqst->brw_len / CFS_PAGE_SIZE,
+ if ((reqstmsg->msg_ses_feats & ~LST_FEATS_MASK) != 0) {
+ replymsg->msg_ses_feats = LST_FEATS_MASK;
+ reply->brw_status = EPROTO;
+ return 0;
+ }
+
+ if ((reqstmsg->msg_ses_feats & LST_FEAT_BULK_LEN) == 0) {
+ /* compat with old version */
+ if ((reqst->brw_len & ~CFS_PAGE_MASK) != 0) {
+ reply->brw_status = EINVAL;
+ return 0;
+ }
+ npg = reqst->brw_len >> CFS_PAGE_SHIFT;
+
+ } else {
+ npg = (reqst->brw_len + CFS_PAGE_SIZE - 1) >> CFS_PAGE_SHIFT;
+ }
+
+ replymsg->msg_ses_feats = reqstmsg->msg_ses_feats;
+
+ if (reqst->brw_len == 0 || npg > LNET_MAX_IOV) {
+ reply->brw_status = EINVAL;
+ return 0;
+ }
+
+ rc = sfw_alloc_pages(rpc, rpc->srpc_scd->scd_cpt, npg,
+ reqst->brw_len,
reqst->brw_rw == LST_BRW_WRITE);
if (rc != 0)
return rc;
name[args->lstio_ses_nmlen] = 0;
- rc = lstcon_session_new(name,
- args->lstio_ses_key,
- args->lstio_ses_timeout,
- args->lstio_ses_force,
- args->lstio_ses_idp);
-
- LIBCFS_FREE(name, args->lstio_ses_nmlen + 1);
-
- return rc;
+ rc = lstcon_session_new(name,
+ args->lstio_ses_key,
+ args->lstio_ses_feats,
+ args->lstio_ses_force,
+ args->lstio_ses_timeout,
+ args->lstio_ses_idp);
+
+ LIBCFS_FREE(name, args->lstio_ses_nmlen + 1);
+ return rc;
}
int
if (args->lstio_ses_idp == NULL || /* address for ouput sid */
args->lstio_ses_keyp == NULL || /* address for ouput key */
+ args->lstio_ses_featp == NULL || /* address for ouput features */
args->lstio_ses_ndinfo == NULL || /* address for output ndinfo */
args->lstio_ses_namep == NULL || /* address for ouput name */
args->lstio_ses_nmlen <= 0 ||
return lstcon_session_info(args->lstio_ses_idp,
args->lstio_ses_keyp,
+ args->lstio_ses_featp,
args->lstio_ses_ndinfo,
args->lstio_ses_namep,
args->lstio_ses_nmlen);
int
lst_nodes_add_ioctl(lstio_group_nodes_args_t *args)
{
+ unsigned feats;
int rc;
char *name;
if (args->lstio_grp_idsp == NULL || /* array of ids */
args->lstio_grp_count <= 0 ||
args->lstio_grp_resultp == NULL ||
- args->lstio_grp_namep == NULL ||
- args->lstio_grp_nmlen <= 0 ||
+ args->lstio_grp_featp == NULL ||
+ args->lstio_grp_namep == NULL ||
+ args->lstio_grp_nmlen <= 0 ||
args->lstio_grp_nmlen > LST_NAME_SIZE)
return -EINVAL;
name[args->lstio_grp_nmlen] = 0;
rc = lstcon_nodes_add(name, args->lstio_grp_count,
- args->lstio_grp_idsp,
- args->lstio_grp_resultp);
+ args->lstio_grp_idsp, &feats,
+ args->lstio_grp_resultp);
- LIBCFS_FREE(name, args->lstio_grp_nmlen + 1);
+ LIBCFS_FREE(name, args->lstio_grp_nmlen + 1);
+ if (rc == 0 &&
+ cfs_copy_to_user(args->lstio_grp_featp, &feats, sizeof(feats))) {
+ return -EINVAL;
+ }
return rc;
}
args->lstio_tes_dgrp_nmlen > LST_NAME_SIZE)
return -EINVAL;
+ if (args->lstio_tes_loop == 0 || /* negative is infinite */
+ args->lstio_tes_concur <= 0 ||
+ args->lstio_tes_dist <= 0 ||
+ args->lstio_tes_span <= 0)
+ return -EINVAL;
+
/* have parameter, check if parameter length is valid */
if (args->lstio_tes_param != NULL &&
(args->lstio_tes_param_len <= 0 ||
*
* Console framework rpcs
*
- * Author: Liang Zhen <liangzhen@clusterfs.com>
+ * Author: Liang Zhen <liang@whamcloud.com>
*/
#ifdef __KERNEL__
#include "conrpc.h"
#include "console.h"
-void lstcon_rpc_stat_reply(int, srpc_msg_t *,
- lstcon_node_t *, lstcon_trans_stat_t *);
+void lstcon_rpc_stat_reply(lstcon_rpc_trans_t *, srpc_msg_t *,
+ lstcon_node_t *, lstcon_trans_stat_t *);
static void
lstcon_rpc_done(srpc_client_rpc_t *rpc)
}
int
-lstcon_rpc_init(lstcon_node_t *nd, int service,
- int npg, int cached, lstcon_rpc_t *crpc)
+lstcon_rpc_init(lstcon_node_t *nd, int service, unsigned feats,
+ int bulk_npg, int bulk_len, int embedded, lstcon_rpc_t *crpc)
{
-
- crpc->crp_rpc = sfw_create_rpc(nd->nd_id, service,
- npg, npg * CFS_PAGE_SIZE,
- lstcon_rpc_done, (void *)crpc);
+ crpc->crp_rpc = sfw_create_rpc(nd->nd_id, service,
+ feats, bulk_npg, bulk_len,
+ lstcon_rpc_done, (void *)crpc);
if (crpc->crp_rpc == NULL)
return -ENOMEM;
crpc->crp_unpacked = 0;
crpc->crp_status = 0;
crpc->crp_stamp = 0;
- crpc->crp_static = !cached;
+ crpc->crp_embedded = embedded;
CFS_INIT_LIST_HEAD(&crpc->crp_link);
cfs_atomic_inc(&console_session.ses_rpc_counter);
}
int
-lstcon_rpc_prep(lstcon_node_t *nd, int service,
- int npg, lstcon_rpc_t **crpcpp)
+lstcon_rpc_prep(lstcon_node_t *nd, int service, unsigned feats,
+ int bulk_npg, int bulk_len, lstcon_rpc_t **crpcpp)
{
lstcon_rpc_t *crpc = NULL;
int rc;
return -ENOMEM;
}
- rc = lstcon_rpc_init(nd, service, npg, 1, crpc);
+ rc = lstcon_rpc_init(nd, service, feats,
+ bulk_npg, bulk_len, 0, crpc);
if (rc == 0) {
*crpcpp = crpc;
return 0;
srpc_client_rpc_decref(crpc->crp_rpc);
- if (crpc->crp_static) {
- /* Static RPC, not allocated */
- memset(crpc, 0, sizeof(*crpc));
- crpc->crp_static = 1;
+ if (crpc->crp_embedded) {
+ /* embedded RPC, don't recycle it */
+ memset(crpc, 0, sizeof(*crpc));
+ crpc->crp_embedded = 1;
} else {
cfs_spin_lock(&console_session.ses_rpc_lock);
LIBCFS_ALLOC(trans, sizeof(*trans));
if (trans == NULL)
return -ENOMEM;
-
+
trans->tas_opc = transop;
- if (translist == NULL)
+ if (translist == NULL)
CFS_INIT_LIST_HEAD(&trans->tas_olink);
else
cfs_list_add_tail(&trans->tas_olink, translist);
cfs_atomic_set(&trans->tas_remaining, 0);
cfs_waitq_init(&trans->tas_waitq);
- *transpp = trans;
+ cfs_spin_lock(&console_session.ses_rpc_lock);
+ trans->tas_features = console_session.ses_features;
+ cfs_spin_unlock(&console_session.ses_rpc_lock);
- return 0;
+ *transpp = trans;
+ return 0;
}
void
sfw_unpack_message(*msgpp);
crpc->crp_unpacked = 1;
}
-
+
if (cfs_time_after(nd->nd_stamp, crpc->crp_stamp))
return 0;
lstcon_rpc_stat_success(stat, 1);
- lstcon_rpc_stat_reply(trans->tas_opc, rep,
- crpc->crp_node, stat);
+ lstcon_rpc_stat_reply(trans, rep, crpc->crp_node, stat);
+ }
+
+ if (trans->tas_opc == LST_TRANS_SESNEW && stat->trs_fwk_errno == 0) {
+ stat->trs_fwk_errno =
+ lstcon_session_feats_check(trans->tas_features);
}
CDEBUG(D_NET, "transaction %s : success %d, failure %d, total %d, "
}
int
-lstcon_sesrpc_prep(lstcon_node_t *nd, int transop, lstcon_rpc_t **crpc)
+lstcon_sesrpc_prep(lstcon_node_t *nd, int transop,
+ unsigned feats, lstcon_rpc_t **crpc)
{
srpc_mksn_reqst_t *msrq;
srpc_rmsn_reqst_t *rsrq;
switch (transop) {
case LST_TRANS_SESNEW:
- rc = lstcon_rpc_prep(nd, SRPC_SERVICE_MAKE_SESSION, 0, crpc);
+ rc = lstcon_rpc_prep(nd, SRPC_SERVICE_MAKE_SESSION,
+ feats, 0, 0, crpc);
if (rc != 0)
return rc;
break;
case LST_TRANS_SESEND:
- rc = lstcon_rpc_prep(nd, SRPC_SERVICE_REMOVE_SESSION, 0, crpc);
+ rc = lstcon_rpc_prep(nd, SRPC_SERVICE_REMOVE_SESSION,
+ feats, 0, 0, crpc);
if (rc != 0)
return rc;
}
int
-lstcon_dbgrpc_prep(lstcon_node_t *nd, lstcon_rpc_t **crpc)
+lstcon_dbgrpc_prep(lstcon_node_t *nd, unsigned feats, lstcon_rpc_t **crpc)
{
- srpc_debug_reqst_t *drq;
- int rc;
+ srpc_debug_reqst_t *drq;
+ int rc;
- rc = lstcon_rpc_prep(nd, SRPC_SERVICE_DEBUG, 0, crpc);
+ rc = lstcon_rpc_prep(nd, SRPC_SERVICE_DEBUG, feats, 0, 0, crpc);
if (rc != 0)
return rc;
drq->dbg_sid = console_session.ses_id;
drq->dbg_flags = 0;
-
+
return rc;
}
int
-lstcon_batrpc_prep(lstcon_node_t *nd, int transop,
- lstcon_tsb_hdr_t *tsb, lstcon_rpc_t **crpc)
+lstcon_batrpc_prep(lstcon_node_t *nd, int transop, unsigned feats,
+ lstcon_tsb_hdr_t *tsb, lstcon_rpc_t **crpc)
{
- lstcon_batch_t *batch;
- srpc_batch_reqst_t *brq;
- int rc;
+ lstcon_batch_t *batch;
+ srpc_batch_reqst_t *brq;
+ int rc;
- rc = lstcon_rpc_prep(nd, SRPC_SERVICE_BATCH, 0, crpc);
+ rc = lstcon_rpc_prep(nd, SRPC_SERVICE_BATCH, feats, 0, 0, crpc);
if (rc != 0)
return rc;
batch = (lstcon_batch_t *)tsb;
brq->bar_arg = batch->bat_arg;
-
+
return 0;
}
int
-lstcon_statrpc_prep(lstcon_node_t *nd, lstcon_rpc_t **crpc)
+lstcon_statrpc_prep(lstcon_node_t *nd, unsigned feats, lstcon_rpc_t **crpc)
{
- srpc_stat_reqst_t *srq;
- int rc;
+ srpc_stat_reqst_t *srq;
+ int rc;
- rc = lstcon_rpc_prep(nd, SRPC_SERVICE_QUERY_STAT, 0, crpc);
+ rc = lstcon_rpc_prep(nd, SRPC_SERVICE_QUERY_STAT, feats, 0, 0, crpc);
if (rc != 0)
return rc;
lstcon_pingrpc_prep(lst_test_ping_param_t *param, srpc_test_reqst_t *req)
{
test_ping_req_t *prq = &req->tsr_u.ping;
-
+
prq->png_size = param->png_size;
prq->png_flags = param->png_flags;
/* TODO dest */
}
int
-lstcon_bulkrpc_prep(lst_test_bulk_param_t *param, srpc_test_reqst_t *req)
+lstcon_bulkrpc_v0_prep(lst_test_bulk_param_t *param, srpc_test_reqst_t *req)
{
- test_bulk_req_t *brq = &req->tsr_u.bulk;
+ test_bulk_req_t *brq = &req->tsr_u.bulk_v0;
brq->blk_opc = param->blk_opc;
brq->blk_npg = (param->blk_size + CFS_PAGE_SIZE - 1) / CFS_PAGE_SIZE;
}
int
-lstcon_testrpc_prep(lstcon_node_t *nd, int transop,
+lstcon_bulkrpc_v1_prep(lst_test_bulk_param_t *param, srpc_test_reqst_t *req)
+{
+ test_bulk_req_v1_t *brq = &req->tsr_u.bulk_v1;
+
+ brq->blk_opc = param->blk_opc;
+ brq->blk_flags = param->blk_flags;
+ brq->blk_len = param->blk_size;
+ brq->blk_offset = 0; /* reserved */
+
+ return 0;
+}
+
+int
+lstcon_testrpc_prep(lstcon_node_t *nd, int transop, unsigned feats,
lstcon_test_t *test, lstcon_rpc_t **crpc)
{
lstcon_group_t *sgrp = test->tes_src_grp;
srpc_test_reqst_t *trq;
srpc_bulk_t *bulk;
int i;
- int n = 0;
- int rc = 0;
-
- if (transop == LST_TRANS_TSBCLIADD)
- n = sfw_id_pages(test->tes_span);
-
- rc = lstcon_rpc_prep(nd, SRPC_SERVICE_TEST, n, crpc);
- if (rc != 0)
+ int npg = 0;
+ int nob = 0;
+ int rc = 0;
+
+ if (transop == LST_TRANS_TSBCLIADD) {
+ npg = sfw_id_pages(test->tes_span);
+ nob = (feats & LST_FEAT_BULK_LEN) == 0 ?
+ npg * CFS_PAGE_SIZE :
+ sizeof(lnet_process_id_packed_t) * test->tes_span;
+ }
+
+ rc = lstcon_rpc_prep(nd, SRPC_SERVICE_TEST, feats, npg, nob, crpc);
+ if (rc != 0)
return rc;
trq = &(*crpc)->crp_rpc->crpc_reqstmsg.msg_body.tes_reqst;
} else {
bulk = &(*crpc)->crp_rpc->crpc_bulk;
- for (i = 0; i < n; i++) {
- bulk->bk_iovs[i].kiov_offset = 0;
- bulk->bk_iovs[i].kiov_len = CFS_PAGE_SIZE;
- bulk->bk_iovs[i].kiov_page = cfs_alloc_page(CFS_ALLOC_STD);
+ for (i = 0; i < npg; i++) {
+ int len;
- if (bulk->bk_iovs[i].kiov_page != NULL)
- continue;
+ LASSERT(nob > 0);
- lstcon_rpc_put(*crpc);
- return -ENOMEM;
+ len = (feats & LST_FEAT_BULK_LEN) == 0 ?
+ CFS_PAGE_SIZE : min_t(int, nob, CFS_PAGE_SIZE);
+ nob -= len;
+
+ bulk->bk_iovs[i].kiov_offset = 0;
+ bulk->bk_iovs[i].kiov_len = len;
+ bulk->bk_iovs[i].kiov_page =
+ cfs_alloc_page(CFS_ALLOC_STD);
+
+ if (bulk->bk_iovs[i].kiov_page == NULL) {
+ lstcon_rpc_put(*crpc);
+ return -ENOMEM;
+ }
}
bulk->bk_sink = 0;
LASSERT (transop == LST_TRANS_TSBCLIADD);
rc = lstcon_dstnodes_prep(test->tes_dst_grp,
- test->tes_cliidx++, test->tes_dist,
- test->tes_span, n, &bulk->bk_iovs[0]);
+ test->tes_cliidx++,
+ test->tes_dist,
+ test->tes_span,
+ npg, &bulk->bk_iovs[0]);
if (rc != 0) {
lstcon_rpc_put(*crpc);
return rc;
switch (test->tes_type) {
case LST_TEST_PING:
trq->tsr_service = SRPC_SERVICE_PING;
- rc = lstcon_pingrpc_prep((lst_test_ping_param_t *)&test->tes_param[0], trq);
- break;
- case LST_TEST_BULK:
- trq->tsr_service = SRPC_SERVICE_BRW;
- rc = lstcon_bulkrpc_prep((lst_test_bulk_param_t *)&test->tes_param[0], trq);
+ rc = lstcon_pingrpc_prep((lst_test_ping_param_t *)
+ &test->tes_param[0], trq);
+ break;
+
+ case LST_TEST_BULK:
+ trq->tsr_service = SRPC_SERVICE_BRW;
+ if ((feats & LST_FEAT_BULK_LEN) == 0) {
+ rc = lstcon_bulkrpc_v0_prep((lst_test_bulk_param_t *)
+ &test->tes_param[0], trq);
+ } else {
+ rc = lstcon_bulkrpc_v1_prep((lst_test_bulk_param_t *)
+ &test->tes_param[0], trq);
+ }
+
break;
default:
LBUG();
return rc;
}
+int
+lstcon_sesnew_stat_reply(lstcon_rpc_trans_t *trans,
+ lstcon_node_t *nd, srpc_msg_t *reply)
+{
+ srpc_mksn_reply_t *mksn_rep = &reply->msg_body.mksn_reply;
+ int status = mksn_rep->mksn_status;
+
+ if (status == 0 &&
+ (reply->msg_ses_feats & ~LST_FEATS_MASK) != 0) {
+ mksn_rep->mksn_status = EPROTO;
+ status = EPROTO;
+ }
+
+ if (status == EPROTO) {
+ CNETERR("session protocol error from %s: %u\n",
+ libcfs_nid2str(nd->nd_id.nid),
+ reply->msg_ses_feats);
+ }
+
+ if (status != 0)
+ return status;
+
+ if (!trans->tas_feats_updated) {
+ trans->tas_feats_updated = 1;
+ trans->tas_features = reply->msg_ses_feats;
+ }
+
+ if (reply->msg_ses_feats != trans->tas_features) {
+ CNETERR("Framework features %x from %s is different with "
+ "features on this transaction: %x\n",
+ reply->msg_ses_feats, libcfs_nid2str(nd->nd_id.nid),
+ trans->tas_features);
+ status = mksn_rep->mksn_status = EPROTO;
+ }
+
+ if (status == 0) {
+ /* session timeout on remote node */
+ nd->nd_timeout = mksn_rep->mksn_timeout;
+ }
+
+ return status;
+}
+
void
-lstcon_rpc_stat_reply(int transop, srpc_msg_t *msg,
+lstcon_rpc_stat_reply(lstcon_rpc_trans_t *trans, srpc_msg_t *msg,
lstcon_node_t *nd, lstcon_trans_stat_t *stat)
{
- srpc_mksn_reply_t *mksn_rep;
srpc_rmsn_reply_t *rmsn_rep;
srpc_debug_reply_t *dbg_rep;
srpc_batch_reply_t *bat_rep;
srpc_stat_reply_t *stat_rep;
int rc = 0;
- switch (transop) {
- case LST_TRANS_SESNEW:
- mksn_rep = &msg->msg_body.mksn_reply;
-
- if (mksn_rep->mksn_status == 0) {
+ switch (trans->tas_opc) {
+ case LST_TRANS_SESNEW:
+ rc = lstcon_sesnew_stat_reply(trans, nd, msg);
+ if (rc == 0) {
lstcon_sesop_stat_success(stat, 1);
- /* session timeout on remote node */
- nd->nd_timeout = mksn_rep->mksn_timeout;
return;
}
- LASSERT (mksn_rep->mksn_status == EBUSY ||
- mksn_rep->mksn_status == EINVAL);
-
lstcon_sesop_stat_failure(stat, 1);
- rc = mksn_rep->mksn_status;
break;
case LST_TRANS_SESEND:
return;
}
- LASSERT (rmsn_rep->rmsn_status == EBUSY ||
- rmsn_rep->rmsn_status == EINVAL);
-
lstcon_sesop_stat_failure(stat, 1);
rc = rmsn_rep->rmsn_status;
break;
if (dbg_rep->dbg_status == ESRCH) {
lstcon_sesqry_stat_unknown(stat, 1);
return;
- }
-
- LASSERT (dbg_rep->dbg_status == 0);
+ }
if (lstcon_session_match(dbg_rep->dbg_sid))
lstcon_sesqry_stat_active(stat, 1);
}
if (bat_rep->bar_status == EPERM &&
- transop == LST_TRANS_TSBSTOP) {
+ trans->tas_opc == LST_TRANS_TSBSTOP) {
lstcon_tsbop_stat_success(stat, 1);
return;
}
lstcon_ndlink_t *ndl;
lstcon_node_t *nd;
lstcon_rpc_t *rpc;
+ unsigned feats;
int rc;
/* Creating session RPG for list of nodes */
return rc;
}
+ feats = trans->tas_features;
cfs_list_for_each_entry_typed(ndl, ndlist, lstcon_ndlink_t, ndl_link) {
rc = condition == NULL ? 1 :
condition(transop, ndl->ndl_node, arg);
switch (transop) {
case LST_TRANS_SESNEW:
case LST_TRANS_SESEND:
- rc = lstcon_sesrpc_prep(nd, transop, &rpc);
- break;
- case LST_TRANS_SESQRY:
- case LST_TRANS_SESPING:
- rc = lstcon_dbgrpc_prep(nd, &rpc);
- break;
- case LST_TRANS_TSBCLIADD:
- case LST_TRANS_TSBSRVADD:
- rc = lstcon_testrpc_prep(nd, transop,
- (lstcon_test_t *)arg, &rpc);
- break;
- case LST_TRANS_TSBRUN:
- case LST_TRANS_TSBSTOP:
- case LST_TRANS_TSBCLIQRY:
- case LST_TRANS_TSBSRVQRY:
- rc = lstcon_batrpc_prep(nd, transop,
- (lstcon_tsb_hdr_t *)arg, &rpc);
- break;
- case LST_TRANS_STATQRY:
- rc = lstcon_statrpc_prep(nd, &rpc);
+ rc = lstcon_sesrpc_prep(nd, transop, feats, &rpc);
+ break;
+ case LST_TRANS_SESQRY:
+ case LST_TRANS_SESPING:
+ rc = lstcon_dbgrpc_prep(nd, feats, &rpc);
+ break;
+ case LST_TRANS_TSBCLIADD:
+ case LST_TRANS_TSBSRVADD:
+ rc = lstcon_testrpc_prep(nd, transop, feats,
+ (lstcon_test_t *)arg, &rpc);
+ break;
+ case LST_TRANS_TSBRUN:
+ case LST_TRANS_TSBSTOP:
+ case LST_TRANS_TSBCLIQRY:
+ case LST_TRANS_TSBSRVQRY:
+ rc = lstcon_batrpc_prep(nd, transop, feats,
+ (lstcon_tsb_hdr_t *)arg, &rpc);
+ break;
+ case LST_TRANS_STATQRY:
+ rc = lstcon_statrpc_prep(nd, feats, &rpc);
break;
default:
rc = -EINVAL;
lstcon_rpc_trans_name(transop), rc);
break;
}
-
+
lstcon_rpc_trans_addreq(trans, rpc);
}
if (nd->nd_state != LST_NODE_ACTIVE)
continue;
- rc = lstcon_sesrpc_prep(nd, LST_TRANS_SESEND, &crpc);
+ rc = lstcon_sesrpc_prep(nd, LST_TRANS_SESEND,
+ trans->tas_features, &crpc);
if (rc != 0) {
CERROR("Out of memory\n");
break;
lstcon_rpc_get_reply(crpc, &rep);
cfs_list_del_init(&crpc->crp_link);
-
+
lstcon_rpc_put(crpc);
}
if (intv < (time_t)nd->nd_timeout / 2)
continue;
- rc = lstcon_rpc_init(nd, SRPC_SERVICE_DEBUG, 0, 0, crpc);
+ rc = lstcon_rpc_init(nd, SRPC_SERVICE_DEBUG,
+ trans->tas_features, 0, 0, 1, crpc);
if (rc != 0) {
CERROR("Out of memory\n");
break;
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright (c) 2012, Whamcloud Inc.
*/
/*
* This file is part of Lustre, http://www.lustre.org/
*
* Console rpc
*
- * Author: Liang Zhen <liangzhen@clusterfs.com>
+ * Author: Liang Zhen <liang@whamcloud.com>
*/
#ifndef __LST_CONRPC_H__
int crp_posted:1; /* rpc is posted */
int crp_finished:1; /* rpc is finished */
int crp_unpacked:1; /* reply is unpacked */
- int crp_static:1; /* not from RPC buffer */
+ /** RPC is embedded in other structure and can't free it */
+ int crp_embedded:1;
int crp_status; /* console rpc errors */
cfs_time_t crp_stamp; /* replied time stamp */
} lstcon_rpc_t;
cfs_list_t tas_olink; /* link chain on owner list */
cfs_list_t tas_link; /* link chain on global list */
int tas_opc; /* operation code of transaction */
+ /* features mask is uptodate */
+ unsigned tas_feats_updated;
+ /* test features mask */
+ unsigned tas_features;
cfs_waitq_t tas_waitq; /* wait queue head */
cfs_atomic_t tas_remaining; /* # of un-scheduled rpcs */
cfs_list_t tas_rpcs_list; /* queued requests */
typedef int (* lstcon_rpc_cond_func_t)(int, struct lstcon_node *, void *);
typedef int (* lstcon_rpc_readent_func_t)(int, srpc_msg_t *, lstcon_rpc_ent_t *);
-int lstcon_sesrpc_prep(struct lstcon_node *nd,
- int transop, lstcon_rpc_t **crpc);
-int lstcon_dbgrpc_prep(struct lstcon_node *nd, lstcon_rpc_t **crpc);
-int lstcon_batrpc_prep(struct lstcon_node *nd, int transop,
+int lstcon_sesrpc_prep(struct lstcon_node *nd, int transop,
+ unsigned version, lstcon_rpc_t **crpc);
+int lstcon_dbgrpc_prep(struct lstcon_node *nd,
+ unsigned version, lstcon_rpc_t **crpc);
+int lstcon_batrpc_prep(struct lstcon_node *nd, int transop, unsigned version,
struct lstcon_tsb_hdr *tsb, lstcon_rpc_t **crpc);
-int lstcon_testrpc_prep(struct lstcon_node *nd, int transop,
+int lstcon_testrpc_prep(struct lstcon_node *nd, int transop, unsigned version,
struct lstcon_test *test, lstcon_rpc_t **crpc);
-int lstcon_statrpc_prep(struct lstcon_node *nd, lstcon_rpc_t **crpc);
+int lstcon_statrpc_prep(struct lstcon_node *nd, unsigned version,
+ lstcon_rpc_t **crpc);
void lstcon_rpc_put(lstcon_rpc_t *crpc);
int lstcon_rpc_trans_prep(cfs_list_t *translist,
int transop, lstcon_rpc_trans_t **transpp);
}
static int
-lstcon_group_nodes_add(lstcon_group_t *grp, int count,
- lnet_process_id_t *ids_up,
- cfs_list_t *result_up)
+lstcon_group_nodes_add(lstcon_group_t *grp,
+ int count, lnet_process_id_t *ids_up,
+ unsigned *featp, cfs_list_t *result_up)
{
lstcon_rpc_trans_t *trans;
lstcon_ndlink_t *ndl;
rc = lstcon_rpc_trans_interpreter(trans, result_up,
lstcon_sesrpc_readent);
+ *featp = trans->tas_features;
+
/* destroy all RPGs */
lstcon_rpc_trans_destroy(trans);
}
int
-lstcon_nodes_add(char *name, int count,
- lnet_process_id_t *ids_up, cfs_list_t *result_up)
+lstcon_nodes_add(char *name, int count, lnet_process_id_t *ids_up,
+ unsigned *featp, cfs_list_t *result_up)
{
lstcon_group_t *grp;
int rc;
return -EBUSY;
}
- rc = lstcon_group_nodes_add(grp, count, ids_up, result_up);
+ rc = lstcon_group_nodes_add(grp, count, ids_up, featp, result_up);
lstcon_group_put(grp);
CDEBUG(D_NET, "Can't change running batch %s\n", name);
return rc;
}
-
+
rc = lstcon_group_find(src_name, &src_grp);
if (rc != 0) {
CDEBUG(D_NET, "Can't find group %s\n", src_name);
extern srpc_service_t lstcon_acceptor_service;
int
-lstcon_session_new(char *name, int key,
- int timeout,int force, lst_sid_t *sid_up)
+lstcon_session_new(char *name, int key, unsigned feats,
+ int timeout, int force, lst_sid_t *sid_up)
{
int rc = 0;
int i;
if (console_session.ses_state != LST_SESSION_NONE) {
/* session exists */
if (!force) {
- CERROR("Session %s already exists\n",
- console_session.ses_name);
+ CNETERR("Session %s already exists\n",
+ console_session.ses_name);
return -EEXIST;
}
return rc;
}
- for (i = 0; i < LST_GLOBAL_HASHSIZE; i++) {
- LASSERT (cfs_list_empty(&console_session.ses_ndl_hash[i]));
- }
+ if ((feats & ~LST_FEATS_MASK) != 0) {
+ CNETERR("Unknown session features %x\n",
+ (feats & ~LST_FEATS_MASK));
+ return -EINVAL;
+ }
+
+ for (i = 0; i < LST_GLOBAL_HASHSIZE; i++)
+ LASSERT(cfs_list_empty(&console_session.ses_ndl_hash[i]));
+
+ lstcon_new_session_id(&console_session.ses_id);
+
+ console_session.ses_key = key;
+ console_session.ses_state = LST_SESSION_ACTIVE;
+ console_session.ses_force = !!force;
+ console_session.ses_features = feats;
+ console_session.ses_feats_updated = 0;
+ console_session.ses_timeout = (timeout <= 0) ?
+ LST_CONSOLE_TIMEOUT : timeout;
+ strcpy(console_session.ses_name, name);
rc = lstcon_batch_add(LST_DEFAULT_BATCH);
if (rc != 0)
return rc;
}
- lstcon_new_session_id(&console_session.ses_id);
-
- console_session.ses_key = key;
- console_session.ses_state = LST_SESSION_ACTIVE;
- console_session.ses_force = !!force;
- console_session.ses_timeout = (timeout <= 0)? LST_CONSOLE_TIMEOUT:
- timeout;
- strcpy(console_session.ses_name, name);
-
if (cfs_copy_to_user(sid_up, &console_session.ses_id,
sizeof(lst_sid_t)) == 0)
return rc;
}
int
-lstcon_session_info(lst_sid_t *sid_up, int *key_up,
+lstcon_session_info(lst_sid_t *sid_up, int *key_up, unsigned *featp,
lstcon_ndlist_ent_t *ndinfo_up, char *name_up, int len)
{
lstcon_ndlist_ent_t *entp;
if (cfs_copy_to_user(sid_up, &console_session.ses_id,
sizeof(lst_sid_t)) ||
- cfs_copy_to_user(key_up, &console_session.ses_key, sizeof(int)) ||
+ cfs_copy_to_user(key_up, &console_session.ses_key,
+ sizeof(*key_up)) ||
+ cfs_copy_to_user(featp, &console_session.ses_features,
+ sizeof(*featp)) ||
cfs_copy_to_user(ndinfo_up, entp, sizeof(*entp)) ||
cfs_copy_to_user(name_up, console_session.ses_name, len))
rc = -EFAULT;
console_session.ses_state = LST_SESSION_NONE;
console_session.ses_key = 0;
console_session.ses_force = 0;
+ console_session.ses_feats_updated = 0;
/* destroy all batches */
while (!cfs_list_empty(&console_session.ses_bat_list)) {
return rc;
}
+int
+lstcon_session_feats_check(unsigned feats)
+{
+ int rc = 0;
+
+ if ((feats & ~LST_FEATS_MASK) != 0) {
+ CERROR("Can't support these features: %x\n",
+ (feats & ~LST_FEATS_MASK));
+ return -EPROTO;
+ }
+
+ cfs_spin_lock(&console_session.ses_rpc_lock);
+
+ if (!console_session.ses_feats_updated) {
+ console_session.ses_feats_updated = 1;
+ console_session.ses_features = feats;
+ }
+
+ if (console_session.ses_features != feats)
+ rc = -EPROTO;
+
+ cfs_spin_unlock(&console_session.ses_rpc_lock);
+
+ if (rc != 0) {
+ CERROR("remote features %x do not match with "
+ "session features %x of console\n",
+ feats, console_session.ses_features);
+ }
+
+ return rc;
+}
+
static int
lstcon_acceptor_handle (srpc_server_rpc_t *rpc)
{
goto out;
}
+ if (lstcon_session_feats_check(req->msg_ses_feats) != 0) {
+ jrep->join_status = EPROTO;
+ goto out;
+ }
+
if (jreq->join_sid.ses_nid != LNET_NID_ANY &&
!lstcon_session_match(jreq->join_sid)) {
jrep->join_status = EBUSY;
jrep->join_status = 0;
out:
+ rep->msg_ses_feats = console_session.ses_features;
if (grp != NULL)
lstcon_group_put(grp);
memset(&console_session, 0, sizeof(lstcon_session_t));
- console_session.ses_id = LST_INVALID_SID;
- console_session.ses_state = LST_SESSION_NONE;
- console_session.ses_timeout = 0;
- console_session.ses_force = 0;
- console_session.ses_expired = 0;
- console_session.ses_laststamp = cfs_time_current_sec();
+ console_session.ses_id = LST_INVALID_SID;
+ console_session.ses_state = LST_SESSION_NONE;
+ console_session.ses_timeout = 0;
+ console_session.ses_force = 0;
+ console_session.ses_expired = 0;
+ console_session.ses_feats_updated = 0;
+ console_session.ses_features = LST_FEATS_MASK;
+ console_session.ses_laststamp = cfs_time_current_sec();
cfs_mutex_init(&console_session.ses_mutex);
int ses_state; /* state of session */
int ses_timeout; /* timeout in seconds */
time_t ses_laststamp; /* last operation stamp (seconds) */
- int ses_force:1; /* force creating */
- int ses_shutdown:1; /* session is shutting down */
- int ses_expired:1; /* console is timedout */
+ /** tests features of the session */
+ unsigned ses_features;
+ /** features are synced with remote test nodes */
+ unsigned ses_feats_updated:1;
+ /** force creating */
+ unsigned ses_force:1;
+ /** session is shutting down */
+ unsigned ses_shutdown:1;
+ /** console is timedout */
+ unsigned ses_expired:1;
__u64 ses_id_cookie; /* batch id cookie */
char ses_name[LST_NAME_SIZE]; /* session name */
lstcon_rpc_trans_t *ses_ping; /* session pinger */
} lstcon_session_t; /*** session descriptor */
extern lstcon_session_t console_session;
+
static inline lstcon_trans_stat_t *
lstcon_trans_stat(void)
{
}
extern int lstcon_session_match(lst_sid_t sid);
-extern int lstcon_session_new(char *name, int key,
+extern int lstcon_session_new(char *name, int key, unsigned version,
int timeout, int flags, lst_sid_t *sid_up);
-extern int lstcon_session_info(lst_sid_t *sid_up, int *key,
+extern int lstcon_session_info(lst_sid_t *sid_up, int *key, unsigned *verp,
lstcon_ndlist_ent_t *entp, char *name_up, int len);
extern int lstcon_session_end(void);
extern int lstcon_session_debug(int timeout, cfs_list_t *result_up);
-extern int lstcon_batch_debug(int timeout, char *name,
+extern int lstcon_session_feats_check(unsigned feats);
+extern int lstcon_batch_debug(int timeout, char *name,
int client, cfs_list_t *result_up);
extern int lstcon_group_debug(int timeout, char *name,
cfs_list_t *result_up);
extern int lstcon_group_clean(char *name, int args);
extern int lstcon_group_refresh(char *name, cfs_list_t *result_up);
extern int lstcon_nodes_add(char *name, int nnd, lnet_process_id_t *nds_up,
- cfs_list_t *result_up);
+ unsigned *featp, cfs_list_t *result_up);
extern int lstcon_nodes_remove(char *name, int nnd, lnet_process_id_t *nds_up,
cfs_list_t *result_up);
extern int lstcon_group_info(char *name, lstcon_ndlist_ent_t *gent_up,
}
static inline void
-sfw_init_session (sfw_session_t *sn, lst_sid_t sid, const char *name)
+sfw_init_session(sfw_session_t *sn, lst_sid_t sid,
+ unsigned features, const char *name)
{
stt_timer_t *timer = &sn->sn_timer;
sn->sn_timer_active = 0;
sn->sn_id = sid;
+ sn->sn_features = features;
sn->sn_timeout = session_timeout;
sn->sn_started = cfs_time_current();
}
int
-sfw_make_session (srpc_mksn_reqst_t *request, srpc_mksn_reply_t *reply)
+sfw_make_session(srpc_mksn_reqst_t *request, srpc_mksn_reply_t *reply)
{
- sfw_session_t *sn = sfw_data.fw_session;
+ sfw_session_t *sn = sfw_data.fw_session;
+ srpc_msg_t *msg = container_of(request, srpc_msg_t,
+ msg_body.mksn_reqst);
if (request->mksn_sid.ses_nid == LNET_NID_ANY) {
reply->mksn_sid = (sn == NULL) ? LST_INVALID_SID : sn->sn_id;
}
}
+ /* reject the request if it requires unknown features
+ * NB: old version will always accept all features because it's not
+ * aware of srpc_msg_t::msg_ses_feats, it's a defect but it's also
+ * harmless because it will return zero feature to console, and it's
+ * console's responsibility to make sure all nodes in a session have
+ * same feature mask. */
+ if ((msg->msg_ses_feats & ~LST_FEATS_MASK) != 0) {
+ reply->mksn_status = EPROTO;
+ return 0;
+ }
+
/* brand new or create by force */
LIBCFS_ALLOC(sn, sizeof(sfw_session_t));
if (sn == NULL) {
return -ENOMEM;
}
- sfw_init_session(sn, request->mksn_sid, &request->mksn_name[0]);
+ sfw_init_session(sn, request->mksn_sid,
+ msg->msg_ses_feats, &request->mksn_name[0]);
cfs_spin_lock(&sfw_data.fw_lock);
}
void
-sfw_unpack_test_req (srpc_msg_t *msg)
+sfw_unpack_addtest_req(srpc_msg_t *msg)
{
srpc_test_reqst_t *req = &msg->msg_body.tes_reqst;
LASSERT (msg->msg_magic == __swab32(SRPC_MSG_MAGIC));
- if (req->tsr_service == SRPC_SERVICE_BRW) {
- test_bulk_req_t *bulk = &req->tsr_u.bulk;
+ if (req->tsr_service == SRPC_SERVICE_BRW) {
+ if ((msg->msg_ses_feats & LST_FEAT_BULK_LEN) == 0) {
+ test_bulk_req_t *bulk = &req->tsr_u.bulk_v0;
- __swab32s(&bulk->blk_opc);
- __swab32s(&bulk->blk_npg);
- __swab32s(&bulk->blk_flags);
- return;
- }
+ __swab32s(&bulk->blk_opc);
+ __swab32s(&bulk->blk_npg);
+ __swab32s(&bulk->blk_flags);
+
+ } else {
+ test_bulk_req_v1_t *bulk = &req->tsr_u.bulk_v1;
+
+ __swab16s(&bulk->blk_opc);
+ __swab16s(&bulk->blk_flags);
+ __swab32s(&bulk->blk_offset);
+ __swab32s(&bulk->blk_len);
+ }
+
+ return;
+ }
if (req->tsr_service == SRPC_SERVICE_PING) {
test_ping_req_t *ping = &req->tsr_u.ping;
LASSERT (bk->bk_pages != NULL);
#endif
LASSERT (bk->bk_niov * SFW_ID_PER_PAGE >= (unsigned int)ndest);
- LASSERT ((unsigned int)bk->bk_len >= sizeof(lnet_process_id_t) * ndest);
+ LASSERT((unsigned int)bk->bk_len >=
+ sizeof(lnet_process_id_packed_t) * ndest);
- sfw_unpack_test_req(msg);
+ sfw_unpack_addtest_req(msg);
memcpy(&tsi->tsi_u, &req->tsr_u, sizeof(tsi->tsi_u));
for (i = 0; i < ndest; i++) {
int done = 0;
tsi->tsi_ops->tso_done_rpc(tsu, rpc);
-
+
cfs_spin_lock(&tsi->tsi_lock);
LASSERT (sfw_test_active(tsi));
}
int
-sfw_create_test_rpc (sfw_test_unit_t *tsu, lnet_process_id_t peer,
- int nblk, int blklen, srpc_client_rpc_t **rpcpp)
+sfw_create_test_rpc(sfw_test_unit_t *tsu, lnet_process_id_t peer,
+ unsigned features, int nblk, int blklen,
+ srpc_client_rpc_t **rpcpp)
{
srpc_client_rpc_t *rpc = NULL;
sfw_test_instance_t *tsi = tsu->tsu_instance;
sfw_test_rpc_fini, tsu);
}
- if (rpc == NULL) {
- CERROR ("Can't create rpc for test %d\n", tsi->tsi_service);
- return -ENOMEM;
- }
+ if (rpc == NULL) {
+ CERROR("Can't create rpc for test %d\n", tsi->tsi_service);
+ return -ENOMEM;
+ }
- *rpcpp = rpc;
- return 0;
+ rpc->crpc_reqstmsg.msg_ses_feats = features;
+ *rpcpp = rpc;
+
+ return 0;
}
int
}
int
-sfw_alloc_pages(struct srpc_server_rpc *rpc, int cpt, int npages, int sink)
+sfw_alloc_pages(struct srpc_server_rpc *rpc, int cpt, int npages, int len,
+ int sink)
{
LASSERT(rpc->srpc_bulk == NULL);
LASSERT(npages > 0 && npages <= LNET_MAX_IOV);
- rpc->srpc_bulk = srpc_alloc_bulk(cpt, npages, sink);
+ rpc->srpc_bulk = srpc_alloc_bulk(cpt, npages, len, sink);
if (rpc->srpc_bulk == NULL)
return -ENOMEM;
if (request->tsr_is_client && rpc->srpc_bulk == NULL) {
/* rpc will be resumed later in sfw_bulk_ready */
- return sfw_alloc_pages(rpc, CFS_CPT_ANY,
- sfw_id_pages(request->tsr_ndest), 1);
+ int npg = sfw_id_pages(request->tsr_ndest);
+ int len;
+
+ if ((sn->sn_features & LST_FEAT_BULK_LEN) == 0) {
+ len = npg * CFS_PAGE_SIZE;
+
+ } else {
+ len = sizeof(lnet_process_id_packed_t) *
+ request->tsr_ndest;
+ }
+
+ return sfw_alloc_pages(rpc, CFS_CPT_ANY, npg, len, 1);
}
rc = sfw_add_test_instance(bat, rpc);
sfw_handle_server_rpc(struct srpc_server_rpc *rpc)
{
struct srpc_service *sv = rpc->srpc_scd->scd_svc;
- srpc_msg_t *reply = &rpc->srpc_replymsg;
- srpc_msg_t *request = &rpc->srpc_reqstbuf->buf_msg;
- int rc = 0;
+ srpc_msg_t *reply = &rpc->srpc_replymsg;
+ srpc_msg_t *request = &rpc->srpc_reqstbuf->buf_msg;
+ unsigned features = LST_FEATS_MASK;
+ int rc = 0;
LASSERT (sfw_data.fw_active_srpc == NULL);
LASSERT (sv->sv_id <= SRPC_FRAMEWORK_SERVICE_MAX_ID);
sfw_unpack_message(request);
LASSERT (request->msg_type == srpc_service2request(sv->sv_id));
+ /* rpc module should have checked this */
+ LASSERT(request->msg_version == SRPC_MSG_VERSION);
+
+ if (sv->sv_id != SRPC_SERVICE_MAKE_SESSION &&
+ sv->sv_id != SRPC_SERVICE_DEBUG) {
+ sfw_session_t *sn = sfw_data.fw_session;
+
+ if (sn != NULL &&
+ sn->sn_features != request->msg_ses_feats) {
+ CNETERR("Features of framework RPC don't match "
+ "features of current session: %x/%x\n",
+ request->msg_ses_feats, sn->sn_features);
+ reply->msg_body.reply.status = EPROTO;
+ reply->msg_body.reply.sid = sn->sn_id;
+ goto out;
+ }
+
+ } else if ((request->msg_ses_feats & ~LST_FEATS_MASK) != 0) {
+ /* NB: at this point, old version will ignore features and
+ * create new session anyway, so console should be able
+ * to handle this */
+ reply->msg_body.reply.status = EPROTO;
+ goto out;
+ }
+
switch(sv->sv_id) {
default:
LBUG ();
break;
}
+ if (sfw_data.fw_session != NULL)
+ features = sfw_data.fw_session->sn_features;
+ out:
+ reply->msg_ses_feats = features;
rpc->srpc_done = sfw_server_rpc_done;
cfs_spin_lock(&sfw_data.fw_lock);
}
srpc_client_rpc_t *
-sfw_create_rpc (lnet_process_id_t peer, int service,
- int nbulkiov, int bulklen,
- void (*done) (srpc_client_rpc_t *), void *priv)
+sfw_create_rpc(lnet_process_id_t peer, int service,
+ unsigned features, int nbulkiov, int bulklen,
+ void (*done)(srpc_client_rpc_t *), void *priv)
{
- srpc_client_rpc_t *rpc;
+ srpc_client_rpc_t *rpc = NULL;
cfs_spin_lock(&sfw_data.fw_lock);
rpc = cfs_list_entry(sfw_data.fw_zombie_rpcs.next,
srpc_client_rpc_t, crpc_list);
cfs_list_del(&rpc->crpc_list);
- cfs_spin_unlock(&sfw_data.fw_lock);
srpc_init_client_rpc(rpc, peer, service, 0, 0,
done, sfw_client_rpc_fini, priv);
- return rpc;
}
cfs_spin_unlock(&sfw_data.fw_lock);
- rpc = srpc_create_client_rpc(peer, service, nbulkiov, bulklen, done,
- nbulkiov != 0 ? NULL : sfw_client_rpc_fini,
- priv);
- return rpc;
+ if (rpc == NULL) {
+ rpc = srpc_create_client_rpc(peer, service,
+ nbulkiov, bulklen, done,
+ nbulkiov != 0 ? NULL :
+ sfw_client_rpc_fini,
+ priv);
+ }
+
+ if (rpc != NULL) /* "session" is concept in framework */
+ rpc->crpc_reqstmsg.msg_ses_feats = features;
+
+ return rpc;
}
void
if (msg->msg_magic == SRPC_MSG_MAGIC)
return; /* no flipping needed */
+ /* srpc module should guarantee I wouldn't get crap */
LASSERT (msg->msg_magic == __swab32(SRPC_MSG_MAGIC));
- __swab32s(&msg->msg_type);
-
if (msg->msg_type == SRPC_MSG_STAT_REQST) {
srpc_stat_reqst_t *req = &msg->msg_body.stat_reqst;
static int
ping_client_init(sfw_test_instance_t *tsi)
{
- LASSERT (tsi->tsi_is_client);
+ sfw_session_t *sn = tsi->tsi_batch->bat_session;
+
+ LASSERT(tsi->tsi_is_client);
+ LASSERT(sn != NULL && (sn->sn_features & ~LST_FEATS_MASK) == 0);
cfs_spin_lock_init(&lst_ping_data.pnd_lock);
lst_ping_data.pnd_counter = 0;
static int
ping_client_prep_rpc(sfw_test_unit_t *tsu,
- lnet_process_id_t dest, srpc_client_rpc_t **rpc)
+ lnet_process_id_t dest, srpc_client_rpc_t **rpc)
{
- srpc_ping_reqst_t *req;
- struct timeval tv;
- int rc;
+ srpc_ping_reqst_t *req;
+ sfw_test_instance_t *tsi = tsu->tsu_instance;
+ sfw_session_t *sn = tsi->tsi_batch->bat_session;
+ struct timeval tv;
+ int rc;
- rc = sfw_create_test_rpc(tsu, dest, 0, 0, rpc);
+ LASSERT(sn != NULL);
+ LASSERT((sn->sn_features & ~LST_FEATS_MASK) == 0);
+
+ rc = sfw_create_test_rpc(tsu, dest, sn->sn_features, 0, 0, rpc);
if (rc != 0)
return rc;
libcfs_id2str(rpc->crpc_dest),
reqst->pnr_seq, rpc->crpc_status);
return;
- }
+ }
if (rpc->crpc_replymsg.msg_magic != SRPC_MSG_MAGIC) {
__swab32s(&reply->pnr_seq);
__swab32s(&reply->pnr_magic);
__swab32s(&reply->pnr_status);
}
-
+
if (reply->pnr_magic != LST_PING_TEST_MAGIC) {
rpc->crpc_status = -EBADMSG;
cfs_atomic_inc(&sn->sn_ping_errors);
reply->pnr_magic, libcfs_id2str(rpc->crpc_dest),
LST_PING_TEST_MAGIC);
return;
- }
-
+ }
+
if (reply->pnr_seq != reqst->pnr_seq) {
rpc->crpc_status = -EBADMSG;
cfs_atomic_inc(&sn->sn_ping_errors);
{
struct srpc_service *sv = rpc->srpc_scd->scd_svc;
srpc_msg_t *reqstmsg = &rpc->srpc_reqstbuf->buf_msg;
+ srpc_msg_t *replymsg = &rpc->srpc_replymsg;
srpc_ping_reqst_t *req = &reqstmsg->msg_body.ping_reqst;
srpc_ping_reply_t *rep = &rpc->srpc_replymsg.msg_body.ping_reply;
if (reqstmsg->msg_magic != SRPC_MSG_MAGIC) {
LASSERT (reqstmsg->msg_magic == __swab32(SRPC_MSG_MAGIC));
- __swab32s(&reqstmsg->msg_type);
__swab32s(&req->pnr_seq);
__swab32s(&req->pnr_magic);
__swab64s(&req->pnr_time_sec);
rep->pnr_seq = req->pnr_seq;
rep->pnr_magic = LST_PING_TEST_MAGIC;
- CDEBUG (D_NET, "Get ping %d from %s\n",
- req->pnr_seq, libcfs_id2str(rpc->srpc_peer));
- return 0;
+ if ((reqstmsg->msg_ses_feats & ~LST_FEATS_MASK) != 0) {
+ replymsg->msg_ses_feats = LST_FEATS_MASK;
+ rep->pnr_status = EPROTO;
+ return 0;
+ }
+
+ replymsg->msg_ses_feats = reqstmsg->msg_ses_feats;
+
+ CDEBUG(D_NET, "Get ping %d from %s\n",
+ req->pnr_seq, libcfs_id2str(rpc->srpc_peer));
+ return 0;
}
sfw_test_client_ops_t ping_test_client;
cfs_spin_unlock(&srpc_data.rpc_glock);
}
-void
-srpc_add_bulk_page (srpc_bulk_t *bk, cfs_page_t *pg, int i)
+int
+srpc_add_bulk_page(srpc_bulk_t *bk, cfs_page_t *pg, int i, int nob)
{
- LASSERT (i >= 0 && i < bk->bk_niov);
+ nob = min(nob, (int)CFS_PAGE_SIZE);
+
+ LASSERT(nob > 0);
+ LASSERT(i >= 0 && i < bk->bk_niov);
#ifdef __KERNEL__
- bk->bk_iovs[i].kiov_offset = 0;
- bk->bk_iovs[i].kiov_page = pg;
- bk->bk_iovs[i].kiov_len = CFS_PAGE_SIZE;
+ bk->bk_iovs[i].kiov_offset = 0;
+ bk->bk_iovs[i].kiov_page = pg;
+ bk->bk_iovs[i].kiov_len = nob;
#else
- LASSERT (bk->bk_pages != NULL);
+ LASSERT(bk->bk_pages != NULL);
- bk->bk_pages[i] = pg;
- bk->bk_iovs[i].iov_len = CFS_PAGE_SIZE;
- bk->bk_iovs[i].iov_base = cfs_page_address(pg);
+ bk->bk_pages[i] = pg;
+ bk->bk_iovs[i].iov_len = nob;
+ bk->bk_iovs[i].iov_base = cfs_page_address(pg);
#endif
- return;
+ return nob;
}
void
}
srpc_bulk_t *
-srpc_alloc_bulk(int cpt, int npages, int sink)
+srpc_alloc_bulk(int cpt, unsigned bulk_npg, unsigned bulk_len, int sink)
{
- srpc_bulk_t *bk;
- cfs_page_t **pages;
- int i;
+ srpc_bulk_t *bk;
+ cfs_page_t **pages;
+ int i;
- LASSERT (npages > 0 && npages <= LNET_MAX_IOV);
+ LASSERT(bulk_npg > 0 && bulk_npg <= LNET_MAX_IOV);
LIBCFS_CPT_ALLOC(bk, lnet_cpt_table(), cpt,
- offsetof(srpc_bulk_t, bk_iovs[npages]));
- if (bk == NULL) {
- CERROR ("Can't allocate descriptor for %d pages\n", npages);
- return NULL;
- }
+ offsetof(srpc_bulk_t, bk_iovs[bulk_npg]));
+ if (bk == NULL) {
+ CERROR("Can't allocate descriptor for %d pages\n", bulk_npg);
+ return NULL;
+ }
- memset(bk, 0, offsetof(srpc_bulk_t, bk_iovs[npages]));
- bk->bk_sink = sink;
- bk->bk_niov = npages;
- bk->bk_len = npages * CFS_PAGE_SIZE;
+ memset(bk, 0, offsetof(srpc_bulk_t, bk_iovs[bulk_npg]));
+ bk->bk_sink = sink;
+ bk->bk_len = bulk_len;
+ bk->bk_niov = bulk_npg;
#ifndef __KERNEL__
LIBCFS_CPT_ALLOC(pages, lnet_cpt_table(), cpt,
- sizeof(cfs_page_t *) * npages);
- if (pages == NULL) {
- LIBCFS_FREE(bk, offsetof(srpc_bulk_t, bk_iovs[npages]));
- CERROR ("Can't allocate page array for %d pages\n", npages);
- return NULL;
- }
+ sizeof(cfs_page_t *) * bulk_npg);
+ if (pages == NULL) {
+ LIBCFS_FREE(bk, offsetof(srpc_bulk_t, bk_iovs[bulk_npg]));
+ CERROR("Can't allocate page array for %d pages\n", bulk_npg);
+ return NULL;
+ }
- memset(pages, 0, sizeof(cfs_page_t *) * npages);
- bk->bk_pages = pages;
+ memset(pages, 0, sizeof(cfs_page_t *) * bulk_npg);
+ bk->bk_pages = pages;
#else
- UNUSED (pages);
+ UNUSED(pages);
#endif
- for (i = 0; i < npages; i++) {
+ for (i = 0; i < bulk_npg; i++) {
cfs_page_t *pg;
+ int nob;
pg = cfs_page_cpt_alloc(lnet_cpt_table(), cpt, CFS_ALLOC_STD);
- if (pg == NULL) {
- CERROR ("Can't allocate page %d of %d\n", i, npages);
- srpc_free_bulk(bk);
- return NULL;
- }
+ if (pg == NULL) {
+ CERROR("Can't allocate page %d of %d\n", i, bulk_npg);
+ srpc_free_bulk(bk);
+ return NULL;
+ }
- srpc_add_bulk_page(bk, pg, i);
- }
+ nob = srpc_add_bulk_page(bk, pg, i, bulk_len);
+ bulk_len -= nob;
+ }
- return bk;
+ return bk;
}
static inline __u64
if (msg->msg_magic == 0) {
/* moaned already in srpc_lnet_ev_handler */
- rc = EBADMSG;
- } else if (msg->msg_version != SRPC_MSG_VERSION &&
- msg->msg_version != __swab32(SRPC_MSG_VERSION)) {
- CWARN ("Version mismatch: %u, %u expected, from %s\n",
- msg->msg_version, SRPC_MSG_VERSION,
- libcfs_id2str(rpc->srpc_peer));
- reply->status = EPROTO;
- } else {
- reply->status = 0;
- rc = (*sv->sv_handler) (rpc);
- LASSERT (reply->status == 0 || !rpc->srpc_bulk);
- }
+ srpc_server_rpc_done(rpc, EBADMSG);
+ return 1;
+ }
- if (rc != 0) {
- srpc_server_rpc_done(rpc, rc);
- return 1;
+ srpc_unpack_msg_hdr(msg);
+ if (msg->msg_version != SRPC_MSG_VERSION) {
+ CWARN("Version mismatch: %u, %u expected, from %s\n",
+ msg->msg_version, SRPC_MSG_VERSION,
+ libcfs_id2str(rpc->srpc_peer));
+ reply->status = EPROTO;
+ /* drop through and send reply */
+ } else {
+ reply->status = 0;
+ rc = (*sv->sv_handler)(rpc);
+ LASSERT(reply->status == 0 || !rpc->srpc_bulk);
+ if (rc != 0) {
+ srpc_server_rpc_done(rpc, rc);
+ return 1;
+ }
}
wi->swi_state = SWI_STATE_BULK_STARTED;
rc = rpc->crpc_replyev.ev_status;
if (rc != 0) break;
- if ((reply->msg_type != type &&
- reply->msg_type != __swab32(type)) ||
- (reply->msg_magic != SRPC_MSG_MAGIC &&
- reply->msg_magic != __swab32(SRPC_MSG_MAGIC))) {
+ srpc_unpack_msg_hdr(reply);
+ if (reply->msg_type != type ||
+ reply->msg_magic != SRPC_MSG_MAGIC) {
CWARN ("Bad message from %s: type %u (%d expected),"
" magic %u (%d expected).\n",
libcfs_id2str(rpc->crpc_dest),
{
LASSERT (!rpc->crpc_aborted);
LASSERT (srpc_data.rpc_state == SRPC_STATE_RUNNING);
- LASSERT ((rpc->crpc_bulk.bk_len & ~CFS_PAGE_MASK) == 0);
CDEBUG (D_NET, "Posting RPC: peer %s, service %d, timeout %d\n",
libcfs_id2str(rpc->crpc_dest), rpc->crpc_service,
} WIRE_ATTR test_bulk_req_t;
typedef struct {
- __u32 png_size; /* size of ping message */
- __u32 png_flags; /* reserved flags */
+ /** bulk operation code */
+ __u16 blk_opc;
+ /** data check flags */
+ __u16 blk_flags;
+ /** data length */
+ __u32 blk_len;
+ /** reserved: offset */
+ __u32 blk_offset;
+} WIRE_ATTR test_bulk_req_v1_t;
+
+typedef struct {
+ __u32 png_size; /* size of ping message */
+ __u32 png_flags; /* reserved flags */
} WIRE_ATTR test_ping_req_t;
typedef struct {
- __u64 tsr_rpyid; /* reply buffer matchbits */
- __u64 tsr_bulkid; /* bulk buffer matchbits */
- lst_sid_t tsr_sid; /* session id */
- lst_bid_t tsr_bid; /* batch id */
- __u32 tsr_service; /* test type: bulk|ping|... */
- /* test client loop count or # server buffers needed */
- __u32 tsr_loop;
- __u32 tsr_concur; /* concurrency of test */
- __u8 tsr_is_client; /* is test client or not */
- __u8 tsr_stop_onerr; /* stop on error */
- __u32 tsr_ndest; /* # of dest nodes */
+ __u64 tsr_rpyid; /* reply buffer matchbits */
+ __u64 tsr_bulkid; /* bulk buffer matchbits */
+ lst_sid_t tsr_sid; /* session id */
+ lst_bid_t tsr_bid; /* batch id */
+ __u32 tsr_service; /* test type: bulk|ping|... */
+ /* test client loop count or # server buffers needed */
+ __u32 tsr_loop;
+ __u32 tsr_concur; /* concurrency of test */
+ __u8 tsr_is_client; /* is test client or not */
+ __u8 tsr_stop_onerr; /* stop on error */
+ __u32 tsr_ndest; /* # of dest nodes */
union {
- test_bulk_req_t bulk;
- test_ping_req_t ping;
- } tsr_u;
+ test_ping_req_t ping;
+ test_bulk_req_t bulk_v0;
+ test_bulk_req_v1_t bulk_v1;
+ } tsr_u;
} WIRE_ATTR srpc_test_reqst_t;
typedef struct {
- __u32 tsr_status; /* returned code */
- lst_sid_t tsr_sid;
+ __u32 tsr_status; /* returned code */
+ lst_sid_t tsr_sid;
} WIRE_ATTR srpc_test_reply_t;
/* TEST RPCs */
#define SRPC_MSG_MAGIC 0xeeb0f00d
#define SRPC_MSG_VERSION 1
+
typedef struct srpc_msg {
- __u32 msg_magic; /* magic */
- __u32 msg_version; /* # version */
- /* what's in msg_body? srpc_msg_type_t */
+ /** magic number */
+ __u32 msg_magic;
+ /** message version number */
+ __u32 msg_version;
+ /** type of message body: srpc_msg_type_t */
__u32 msg_type;
- __u32 msg_reserved0; /* reserved seats */
- __u32 msg_reserved1;
- __u32 msg_reserved2;
+ __u32 msg_reserved0;
+ __u32 msg_reserved1;
+ /** test session features */
+ __u32 msg_ses_feats;
union {
srpc_generic_reqst_t reqst;
srpc_generic_reply_t reply;
#include <libcfs/libcfs_unpack.h>
+static inline void
+srpc_unpack_msg_hdr(srpc_msg_t *msg)
+{
+ if (msg->msg_magic == SRPC_MSG_MAGIC)
+ return; /* no flipping needed */
+
+ __swab32s(&msg->msg_magic);
+ __swab32s(&msg->msg_type);
+ __swab32s(&msg->msg_version);
+ __swab32s(&msg->msg_ses_feats);
+ __swab32s(&msg->msg_reserved0);
+ __swab32s(&msg->msg_reserved1);
+}
+
#endif /* __SELFTEST_RPC_H__ */
lst_sid_t sn_id; /* unique identifier */
unsigned int sn_timeout; /* # seconds' inactivity to expire */
int sn_timer_active;
+ unsigned int sn_features;
stt_timer_t sn_timer;
cfs_list_t sn_batches; /* list of batches */
char sn_name[LST_NAME_SIZE];
cfs_list_t tsi_free_rpcs; /* free rpcs */
cfs_list_t tsi_active_rpcs; /* active rpcs */
- union {
- test_bulk_req_t bulk; /* bulk parameter */
- test_ping_req_t ping; /* ping parameter */
- } tsi_u;
+ union {
+ test_ping_req_t ping; /* ping parameter */
+ test_bulk_req_t bulk_v0; /* bulk parameter */
+ test_bulk_req_v1_t bulk_v1; /* bulk v1 parameter */
+ } tsi_u;
} sfw_test_instance_t;
/* XXX: trailing (CFS_PAGE_SIZE % sizeof(lnet_process_id_t)) bytes at
} sfw_test_case_t;
srpc_client_rpc_t *
-sfw_create_rpc(lnet_process_id_t peer, int service, int nbulkiov, int bulklen,
- void (*done) (srpc_client_rpc_t *), void *priv);
-int sfw_create_test_rpc(sfw_test_unit_t *tsu, lnet_process_id_t peer,
- int nblk, int blklen, srpc_client_rpc_t **rpc);
+sfw_create_rpc(lnet_process_id_t peer, int service,
+ unsigned features, int nbulkiov, int bulklen,
+ void (*done) (srpc_client_rpc_t *), void *priv);
+int sfw_create_test_rpc(sfw_test_unit_t *tsu,
+ lnet_process_id_t peer, unsigned features,
+ int nblk, int blklen, srpc_client_rpc_t **rpc);
void sfw_abort_rpc(srpc_client_rpc_t *rpc);
void sfw_post_rpc(srpc_client_rpc_t *rpc);
void sfw_client_rpc_done(srpc_client_rpc_t *rpc);
void sfw_unpack_message(srpc_msg_t *msg);
void sfw_free_pages(srpc_server_rpc_t *rpc);
void sfw_add_bulk_page(srpc_bulk_t *bk, cfs_page_t *pg, int i);
-int sfw_alloc_pages(srpc_server_rpc_t *rpc, int cpt, int npages, int sink);
+int sfw_alloc_pages(srpc_server_rpc_t *rpc, int cpt, int npages, int len,
+ int sink);
int sfw_make_session (srpc_mksn_reqst_t *request, srpc_mksn_reply_t *reply);
srpc_client_rpc_t *
void srpc_post_rpc(srpc_client_rpc_t *rpc);
void srpc_abort_rpc(srpc_client_rpc_t *rpc, int why);
void srpc_free_bulk(srpc_bulk_t *bk);
-srpc_bulk_t *srpc_alloc_bulk(int cpt, int npages, int sink);
+srpc_bulk_t *srpc_alloc_bulk(int cpt, unsigned bulk_npg, unsigned bulk_len,
+ int sink);
int srpc_send_rpc(swi_workitem_t *wi);
int srpc_send_reply(srpc_server_rpc_t *rpc);
int srpc_add_service(srpc_service_t *sv);
#include <libcfs/libcfsutil.h>
#include <lnet/lnetctl.h>
#include <lnet/lnetst.h>
-
+/* NB: these includes are layering violation */
+#include <lustre_ver.h>
+#include <lustre/lustre_idl.h>
lst_sid_t LST_INVALID_SID = {LNET_NID_ANY, -1};
static lst_sid_t session_id;
static int session_key;
+
+#if LUSTRE_VERSION_CODE >= OBD_OCD_VERSION(2, 6, 50, 0)
+/* assume all nodes can understand feature LST_FEAT_BULK_LEN */
+static unsigned session_features = LST_FEATS_MASK;
+#else
+static unsigned session_features = LST_FEATS_EMPTY;
+#endif
+
static lstcon_trans_stat_t trans_stat;
typedef struct list_string {
continue;
}
- fprintf(stderr, "%s failed on %s: %s\n",
+ fprintf(stderr, "operation %s failed on %s: %s\n",
optstr, libcfs_id2str(ent->rpe_peer),
strerror(ent->rpe_fwk_errno));
}
}
int
-lst_new_session_ioctl (char *name, int timeout, int force, lst_sid_t *sid)
+lst_new_session_ioctl(char *name, int timeout, int force, lst_sid_t *sid)
{
lstio_session_new_args_t args = {0};
args.lstio_ses_timeout = timeout;
args.lstio_ses_force = force;
args.lstio_ses_idp = sid;
+ args.lstio_ses_feats = session_features;
args.lstio_ses_nmlen = strlen(name);
args.lstio_ses_namep = name;
}
rc = lst_new_session_ioctl(name, timeout, force, &session_id);
-
if (rc != 0) {
lst_print_error("session", "Failed to create session: %s\n",
strerror(errno));
return rc;
}
- fprintf(stdout, "SESSION: %s TIMEOUT: %d FORCE: %s\n",
- name, timeout, force ? "Yes": "No");
-
- return rc;
+ fprintf(stdout, "SESSION: %s FEATURES: %x TIMEOUT: %d FORCE: %s\n",
+ name, session_features, timeout, force ? "Yes" : "No");
+ return 0;
}
int
-lst_session_info_ioctl(char *name, int len, int *key,
- lst_sid_t *sid, lstcon_ndlist_ent_t *ndinfo)
+lst_session_info_ioctl(char *name, int len, int *key, unsigned *featp,
+ lst_sid_t *sid, lstcon_ndlist_ent_t *ndinfo)
{
- lstio_session_info_args_t args = {0};
+ lstio_session_info_args_t args = {0};
- args.lstio_ses_idp = sid;
- args.lstio_ses_keyp = key;
- args.lstio_ses_ndinfo = ndinfo;
- args.lstio_ses_nmlen = len;
- args.lstio_ses_namep = name;
+ args.lstio_ses_idp = sid;
+ args.lstio_ses_keyp = key;
+ args.lstio_ses_featp = featp;
+ args.lstio_ses_ndinfo = ndinfo;
+ args.lstio_ses_nmlen = len;
+ args.lstio_ses_namep = name;
- return lst_ioctl(LSTIO_SESSION_INFO, &args, sizeof(args));
+ return lst_ioctl(LSTIO_SESSION_INFO, &args, sizeof(args));
}
int
lstcon_ndlist_ent_t ndinfo;
lst_sid_t sid;
char name[LST_NAME_SIZE];
- int key;
- int rc;
+ unsigned feats;
+ int key;
+ int rc;
- rc = lst_session_info_ioctl(name, LST_NAME_SIZE, &key, &sid, &ndinfo);
+ rc = lst_session_info_ioctl(name, LST_NAME_SIZE, &key,
+ &feats, &sid, &ndinfo);
if (rc != 0) {
lst_print_error("session", "Failed to show session: %s\n",
return -1;
}
- fprintf(stdout, "%s ID: "LPU64"@%s, KEY: %d NODES: %d\n",
- name, sid.ses_stamp, libcfs_nid2str(sid.ses_nid),
- key, ndinfo.nle_nnode);
+ fprintf(stdout, "%s ID: "LPU64"@%s, KEY: %d FEATURES: %x NODES: %d\n",
+ name, sid.ses_stamp, libcfs_nid2str(sid.ses_nid),
+ key, feats, ndinfo.nle_nnode);
return 0;
}
lstcon_test_batch_ent_t ent;
lstcon_ndlist_ent_t *entp = &ent.tbe_cli_nle;
lst_sid_t sid;
- int key;
- int rc;
+ unsigned feats;
+ int key;
+ int rc;
- switch (type) {
- case LST_OPC_SESSION:
- rc = lst_session_info_ioctl(buf, LST_NAME_SIZE,
- &key, &sid, entp);
- break;
+ switch (type) {
+ case LST_OPC_SESSION:
+ rc = lst_session_info_ioctl(buf, LST_NAME_SIZE,
+ &key, &feats, &sid, entp);
+ break;
case LST_OPC_BATCHSRV:
entp = &ent.tbe_srv_nle;
int
lst_add_nodes_ioctl (char *name, int count, lnet_process_id_t *ids,
- cfs_list_t *resultp)
+ unsigned *featp, cfs_list_t *resultp)
{
lstio_group_nodes_args_t args = {0};
args.lstio_grp_nmlen = strlen(name);
args.lstio_grp_namep = name;
args.lstio_grp_count = count;
+ args.lstio_grp_featp = featp;
args.lstio_grp_idsp = ids;
args.lstio_grp_resultp = resultp;
cfs_list_t head;
lnet_process_id_t *ids;
char *name;
+ unsigned feats = session_features;
int count;
int rc;
int i;
rc = lst_alloc_rpcent(&head, count, 0);
if (rc != 0) {
fprintf(stderr, "Out of memory\n");
- break;
- }
+ return -1;
+ }
- rc = lst_add_nodes_ioctl(name, count, ids, &head);
+ rc = lst_add_nodes_ioctl(name, count, ids, &feats, &head);
- free(ids);
+ free(ids);
- if (rc == 0) {
- lst_free_rpcent(&head);
- fprintf(stderr, "%s are added to session\n", argv[i]);
- continue;
- }
+ if (rc != 0)
+ goto failed;
- if (rc == -1) {
- lst_free_rpcent(&head);
- lst_print_error("group", "Failed to add nodes %s: %s\n",
- argv[i], strerror(errno));
- break;
- }
+ fprintf(stdout, "%s are added to session\n", argv[i]);
- lst_print_transerr(&head, "create session");
- lst_free_rpcent(&head);
- }
+ if ((feats & session_features) != session_features) {
+ fprintf(stdout,
+ "Warning, this session will run with "
+ "compatible mode because some test nodes "
+ "might not understand these features: %x\n",
+ (~feats & session_features));
+ }
- return rc;
+ lst_free_rpcent(&head);
+ }
+
+ return 0;
+
+failed:
+ if (rc == -1) {
+ lst_print_error("group", "Failed to add nodes %s: %s\n",
+ argv[i], strerror(errno));
+
+ } else {
+ if (trans_stat.trs_fwk_errno == EPROTO) {
+ fprintf(stderr,
+ "test nodes might have different LST "
+ "features, please disable some features by "
+ "setting LST_FEATURES\n");
+ }
+
+ lst_print_transerr(&head, "create session");
+ }
+
+ lst_free_rpcent(&head);
+
+ return rc;
}
int
int
lst_initialize(void)
{
- char *key;
+ char *key;
+ char *feats;
+
+ feats = getenv("LST_FEATURES");
+ if (feats != NULL)
+ session_features = strtol(feats, NULL, 16);
+
+ if ((session_features & ~LST_FEATS_MASK) != 0) {
+ fprintf(stderr,
+ "Unsupported session features %x, "
+ "only support these features so far: %x\n",
+ (session_features & ~LST_FEATS_MASK), LST_FEATS_MASK);
+ return -1;
+ }
key = getenv("LST_SESSION");
{
{"sesid", required_argument, 0, 's' },
{"group", required_argument, 0, 'g' },
+ {"features", required_argument, 0, 'f' },
{"server_mode", no_argument, 0, 'm' },
{0, 0, 0, 0 }
};
}
int
-lstjn_join_session(char *ses, char *grp)
+lstjn_join_session(char *ses, char *grp, unsigned feats)
{
lnet_process_id_t sesid;
srpc_client_rpc_t *rpc;
return -1;
}
- rpc = sfw_create_rpc(sesid, SRPC_SERVICE_JOIN, 0,
- 0, lstjn_rpc_done, NULL);
+ rpc = sfw_create_rpc(sesid, SRPC_SERVICE_JOIN, feats,
+ 0, 0, lstjn_rpc_done, NULL);
if (rpc == NULL) {
fprintf(stderr, "Out of memory\n");
return -1;
return -1;
}
+ if (rpc->crpc_replymsg.msg_ses_feats != feats) {
+ /* this can only happen when connecting to old console
+ * which will ignore features */
+ fprintf(stderr, "Can't join session %s group %s because "
+ "feature bits can't match: %x/%x, please set "
+ "feature bits by -f FEATURES and retry\n",
+ ses, grp, feats, rpc->crpc_replymsg.msg_ses_feats);
+ srpc_client_rpc_decref(rpc);
+ return -1;
+ }
+
sreq = &rpc->crpc_reqstmsg.msg_body.mksn_reqst;
sreq->mksn_sid = rep->join_sid;
sreq->mksn_force = 0;
int
main(int argc, char **argv)
{
- char *ses = NULL;
- char *grp = NULL;
- int server_mode_flag = 0;
- int optidx;
- int c;
- int rc;
-
- const char *usage_string =
- "Usage: lstclient --sesid ID --group GROUP [--server_mode]\n";
-
- while (1) {
- c = getopt_long(argc, argv, "s:g:m",
- lstjn_options, &optidx);
+ char *ses = NULL;
+ char *grp = NULL;
+ unsigned feats = LST_FEATS_MASK;
+ int server_mode_flag = 0;
+ int optidx;
+ int c;
+ int rc;
+
+ const char *usage_string =
+ "Usage: lstclient --sesid ID --group GROUP "
+ "--features FEATURES [--server_mode]\n";
+
+ while (1) {
+ c = getopt_long(argc, argv, "s:g:f:m",
+ lstjn_options, &optidx);
if (c == -1)
break;
case 'g':
grp = optarg;
break;
+ case 'f':
+ feats = strtol(optarg, NULL, 16);
+ break;
+
case 'm':
server_mode_flag = 1;
break;
return -1;
}
- rc = libcfs_debug_init(5 * 1024 * 1024);
- if (rc != 0) {
- CERROR("libcfs_debug_init() failed: %d\n", rc);
- return -1;
- }
-
- rc = cfs_wi_startup();
- if (rc != 0) {
- CERROR("cfs_wi_startup() failed: %d\n", rc);
- libcfs_debug_cleanup();
- return -1;
- }
-
- rc = LNetInit();
- if (rc != 0) {
- CERROR("LNetInit() failed: %d\n", rc);
- cfs_wi_shutdown();
- libcfs_debug_cleanup();
- return -1;
- }
+ if ((feats & ~LST_FEATS_MASK) != 0) {
+ fprintf(stderr,
+ "lstclient can't understand these feature bits: %x\n",
+ (feats & ~LST_FEATS_MASK));
+ return -1;
+ }
+
+ rc = libcfs_debug_init(5 * 1024 * 1024);
+ if (rc != 0) {
+ fprintf(stderr, "libcfs_debug_init() failed: %d\n", rc);
+ return -1;
+ }
+
+ rc = cfs_wi_startup();
+ if (rc != 0) {
+ fprintf(stderr, "cfs_wi_startup() failed: %d\n", rc);
+ libcfs_debug_cleanup();
+ return -1;
+ }
+
+ rc = LNetInit();
+ if (rc != 0) {
+ fprintf(stderr, "LNetInit() failed: %d\n", rc);
+ cfs_wi_shutdown();
+ libcfs_debug_cleanup();
+ return -1;
+ }
if (server_mode_flag)
lnet_server_mode();
return -1;
}
- rc = lstjn_join_session(ses, grp);
+ rc = lstjn_join_session(ses, grp, feats);
if (rc != 0)
goto out;