aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/lustre/lnet/selftest
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/lustre/lnet/selftest')
-rw-r--r--drivers/staging/lustre/lnet/selftest/Makefile7
-rw-r--r--drivers/staging/lustre/lnet/selftest/brw_test.c526
-rw-r--r--drivers/staging/lustre/lnet/selftest/conctl.c799
-rw-r--r--drivers/staging/lustre/lnet/selftest/conrpc.c1397
-rw-r--r--drivers/staging/lustre/lnet/selftest/conrpc.h143
-rw-r--r--drivers/staging/lustre/lnet/selftest/console.c2101
-rw-r--r--drivers/staging/lustre/lnet/selftest/console.h244
-rw-r--r--drivers/staging/lustre/lnet/selftest/framework.c1786
-rw-r--r--drivers/staging/lustre/lnet/selftest/module.c165
-rw-r--r--drivers/staging/lustre/lnet/selftest/ping_test.c228
-rw-r--r--drivers/staging/lustre/lnet/selftest/rpc.c1682
-rw-r--r--drivers/staging/lustre/lnet/selftest/rpc.h295
-rw-r--r--drivers/staging/lustre/lnet/selftest/selftest.h623
-rw-r--r--drivers/staging/lustre/lnet/selftest/timer.c244
-rw-r--r--drivers/staging/lustre/lnet/selftest/timer.h50
15 files changed, 0 insertions, 10290 deletions
diff --git a/drivers/staging/lustre/lnet/selftest/Makefile b/drivers/staging/lustre/lnet/selftest/Makefile
deleted file mode 100644
index 3ccc8966b566..000000000000
--- a/drivers/staging/lustre/lnet/selftest/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-subdir-ccflags-y += -I$(srctree)/drivers/staging/lustre/include
-subdir-ccflags-y += -I$(srctree)/drivers/staging/lustre/lustre/include
-
-obj-$(CONFIG_LNET_SELFTEST) := lnet_selftest.o
-
-lnet_selftest-y := console.o conrpc.o conctl.o framework.o timer.o rpc.o \
- module.o ping_test.o brw_test.o
diff --git a/drivers/staging/lustre/lnet/selftest/brw_test.c b/drivers/staging/lustre/lnet/selftest/brw_test.c
deleted file mode 100644
index f1ee219bc8f3..000000000000
--- a/drivers/staging/lustre/lnet/selftest/brw_test.c
+++ /dev/null
@@ -1,526 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * GPL HEADER START
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 only,
- * as published by the Free Software Foundation.
- *
- * This program 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 version 2 for more details (a copy is included
- * in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2011, 2015, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * lnet/selftest/brw_test.c
- *
- * Author: Isaac Huang <isaac@clusterfs.com>
- */
-
-#include "selftest.h"
-
-static int brw_srv_workitems = SFW_TEST_WI_MAX;
-module_param(brw_srv_workitems, int, 0644);
-MODULE_PARM_DESC(brw_srv_workitems, "# BRW server workitems");
-
-static int brw_inject_errors;
-module_param(brw_inject_errors, int, 0644);
-MODULE_PARM_DESC(brw_inject_errors, "# data errors to inject randomly, zero by default");
-
-#define BRW_POISON 0xbeefbeefbeefbeefULL
-#define BRW_MAGIC 0xeeb0eeb1eeb2eeb3ULL
-#define BRW_MSIZE sizeof(u64)
-
-static void
-brw_client_fini(struct sfw_test_instance *tsi)
-{
- struct srpc_bulk *bulk;
- struct sfw_test_unit *tsu;
-
- LASSERT(tsi->tsi_is_client);
-
- list_for_each_entry(tsu, &tsi->tsi_units, tsu_list) {
- bulk = tsu->tsu_private;
- if (!bulk)
- continue;
-
- srpc_free_bulk(bulk);
- tsu->tsu_private = NULL;
- }
-}
-
-static int
-brw_client_init(struct sfw_test_instance *tsi)
-{
- struct sfw_session *sn = tsi->tsi_batch->bat_session;
- int flags;
- int off;
- int npg;
- int len;
- int opc;
- struct srpc_bulk *bulk;
- struct sfw_test_unit *tsu;
-
- LASSERT(sn);
- LASSERT(tsi->tsi_is_client);
-
- if (!(sn->sn_features & LST_FEAT_BULK_LEN)) {
- struct test_bulk_req *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 * PAGE_SIZE;
- off = 0;
- } else {
- struct test_bulk_req_v1 *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));
-
- opc = breq->blk_opc;
- flags = breq->blk_flags;
- len = breq->blk_len;
- off = breq->blk_offset & ~PAGE_MASK;
- npg = (off + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
- }
-
- if (off % BRW_MSIZE)
- return -EINVAL;
-
- 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;
-
- list_for_each_entry(tsu, &tsi->tsi_units, tsu_list) {
- bulk = srpc_alloc_bulk(lnet_cpt_of_nid(tsu->tsu_dest.nid),
- off, npg, len, opc == LST_BRW_READ);
- if (!bulk) {
- brw_client_fini(tsi);
- return -ENOMEM;
- }
-
- tsu->tsu_private = bulk;
- }
-
- return 0;
-}
-
-static int brw_inject_one_error(void)
-{
- struct timespec64 ts;
-
- if (brw_inject_errors <= 0)
- return 0;
-
- ktime_get_ts64(&ts);
-
- if (!((ts.tv_nsec / NSEC_PER_USEC) & 1))
- return 0;
-
- return brw_inject_errors--;
-}
-
-static void
-brw_fill_page(struct page *pg, int off, int len, int pattern, __u64 magic)
-{
- char *addr = page_address(pg) + off;
- int i;
-
- LASSERT(addr);
- LASSERT(!(off % BRW_MSIZE) && !(len % BRW_MSIZE));
-
- if (pattern == LST_BRW_CHECK_NONE)
- return;
-
- if (magic == BRW_MAGIC)
- magic += brw_inject_one_error();
-
- if (pattern == LST_BRW_CHECK_SIMPLE) {
- memcpy(addr, &magic, BRW_MSIZE);
- if (len > BRW_MSIZE) {
- addr += PAGE_SIZE - BRW_MSIZE;
- memcpy(addr, &magic, BRW_MSIZE);
- }
- return;
- }
-
- if (pattern == LST_BRW_CHECK_FULL) {
- for (i = 0; i < len; i += BRW_MSIZE)
- memcpy(addr + i, &magic, BRW_MSIZE);
- return;
- }
-
- LBUG();
-}
-
-static int
-brw_check_page(struct page *pg, int off, int len, int pattern, __u64 magic)
-{
- char *addr = page_address(pg) + off;
- __u64 data = 0; /* make compiler happy */
- int i;
-
- LASSERT(addr);
- LASSERT(!(off % BRW_MSIZE) && !(len % BRW_MSIZE));
-
- if (pattern == LST_BRW_CHECK_NONE)
- return 0;
-
- if (pattern == LST_BRW_CHECK_SIMPLE) {
- data = *((__u64 *)addr);
- if (data != magic)
- goto bad_data;
-
- if (len > BRW_MSIZE) {
- addr += PAGE_SIZE - BRW_MSIZE;
- data = *((__u64 *)addr);
- if (data != magic)
- goto bad_data;
- }
- return 0;
- }
-
- if (pattern == LST_BRW_CHECK_FULL) {
- for (i = 0; i < len; i += BRW_MSIZE) {
- data = *(u64 *)(addr + i);
- if (data != magic)
- goto bad_data;
- }
- return 0;
- }
-
- LBUG();
-
-bad_data:
- CERROR("Bad data in page %p: %#llx, %#llx expected\n",
- pg, data, magic);
- return 1;
-}
-
-static void
-brw_fill_bulk(struct srpc_bulk *bk, int pattern, __u64 magic)
-{
- int i;
- struct page *pg;
-
- for (i = 0; i < bk->bk_niov; i++) {
- int off, len;
-
- pg = bk->bk_iovs[i].bv_page;
- off = bk->bk_iovs[i].bv_offset;
- len = bk->bk_iovs[i].bv_len;
- brw_fill_page(pg, off, len, pattern, magic);
- }
-}
-
-static int
-brw_check_bulk(struct srpc_bulk *bk, int pattern, __u64 magic)
-{
- int i;
- struct page *pg;
-
- for (i = 0; i < bk->bk_niov; i++) {
- int off, len;
-
- pg = bk->bk_iovs[i].bv_page;
- off = bk->bk_iovs[i].bv_offset;
- len = bk->bk_iovs[i].bv_len;
- if (brw_check_page(pg, off, len, pattern, magic)) {
- CERROR("Bulk page %p (%d/%d) is corrupted!\n",
- pg, i, bk->bk_niov);
- return 1;
- }
- }
-
- return 0;
-}
-
-static int
-brw_client_prep_rpc(struct sfw_test_unit *tsu, struct lnet_process_id dest,
- struct srpc_client_rpc **rpcpp)
-{
- struct srpc_bulk *bulk = tsu->tsu_private;
- struct sfw_test_instance *tsi = tsu->tsu_instance;
- struct sfw_session *sn = tsi->tsi_batch->bat_session;
- struct srpc_client_rpc *rpc;
- struct srpc_brw_reqst *req;
- int flags;
- int npg;
- int len;
- int opc;
- int rc;
-
- LASSERT(sn);
- LASSERT(bulk);
-
- if (!(sn->sn_features & LST_FEAT_BULK_LEN)) {
- struct test_bulk_req *breq = &tsi->tsi_u.bulk_v0;
-
- opc = breq->blk_opc;
- flags = breq->blk_flags;
- npg = breq->blk_npg;
- len = npg * PAGE_SIZE;
- } else {
- struct test_bulk_req_v1 *breq = &tsi->tsi_u.bulk_v1;
- int off;
-
- /*
- * 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));
-
- opc = breq->blk_opc;
- flags = breq->blk_flags;
- len = breq->blk_len;
- off = breq->blk_offset;
- npg = (off + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
- }
-
- rc = sfw_create_test_rpc(tsu, dest, sn->sn_features, npg, len, &rpc);
- if (rc)
- return rc;
-
- memcpy(&rpc->crpc_bulk, bulk, offsetof(struct srpc_bulk, 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);
-
- 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
-brw_client_done_rpc(struct sfw_test_unit *tsu, struct srpc_client_rpc *rpc)
-{
- __u64 magic = BRW_MAGIC;
- struct sfw_test_instance *tsi = tsu->tsu_instance;
- struct sfw_session *sn = tsi->tsi_batch->bat_session;
- struct srpc_msg *msg = &rpc->crpc_replymsg;
- struct srpc_brw_reply *reply = &msg->msg_body.brw_reply;
- struct srpc_brw_reqst *reqst = &rpc->crpc_reqstmsg.msg_body.brw_reqst;
-
- LASSERT(sn);
-
- if (rpc->crpc_status) {
- CERROR("BRW RPC to %s failed with %d\n",
- libcfs_id2str(rpc->crpc_dest), rpc->crpc_status);
- if (!tsi->tsi_stopping) /* rpc could have been aborted */
- atomic_inc(&sn->sn_brw_errors);
- return;
- }
-
- if (msg->msg_magic != SRPC_MSG_MAGIC) {
- __swab64s(&magic);
- __swab32s(&reply->brw_status);
- }
-
- CDEBUG(reply->brw_status ? D_WARNING : D_NET,
- "BRW RPC to %s finished with brw_status: %d\n",
- libcfs_id2str(rpc->crpc_dest), reply->brw_status);
-
- if (reply->brw_status) {
- atomic_inc(&sn->sn_brw_errors);
- rpc->crpc_status = -(int)reply->brw_status;
- return;
- }
-
- if (reqst->brw_rw == LST_BRW_WRITE)
- return;
-
- if (brw_check_bulk(&rpc->crpc_bulk, reqst->brw_flags, magic)) {
- CERROR("Bulk data from %s is corrupted!\n",
- libcfs_id2str(rpc->crpc_dest));
- atomic_inc(&sn->sn_brw_errors);
- rpc->crpc_status = -EBADMSG;
- }
-}
-
-static void
-brw_server_rpc_done(struct srpc_server_rpc *rpc)
-{
- struct srpc_bulk *blk = rpc->srpc_bulk;
-
- if (!blk)
- return;
-
- if (rpc->srpc_status)
- CERROR("Bulk transfer %s %s has failed: %d\n",
- blk->bk_sink ? "from" : "to",
- libcfs_id2str(rpc->srpc_peer), rpc->srpc_status);
- else
- CDEBUG(D_NET, "Transferred %d pages bulk data %s %s\n",
- blk->bk_niov, blk->bk_sink ? "from" : "to",
- libcfs_id2str(rpc->srpc_peer));
-
- sfw_free_pages(rpc);
-}
-
-static int
-brw_bulk_ready(struct srpc_server_rpc *rpc, int status)
-{
- __u64 magic = BRW_MAGIC;
- struct srpc_brw_reply *reply = &rpc->srpc_replymsg.msg_body.brw_reply;
- struct srpc_brw_reqst *reqst;
- struct srpc_msg *reqstmsg;
-
- LASSERT(rpc->srpc_bulk);
- LASSERT(rpc->srpc_reqstbuf);
-
- reqstmsg = &rpc->srpc_reqstbuf->buf_msg;
- reqst = &reqstmsg->msg_body.brw_reqst;
-
- if (status) {
- CERROR("BRW bulk %s failed for RPC from %s: %d\n",
- reqst->brw_rw == LST_BRW_READ ? "READ" : "WRITE",
- libcfs_id2str(rpc->srpc_peer), status);
- return -EIO;
- }
-
- if (reqst->brw_rw == LST_BRW_READ)
- return 0;
-
- if (reqstmsg->msg_magic != SRPC_MSG_MAGIC)
- __swab64s(&magic);
-
- if (brw_check_bulk(rpc->srpc_bulk, reqst->brw_flags, magic)) {
- CERROR("Bulk data from %s is corrupted!\n",
- libcfs_id2str(rpc->srpc_peer));
- reply->brw_status = EBADMSG;
- }
-
- return 0;
-}
-
-static int
-brw_server_handle(struct srpc_server_rpc *rpc)
-{
- struct srpc_service *sv = rpc->srpc_scd->scd_svc;
- struct srpc_msg *replymsg = &rpc->srpc_replymsg;
- struct srpc_msg *reqstmsg = &rpc->srpc_reqstbuf->buf_msg;
- struct srpc_brw_reply *reply = &replymsg->msg_body.brw_reply;
- struct srpc_brw_reqst *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(&reqst->brw_rw);
- __swab32s(&reqst->brw_len);
- __swab32s(&reqst->brw_flags);
- __swab64s(&reqst->brw_rpyid);
- __swab64s(&reqst->brw_bulkid);
- }
- 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_flags != LST_BRW_CHECK_NONE &&
- reqst->brw_flags != LST_BRW_CHECK_FULL &&
- reqst->brw_flags != LST_BRW_CHECK_SIMPLE)) {
- reply->brw_status = EINVAL;
- return 0;
- }
-
- if (reqstmsg->msg_ses_feats & ~LST_FEATS_MASK) {
- replymsg->msg_ses_feats = LST_FEATS_MASK;
- reply->brw_status = EPROTO;
- return 0;
- }
-
- if (!(reqstmsg->msg_ses_feats & LST_FEAT_BULK_LEN)) {
- /* compat with old version */
- if (reqst->brw_len & ~PAGE_MASK) {
- reply->brw_status = EINVAL;
- return 0;
- }
- npg = reqst->brw_len >> PAGE_SHIFT;
-
- } else {
- npg = (reqst->brw_len + PAGE_SIZE - 1) >> PAGE_SHIFT;
- }
-
- replymsg->msg_ses_feats = reqstmsg->msg_ses_feats;
-
- if (!reqst->brw_len || 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)
- return rc;
-
- if (reqst->brw_rw == LST_BRW_READ)
- brw_fill_bulk(rpc->srpc_bulk, reqst->brw_flags, BRW_MAGIC);
- else
- brw_fill_bulk(rpc->srpc_bulk, reqst->brw_flags, BRW_POISON);
-
- return 0;
-}
-
-struct sfw_test_client_ops brw_test_client;
-
-void brw_init_test_client(void)
-{
- brw_test_client.tso_init = brw_client_init;
- brw_test_client.tso_fini = brw_client_fini;
- brw_test_client.tso_prep_rpc = brw_client_prep_rpc;
- brw_test_client.tso_done_rpc = brw_client_done_rpc;
-};
-
-struct srpc_service brw_test_service;
-
-void brw_init_test_service(void)
-{
- brw_test_service.sv_id = SRPC_SERVICE_BRW;
- brw_test_service.sv_name = "brw_test";
- brw_test_service.sv_handler = brw_server_handle;
- brw_test_service.sv_bulk_ready = brw_bulk_ready;
- brw_test_service.sv_wi_total = brw_srv_workitems;
-}
diff --git a/drivers/staging/lustre/lnet/selftest/conctl.c b/drivers/staging/lustre/lnet/selftest/conctl.c
deleted file mode 100644
index a2d8092bdeb7..000000000000
--- a/drivers/staging/lustre/lnet/selftest/conctl.c
+++ /dev/null
@@ -1,799 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * GPL HEADER START
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 only,
- * as published by the Free Software Foundation.
- *
- * This program 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 version 2 for more details (a copy is included
- * in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2012, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * lnet/selftest/conctl.c
- *
- * IOC handle in kernel
- *
- * Author: Liang Zhen <liangzhen@clusterfs.com>
- */
-
-#include <linux/libcfs/libcfs.h>
-#include <linux/lnet/lib-lnet.h>
-#include <uapi/linux/lnet/lnetst.h>
-#include "console.h"
-
-static int
-lst_session_new_ioctl(struct lstio_session_new_args *args)
-{
- char name[LST_NAME_SIZE + 1];
- int rc;
-
- if (!args->lstio_ses_idp || /* address for output sid */
- !args->lstio_ses_key || /* no key is specified */
- !args->lstio_ses_namep || /* session name */
- args->lstio_ses_nmlen <= 0 ||
- args->lstio_ses_nmlen > LST_NAME_SIZE)
- return -EINVAL;
-
- if (copy_from_user(name, args->lstio_ses_namep,
- args->lstio_ses_nmlen)) {
- return -EFAULT;
- }
-
- name[args->lstio_ses_nmlen] = 0;
-
- rc = lstcon_session_new(name,
- args->lstio_ses_key,
- args->lstio_ses_feats,
- args->lstio_ses_timeout,
- args->lstio_ses_force,
- args->lstio_ses_idp);
-
- return rc;
-}
-
-static int
-lst_session_end_ioctl(struct lstio_session_end_args *args)
-{
- if (args->lstio_ses_key != console_session.ses_key)
- return -EACCES;
-
- return lstcon_session_end();
-}
-
-static int
-lst_session_info_ioctl(struct lstio_session_info_args *args)
-{
- /* no checking of key */
-
- if (!args->lstio_ses_idp || /* address for output sid */
- !args->lstio_ses_keyp || /* address for output key */
- !args->lstio_ses_featp || /* address for output features */
- !args->lstio_ses_ndinfo || /* address for output ndinfo */
- !args->lstio_ses_namep || /* address for output name */
- args->lstio_ses_nmlen <= 0 ||
- args->lstio_ses_nmlen > LST_NAME_SIZE)
- return -EINVAL;
-
- 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);
-}
-
-static int
-lst_debug_ioctl(struct lstio_debug_args *args)
-{
- char name[LST_NAME_SIZE + 1];
- int client = 1;
- int rc;
-
- if (args->lstio_dbg_key != console_session.ses_key)
- return -EACCES;
-
- if (!args->lstio_dbg_resultp)
- return -EINVAL;
-
- if (args->lstio_dbg_namep && /* name of batch/group */
- (args->lstio_dbg_nmlen <= 0 ||
- args->lstio_dbg_nmlen > LST_NAME_SIZE))
- return -EINVAL;
-
- if (args->lstio_dbg_namep) {
-
- if (copy_from_user(name, args->lstio_dbg_namep,
- args->lstio_dbg_nmlen))
- return -EFAULT;
-
- name[args->lstio_dbg_nmlen] = 0;
- }
-
- rc = -EINVAL;
-
- switch (args->lstio_dbg_type) {
- case LST_OPC_SESSION:
- rc = lstcon_session_debug(args->lstio_dbg_timeout,
- args->lstio_dbg_resultp);
- break;
-
- case LST_OPC_BATCHSRV:
- client = 0;
- /* fall through */
- case LST_OPC_BATCHCLI:
- if (!args->lstio_dbg_namep)
- goto out;
-
- rc = lstcon_batch_debug(args->lstio_dbg_timeout,
- name, client, args->lstio_dbg_resultp);
- break;
-
- case LST_OPC_GROUP:
- if (!args->lstio_dbg_namep)
- goto out;
-
- rc = lstcon_group_debug(args->lstio_dbg_timeout,
- name, args->lstio_dbg_resultp);
- break;
-
- case LST_OPC_NODES:
- if (args->lstio_dbg_count <= 0 ||
- !args->lstio_dbg_idsp)
- goto out;
-
- rc = lstcon_nodes_debug(args->lstio_dbg_timeout,
- args->lstio_dbg_count,
- args->lstio_dbg_idsp,
- args->lstio_dbg_resultp);
- break;
-
- default:
- break;
- }
-
-out:
- return rc;
-}
-
-static int
-lst_group_add_ioctl(struct lstio_group_add_args *args)
-{
- char name[LST_NAME_SIZE + 1];
- int rc;
-
- if (args->lstio_grp_key != console_session.ses_key)
- return -EACCES;
-
- if (!args->lstio_grp_namep ||
- args->lstio_grp_nmlen <= 0 ||
- args->lstio_grp_nmlen > LST_NAME_SIZE)
- return -EINVAL;
-
- if (copy_from_user(name, args->lstio_grp_namep,
- args->lstio_grp_nmlen))
- return -EFAULT;
-
- name[args->lstio_grp_nmlen] = 0;
-
- rc = lstcon_group_add(name);
-
- return rc;
-}
-
-static int
-lst_group_del_ioctl(struct lstio_group_del_args *args)
-{
- int rc;
- char name[LST_NAME_SIZE + 1];
-
- if (args->lstio_grp_key != console_session.ses_key)
- return -EACCES;
-
- if (!args->lstio_grp_namep ||
- args->lstio_grp_nmlen <= 0 ||
- args->lstio_grp_nmlen > LST_NAME_SIZE)
- return -EINVAL;
-
- if (copy_from_user(name, args->lstio_grp_namep,
- args->lstio_grp_nmlen))
- return -EFAULT;
-
- name[args->lstio_grp_nmlen] = 0;
-
- rc = lstcon_group_del(name);
-
- return rc;
-}
-
-static int
-lst_group_update_ioctl(struct lstio_group_update_args *args)
-{
- int rc;
- char name[LST_NAME_SIZE + 1];
-
- if (args->lstio_grp_key != console_session.ses_key)
- return -EACCES;
-
- if (!args->lstio_grp_resultp ||
- !args->lstio_grp_namep ||
- args->lstio_grp_nmlen <= 0 ||
- args->lstio_grp_nmlen > LST_NAME_SIZE)
- return -EINVAL;
-
- if (copy_from_user(name, args->lstio_grp_namep,
- args->lstio_grp_nmlen))
- return -EFAULT;
-
- name[args->lstio_grp_nmlen] = 0;
-
- switch (args->lstio_grp_opc) {
- case LST_GROUP_CLEAN:
- rc = lstcon_group_clean(name, args->lstio_grp_args);
- break;
-
- case LST_GROUP_REFRESH:
- rc = lstcon_group_refresh(name, args->lstio_grp_resultp);
- break;
-
- case LST_GROUP_RMND:
- if (args->lstio_grp_count <= 0 ||
- !args->lstio_grp_idsp) {
- rc = -EINVAL;
- break;
- }
- rc = lstcon_nodes_remove(name, args->lstio_grp_count,
- args->lstio_grp_idsp,
- args->lstio_grp_resultp);
- break;
-
- default:
- rc = -EINVAL;
- break;
- }
-
- return rc;
-}
-
-static int
-lst_nodes_add_ioctl(struct lstio_group_nodes_args *args)
-{
- unsigned int feats;
- int rc;
- char name[LST_NAME_SIZE + 1];
-
- if (args->lstio_grp_key != console_session.ses_key)
- return -EACCES;
-
- if (!args->lstio_grp_idsp || /* array of ids */
- args->lstio_grp_count <= 0 ||
- !args->lstio_grp_resultp ||
- !args->lstio_grp_featp ||
- !args->lstio_grp_namep ||
- args->lstio_grp_nmlen <= 0 ||
- args->lstio_grp_nmlen > LST_NAME_SIZE)
- return -EINVAL;
-
- if (copy_from_user(name, args->lstio_grp_namep,
- args->lstio_grp_nmlen))
- return -EFAULT;
-
- name[args->lstio_grp_nmlen] = 0;
-
- rc = lstcon_nodes_add(name, args->lstio_grp_count,
- args->lstio_grp_idsp, &feats,
- args->lstio_grp_resultp);
-
- if (!rc &&
- copy_to_user(args->lstio_grp_featp, &feats, sizeof(feats))) {
- return -EINVAL;
- }
-
- return rc;
-}
-
-static int
-lst_group_list_ioctl(struct lstio_group_list_args *args)
-{
- if (args->lstio_grp_key != console_session.ses_key)
- return -EACCES;
-
- if (args->lstio_grp_idx < 0 ||
- !args->lstio_grp_namep ||
- args->lstio_grp_nmlen <= 0 ||
- args->lstio_grp_nmlen > LST_NAME_SIZE)
- return -EINVAL;
-
- return lstcon_group_list(args->lstio_grp_idx,
- args->lstio_grp_nmlen,
- args->lstio_grp_namep);
-}
-
-static int
-lst_group_info_ioctl(struct lstio_group_info_args *args)
-{
- char name[LST_NAME_SIZE + 1];
- int ndent;
- int index;
- int rc;
-
- if (args->lstio_grp_key != console_session.ses_key)
- return -EACCES;
-
- if (!args->lstio_grp_namep ||
- args->lstio_grp_nmlen <= 0 ||
- args->lstio_grp_nmlen > LST_NAME_SIZE)
- return -EINVAL;
-
- if (!args->lstio_grp_entp && /* output: group entry */
- !args->lstio_grp_dentsp) /* output: node entry */
- return -EINVAL;
-
- if (args->lstio_grp_dentsp) { /* have node entry */
- if (!args->lstio_grp_idxp || /* node index */
- !args->lstio_grp_ndentp) /* # of node entry */
- return -EINVAL;
-
- if (copy_from_user(&ndent, args->lstio_grp_ndentp,
- sizeof(ndent)) ||
- copy_from_user(&index, args->lstio_grp_idxp,
- sizeof(index)))
- return -EFAULT;
-
- if (ndent <= 0 || index < 0)
- return -EINVAL;
- }
-
- if (copy_from_user(name, args->lstio_grp_namep,
- args->lstio_grp_nmlen))
- return -EFAULT;
-
- name[args->lstio_grp_nmlen] = 0;
-
- rc = lstcon_group_info(name, args->lstio_grp_entp,
- &index, &ndent, args->lstio_grp_dentsp);
-
- if (rc)
- return rc;
-
- if (args->lstio_grp_dentsp &&
- (copy_to_user(args->lstio_grp_idxp, &index, sizeof(index)) ||
- copy_to_user(args->lstio_grp_ndentp, &ndent, sizeof(ndent))))
- return -EFAULT;
-
- return 0;
-}
-
-static int
-lst_batch_add_ioctl(struct lstio_batch_add_args *args)
-{
- int rc;
- char name[LST_NAME_SIZE + 1];
-
- if (args->lstio_bat_key != console_session.ses_key)
- return -EACCES;
-
- if (!args->lstio_bat_namep ||
- args->lstio_bat_nmlen <= 0 ||
- args->lstio_bat_nmlen > LST_NAME_SIZE)
- return -EINVAL;
-
- if (copy_from_user(name, args->lstio_bat_namep,
- args->lstio_bat_nmlen))
- return -EFAULT;
-
- name[args->lstio_bat_nmlen] = 0;
-
- rc = lstcon_batch_add(name);
-
- return rc;
-}
-
-static int
-lst_batch_run_ioctl(struct lstio_batch_run_args *args)
-{
- int rc;
- char name[LST_NAME_SIZE + 1];
-
- if (args->lstio_bat_key != console_session.ses_key)
- return -EACCES;
-
- if (!args->lstio_bat_namep ||
- args->lstio_bat_nmlen <= 0 ||
- args->lstio_bat_nmlen > LST_NAME_SIZE)
- return -EINVAL;
-
- if (copy_from_user(name, args->lstio_bat_namep,
- args->lstio_bat_nmlen))
- return -EFAULT;
-
- name[args->lstio_bat_nmlen] = 0;
-
- rc = lstcon_batch_run(name, args->lstio_bat_timeout,
- args->lstio_bat_resultp);
-
- return rc;
-}
-
-static int
-lst_batch_stop_ioctl(struct lstio_batch_stop_args *args)
-{
- int rc;
- char name[LST_NAME_SIZE + 1];
-
- if (args->lstio_bat_key != console_session.ses_key)
- return -EACCES;
-
- if (!args->lstio_bat_resultp ||
- !args->lstio_bat_namep ||
- args->lstio_bat_nmlen <= 0 ||
- args->lstio_bat_nmlen > LST_NAME_SIZE)
- return -EINVAL;
-
- if (copy_from_user(name, args->lstio_bat_namep,
- args->lstio_bat_nmlen))
- return -EFAULT;
-
- name[args->lstio_bat_nmlen] = 0;
-
- rc = lstcon_batch_stop(name, args->lstio_bat_force,
- args->lstio_bat_resultp);
-
- return rc;
-}
-
-static int
-lst_batch_query_ioctl(struct lstio_batch_query_args *args)
-{
- char name[LST_NAME_SIZE + 1];
- int rc;
-
- if (args->lstio_bat_key != console_session.ses_key)
- return -EACCES;
-
- if (!args->lstio_bat_resultp ||
- !args->lstio_bat_namep ||
- args->lstio_bat_nmlen <= 0 ||
- args->lstio_bat_nmlen > LST_NAME_SIZE)
- return -EINVAL;
-
- if (args->lstio_bat_testidx < 0)
- return -EINVAL;
-
- if (copy_from_user(name, args->lstio_bat_namep,
- args->lstio_bat_nmlen))
- return -EFAULT;
-
- name[args->lstio_bat_nmlen] = 0;
-
- rc = lstcon_test_batch_query(name,
- args->lstio_bat_testidx,
- args->lstio_bat_client,
- args->lstio_bat_timeout,
- args->lstio_bat_resultp);
-
- return rc;
-}
-
-static int
-lst_batch_list_ioctl(struct lstio_batch_list_args *args)
-{
- if (args->lstio_bat_key != console_session.ses_key)
- return -EACCES;
-
- if (args->lstio_bat_idx < 0 ||
- !args->lstio_bat_namep ||
- args->lstio_bat_nmlen <= 0 ||
- args->lstio_bat_nmlen > LST_NAME_SIZE)
- return -EINVAL;
-
- return lstcon_batch_list(args->lstio_bat_idx,
- args->lstio_bat_nmlen,
- args->lstio_bat_namep);
-}
-
-static int
-lst_batch_info_ioctl(struct lstio_batch_info_args *args)
-{
- char name[LST_NAME_SIZE + 1];
- int rc;
- int index;
- int ndent;
-
- if (args->lstio_bat_key != console_session.ses_key)
- return -EACCES;
-
- if (!args->lstio_bat_namep || /* batch name */
- args->lstio_bat_nmlen <= 0 ||
- args->lstio_bat_nmlen > LST_NAME_SIZE)
- return -EINVAL;
-
- if (!args->lstio_bat_entp && /* output: batch entry */
- !args->lstio_bat_dentsp) /* output: node entry */
- return -EINVAL;
-
- if (args->lstio_bat_dentsp) { /* have node entry */
- if (!args->lstio_bat_idxp || /* node index */
- !args->lstio_bat_ndentp) /* # of node entry */
- return -EINVAL;
-
- if (copy_from_user(&index, args->lstio_bat_idxp,
- sizeof(index)) ||
- copy_from_user(&ndent, args->lstio_bat_ndentp,
- sizeof(ndent)))
- return -EFAULT;
-
- if (ndent <= 0 || index < 0)
- return -EINVAL;
- }
-
- if (copy_from_user(name, args->lstio_bat_namep,
- args->lstio_bat_nmlen))
- return -EFAULT;
-
- name[args->lstio_bat_nmlen] = 0;
-
- rc = lstcon_batch_info(name, args->lstio_bat_entp,
- args->lstio_bat_server, args->lstio_bat_testidx,
- &index, &ndent, args->lstio_bat_dentsp);
-
- if (rc)
- return rc;
-
- if (args->lstio_bat_dentsp &&
- (copy_to_user(args->lstio_bat_idxp, &index, sizeof(index)) ||
- copy_to_user(args->lstio_bat_ndentp, &ndent, sizeof(ndent))))
- rc = -EFAULT;
-
- return rc;
-}
-
-static int
-lst_stat_query_ioctl(struct lstio_stat_args *args)
-{
- int rc;
- char name[LST_NAME_SIZE + 1];
-
- /* TODO: not finished */
- if (args->lstio_sta_key != console_session.ses_key)
- return -EACCES;
-
- if (!args->lstio_sta_resultp)
- return -EINVAL;
-
- if (args->lstio_sta_idsp) {
- if (args->lstio_sta_count <= 0)
- return -EINVAL;
-
- rc = lstcon_nodes_stat(args->lstio_sta_count,
- args->lstio_sta_idsp,
- args->lstio_sta_timeout,
- args->lstio_sta_resultp);
- } else if (args->lstio_sta_namep) {
- if (args->lstio_sta_nmlen <= 0 ||
- args->lstio_sta_nmlen > LST_NAME_SIZE)
- return -EINVAL;
-
- rc = copy_from_user(name, args->lstio_sta_namep,
- args->lstio_sta_nmlen);
- if (!rc)
- rc = lstcon_group_stat(name, args->lstio_sta_timeout,
- args->lstio_sta_resultp);
- else
- rc = -EFAULT;
- } else {
- rc = -EINVAL;
- }
-
- return rc;
-}
-
-static int lst_test_add_ioctl(struct lstio_test_args *args)
-{
- char batch_name[LST_NAME_SIZE + 1];
- char src_name[LST_NAME_SIZE + 1];
- char dst_name[LST_NAME_SIZE + 1];
- void *param = NULL;
- int ret = 0;
- int rc = -ENOMEM;
-
- if (!args->lstio_tes_resultp ||
- !args->lstio_tes_retp ||
- !args->lstio_tes_bat_name || /* no specified batch */
- args->lstio_tes_bat_nmlen <= 0 ||
- args->lstio_tes_bat_nmlen > LST_NAME_SIZE ||
- !args->lstio_tes_sgrp_name || /* no source group */
- args->lstio_tes_sgrp_nmlen <= 0 ||
- args->lstio_tes_sgrp_nmlen > LST_NAME_SIZE ||
- !args->lstio_tes_dgrp_name || /* no target group */
- args->lstio_tes_dgrp_nmlen <= 0 ||
- args->lstio_tes_dgrp_nmlen > LST_NAME_SIZE)
- return -EINVAL;
-
- if (!args->lstio_tes_loop || /* 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 &&
- (args->lstio_tes_param_len <= 0 ||
- args->lstio_tes_param_len >
- PAGE_SIZE - sizeof(struct lstcon_test)))
- return -EINVAL;
-
- /* Enforce zero parameter length if there's no parameter */
- if (!args->lstio_tes_param && args->lstio_tes_param_len)
- return -EINVAL;
-
- if (args->lstio_tes_param) {
- param = memdup_user(args->lstio_tes_param,
- args->lstio_tes_param_len);
- if (IS_ERR(param))
- return PTR_ERR(param);
- }
-
- rc = -EFAULT;
- if (copy_from_user(batch_name, args->lstio_tes_bat_name,
- args->lstio_tes_bat_nmlen) ||
- copy_from_user(src_name, args->lstio_tes_sgrp_name,
- args->lstio_tes_sgrp_nmlen) ||
- copy_from_user(dst_name, args->lstio_tes_dgrp_name,
- args->lstio_tes_dgrp_nmlen))
- goto out;
-
- rc = lstcon_test_add(batch_name, args->lstio_tes_type,
- args->lstio_tes_loop, args->lstio_tes_concur,
- args->lstio_tes_dist, args->lstio_tes_span,
- src_name, dst_name, param,
- args->lstio_tes_param_len,
- &ret, args->lstio_tes_resultp);
-
- if (!rc && ret)
- rc = (copy_to_user(args->lstio_tes_retp, &ret,
- sizeof(ret))) ? -EFAULT : 0;
-out:
- kfree(param);
-
- return rc;
-}
-
-int
-lstcon_ioctl_entry(unsigned int cmd, struct libcfs_ioctl_hdr *hdr)
-{
- char *buf;
- struct libcfs_ioctl_data *data;
- int opc;
- int rc;
-
- if (cmd != IOC_LIBCFS_LNETST)
- return -EINVAL;
-
- data = container_of(hdr, struct libcfs_ioctl_data, ioc_hdr);
-
- opc = data->ioc_u32[0];
-
- if (data->ioc_plen1 > PAGE_SIZE)
- return -EINVAL;
-
- buf = kmalloc(data->ioc_plen1, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- /* copy in parameter */
- if (copy_from_user(buf, data->ioc_pbuf1, data->ioc_plen1)) {
- kfree(buf);
- return -EFAULT;
- }
-
- mutex_lock(&console_session.ses_mutex);
-
- console_session.ses_laststamp = ktime_get_real_seconds();
-
- if (console_session.ses_shutdown) {
- rc = -ESHUTDOWN;
- goto out;
- }
-
- if (console_session.ses_expired)
- lstcon_session_end();
-
- if (opc != LSTIO_SESSION_NEW &&
- console_session.ses_state == LST_SESSION_NONE) {
- CDEBUG(D_NET, "LST no active session\n");
- rc = -ESRCH;
- goto out;
- }
-
- memset(&console_session.ses_trans_stat, 0, sizeof(struct lstcon_trans_stat));
-
- switch (opc) {
- case LSTIO_SESSION_NEW:
- rc = lst_session_new_ioctl((struct lstio_session_new_args *)buf);
- break;
- case LSTIO_SESSION_END:
- rc = lst_session_end_ioctl((struct lstio_session_end_args *)buf);
- break;
- case LSTIO_SESSION_INFO:
- rc = lst_session_info_ioctl((struct lstio_session_info_args *)buf);
- break;
- case LSTIO_DEBUG:
- rc = lst_debug_ioctl((struct lstio_debug_args *)buf);
- break;
- case LSTIO_GROUP_ADD:
- rc = lst_group_add_ioctl((struct lstio_group_add_args *)buf);
- break;
- case LSTIO_GROUP_DEL:
- rc = lst_group_del_ioctl((struct lstio_group_del_args *)buf);
- break;
- case LSTIO_GROUP_UPDATE:
- rc = lst_group_update_ioctl((struct lstio_group_update_args *)buf);
- break;
- case LSTIO_NODES_ADD:
- rc = lst_nodes_add_ioctl((struct lstio_group_nodes_args *)buf);
- break;
- case LSTIO_GROUP_LIST:
- rc = lst_group_list_ioctl((struct lstio_group_list_args *)buf);
- break;
- case LSTIO_GROUP_INFO:
- rc = lst_group_info_ioctl((struct lstio_group_info_args *)buf);
- break;
- case LSTIO_BATCH_ADD:
- rc = lst_batch_add_ioctl((struct lstio_batch_add_args *)buf);
- break;
- case LSTIO_BATCH_START:
- rc = lst_batch_run_ioctl((struct lstio_batch_run_args *)buf);
- break;
- case LSTIO_BATCH_STOP:
- rc = lst_batch_stop_ioctl((struct lstio_batch_stop_args *)buf);
- break;
- case LSTIO_BATCH_QUERY:
- rc = lst_batch_query_ioctl((struct lstio_batch_query_args *)buf);
- break;
- case LSTIO_BATCH_LIST:
- rc = lst_batch_list_ioctl((struct lstio_batch_list_args *)buf);
- break;
- case LSTIO_BATCH_INFO:
- rc = lst_batch_info_ioctl((struct lstio_batch_info_args *)buf);
- break;
- case LSTIO_TEST_ADD:
- rc = lst_test_add_ioctl((struct lstio_test_args *)buf);
- break;
- case LSTIO_STAT_QUERY:
- rc = lst_stat_query_ioctl((struct lstio_stat_args *)buf);
- break;
- default:
- rc = -EINVAL;
- }
-
- if (copy_to_user(data->ioc_pbuf2, &console_session.ses_trans_stat,
- sizeof(struct lstcon_trans_stat)))
- rc = -EFAULT;
-out:
- mutex_unlock(&console_session.ses_mutex);
-
- kfree(buf);
-
- return rc;
-}
diff --git a/drivers/staging/lustre/lnet/selftest/conrpc.c b/drivers/staging/lustre/lnet/selftest/conrpc.c
deleted file mode 100644
index 6dcc966b293b..000000000000
--- a/drivers/staging/lustre/lnet/selftest/conrpc.c
+++ /dev/null
@@ -1,1397 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * GPL HEADER START
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 only,
- * as published by the Free Software Foundation.
- *
- * This program 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 version 2 for more details (a copy is included
- * in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2011, 2012, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * lnet/selftest/conctl.c
- *
- * Console framework rpcs
- *
- * Author: Liang Zhen <liang@whamcloud.com>
- */
-
-#include <linux/libcfs/libcfs.h>
-#include <linux/lnet/lib-lnet.h>
-#include "timer.h"
-#include "conrpc.h"
-#include "console.h"
-
-void lstcon_rpc_stat_reply(struct lstcon_rpc_trans *, struct srpc_msg *,
- struct lstcon_node *, struct lstcon_trans_stat *);
-
-static void
-lstcon_rpc_done(struct srpc_client_rpc *rpc)
-{
- struct lstcon_rpc *crpc = (struct lstcon_rpc *)rpc->crpc_priv;
-
- LASSERT(crpc && rpc == crpc->crp_rpc);
- LASSERT(crpc->crp_posted && !crpc->crp_finished);
-
- spin_lock(&rpc->crpc_lock);
-
- if (!crpc->crp_trans) {
- /*
- * Orphan RPC is not in any transaction,
- * I'm just a poor body and nobody loves me
- */
- spin_unlock(&rpc->crpc_lock);
-
- /* release it */
- lstcon_rpc_put(crpc);
- return;
- }
-
- /* not an orphan RPC */
- crpc->crp_finished = 1;
-
- if (!crpc->crp_stamp) {
- /* not aborted */
- LASSERT(!crpc->crp_status);
-
- crpc->crp_stamp = cfs_time_current();
- crpc->crp_status = rpc->crpc_status;
- }
-
- /* wakeup (transaction)thread if I'm the last RPC in the transaction */
- if (atomic_dec_and_test(&crpc->crp_trans->tas_remaining))
- wake_up(&crpc->crp_trans->tas_waitq);
-
- spin_unlock(&rpc->crpc_lock);
-}
-
-static int
-lstcon_rpc_init(struct lstcon_node *nd, int service, unsigned int feats,
- int bulk_npg, int bulk_len, int embedded,
- struct lstcon_rpc *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)
- return -ENOMEM;
-
- crpc->crp_trans = NULL;
- crpc->crp_node = nd;
- crpc->crp_posted = 0;
- crpc->crp_finished = 0;
- crpc->crp_unpacked = 0;
- crpc->crp_status = 0;
- crpc->crp_stamp = 0;
- crpc->crp_embedded = embedded;
- INIT_LIST_HEAD(&crpc->crp_link);
-
- atomic_inc(&console_session.ses_rpc_counter);
-
- return 0;
-}
-
-static int
-lstcon_rpc_prep(struct lstcon_node *nd, int service, unsigned int feats,
- int bulk_npg, int bulk_len, struct lstcon_rpc **crpcpp)
-{
- struct lstcon_rpc *crpc = NULL;
- int rc;
-
- spin_lock(&console_session.ses_rpc_lock);
-
- crpc = list_first_entry_or_null(&console_session.ses_rpc_freelist,
- struct lstcon_rpc, crp_link);
- if (crpc)
- list_del_init(&crpc->crp_link);
-
- spin_unlock(&console_session.ses_rpc_lock);
-
- if (!crpc) {
- crpc = kzalloc(sizeof(*crpc), GFP_NOFS);
- if (!crpc)
- return -ENOMEM;
- }
-
- rc = lstcon_rpc_init(nd, service, feats, bulk_npg, bulk_len, 0, crpc);
- if (!rc) {
- *crpcpp = crpc;
- return 0;
- }
-
- kfree(crpc);
-
- return rc;
-}
-
-void
-lstcon_rpc_put(struct lstcon_rpc *crpc)
-{
- struct srpc_bulk *bulk = &crpc->crp_rpc->crpc_bulk;
- int i;
-
- LASSERT(list_empty(&crpc->crp_link));
-
- for (i = 0; i < bulk->bk_niov; i++) {
- if (!bulk->bk_iovs[i].bv_page)
- continue;
-
- __free_page(bulk->bk_iovs[i].bv_page);
- }
-
- srpc_client_rpc_decref(crpc->crp_rpc);
-
- if (crpc->crp_embedded) {
- /* embedded RPC, don't recycle it */
- memset(crpc, 0, sizeof(*crpc));
- crpc->crp_embedded = 1;
-
- } else {
- spin_lock(&console_session.ses_rpc_lock);
-
- list_add(&crpc->crp_link,
- &console_session.ses_rpc_freelist);
-
- spin_unlock(&console_session.ses_rpc_lock);
- }
-
- /* RPC is not alive now */
- atomic_dec(&console_session.ses_rpc_counter);
-}
-
-static void
-lstcon_rpc_post(struct lstcon_rpc *crpc)
-{
- struct lstcon_rpc_trans *trans = crpc->crp_trans;
-
- LASSERT(trans);
-
- atomic_inc(&trans->tas_remaining);
- crpc->crp_posted = 1;
-
- sfw_post_rpc(crpc->crp_rpc);
-}
-
-static char *
-lstcon_rpc_trans_name(int transop)
-{
- if (transop == LST_TRANS_SESNEW)
- return "SESNEW";
-
- if (transop == LST_TRANS_SESEND)
- return "SESEND";
-
- if (transop == LST_TRANS_SESQRY)
- return "SESQRY";
-
- if (transop == LST_TRANS_SESPING)
- return "SESPING";
-
- if (transop == LST_TRANS_TSBCLIADD)
- return "TSBCLIADD";
-
- if (transop == LST_TRANS_TSBSRVADD)
- return "TSBSRVADD";
-
- if (transop == LST_TRANS_TSBRUN)
- return "TSBRUN";
-
- if (transop == LST_TRANS_TSBSTOP)
- return "TSBSTOP";
-
- if (transop == LST_TRANS_TSBCLIQRY)
- return "TSBCLIQRY";
-
- if (transop == LST_TRANS_TSBSRVQRY)
- return "TSBSRVQRY";
-
- if (transop == LST_TRANS_STATQRY)
- return "STATQRY";
-
- return "Unknown";
-}
-
-int
-lstcon_rpc_trans_prep(struct list_head *translist, int transop,
- struct lstcon_rpc_trans **transpp)
-{
- struct lstcon_rpc_trans *trans;
-
- if (translist) {
- list_for_each_entry(trans, translist, tas_link) {
- /*
- * Can't enqueue two private transaction on
- * the same object
- */
- if ((trans->tas_opc & transop) == LST_TRANS_PRIVATE)
- return -EPERM;
- }
- }
-
- /* create a trans group */
- trans = kzalloc(sizeof(*trans), GFP_NOFS);
- if (!trans)
- return -ENOMEM;
-
- trans->tas_opc = transop;
-
- if (!translist)
- INIT_LIST_HEAD(&trans->tas_olink);
- else
- list_add_tail(&trans->tas_olink, translist);
-
- list_add_tail(&trans->tas_link, &console_session.ses_trans_list);
-
- INIT_LIST_HEAD(&trans->tas_rpcs_list);
- atomic_set(&trans->tas_remaining, 0);
- init_waitqueue_head(&trans->tas_waitq);
-
- spin_lock(&console_session.ses_rpc_lock);
- trans->tas_features = console_session.ses_features;
- spin_unlock(&console_session.ses_rpc_lock);
-
- *transpp = trans;
- return 0;
-}
-
-void
-lstcon_rpc_trans_addreq(struct lstcon_rpc_trans *trans, struct lstcon_rpc *crpc)
-{
- list_add_tail(&crpc->crp_link, &trans->tas_rpcs_list);
- crpc->crp_trans = trans;
-}
-
-void
-lstcon_rpc_trans_abort(struct lstcon_rpc_trans *trans, int error)
-{
- struct srpc_client_rpc *rpc;
- struct lstcon_rpc *crpc;
- struct lstcon_node *nd;
-
- list_for_each_entry(crpc, &trans->tas_rpcs_list, crp_link) {
- rpc = crpc->crp_rpc;
-
- spin_lock(&rpc->crpc_lock);
-
- if (!crpc->crp_posted || /* not posted */
- crpc->crp_stamp) { /* rpc done or aborted already */
- if (!crpc->crp_stamp) {
- crpc->crp_stamp = cfs_time_current();
- crpc->crp_status = -EINTR;
- }
- spin_unlock(&rpc->crpc_lock);
- continue;
- }
-
- crpc->crp_stamp = cfs_time_current();
- crpc->crp_status = error;
-
- spin_unlock(&rpc->crpc_lock);
-
- sfw_abort_rpc(rpc);
-
- if (error != -ETIMEDOUT)
- continue;
-
- nd = crpc->crp_node;
- if (cfs_time_after(nd->nd_stamp, crpc->crp_stamp))
- continue;
-
- nd->nd_stamp = crpc->crp_stamp;
- nd->nd_state = LST_NODE_DOWN;
- }
-}
-
-static int
-lstcon_rpc_trans_check(struct lstcon_rpc_trans *trans)
-{
- if (console_session.ses_shutdown &&
- !list_empty(&trans->tas_olink)) /* Not an end session RPC */
- return 1;
-
- return !atomic_read(&trans->tas_remaining) ? 1 : 0;
-}
-
-int
-lstcon_rpc_trans_postwait(struct lstcon_rpc_trans *trans, int timeout)
-{
- struct lstcon_rpc *crpc;
- int rc;
-
- if (list_empty(&trans->tas_rpcs_list))
- return 0;
-
- if (timeout < LST_TRANS_MIN_TIMEOUT)
- timeout = LST_TRANS_MIN_TIMEOUT;
-
- CDEBUG(D_NET, "Transaction %s started\n",
- lstcon_rpc_trans_name(trans->tas_opc));
-
- /* post all requests */
- list_for_each_entry(crpc, &trans->tas_rpcs_list, crp_link) {
- LASSERT(!crpc->crp_posted);
-
- lstcon_rpc_post(crpc);
- }
-
- mutex_unlock(&console_session.ses_mutex);
-
- rc = wait_event_interruptible_timeout(trans->tas_waitq,
- lstcon_rpc_trans_check(trans),
- timeout * HZ);
- rc = (rc > 0) ? 0 : ((rc < 0) ? -EINTR : -ETIMEDOUT);
-
- mutex_lock(&console_session.ses_mutex);
-
- if (console_session.ses_shutdown)
- rc = -ESHUTDOWN;
-
- if (rc || atomic_read(&trans->tas_remaining)) {
- /* treat short timeout as canceled */
- if (rc == -ETIMEDOUT && timeout < LST_TRANS_MIN_TIMEOUT * 2)
- rc = -EINTR;
-
- lstcon_rpc_trans_abort(trans, rc);
- }
-
- CDEBUG(D_NET, "Transaction %s stopped: %d\n",
- lstcon_rpc_trans_name(trans->tas_opc), rc);
-
- lstcon_rpc_trans_stat(trans, lstcon_trans_stat());
-
- return rc;
-}
-
-static int
-lstcon_rpc_get_reply(struct lstcon_rpc *crpc, struct srpc_msg **msgpp)
-{
- struct lstcon_node *nd = crpc->crp_node;
- struct srpc_client_rpc *rpc = crpc->crp_rpc;
- struct srpc_generic_reply *rep;
-
- LASSERT(nd && rpc);
- LASSERT(crpc->crp_stamp);
-
- if (crpc->crp_status) {
- *msgpp = NULL;
- return crpc->crp_status;
- }
-
- *msgpp = &rpc->crpc_replymsg;
- if (!crpc->crp_unpacked) {
- sfw_unpack_message(*msgpp);
- crpc->crp_unpacked = 1;
- }
-
- if (cfs_time_after(nd->nd_stamp, crpc->crp_stamp))
- return 0;
-
- nd->nd_stamp = crpc->crp_stamp;
- rep = &(*msgpp)->msg_body.reply;
-
- if (rep->sid.ses_nid == LNET_NID_ANY)
- nd->nd_state = LST_NODE_UNKNOWN;
- else if (lstcon_session_match(rep->sid))
- nd->nd_state = LST_NODE_ACTIVE;
- else
- nd->nd_state = LST_NODE_BUSY;
-
- return 0;
-}
-
-void
-lstcon_rpc_trans_stat(struct lstcon_rpc_trans *trans, struct lstcon_trans_stat *stat)
-{
- struct lstcon_rpc *crpc;
- struct srpc_msg *rep;
- int error;
-
- LASSERT(stat);
-
- memset(stat, 0, sizeof(*stat));
-
- list_for_each_entry(crpc, &trans->tas_rpcs_list, crp_link) {
- lstcon_rpc_stat_total(stat, 1);
-
- LASSERT(crpc->crp_stamp);
-
- error = lstcon_rpc_get_reply(crpc, &rep);
- if (error) {
- lstcon_rpc_stat_failure(stat, 1);
- if (!stat->trs_rpc_errno)
- stat->trs_rpc_errno = -error;
-
- continue;
- }
-
- lstcon_rpc_stat_success(stat, 1);
-
- lstcon_rpc_stat_reply(trans, rep, crpc->crp_node, stat);
- }
-
- if (trans->tas_opc == LST_TRANS_SESNEW && !stat->trs_fwk_errno) {
- stat->trs_fwk_errno =
- lstcon_session_feats_check(trans->tas_features);
- }
-
- CDEBUG(D_NET, "transaction %s : success %d, failure %d, total %d, RPC error(%d), Framework error(%d)\n",
- lstcon_rpc_trans_name(trans->tas_opc),
- lstcon_rpc_stat_success(stat, 0),
- lstcon_rpc_stat_failure(stat, 0),
- lstcon_rpc_stat_total(stat, 0),
- stat->trs_rpc_errno, stat->trs_fwk_errno);
-}
-
-int
-lstcon_rpc_trans_interpreter(struct lstcon_rpc_trans *trans,
- struct list_head __user *head_up,
- lstcon_rpc_readent_func_t readent)
-{
- struct list_head tmp;
- struct list_head __user *next;
- struct lstcon_rpc_ent *ent;
- struct srpc_generic_reply *rep;
- struct lstcon_rpc *crpc;
- struct srpc_msg *msg;
- struct lstcon_node *nd;
- long dur;
- struct timeval tv;
- int error;
-
- LASSERT(head_up);
-
- next = head_up;
-
- list_for_each_entry(crpc, &trans->tas_rpcs_list, crp_link) {
- if (copy_from_user(&tmp, next,
- sizeof(struct list_head)))
- return -EFAULT;
-
- next = tmp.next;
- if (next == head_up)
- return 0;
-
- ent = list_entry(next, struct lstcon_rpc_ent, rpe_link);
-
- LASSERT(crpc->crp_stamp);
-
- error = lstcon_rpc_get_reply(crpc, &msg);
-
- nd = crpc->crp_node;
-
- dur = (long)cfs_time_sub(crpc->crp_stamp,
- (unsigned long)console_session.ses_id.ses_stamp);
- jiffies_to_timeval(dur, &tv);
-
- if (copy_to_user(&ent->rpe_peer, &nd->nd_id,
- sizeof(struct lnet_process_id)) ||
- copy_to_user(&ent->rpe_stamp, &tv, sizeof(tv)) ||
- copy_to_user(&ent->rpe_state, &nd->nd_state,
- sizeof(nd->nd_state)) ||
- copy_to_user(&ent->rpe_rpc_errno, &error,
- sizeof(error)))
- return -EFAULT;
-
- if (error)
- continue;
-
- /* RPC is done */
- rep = (struct srpc_generic_reply *)&msg->msg_body.reply;
-
- if (copy_to_user(&ent->rpe_sid, &rep->sid, sizeof(rep->sid)) ||
- copy_to_user(&ent->rpe_fwk_errno, &rep->status,
- sizeof(rep->status)))
- return -EFAULT;
-
- if (!readent)
- continue;
-
- error = readent(trans->tas_opc, msg, ent);
- if (error)
- return error;
- }
-
- return 0;
-}
-
-void
-lstcon_rpc_trans_destroy(struct lstcon_rpc_trans *trans)
-{
- struct srpc_client_rpc *rpc;
- struct lstcon_rpc *crpc;
- struct lstcon_rpc *tmp;
- int count = 0;
-
- list_for_each_entry_safe(crpc, tmp, &trans->tas_rpcs_list, crp_link) {
- rpc = crpc->crp_rpc;
-
- spin_lock(&rpc->crpc_lock);
-
- /* free it if not posted or finished already */
- if (!crpc->crp_posted || crpc->crp_finished) {
- spin_unlock(&rpc->crpc_lock);
-
- list_del_init(&crpc->crp_link);
- lstcon_rpc_put(crpc);
-
- continue;
- }
-
- /*
- * rpcs can be still not callbacked (even LNetMDUnlink is
- * called) because huge timeout for inaccessible network,
- * don't make user wait for them, just abandon them, they
- * will be recycled in callback
- */
- LASSERT(crpc->crp_status);
-
- crpc->crp_node = NULL;
- crpc->crp_trans = NULL;
- list_del_init(&crpc->crp_link);
- count++;
-
- spin_unlock(&rpc->crpc_lock);
-
- atomic_dec(&trans->tas_remaining);
- }
-
- LASSERT(!atomic_read(&trans->tas_remaining));
-
- list_del(&trans->tas_link);
- if (!list_empty(&trans->tas_olink))
- list_del(&trans->tas_olink);
-
- CDEBUG(D_NET, "Transaction %s destroyed with %d pending RPCs\n",
- lstcon_rpc_trans_name(trans->tas_opc), count);
-
- kfree(trans);
-}
-
-int
-lstcon_sesrpc_prep(struct lstcon_node *nd, int transop,
- unsigned int feats, struct lstcon_rpc **crpc)
-{
- struct srpc_mksn_reqst *msrq;
- struct srpc_rmsn_reqst *rsrq;
- int rc;
-
- switch (transop) {
- case LST_TRANS_SESNEW:
- rc = lstcon_rpc_prep(nd, SRPC_SERVICE_MAKE_SESSION,
- feats, 0, 0, crpc);
- if (rc)
- return rc;
-
- msrq = &(*crpc)->crp_rpc->crpc_reqstmsg.msg_body.mksn_reqst;
- msrq->mksn_sid = console_session.ses_id;
- msrq->mksn_force = console_session.ses_force;
- strlcpy(msrq->mksn_name, console_session.ses_name,
- sizeof(msrq->mksn_name));
- break;
-
- case LST_TRANS_SESEND:
- rc = lstcon_rpc_prep(nd, SRPC_SERVICE_REMOVE_SESSION,
- feats, 0, 0, crpc);
- if (rc)
- return rc;
-
- rsrq = &(*crpc)->crp_rpc->crpc_reqstmsg.msg_body.rmsn_reqst;
- rsrq->rmsn_sid = console_session.ses_id;
- break;
-
- default:
- LBUG();
- }
-
- return 0;
-}
-
-int
-lstcon_dbgrpc_prep(struct lstcon_node *nd, unsigned int feats,
- struct lstcon_rpc **crpc)
-{
- struct srpc_debug_reqst *drq;
- int rc;
-
- rc = lstcon_rpc_prep(nd, SRPC_SERVICE_DEBUG, feats, 0, 0, crpc);
- if (rc)
- return rc;
-
- drq = &(*crpc)->crp_rpc->crpc_reqstmsg.msg_body.dbg_reqst;
-
- drq->dbg_sid = console_session.ses_id;
- drq->dbg_flags = 0;
-
- return rc;
-}
-
-int
-lstcon_batrpc_prep(struct lstcon_node *nd, int transop, unsigned int feats,
- struct lstcon_tsb_hdr *tsb, struct lstcon_rpc **crpc)
-{
- struct lstcon_batch *batch;
- struct srpc_batch_reqst *brq;
- int rc;
-
- rc = lstcon_rpc_prep(nd, SRPC_SERVICE_BATCH, feats, 0, 0, crpc);
- if (rc)
- return rc;
-
- brq = &(*crpc)->crp_rpc->crpc_reqstmsg.msg_body.bat_reqst;
-
- brq->bar_sid = console_session.ses_id;
- brq->bar_bid = tsb->tsb_id;
- brq->bar_testidx = tsb->tsb_index;
- brq->bar_opc = transop == LST_TRANS_TSBRUN ? SRPC_BATCH_OPC_RUN :
- (transop == LST_TRANS_TSBSTOP ? SRPC_BATCH_OPC_STOP :
- SRPC_BATCH_OPC_QUERY);
-
- if (transop != LST_TRANS_TSBRUN &&
- transop != LST_TRANS_TSBSTOP)
- return 0;
-
- LASSERT(!tsb->tsb_index);
-
- batch = (struct lstcon_batch *)tsb;
- brq->bar_arg = batch->bat_arg;
-
- return 0;
-}
-
-int
-lstcon_statrpc_prep(struct lstcon_node *nd, unsigned int feats,
- struct lstcon_rpc **crpc)
-{
- struct srpc_stat_reqst *srq;
- int rc;
-
- rc = lstcon_rpc_prep(nd, SRPC_SERVICE_QUERY_STAT, feats, 0, 0, crpc);
- if (rc)
- return rc;
-
- srq = &(*crpc)->crp_rpc->crpc_reqstmsg.msg_body.stat_reqst;
-
- srq->str_sid = console_session.ses_id;
- srq->str_type = 0; /* XXX remove it */
-
- return 0;
-}
-
-static struct lnet_process_id_packed *
-lstcon_next_id(int idx, int nkiov, struct bio_vec *kiov)
-{
- struct lnet_process_id_packed *pid;
- int i;
-
- i = idx / SFW_ID_PER_PAGE;
-
- LASSERT(i < nkiov);
-
- pid = (struct lnet_process_id_packed *)page_address(kiov[i].bv_page);
-
- return &pid[idx % SFW_ID_PER_PAGE];
-}
-
-static int
-lstcon_dstnodes_prep(struct lstcon_group *grp, int idx,
- int dist, int span, int nkiov, struct bio_vec *kiov)
-{
- struct lnet_process_id_packed *pid;
- struct lstcon_ndlink *ndl;
- struct lstcon_node *nd;
- int start;
- int end;
- int i = 0;
-
- LASSERT(dist >= 1);
- LASSERT(span >= 1);
- LASSERT(grp->grp_nnode >= 1);
-
- if (span > grp->grp_nnode)
- return -EINVAL;
-
- start = ((idx / dist) * span) % grp->grp_nnode;
- end = ((idx / dist) * span + span - 1) % grp->grp_nnode;
-
- list_for_each_entry(ndl, &grp->grp_ndl_list, ndl_link) {
- nd = ndl->ndl_node;
- if (i < start) {
- i++;
- continue;
- }
-
- if (i > (end >= start ? end : grp->grp_nnode))
- break;
-
- pid = lstcon_next_id((i - start), nkiov, kiov);
- pid->nid = nd->nd_id.nid;
- pid->pid = nd->nd_id.pid;
- i++;
- }
-
- if (start <= end) /* done */
- return 0;
-
- list_for_each_entry(ndl, &grp->grp_ndl_list, ndl_link) {
- if (i > grp->grp_nnode + end)
- break;
-
- nd = ndl->ndl_node;
- pid = lstcon_next_id((i - start), nkiov, kiov);
- pid->nid = nd->nd_id.nid;
- pid->pid = nd->nd_id.pid;
- i++;
- }
-
- return 0;
-}
-
-static int
-lstcon_pingrpc_prep(struct lst_test_ping_param *param, struct srpc_test_reqst *req)
-{
- struct test_ping_req *prq = &req->tsr_u.ping;
-
- prq->png_size = param->png_size;
- prq->png_flags = param->png_flags;
- /* TODO dest */
- return 0;
-}
-
-static int
-lstcon_bulkrpc_v0_prep(struct lst_test_bulk_param *param,
- struct srpc_test_reqst *req)
-{
- struct test_bulk_req *brq = &req->tsr_u.bulk_v0;
-
- brq->blk_opc = param->blk_opc;
- brq->blk_npg = DIV_ROUND_UP(param->blk_size, PAGE_SIZE);
- brq->blk_flags = param->blk_flags;
-
- return 0;
-}
-
-static int
-lstcon_bulkrpc_v1_prep(struct lst_test_bulk_param *param, bool is_client,
- struct srpc_test_reqst *req)
-{
- struct test_bulk_req_v1 *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 = is_client ? param->blk_cli_off : param->blk_srv_off;
-
- return 0;
-}
-
-int
-lstcon_testrpc_prep(struct lstcon_node *nd, int transop, unsigned int feats,
- struct lstcon_test *test, struct lstcon_rpc **crpc)
-{
- struct lstcon_group *sgrp = test->tes_src_grp;
- struct lstcon_group *dgrp = test->tes_dst_grp;
- struct srpc_test_reqst *trq;
- struct srpc_bulk *bulk;
- int i;
- 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) ?
- npg * PAGE_SIZE :
- sizeof(struct lnet_process_id_packed) * test->tes_span;
- }
-
- rc = lstcon_rpc_prep(nd, SRPC_SERVICE_TEST, feats, npg, nob, crpc);
- if (rc)
- return rc;
-
- trq = &(*crpc)->crp_rpc->crpc_reqstmsg.msg_body.tes_reqst;
-
- if (transop == LST_TRANS_TSBSRVADD) {
- int ndist = DIV_ROUND_UP(sgrp->grp_nnode, test->tes_dist);
- int nspan = DIV_ROUND_UP(dgrp->grp_nnode, test->tes_span);
- int nmax = DIV_ROUND_UP(ndist, nspan);
-
- trq->tsr_ndest = 0;
- trq->tsr_loop = nmax * test->tes_dist * test->tes_concur;
- } else {
- bulk = &(*crpc)->crp_rpc->crpc_bulk;
-
- for (i = 0; i < npg; i++) {
- int len;
-
- LASSERT(nob > 0);
-
- len = !(feats & LST_FEAT_BULK_LEN) ?
- PAGE_SIZE :
- min_t(int, nob, PAGE_SIZE);
- nob -= len;
-
- bulk->bk_iovs[i].bv_offset = 0;
- bulk->bk_iovs[i].bv_len = len;
- bulk->bk_iovs[i].bv_page = alloc_page(GFP_KERNEL);
-
- if (!bulk->bk_iovs[i].bv_page) {
- 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,
- npg, &bulk->bk_iovs[0]);
- if (rc) {
- lstcon_rpc_put(*crpc);
- return rc;
- }
-
- trq->tsr_ndest = test->tes_span;
- trq->tsr_loop = test->tes_loop;
- }
-
- trq->tsr_sid = console_session.ses_id;
- trq->tsr_bid = test->tes_hdr.tsb_id;
- trq->tsr_concur = test->tes_concur;
- trq->tsr_is_client = (transop == LST_TRANS_TSBCLIADD) ? 1 : 0;
- trq->tsr_stop_onerr = !!test->tes_stop_onerr;
-
- switch (test->tes_type) {
- case LST_TEST_PING:
- trq->tsr_service = SRPC_SERVICE_PING;
- rc = lstcon_pingrpc_prep((struct lst_test_ping_param *)
- &test->tes_param[0], trq);
- break;
-
- case LST_TEST_BULK:
- trq->tsr_service = SRPC_SERVICE_BRW;
- if (!(feats & LST_FEAT_BULK_LEN)) {
- rc = lstcon_bulkrpc_v0_prep((struct lst_test_bulk_param *)
- &test->tes_param[0], trq);
- } else {
- rc = lstcon_bulkrpc_v1_prep((struct lst_test_bulk_param *)
- &test->tes_param[0],
- trq->tsr_is_client, trq);
- }
-
- break;
- default:
- LBUG();
- break;
- }
-
- return rc;
-}
-
-static int
-lstcon_sesnew_stat_reply(struct lstcon_rpc_trans *trans,
- struct lstcon_node *nd, struct srpc_msg *reply)
-{
- struct srpc_mksn_reply *mksn_rep = &reply->msg_body.mksn_reply;
- int status = mksn_rep->mksn_status;
-
- if (!status &&
- (reply->msg_ses_feats & ~LST_FEATS_MASK)) {
- 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)
- return status;
-
- if (!trans->tas_feats_updated) {
- spin_lock(&console_session.ses_rpc_lock);
- if (!trans->tas_feats_updated) { /* recheck with lock */
- trans->tas_feats_updated = 1;
- trans->tas_features = reply->msg_ses_feats;
- }
- spin_unlock(&console_session.ses_rpc_lock);
- }
-
- 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);
- mksn_rep->mksn_status = EPROTO;
- status = EPROTO;
- }
-
- if (!status) {
- /* session timeout on remote node */
- nd->nd_timeout = mksn_rep->mksn_timeout;
- }
-
- return status;
-}
-
-void
-lstcon_rpc_stat_reply(struct lstcon_rpc_trans *trans, struct srpc_msg *msg,
- struct lstcon_node *nd, struct lstcon_trans_stat *stat)
-{
- struct srpc_rmsn_reply *rmsn_rep;
- struct srpc_debug_reply *dbg_rep;
- struct srpc_batch_reply *bat_rep;
- struct srpc_test_reply *test_rep;
- struct srpc_stat_reply *stat_rep;
- int rc = 0;
-
- switch (trans->tas_opc) {
- case LST_TRANS_SESNEW:
- rc = lstcon_sesnew_stat_reply(trans, nd, msg);
- if (!rc) {
- lstcon_sesop_stat_success(stat, 1);
- return;
- }
-
- lstcon_sesop_stat_failure(stat, 1);
- break;
-
- case LST_TRANS_SESEND:
- rmsn_rep = &msg->msg_body.rmsn_reply;
- /* ESRCH is not an error for end session */
- if (!rmsn_rep->rmsn_status ||
- rmsn_rep->rmsn_status == ESRCH) {
- lstcon_sesop_stat_success(stat, 1);
- return;
- }
-
- lstcon_sesop_stat_failure(stat, 1);
- rc = rmsn_rep->rmsn_status;
- break;
-
- case LST_TRANS_SESQRY:
- case LST_TRANS_SESPING:
- dbg_rep = &msg->msg_body.dbg_reply;
-
- if (dbg_rep->dbg_status == ESRCH) {
- lstcon_sesqry_stat_unknown(stat, 1);
- return;
- }
-
- if (lstcon_session_match(dbg_rep->dbg_sid))
- lstcon_sesqry_stat_active(stat, 1);
- else
- lstcon_sesqry_stat_busy(stat, 1);
- return;
-
- case LST_TRANS_TSBRUN:
- case LST_TRANS_TSBSTOP:
- bat_rep = &msg->msg_body.bat_reply;
-
- if (!bat_rep->bar_status) {
- lstcon_tsbop_stat_success(stat, 1);
- return;
- }
-
- if (bat_rep->bar_status == EPERM &&
- trans->tas_opc == LST_TRANS_TSBSTOP) {
- lstcon_tsbop_stat_success(stat, 1);
- return;
- }
-
- lstcon_tsbop_stat_failure(stat, 1);
- rc = bat_rep->bar_status;
- break;
-
- case LST_TRANS_TSBCLIQRY:
- case LST_TRANS_TSBSRVQRY:
- bat_rep = &msg->msg_body.bat_reply;
-
- if (bat_rep->bar_active)
- lstcon_tsbqry_stat_run(stat, 1);
- else
- lstcon_tsbqry_stat_idle(stat, 1);
-
- if (!bat_rep->bar_status)
- return;
-
- lstcon_tsbqry_stat_failure(stat, 1);
- rc = bat_rep->bar_status;
- break;
-
- case LST_TRANS_TSBCLIADD:
- case LST_TRANS_TSBSRVADD:
- test_rep = &msg->msg_body.tes_reply;
-
- if (!test_rep->tsr_status) {
- lstcon_tsbop_stat_success(stat, 1);
- return;
- }
-
- lstcon_tsbop_stat_failure(stat, 1);
- rc = test_rep->tsr_status;
- break;
-
- case LST_TRANS_STATQRY:
- stat_rep = &msg->msg_body.stat_reply;
-
- if (!stat_rep->str_status) {
- lstcon_statqry_stat_success(stat, 1);
- return;
- }
-
- lstcon_statqry_stat_failure(stat, 1);
- rc = stat_rep->str_status;
- break;
-
- default:
- LBUG();
- }
-
- if (!stat->trs_fwk_errno)
- stat->trs_fwk_errno = rc;
-}
-
-int
-lstcon_rpc_trans_ndlist(struct list_head *ndlist,
- struct list_head *translist, int transop,
- void *arg, lstcon_rpc_cond_func_t condition,
- struct lstcon_rpc_trans **transpp)
-{
- struct lstcon_rpc_trans *trans;
- struct lstcon_ndlink *ndl;
- struct lstcon_node *nd;
- struct lstcon_rpc *rpc;
- unsigned int feats;
- int rc;
-
- /* Creating session RPG for list of nodes */
-
- rc = lstcon_rpc_trans_prep(translist, transop, &trans);
- if (rc) {
- CERROR("Can't create transaction %d: %d\n", transop, rc);
- return rc;
- }
-
- feats = trans->tas_features;
- list_for_each_entry(ndl, ndlist, ndl_link) {
- rc = !condition ? 1 :
- condition(transop, ndl->ndl_node, arg);
-
- if (!rc)
- continue;
-
- if (rc < 0) {
- CDEBUG(D_NET, "Condition error while creating RPC for transaction %d: %d\n",
- transop, rc);
- break;
- }
-
- nd = ndl->ndl_node;
-
- switch (transop) {
- case LST_TRANS_SESNEW:
- case LST_TRANS_SESEND:
- 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,
- (struct lstcon_test *)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,
- (struct lstcon_tsb_hdr *)arg,
- &rpc);
- break;
- case LST_TRANS_STATQRY:
- rc = lstcon_statrpc_prep(nd, feats, &rpc);
- break;
- default:
- rc = -EINVAL;
- break;
- }
-
- if (rc) {
- CERROR("Failed to create RPC for transaction %s: %d\n",
- lstcon_rpc_trans_name(transop), rc);
- break;
- }
-
- lstcon_rpc_trans_addreq(trans, rpc);
- }
-
- if (!rc) {
- *transpp = trans;
- return 0;
- }
-
- lstcon_rpc_trans_destroy(trans);
-
- return rc;
-}
-
-static void
-lstcon_rpc_pinger(void *arg)
-{
- struct stt_timer *ptimer = (struct stt_timer *)arg;
- struct lstcon_rpc_trans *trans;
- struct lstcon_rpc *crpc;
- struct srpc_msg *rep;
- struct srpc_debug_reqst *drq;
- struct lstcon_ndlink *ndl;
- struct lstcon_node *nd;
- int intv;
- int count = 0;
- int rc;
-
- /*
- * RPC pinger is a special case of transaction,
- * it's called by timer at 8 seconds interval.
- */
- mutex_lock(&console_session.ses_mutex);
-
- if (console_session.ses_shutdown || console_session.ses_expired) {
- mutex_unlock(&console_session.ses_mutex);
- return;
- }
-
- if (!console_session.ses_expired &&
- ktime_get_real_seconds() - console_session.ses_laststamp >
- (time64_t)console_session.ses_timeout)
- console_session.ses_expired = 1;
-
- trans = console_session.ses_ping;
-
- LASSERT(trans);
-
- list_for_each_entry(ndl, &console_session.ses_ndl_list, ndl_link) {
- nd = ndl->ndl_node;
-
- if (console_session.ses_expired) {
- /* idle console, end session on all nodes */
- if (nd->nd_state != LST_NODE_ACTIVE)
- continue;
-
- rc = lstcon_sesrpc_prep(nd, LST_TRANS_SESEND,
- trans->tas_features, &crpc);
- if (rc) {
- CERROR("Out of memory\n");
- break;
- }
-
- lstcon_rpc_trans_addreq(trans, crpc);
- lstcon_rpc_post(crpc);
-
- continue;
- }
-
- crpc = &nd->nd_ping;
-
- if (crpc->crp_rpc) {
- LASSERT(crpc->crp_trans == trans);
- LASSERT(!list_empty(&crpc->crp_link));
-
- spin_lock(&crpc->crp_rpc->crpc_lock);
-
- LASSERT(crpc->crp_posted);
-
- if (!crpc->crp_finished) {
- /* in flight */
- spin_unlock(&crpc->crp_rpc->crpc_lock);
- continue;
- }
-
- spin_unlock(&crpc->crp_rpc->crpc_lock);
-
- lstcon_rpc_get_reply(crpc, &rep);
-
- list_del_init(&crpc->crp_link);
-
- lstcon_rpc_put(crpc);
- }
-
- if (nd->nd_state != LST_NODE_ACTIVE)
- continue;
-
- intv = (jiffies - nd->nd_stamp) / msecs_to_jiffies(MSEC_PER_SEC);
- if (intv < nd->nd_timeout / 2)
- continue;
-
- rc = lstcon_rpc_init(nd, SRPC_SERVICE_DEBUG,
- trans->tas_features, 0, 0, 1, crpc);
- if (rc) {
- CERROR("Out of memory\n");
- break;
- }
-
- drq = &crpc->crp_rpc->crpc_reqstmsg.msg_body.dbg_reqst;
-
- drq->dbg_sid = console_session.ses_id;
- drq->dbg_flags = 0;
-
- lstcon_rpc_trans_addreq(trans, crpc);
- lstcon_rpc_post(crpc);
-
- count++;
- }
-
- if (console_session.ses_expired) {
- mutex_unlock(&console_session.ses_mutex);
- return;
- }
-
- CDEBUG(D_NET, "Ping %d nodes in session\n", count);
-
- ptimer->stt_expires = ktime_get_real_seconds() + LST_PING_INTERVAL;
- stt_add_timer(ptimer);
-
- mutex_unlock(&console_session.ses_mutex);
-}
-
-int
-lstcon_rpc_pinger_start(void)
-{
- struct stt_timer *ptimer;
- int rc;
-
- LASSERT(list_empty(&console_session.ses_rpc_freelist));
- LASSERT(!atomic_read(&console_session.ses_rpc_counter));
-
- rc = lstcon_rpc_trans_prep(NULL, LST_TRANS_SESPING,
- &console_session.ses_ping);
- if (rc) {
- CERROR("Failed to create console pinger\n");
- return rc;
- }
-
- ptimer = &console_session.ses_ping_timer;
- ptimer->stt_expires = ktime_get_real_seconds() + LST_PING_INTERVAL;
-
- stt_add_timer(ptimer);
-
- return 0;
-}
-
-void
-lstcon_rpc_pinger_stop(void)
-{
- LASSERT(console_session.ses_shutdown);
-
- stt_del_timer(&console_session.ses_ping_timer);
-
- lstcon_rpc_trans_abort(console_session.ses_ping, -ESHUTDOWN);
- lstcon_rpc_trans_stat(console_session.ses_ping, lstcon_trans_stat());
- lstcon_rpc_trans_destroy(console_session.ses_ping);
-
- memset(lstcon_trans_stat(), 0, sizeof(struct lstcon_trans_stat));
-
- console_session.ses_ping = NULL;
-}
-
-void
-lstcon_rpc_cleanup_wait(void)
-{
- struct lstcon_rpc_trans *trans;
- struct lstcon_rpc *crpc;
- struct lstcon_rpc *temp;
- struct list_head *pacer;
- struct list_head zlist;
-
- /* Called with hold of global mutex */
-
- LASSERT(console_session.ses_shutdown);
-
- while (!list_empty(&console_session.ses_trans_list)) {
- list_for_each(pacer, &console_session.ses_trans_list) {
- trans = list_entry(pacer, struct lstcon_rpc_trans,
- tas_link);
-
- CDEBUG(D_NET, "Session closed, wakeup transaction %s\n",
- lstcon_rpc_trans_name(trans->tas_opc));
-
- wake_up(&trans->tas_waitq);
- }
-
- mutex_unlock(&console_session.ses_mutex);
-
- CWARN("Session is shutting down, waiting for termination of transactions\n");
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ);
-
- mutex_lock(&console_session.ses_mutex);
- }
-
- spin_lock(&console_session.ses_rpc_lock);
-
- lst_wait_until(!atomic_read(&console_session.ses_rpc_counter),
- console_session.ses_rpc_lock,
- "Network is not accessible or target is down, waiting for %d console RPCs to being recycled\n",
- atomic_read(&console_session.ses_rpc_counter));
-
- list_add(&zlist, &console_session.ses_rpc_freelist);
- list_del_init(&console_session.ses_rpc_freelist);
-
- spin_unlock(&console_session.ses_rpc_lock);
-
- list_for_each_entry_safe(crpc, temp, &zlist, crp_link) {
- list_del(&crpc->crp_link);
- kfree(crpc);
- }
-}
-
-int
-lstcon_rpc_module_init(void)
-{
- INIT_LIST_HEAD(&console_session.ses_ping_timer.stt_list);
- console_session.ses_ping_timer.stt_func = lstcon_rpc_pinger;
- console_session.ses_ping_timer.stt_data = &console_session.ses_ping_timer;
-
- console_session.ses_ping = NULL;
-
- spin_lock_init(&console_session.ses_rpc_lock);
- atomic_set(&console_session.ses_rpc_counter, 0);
- INIT_LIST_HEAD(&console_session.ses_rpc_freelist);
-
- return 0;
-}
-
-void
-lstcon_rpc_module_fini(void)
-{
- LASSERT(list_empty(&console_session.ses_rpc_freelist));
- LASSERT(!atomic_read(&console_session.ses_rpc_counter));
-}
diff --git a/drivers/staging/lustre/lnet/selftest/conrpc.h b/drivers/staging/lustre/lnet/selftest/conrpc.h
deleted file mode 100644
index 374a5f31ef6f..000000000000
--- a/drivers/staging/lustre/lnet/selftest/conrpc.h
+++ /dev/null
@@ -1,143 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * GPL HEADER START
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 only,
- * as published by the Free Software Foundation.
- *
- * This program 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 version 2 for more details (a copy is included
- * in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2011, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * /lnet/selftest/conrpc.h
- *
- * Console rpc
- *
- * Author: Liang Zhen <liang@whamcloud.com>
- */
-
-#ifndef __LST_CONRPC_H__
-#define __LST_CONRPC_H__
-
-#include <linux/libcfs/libcfs.h>
-#include <linux/lnet/lib-types.h>
-#include <uapi/linux/lnet/lnetst.h>
-#include "rpc.h"
-#include "selftest.h"
-
-/* Console rpc and rpc transaction */
-#define LST_TRANS_TIMEOUT 30
-#define LST_TRANS_MIN_TIMEOUT 3
-
-#define LST_VALIDATE_TIMEOUT(t) min(max(t, LST_TRANS_MIN_TIMEOUT), LST_TRANS_TIMEOUT)
-
-#define LST_PING_INTERVAL 8
-
-struct lstcon_rpc_trans;
-struct lstcon_tsb_hdr;
-struct lstcon_test;
-struct lstcon_node;
-
-struct lstcon_rpc {
- struct list_head crp_link; /* chain on rpc transaction */
- struct srpc_client_rpc *crp_rpc; /* client rpc */
- struct lstcon_node *crp_node; /* destination node */
- struct lstcon_rpc_trans *crp_trans; /* conrpc transaction */
-
- unsigned int crp_posted:1; /* rpc is posted */
- unsigned int crp_finished:1; /* rpc is finished */
- unsigned int crp_unpacked:1; /* reply is unpacked */
- /** RPC is embedded in other structure and can't free it */
- unsigned int crp_embedded:1;
- int crp_status; /* console rpc errors */
- unsigned long crp_stamp; /* replied time stamp */
-};
-
-struct lstcon_rpc_trans {
- struct list_head tas_olink; /* link chain on owner list */
- struct list_head tas_link; /* link chain on global list */
- int tas_opc; /* operation code of transaction */
- unsigned int tas_feats_updated; /* features mask is uptodate */
- unsigned int tas_features; /* test features mask */
- wait_queue_head_t tas_waitq; /* wait queue head */
- atomic_t tas_remaining; /* # of un-scheduled rpcs */
- struct list_head tas_rpcs_list; /* queued requests */
-};
-
-#define LST_TRANS_PRIVATE 0x1000
-
-#define LST_TRANS_SESNEW (LST_TRANS_PRIVATE | 0x01)
-#define LST_TRANS_SESEND (LST_TRANS_PRIVATE | 0x02)
-#define LST_TRANS_SESQRY 0x03
-#define LST_TRANS_SESPING 0x04
-
-#define LST_TRANS_TSBCLIADD (LST_TRANS_PRIVATE | 0x11)
-#define LST_TRANS_TSBSRVADD (LST_TRANS_PRIVATE | 0x12)
-#define LST_TRANS_TSBRUN (LST_TRANS_PRIVATE | 0x13)
-#define LST_TRANS_TSBSTOP (LST_TRANS_PRIVATE | 0x14)
-#define LST_TRANS_TSBCLIQRY 0x15
-#define LST_TRANS_TSBSRVQRY 0x16
-
-#define LST_TRANS_STATQRY 0x21
-
-typedef int (*lstcon_rpc_cond_func_t)(int, struct lstcon_node *, void *);
-typedef int (*lstcon_rpc_readent_func_t)(int, struct srpc_msg *,
- struct lstcon_rpc_ent __user *);
-
-int lstcon_sesrpc_prep(struct lstcon_node *nd, int transop,
- unsigned int version, struct lstcon_rpc **crpc);
-int lstcon_dbgrpc_prep(struct lstcon_node *nd,
- unsigned int version, struct lstcon_rpc **crpc);
-int lstcon_batrpc_prep(struct lstcon_node *nd, int transop,
- unsigned int version, struct lstcon_tsb_hdr *tsb,
- struct lstcon_rpc **crpc);
-int lstcon_testrpc_prep(struct lstcon_node *nd, int transop,
- unsigned int version, struct lstcon_test *test,
- struct lstcon_rpc **crpc);
-int lstcon_statrpc_prep(struct lstcon_node *nd, unsigned int version,
- struct lstcon_rpc **crpc);
-void lstcon_rpc_put(struct lstcon_rpc *crpc);
-int lstcon_rpc_trans_prep(struct list_head *translist,
- int transop, struct lstcon_rpc_trans **transpp);
-int lstcon_rpc_trans_ndlist(struct list_head *ndlist,
- struct list_head *translist, int transop,
- void *arg, lstcon_rpc_cond_func_t condition,
- struct lstcon_rpc_trans **transpp);
-void lstcon_rpc_trans_stat(struct lstcon_rpc_trans *trans,
- struct lstcon_trans_stat *stat);
-int lstcon_rpc_trans_interpreter(struct lstcon_rpc_trans *trans,
- struct list_head __user *head_up,
- lstcon_rpc_readent_func_t readent);
-void lstcon_rpc_trans_abort(struct lstcon_rpc_trans *trans, int error);
-void lstcon_rpc_trans_destroy(struct lstcon_rpc_trans *trans);
-void lstcon_rpc_trans_addreq(struct lstcon_rpc_trans *trans,
- struct lstcon_rpc *req);
-int lstcon_rpc_trans_postwait(struct lstcon_rpc_trans *trans, int timeout);
-int lstcon_rpc_pinger_start(void);
-void lstcon_rpc_pinger_stop(void);
-void lstcon_rpc_cleanup_wait(void);
-int lstcon_rpc_module_init(void);
-void lstcon_rpc_module_fini(void);
-
-#endif
diff --git a/drivers/staging/lustre/lnet/selftest/console.c b/drivers/staging/lustre/lnet/selftest/console.c
deleted file mode 100644
index 1acd5cb324b1..000000000000
--- a/drivers/staging/lustre/lnet/selftest/console.c
+++ /dev/null
@@ -1,2101 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * GPL HEADER START
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 only,
- * as published by the Free Software Foundation.
- *
- * This program 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 version 2 for more details (a copy is included
- * in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2012, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * lnet/selftest/conctl.c
- *
- * Infrastructure of LST console
- *
- * Author: Liang Zhen <liangzhen@clusterfs.com>
- */
-
-#include <linux/libcfs/libcfs.h>
-#include <linux/lnet/lib-lnet.h>
-#include "console.h"
-#include "conrpc.h"
-
-#define LST_NODE_STATE_COUNTER(nd, p) \
-do { \
- if ((nd)->nd_state == LST_NODE_ACTIVE) \
- (p)->nle_nactive++; \
- else if ((nd)->nd_state == LST_NODE_BUSY) \
- (p)->nle_nbusy++; \
- else if ((nd)->nd_state == LST_NODE_DOWN) \
- (p)->nle_ndown++; \
- else \
- (p)->nle_nunknown++; \
- (p)->nle_nnode++; \
-} while (0)
-
-struct lstcon_session console_session;
-
-static void
-lstcon_node_get(struct lstcon_node *nd)
-{
- LASSERT(nd->nd_ref >= 1);
-
- nd->nd_ref++;
-}
-
-static int
-lstcon_node_find(struct lnet_process_id id, struct lstcon_node **ndpp,
- int create)
-{
- struct lstcon_ndlink *ndl;
- unsigned int idx = LNET_NIDADDR(id.nid) % LST_GLOBAL_HASHSIZE;
-
- LASSERT(id.nid != LNET_NID_ANY);
-
- list_for_each_entry(ndl, &console_session.ses_ndl_hash[idx],
- ndl_hlink) {
- if (ndl->ndl_node->nd_id.nid != id.nid ||
- ndl->ndl_node->nd_id.pid != id.pid)
- continue;
-
- lstcon_node_get(ndl->ndl_node);
- *ndpp = ndl->ndl_node;
- return 0;
- }
-
- if (!create)
- return -ENOENT;
-
- *ndpp = kzalloc(sizeof(**ndpp) + sizeof(*ndl), GFP_KERNEL);
- if (!*ndpp)
- return -ENOMEM;
-
- ndl = (struct lstcon_ndlink *)(*ndpp + 1);
-
- ndl->ndl_node = *ndpp;
-
- ndl->ndl_node->nd_ref = 1;
- ndl->ndl_node->nd_id = id;
- ndl->ndl_node->nd_stamp = cfs_time_current();
- ndl->ndl_node->nd_state = LST_NODE_UNKNOWN;
- ndl->ndl_node->nd_timeout = 0;
- memset(&ndl->ndl_node->nd_ping, 0, sizeof(struct lstcon_rpc));
-
- /*
- * queued in global hash & list, no refcount is taken by
- * global hash & list, if caller release his refcount,
- * node will be released
- */
- list_add_tail(&ndl->ndl_hlink, &console_session.ses_ndl_hash[idx]);
- list_add_tail(&ndl->ndl_link, &console_session.ses_ndl_list);
-
- return 0;
-}
-
-static void
-lstcon_node_put(struct lstcon_node *nd)
-{
- struct lstcon_ndlink *ndl;
-
- LASSERT(nd->nd_ref > 0);
-
- if (--nd->nd_ref > 0)
- return;
-
- ndl = (struct lstcon_ndlink *)(nd + 1);
-
- LASSERT(!list_empty(&ndl->ndl_link));
- LASSERT(!list_empty(&ndl->ndl_hlink));
-
- /* remove from session */
- list_del(&ndl->ndl_link);
- list_del(&ndl->ndl_hlink);
-
- kfree(nd);
-}
-
-static int
-lstcon_ndlink_find(struct list_head *hash, struct lnet_process_id id,
- struct lstcon_ndlink **ndlpp, int create)
-{
- unsigned int idx = LNET_NIDADDR(id.nid) % LST_NODE_HASHSIZE;
- struct lstcon_ndlink *ndl;
- struct lstcon_node *nd;
- int rc;
-
- if (id.nid == LNET_NID_ANY)
- return -EINVAL;
-
- /* search in hash */
- list_for_each_entry(ndl, &hash[idx], ndl_hlink) {
- if (ndl->ndl_node->nd_id.nid != id.nid ||
- ndl->ndl_node->nd_id.pid != id.pid)
- continue;
-
- *ndlpp = ndl;
- return 0;
- }
-
- if (!create)
- return -ENOENT;
-
- /* find or create in session hash */
- rc = lstcon_node_find(id, &nd, (create == 1) ? 1 : 0);
- if (rc)
- return rc;
-
- ndl = kzalloc(sizeof(struct lstcon_ndlink), GFP_NOFS);
- if (!ndl) {
- lstcon_node_put(nd);
- return -ENOMEM;
- }
-
- *ndlpp = ndl;
-
- ndl->ndl_node = nd;
- INIT_LIST_HEAD(&ndl->ndl_link);
- list_add_tail(&ndl->ndl_hlink, &hash[idx]);
-
- return 0;
-}
-
-static void
-lstcon_ndlink_release(struct lstcon_ndlink *ndl)
-{
- LASSERT(list_empty(&ndl->ndl_link));
- LASSERT(!list_empty(&ndl->ndl_hlink));
-
- list_del(&ndl->ndl_hlink); /* delete from hash */
- lstcon_node_put(ndl->ndl_node);
-
- kfree(ndl);
-}
-
-static int
-lstcon_group_alloc(char *name, struct lstcon_group **grpp)
-{
- struct lstcon_group *grp;
- int i;
-
- grp = kmalloc(offsetof(struct lstcon_group,
- grp_ndl_hash[LST_NODE_HASHSIZE]),
- GFP_KERNEL);
- if (!grp)
- return -ENOMEM;
-
- grp->grp_ref = 1;
- if (name) {
- if (strlen(name) > sizeof(grp->grp_name) - 1) {
- kfree(grp);
- return -E2BIG;
- }
- strncpy(grp->grp_name, name, sizeof(grp->grp_name));
- }
-
- INIT_LIST_HEAD(&grp->grp_link);
- INIT_LIST_HEAD(&grp->grp_ndl_list);
- INIT_LIST_HEAD(&grp->grp_trans_list);
-
- for (i = 0; i < LST_NODE_HASHSIZE; i++)
- INIT_LIST_HEAD(&grp->grp_ndl_hash[i]);
-
- *grpp = grp;
-
- return 0;
-}
-
-static void
-lstcon_group_addref(struct lstcon_group *grp)
-{
- grp->grp_ref++;
-}
-
-static void lstcon_group_ndlink_release(struct lstcon_group *,
- struct lstcon_ndlink *);
-
-static void
-lstcon_group_drain(struct lstcon_group *grp, int keep)
-{
- struct lstcon_ndlink *ndl;
- struct lstcon_ndlink *tmp;
-
- list_for_each_entry_safe(ndl, tmp, &grp->grp_ndl_list, ndl_link) {
- if (!(ndl->ndl_node->nd_state & keep))
- lstcon_group_ndlink_release(grp, ndl);
- }
-}
-
-static void
-lstcon_group_decref(struct lstcon_group *grp)
-{
- int i;
-
- if (--grp->grp_ref > 0)
- return;
-
- if (!list_empty(&grp->grp_link))
- list_del(&grp->grp_link);
-
- lstcon_group_drain(grp, 0);
-
- for (i = 0; i < LST_NODE_HASHSIZE; i++)
- LASSERT(list_empty(&grp->grp_ndl_hash[i]));
-
- kfree(grp);
-}
-
-static int
-lstcon_group_find(const char *name, struct lstcon_group **grpp)
-{
- struct lstcon_group *grp;
-
- list_for_each_entry(grp, &console_session.ses_grp_list, grp_link) {
- if (strncmp(grp->grp_name, name, LST_NAME_SIZE))
- continue;
-
- lstcon_group_addref(grp); /* +1 ref for caller */
- *grpp = grp;
- return 0;
- }
-
- return -ENOENT;
-}
-
-static int
-lstcon_group_ndlink_find(struct lstcon_group *grp, struct lnet_process_id id,
- struct lstcon_ndlink **ndlpp, int create)
-{
- int rc;
-
- rc = lstcon_ndlink_find(&grp->grp_ndl_hash[0], id, ndlpp, create);
- if (rc)
- return rc;
-
- if (!list_empty(&(*ndlpp)->ndl_link))
- return 0;
-
- list_add_tail(&(*ndlpp)->ndl_link, &grp->grp_ndl_list);
- grp->grp_nnode++;
-
- return 0;
-}
-
-static void
-lstcon_group_ndlink_release(struct lstcon_group *grp, struct lstcon_ndlink *ndl)
-{
- list_del_init(&ndl->ndl_link);
- lstcon_ndlink_release(ndl);
- grp->grp_nnode--;
-}
-
-static void
-lstcon_group_ndlink_move(struct lstcon_group *old,
- struct lstcon_group *new, struct lstcon_ndlink *ndl)
-{
- unsigned int idx = LNET_NIDADDR(ndl->ndl_node->nd_id.nid) %
- LST_NODE_HASHSIZE;
-
- list_del(&ndl->ndl_hlink);
- list_del(&ndl->ndl_link);
- old->grp_nnode--;
-
- list_add_tail(&ndl->ndl_hlink, &new->grp_ndl_hash[idx]);
- list_add_tail(&ndl->ndl_link, &new->grp_ndl_list);
- new->grp_nnode++;
-}
-
-static void
-lstcon_group_move(struct lstcon_group *old, struct lstcon_group *new)
-{
- struct lstcon_ndlink *ndl;
-
- while (!list_empty(&old->grp_ndl_list)) {
- ndl = list_entry(old->grp_ndl_list.next,
- struct lstcon_ndlink, ndl_link);
- lstcon_group_ndlink_move(old, new, ndl);
- }
-}
-
-static int
-lstcon_sesrpc_condition(int transop, struct lstcon_node *nd, void *arg)
-{
- struct lstcon_group *grp = (struct lstcon_group *)arg;
-
- switch (transop) {
- case LST_TRANS_SESNEW:
- if (nd->nd_state == LST_NODE_ACTIVE)
- return 0;
- break;
-
- case LST_TRANS_SESEND:
- if (nd->nd_state != LST_NODE_ACTIVE)
- return 0;
-
- if (grp && nd->nd_ref > 1)
- return 0;
- break;
-
- case LST_TRANS_SESQRY:
- break;
-
- default:
- LBUG();
- }
-
- return 1;
-}
-
-static int
-lstcon_sesrpc_readent(int transop, struct srpc_msg *msg,
- struct lstcon_rpc_ent __user *ent_up)
-{
- struct srpc_debug_reply *rep;
-
- switch (transop) {
- case LST_TRANS_SESNEW:
- case LST_TRANS_SESEND:
- return 0;
-
- case LST_TRANS_SESQRY:
- rep = &msg->msg_body.dbg_reply;
-
- if (copy_to_user(&ent_up->rpe_priv[0],
- &rep->dbg_timeout, sizeof(int)) ||
- copy_to_user(&ent_up->rpe_payload[0],
- &rep->dbg_name, LST_NAME_SIZE))
- return -EFAULT;
-
- return 0;
-
- default:
- LBUG();
- }
-
- return 0;
-}
-
-static int
-lstcon_group_nodes_add(struct lstcon_group *grp,
- int count, struct lnet_process_id __user *ids_up,
- unsigned int *featp,
- struct list_head __user *result_up)
-{
- struct lstcon_rpc_trans *trans;
- struct lstcon_ndlink *ndl;
- struct lstcon_group *tmp;
- struct lnet_process_id id;
- int i;
- int rc;
-
- rc = lstcon_group_alloc(NULL, &tmp);
- if (rc) {
- CERROR("Out of memory\n");
- return -ENOMEM;
- }
-
- for (i = 0 ; i < count; i++) {
- if (copy_from_user(&id, &ids_up[i], sizeof(id))) {
- rc = -EFAULT;
- break;
- }
-
- /* skip if it's in this group already */
- rc = lstcon_group_ndlink_find(grp, id, &ndl, 0);
- if (!rc)
- continue;
-
- /* add to tmp group */
- rc = lstcon_group_ndlink_find(tmp, id, &ndl, 1);
- if (rc) {
- CERROR("Can't create ndlink, out of memory\n");
- break;
- }
- }
-
- if (rc) {
- lstcon_group_decref(tmp);
- return rc;
- }
-
- rc = lstcon_rpc_trans_ndlist(&tmp->grp_ndl_list,
- &tmp->grp_trans_list, LST_TRANS_SESNEW,
- tmp, lstcon_sesrpc_condition, &trans);
- if (rc) {
- CERROR("Can't create transaction: %d\n", rc);
- lstcon_group_decref(tmp);
- return rc;
- }
-
- /* post all RPCs */
- lstcon_rpc_trans_postwait(trans, LST_TRANS_TIMEOUT);
-
- rc = lstcon_rpc_trans_interpreter(trans, result_up,
- lstcon_sesrpc_readent);
- *featp = trans->tas_features;
-
- /* destroy all RPGs */
- lstcon_rpc_trans_destroy(trans);
-
- lstcon_group_move(tmp, grp);
- lstcon_group_decref(tmp);
-
- return rc;
-}
-
-static int
-lstcon_group_nodes_remove(struct lstcon_group *grp,
- int count, struct lnet_process_id __user *ids_up,
- struct list_head __user *result_up)
-{
- struct lstcon_rpc_trans *trans;
- struct lstcon_ndlink *ndl;
- struct lstcon_group *tmp;
- struct lnet_process_id id;
- int rc;
- int i;
-
- /* End session and remove node from the group */
-
- rc = lstcon_group_alloc(NULL, &tmp);
- if (rc) {
- CERROR("Out of memory\n");
- return -ENOMEM;
- }
-
- for (i = 0; i < count; i++) {
- if (copy_from_user(&id, &ids_up[i], sizeof(id))) {
- rc = -EFAULT;
- goto error;
- }
-
- /* move node to tmp group */
- if (!lstcon_group_ndlink_find(grp, id, &ndl, 0))
- lstcon_group_ndlink_move(grp, tmp, ndl);
- }
-
- rc = lstcon_rpc_trans_ndlist(&tmp->grp_ndl_list,
- &tmp->grp_trans_list, LST_TRANS_SESEND,
- tmp, lstcon_sesrpc_condition, &trans);
- if (rc) {
- CERROR("Can't create transaction: %d\n", rc);
- goto error;
- }
-
- lstcon_rpc_trans_postwait(trans, LST_TRANS_TIMEOUT);
-
- rc = lstcon_rpc_trans_interpreter(trans, result_up, NULL);
-
- lstcon_rpc_trans_destroy(trans);
- /* release nodes anyway, because we can't rollback status */
- lstcon_group_decref(tmp);
-
- return rc;
-error:
- lstcon_group_move(tmp, grp);
- lstcon_group_decref(tmp);
-
- return rc;
-}
-
-int
-lstcon_group_add(char *name)
-{
- struct lstcon_group *grp;
- int rc;
-
- rc = lstcon_group_find(name, &grp) ? 0 : -EEXIST;
- if (rc) {
- /* find a group with same name */
- lstcon_group_decref(grp);
- return rc;
- }
-
- rc = lstcon_group_alloc(name, &grp);
- if (rc) {
- CERROR("Can't allocate descriptor for group %s\n", name);
- return -ENOMEM;
- }
-
- list_add_tail(&grp->grp_link, &console_session.ses_grp_list);
-
- return rc;
-}
-
-int
-lstcon_nodes_add(char *name, int count, struct lnet_process_id __user *ids_up,
- unsigned int *featp, struct list_head __user *result_up)
-{
- struct lstcon_group *grp;
- int rc;
-
- LASSERT(count > 0);
- LASSERT(ids_up);
-
- rc = lstcon_group_find(name, &grp);
- if (rc) {
- CDEBUG(D_NET, "Can't find group %s\n", name);
- return rc;
- }
-
- if (grp->grp_ref > 2) {
- /* referred by other threads or test */
- CDEBUG(D_NET, "Group %s is busy\n", name);
- lstcon_group_decref(grp);
-
- return -EBUSY;
- }
-
- rc = lstcon_group_nodes_add(grp, count, ids_up, featp, result_up);
-
- lstcon_group_decref(grp);
-
- return rc;
-}
-
-int
-lstcon_group_del(char *name)
-{
- struct lstcon_rpc_trans *trans;
- struct lstcon_group *grp;
- int rc;
-
- rc = lstcon_group_find(name, &grp);
- if (rc) {
- CDEBUG(D_NET, "Can't find group: %s\n", name);
- return rc;
- }
-
- if (grp->grp_ref > 2) {
- /* referred by others threads or test */
- CDEBUG(D_NET, "Group %s is busy\n", name);
- lstcon_group_decref(grp);
- return -EBUSY;
- }
-
- rc = lstcon_rpc_trans_ndlist(&grp->grp_ndl_list,
- &grp->grp_trans_list, LST_TRANS_SESEND,
- grp, lstcon_sesrpc_condition, &trans);
- if (rc) {
- CERROR("Can't create transaction: %d\n", rc);
- lstcon_group_decref(grp);
- return rc;
- }
-
- lstcon_rpc_trans_postwait(trans, LST_TRANS_TIMEOUT);
-
- lstcon_rpc_trans_destroy(trans);
-
- lstcon_group_decref(grp);
- /*
- * -ref for session, it's destroyed,
- * status can't be rolled back, destroy group anyway
- */
- lstcon_group_decref(grp);
-
- return rc;
-}
-
-int
-lstcon_group_clean(char *name, int args)
-{
- struct lstcon_group *grp = NULL;
- int rc;
-
- rc = lstcon_group_find(name, &grp);
- if (rc) {
- CDEBUG(D_NET, "Can't find group %s\n", name);
- return rc;
- }
-
- if (grp->grp_ref > 2) {
- /* referred by test */
- CDEBUG(D_NET, "Group %s is busy\n", name);
- lstcon_group_decref(grp);
- return -EBUSY;
- }
-
- args = (LST_NODE_ACTIVE | LST_NODE_BUSY |
- LST_NODE_DOWN | LST_NODE_UNKNOWN) & ~args;
-
- lstcon_group_drain(grp, args);
-
- lstcon_group_decref(grp);
- /* release empty group */
- if (list_empty(&grp->grp_ndl_list))
- lstcon_group_decref(grp);
-
- return 0;
-}
-
-int
-lstcon_nodes_remove(char *name, int count,
- struct lnet_process_id __user *ids_up,
- struct list_head __user *result_up)
-{
- struct lstcon_group *grp = NULL;
- int rc;
-
- rc = lstcon_group_find(name, &grp);
- if (rc) {
- CDEBUG(D_NET, "Can't find group: %s\n", name);
- return rc;
- }
-
- if (grp->grp_ref > 2) {
- /* referred by test */
- CDEBUG(D_NET, "Group %s is busy\n", name);
- lstcon_group_decref(grp);
- return -EBUSY;
- }
-
- rc = lstcon_group_nodes_remove(grp, count, ids_up, result_up);
-
- lstcon_group_decref(grp);
- /* release empty group */
- if (list_empty(&grp->grp_ndl_list))
- lstcon_group_decref(grp);
-
- return rc;
-}
-
-int
-lstcon_group_refresh(char *name, struct list_head __user *result_up)
-{
- struct lstcon_rpc_trans *trans;
- struct lstcon_group *grp;
- int rc;
-
- rc = lstcon_group_find(name, &grp);
- if (rc) {
- CDEBUG(D_NET, "Can't find group: %s\n", name);
- return rc;
- }
-
- if (grp->grp_ref > 2) {
- /* referred by test */
- CDEBUG(D_NET, "Group %s is busy\n", name);
- lstcon_group_decref(grp);
- return -EBUSY;
- }
-
- /* re-invite all inactive nodes int the group */
- rc = lstcon_rpc_trans_ndlist(&grp->grp_ndl_list,
- &grp->grp_trans_list, LST_TRANS_SESNEW,
- grp, lstcon_sesrpc_condition, &trans);
- if (rc) {
- /* local error, return */
- CDEBUG(D_NET, "Can't create transaction: %d\n", rc);
- lstcon_group_decref(grp);
- return rc;
- }
-
- lstcon_rpc_trans_postwait(trans, LST_TRANS_TIMEOUT);
-
- rc = lstcon_rpc_trans_interpreter(trans, result_up, NULL);
-
- lstcon_rpc_trans_destroy(trans);
- /* -ref for me */
- lstcon_group_decref(grp);
-
- return rc;
-}
-
-int
-lstcon_group_list(int index, int len, char __user *name_up)
-{
- struct lstcon_group *grp;
-
- LASSERT(index >= 0);
- LASSERT(name_up);
-
- list_for_each_entry(grp, &console_session.ses_grp_list, grp_link) {
- if (!index--) {
- return copy_to_user(name_up, grp->grp_name, len) ?
- -EFAULT : 0;
- }
- }
-
- return -ENOENT;
-}
-
-static int
-lstcon_nodes_getent(struct list_head *head, int *index_p,
- int *count_p, struct lstcon_node_ent __user *dents_up)
-{
- struct lstcon_ndlink *ndl;
- struct lstcon_node *nd;
- int count = 0;
- int index = 0;
-
- LASSERT(index_p && count_p);
- LASSERT(dents_up);
- LASSERT(*index_p >= 0);
- LASSERT(*count_p > 0);
-
- list_for_each_entry(ndl, head, ndl_link) {
- if (index++ < *index_p)
- continue;
-
- if (count >= *count_p)
- break;
-
- nd = ndl->ndl_node;
- if (copy_to_user(&dents_up[count].nde_id,
- &nd->nd_id, sizeof(nd->nd_id)) ||
- copy_to_user(&dents_up[count].nde_state,
- &nd->nd_state, sizeof(nd->nd_state)))
- return -EFAULT;
-
- count++;
- }
-
- if (index <= *index_p)
- return -ENOENT;
-
- *count_p = count;
- *index_p = index;
-
- return 0;
-}
-
-int
-lstcon_group_info(char *name, struct lstcon_ndlist_ent __user *gents_p,
- int *index_p, int *count_p,
- struct lstcon_node_ent __user *dents_up)
-{
- struct lstcon_ndlist_ent *gentp;
- struct lstcon_group *grp;
- struct lstcon_ndlink *ndl;
- int rc;
-
- rc = lstcon_group_find(name, &grp);
- if (rc) {
- CDEBUG(D_NET, "Can't find group %s\n", name);
- return rc;
- }
-
- if (dents_up) {
- /* verbose query */
- rc = lstcon_nodes_getent(&grp->grp_ndl_list,
- index_p, count_p, dents_up);
- lstcon_group_decref(grp);
-
- return rc;
- }
-
- /* non-verbose query */
- gentp = kzalloc(sizeof(struct lstcon_ndlist_ent), GFP_NOFS);
- if (!gentp) {
- CERROR("Can't allocate ndlist_ent\n");
- lstcon_group_decref(grp);
-
- return -ENOMEM;
- }
-
- list_for_each_entry(ndl, &grp->grp_ndl_list, ndl_link)
- LST_NODE_STATE_COUNTER(ndl->ndl_node, gentp);
-
- rc = copy_to_user(gents_p, gentp,
- sizeof(struct lstcon_ndlist_ent)) ? -EFAULT : 0;
-
- kfree(gentp);
-
- lstcon_group_decref(grp);
-
- return rc;
-}
-
-static int
-lstcon_batch_find(const char *name, struct lstcon_batch **batpp)
-{
- struct lstcon_batch *bat;
-
- list_for_each_entry(bat, &console_session.ses_bat_list, bat_link) {
- if (!strncmp(bat->bat_name, name, LST_NAME_SIZE)) {
- *batpp = bat;
- return 0;
- }
- }
-
- return -ENOENT;
-}
-
-int
-lstcon_batch_add(char *name)
-{
- struct lstcon_batch *bat;
- int i;
- int rc;
-
- rc = !lstcon_batch_find(name, &bat) ? -EEXIST : 0;
- if (rc) {
- CDEBUG(D_NET, "Batch %s already exists\n", name);
- return rc;
- }
-
- bat = kzalloc(sizeof(struct lstcon_batch), GFP_NOFS);
- if (!bat) {
- CERROR("Can't allocate descriptor for batch %s\n", name);
- return -ENOMEM;
- }
-
- bat->bat_cli_hash = kmalloc(sizeof(struct list_head) * LST_NODE_HASHSIZE,
- GFP_KERNEL);
- if (!bat->bat_cli_hash) {
- CERROR("Can't allocate hash for batch %s\n", name);
- kfree(bat);
-
- return -ENOMEM;
- }
-
- bat->bat_srv_hash = kmalloc(sizeof(struct list_head) * LST_NODE_HASHSIZE,
- GFP_KERNEL);
- if (!bat->bat_srv_hash) {
- CERROR("Can't allocate hash for batch %s\n", name);
- kfree(bat->bat_cli_hash);
- kfree(bat);
-
- return -ENOMEM;
- }
-
- if (strlen(name) > sizeof(bat->bat_name) - 1) {
- kfree(bat->bat_srv_hash);
- kfree(bat->bat_cli_hash);
- kfree(bat);
- return -E2BIG;
- }
- strncpy(bat->bat_name, name, sizeof(bat->bat_name));
- bat->bat_hdr.tsb_index = 0;
- bat->bat_hdr.tsb_id.bat_id = ++console_session.ses_id_cookie;
-
- bat->bat_ntest = 0;
- bat->bat_state = LST_BATCH_IDLE;
-
- INIT_LIST_HEAD(&bat->bat_cli_list);
- INIT_LIST_HEAD(&bat->bat_srv_list);
- INIT_LIST_HEAD(&bat->bat_test_list);
- INIT_LIST_HEAD(&bat->bat_trans_list);
-
- for (i = 0; i < LST_NODE_HASHSIZE; i++) {
- INIT_LIST_HEAD(&bat->bat_cli_hash[i]);
- INIT_LIST_HEAD(&bat->bat_srv_hash[i]);
- }
-
- list_add_tail(&bat->bat_link, &console_session.ses_bat_list);
-
- return rc;
-}
-
-int
-lstcon_batch_list(int index, int len, char __user *name_up)
-{
- struct lstcon_batch *bat;
-
- LASSERT(name_up);
- LASSERT(index >= 0);
-
- list_for_each_entry(bat, &console_session.ses_bat_list, bat_link) {
- if (!index--) {
- return copy_to_user(name_up, bat->bat_name, len) ?
- -EFAULT : 0;
- }
- }
-
- return -ENOENT;
-}
-
-int
-lstcon_batch_info(char *name, struct lstcon_test_batch_ent __user *ent_up,
- int server, int testidx, int *index_p, int *ndent_p,
- struct lstcon_node_ent __user *dents_up)
-{
- struct lstcon_test_batch_ent *entp;
- struct list_head *clilst;
- struct list_head *srvlst;
- struct lstcon_test *test = NULL;
- struct lstcon_batch *bat;
- struct lstcon_ndlink *ndl;
- int rc;
-
- rc = lstcon_batch_find(name, &bat);
- if (rc) {
- CDEBUG(D_NET, "Can't find batch %s\n", name);
- return -ENOENT;
- }
-
- if (testidx > 0) {
- /* query test, test index start from 1 */
- list_for_each_entry(test, &bat->bat_test_list, tes_link) {
- if (testidx-- == 1)
- break;
- }
-
- if (testidx > 0) {
- CDEBUG(D_NET, "Can't find specified test in batch\n");
- return -ENOENT;
- }
- }
-
- clilst = !test ? &bat->bat_cli_list :
- &test->tes_src_grp->grp_ndl_list;
- srvlst = !test ? &bat->bat_srv_list :
- &test->tes_dst_grp->grp_ndl_list;
-
- if (dents_up) {
- rc = lstcon_nodes_getent((server ? srvlst : clilst),
- index_p, ndent_p, dents_up);
- return rc;
- }
-
- /* non-verbose query */
- entp = kzalloc(sizeof(struct lstcon_test_batch_ent), GFP_NOFS);
- if (!entp)
- return -ENOMEM;
-
- if (!test) {
- entp->u.tbe_batch.bae_ntest = bat->bat_ntest;
- entp->u.tbe_batch.bae_state = bat->bat_state;
- } else {
- entp->u.tbe_test.tse_type = test->tes_type;
- entp->u.tbe_test.tse_loop = test->tes_loop;
- entp->u.tbe_test.tse_concur = test->tes_concur;
- }
-
- list_for_each_entry(ndl, clilst, ndl_link)
- LST_NODE_STATE_COUNTER(ndl->ndl_node, &entp->tbe_cli_nle);
-
- list_for_each_entry(ndl, srvlst, ndl_link)
- LST_NODE_STATE_COUNTER(ndl->ndl_node, &entp->tbe_srv_nle);
-
- rc = copy_to_user(ent_up, entp,
- sizeof(struct lstcon_test_batch_ent)) ? -EFAULT : 0;
-
- kfree(entp);
-
- return rc;
-}
-
-static int
-lstcon_batrpc_condition(int transop, struct lstcon_node *nd, void *arg)
-{
- switch (transop) {
- case LST_TRANS_TSBRUN:
- if (nd->nd_state != LST_NODE_ACTIVE)
- return -ENETDOWN;
- break;
-
- case LST_TRANS_TSBSTOP:
- if (nd->nd_state != LST_NODE_ACTIVE)
- return 0;
- break;
-
- case LST_TRANS_TSBCLIQRY:
- case LST_TRANS_TSBSRVQRY:
- break;
- }
-
- return 1;
-}
-
-static int
-lstcon_batch_op(struct lstcon_batch *bat, int transop,
- struct list_head __user *result_up)
-{
- struct lstcon_rpc_trans *trans;
- int rc;
-
- rc = lstcon_rpc_trans_ndlist(&bat->bat_cli_list,
- &bat->bat_trans_list, transop,
- bat, lstcon_batrpc_condition, &trans);
- if (rc) {
- CERROR("Can't create transaction: %d\n", rc);
- return rc;
- }
-
- lstcon_rpc_trans_postwait(trans, LST_TRANS_TIMEOUT);
-
- rc = lstcon_rpc_trans_interpreter(trans, result_up, NULL);
-
- lstcon_rpc_trans_destroy(trans);
-
- return rc;
-}
-
-int
-lstcon_batch_run(char *name, int timeout, struct list_head __user *result_up)
-{
- struct lstcon_batch *bat;
- int rc;
-
- if (lstcon_batch_find(name, &bat)) {
- CDEBUG(D_NET, "Can't find batch %s\n", name);
- return -ENOENT;
- }
-
- bat->bat_arg = timeout;
-
- rc = lstcon_batch_op(bat, LST_TRANS_TSBRUN, result_up);
-
- /* mark batch as running if it's started in any node */
- if (lstcon_tsbop_stat_success(lstcon_trans_stat(), 0))
- bat->bat_state = LST_BATCH_RUNNING;
-
- return rc;
-}
-
-int
-lstcon_batch_stop(char *name, int force, struct list_head __user *result_up)
-{
- struct lstcon_batch *bat;
- int rc;
-
- if (lstcon_batch_find(name, &bat)) {
- CDEBUG(D_NET, "Can't find batch %s\n", name);
- return -ENOENT;
- }
-
- bat->bat_arg = force;
-
- rc = lstcon_batch_op(bat, LST_TRANS_TSBSTOP, result_up);
-
- /* mark batch as stopped if all RPCs finished */
- if (!lstcon_tsbop_stat_failure(lstcon_trans_stat(), 0))
- bat->bat_state = LST_BATCH_IDLE;
-
- return rc;
-}
-
-static void
-lstcon_batch_destroy(struct lstcon_batch *bat)
-{
- struct lstcon_ndlink *ndl;
- struct lstcon_test *test;
- int i;
-
- list_del(&bat->bat_link);
-
- while (!list_empty(&bat->bat_test_list)) {
- test = list_entry(bat->bat_test_list.next,
- struct lstcon_test, tes_link);
- LASSERT(list_empty(&test->tes_trans_list));
-
- list_del(&test->tes_link);
-
- lstcon_group_decref(test->tes_src_grp);
- lstcon_group_decref(test->tes_dst_grp);
-
- kfree(test);
- }
-
- LASSERT(list_empty(&bat->bat_trans_list));
-
- while (!list_empty(&bat->bat_cli_list)) {
- ndl = list_entry(bat->bat_cli_list.next,
- struct lstcon_ndlink, ndl_link);
- list_del_init(&ndl->ndl_link);
-
- lstcon_ndlink_release(ndl);
- }
-
- while (!list_empty(&bat->bat_srv_list)) {
- ndl = list_entry(bat->bat_srv_list.next,
- struct lstcon_ndlink, ndl_link);
- list_del_init(&ndl->ndl_link);
-
- lstcon_ndlink_release(ndl);
- }
-
- for (i = 0; i < LST_NODE_HASHSIZE; i++) {
- LASSERT(list_empty(&bat->bat_cli_hash[i]));
- LASSERT(list_empty(&bat->bat_srv_hash[i]));
- }
-
- kfree(bat->bat_cli_hash);
- kfree(bat->bat_srv_hash);
- kfree(bat);
-}
-
-static int
-lstcon_testrpc_condition(int transop, struct lstcon_node *nd, void *arg)
-{
- struct lstcon_test *test;
- struct lstcon_batch *batch;
- struct lstcon_ndlink *ndl;
- struct list_head *hash;
- struct list_head *head;
-
- test = (struct lstcon_test *)arg;
- LASSERT(test);
-
- batch = test->tes_batch;
- LASSERT(batch);
-
- if (test->tes_oneside &&
- transop == LST_TRANS_TSBSRVADD)
- return 0;
-
- if (nd->nd_state != LST_NODE_ACTIVE)
- return -ENETDOWN;
-
- if (transop == LST_TRANS_TSBCLIADD) {
- hash = batch->bat_cli_hash;
- head = &batch->bat_cli_list;
-
- } else {
- LASSERT(transop == LST_TRANS_TSBSRVADD);
-
- hash = batch->bat_srv_hash;
- head = &batch->bat_srv_list;
- }
-
- LASSERT(nd->nd_id.nid != LNET_NID_ANY);
-
- if (lstcon_ndlink_find(hash, nd->nd_id, &ndl, 1))
- return -ENOMEM;
-
- if (list_empty(&ndl->ndl_link))
- list_add_tail(&ndl->ndl_link, head);
-
- return 1;
-}
-
-static int
-lstcon_test_nodes_add(struct lstcon_test *test,
- struct list_head __user *result_up)
-{
- struct lstcon_rpc_trans *trans;
- struct lstcon_group *grp;
- int transop;
- int rc;
-
- LASSERT(test->tes_src_grp);
- LASSERT(test->tes_dst_grp);
-
- transop = LST_TRANS_TSBSRVADD;
- grp = test->tes_dst_grp;
-again:
- rc = lstcon_rpc_trans_ndlist(&grp->grp_ndl_list,
- &test->tes_trans_list, transop,
- test, lstcon_testrpc_condition, &trans);
- if (rc) {
- CERROR("Can't create transaction: %d\n", rc);
- return rc;
- }
-
- lstcon_rpc_trans_postwait(trans, LST_TRANS_TIMEOUT);
-
- if (lstcon_trans_stat()->trs_rpc_errno ||
- lstcon_trans_stat()->trs_fwk_errno) {
- lstcon_rpc_trans_interpreter(trans, result_up, NULL);
-
- lstcon_rpc_trans_destroy(trans);
- /* return if any error */
- CDEBUG(D_NET, "Failed to add test %s, RPC error %d, framework error %d\n",
- transop == LST_TRANS_TSBCLIADD ? "client" : "server",
- lstcon_trans_stat()->trs_rpc_errno,
- lstcon_trans_stat()->trs_fwk_errno);
-
- return rc;
- }
-
- lstcon_rpc_trans_destroy(trans);
-
- if (transop == LST_TRANS_TSBCLIADD)
- return rc;
-
- transop = LST_TRANS_TSBCLIADD;
- grp = test->tes_src_grp;
- test->tes_cliidx = 0;
-
- /* requests to test clients */
- goto again;
-}
-
-static int
-lstcon_verify_batch(const char *name, struct lstcon_batch **batch)
-{
- int rc;
-
- rc = lstcon_batch_find(name, batch);
- if (rc) {
- CDEBUG(D_NET, "Can't find batch %s\n", name);
- return rc;
- }
-
- if ((*batch)->bat_state != LST_BATCH_IDLE) {
- CDEBUG(D_NET, "Can't change running batch %s\n", name);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int
-lstcon_verify_group(const char *name, struct lstcon_group **grp)
-{
- int rc;
- struct lstcon_ndlink *ndl;
-
- rc = lstcon_group_find(name, grp);
- if (rc) {
- CDEBUG(D_NET, "can't find group %s\n", name);
- return rc;
- }
-
- list_for_each_entry(ndl, &(*grp)->grp_ndl_list, ndl_link) {
- if (ndl->ndl_node->nd_state == LST_NODE_ACTIVE)
- return 0;
- }
-
- CDEBUG(D_NET, "Group %s has no ACTIVE nodes\n", name);
-
- return -EINVAL;
-}
-
-int
-lstcon_test_add(char *batch_name, int type, int loop,
- int concur, int dist, int span,
- char *src_name, char *dst_name,
- void *param, int paramlen, int *retp,
- struct list_head __user *result_up)
-{
- struct lstcon_test *test = NULL;
- int rc;
- struct lstcon_group *src_grp = NULL;
- struct lstcon_group *dst_grp = NULL;
- struct lstcon_batch *batch = NULL;
-
- /*
- * verify that a batch of the given name exists, and the groups
- * that will be part of the batch exist and have at least one
- * active node
- */
- rc = lstcon_verify_batch(batch_name, &batch);
- if (rc)
- goto out;
-
- rc = lstcon_verify_group(src_name, &src_grp);
- if (rc)
- goto out;
-
- rc = lstcon_verify_group(dst_name, &dst_grp);
- if (rc)
- goto out;
-
- if (dst_grp->grp_userland)
- *retp = 1;
-
- test = kzalloc(offsetof(struct lstcon_test, tes_param[paramlen]),
- GFP_KERNEL);
- if (!test) {
- CERROR("Can't allocate test descriptor\n");
- rc = -ENOMEM;
-
- goto out;
- }
-
- test->tes_hdr.tsb_id = batch->bat_hdr.tsb_id;
- test->tes_batch = batch;
- test->tes_type = type;
- test->tes_oneside = 0; /* TODO */
- test->tes_loop = loop;
- test->tes_concur = concur;
- test->tes_stop_onerr = 1; /* TODO */
- test->tes_span = span;
- test->tes_dist = dist;
- test->tes_cliidx = 0; /* just used for creating RPC */
- test->tes_src_grp = src_grp;
- test->tes_dst_grp = dst_grp;
- INIT_LIST_HEAD(&test->tes_trans_list);
-
- if (param) {
- test->tes_paramlen = paramlen;
- memcpy(&test->tes_param[0], param, paramlen);
- }
-
- rc = lstcon_test_nodes_add(test, result_up);
-
- if (rc)
- goto out;
-
- if (lstcon_trans_stat()->trs_rpc_errno ||
- lstcon_trans_stat()->trs_fwk_errno)
- CDEBUG(D_NET, "Failed to add test %d to batch %s\n", type,
- batch_name);
-
- /* add to test list anyway, so user can check what's going on */
- list_add_tail(&test->tes_link, &batch->bat_test_list);
-
- batch->bat_ntest++;
- test->tes_hdr.tsb_index = batch->bat_ntest;
-
- /* hold groups so nobody can change them */
- return rc;
-out:
- kfree(test);
-
- if (dst_grp)
- lstcon_group_decref(dst_grp);
-
- if (src_grp)
- lstcon_group_decref(src_grp);
-
- return rc;
-}
-
-static int
-lstcon_test_find(struct lstcon_batch *batch, int idx,
- struct lstcon_test **testpp)
-{
- struct lstcon_test *test;
-
- list_for_each_entry(test, &batch->bat_test_list, tes_link) {
- if (idx == test->tes_hdr.tsb_index) {
- *testpp = test;
- return 0;
- }
- }
-
- return -ENOENT;
-}
-
-static int
-lstcon_tsbrpc_readent(int transop, struct srpc_msg *msg,
- struct lstcon_rpc_ent __user *ent_up)
-{
- struct srpc_batch_reply *rep = &msg->msg_body.bat_reply;
-
- LASSERT(transop == LST_TRANS_TSBCLIQRY ||
- transop == LST_TRANS_TSBSRVQRY);
-
- /* positive errno, framework error code */
- if (copy_to_user(&ent_up->rpe_priv[0], &rep->bar_active,
- sizeof(rep->bar_active)))
- return -EFAULT;
-
- return 0;
-}
-
-int
-lstcon_test_batch_query(char *name, int testidx, int client,
- int timeout, struct list_head __user *result_up)
-{
- struct lstcon_rpc_trans *trans;
- struct list_head *translist;
- struct list_head *ndlist;
- struct lstcon_tsb_hdr *hdr;
- struct lstcon_batch *batch;
- struct lstcon_test *test = NULL;
- int transop;
- int rc;
-
- rc = lstcon_batch_find(name, &batch);
- if (rc) {
- CDEBUG(D_NET, "Can't find batch: %s\n", name);
- return rc;
- }
-
- if (!testidx) {
- translist = &batch->bat_trans_list;
- ndlist = &batch->bat_cli_list;
- hdr = &batch->bat_hdr;
- } else {
- /* query specified test only */
- rc = lstcon_test_find(batch, testidx, &test);
- if (rc) {
- CDEBUG(D_NET, "Can't find test: %d\n", testidx);
- return rc;
- }
-
- translist = &test->tes_trans_list;
- ndlist = &test->tes_src_grp->grp_ndl_list;
- hdr = &test->tes_hdr;
- }
-
- transop = client ? LST_TRANS_TSBCLIQRY : LST_TRANS_TSBSRVQRY;
-
- rc = lstcon_rpc_trans_ndlist(ndlist, translist, transop, hdr,
- lstcon_batrpc_condition, &trans);
- if (rc) {
- CERROR("Can't create transaction: %d\n", rc);
- return rc;
- }
-
- lstcon_rpc_trans_postwait(trans, timeout);
-
- /* query a batch, not a test */
- if (!testidx &&
- !lstcon_rpc_stat_failure(lstcon_trans_stat(), 0) &&
- !lstcon_tsbqry_stat_run(lstcon_trans_stat(), 0)) {
- /* all RPCs finished, and no active test */
- batch->bat_state = LST_BATCH_IDLE;
- }
-
- rc = lstcon_rpc_trans_interpreter(trans, result_up,
- lstcon_tsbrpc_readent);
- lstcon_rpc_trans_destroy(trans);
-
- return rc;
-}
-
-static int
-lstcon_statrpc_readent(int transop, struct srpc_msg *msg,
- struct lstcon_rpc_ent __user *ent_up)
-{
- struct srpc_stat_reply *rep = &msg->msg_body.stat_reply;
- struct sfw_counters __user *sfwk_stat;
- struct srpc_counters __user *srpc_stat;
- struct lnet_counters __user *lnet_stat;
-
- if (rep->str_status)
- return 0;
-
- sfwk_stat = (struct sfw_counters __user *)&ent_up->rpe_payload[0];
- srpc_stat = (struct srpc_counters __user *)(sfwk_stat + 1);
- lnet_stat = (struct lnet_counters __user *)(srpc_stat + 1);
-
- if (copy_to_user(sfwk_stat, &rep->str_fw, sizeof(*sfwk_stat)) ||
- copy_to_user(srpc_stat, &rep->str_rpc, sizeof(*srpc_stat)) ||
- copy_to_user(lnet_stat, &rep->str_lnet, sizeof(*lnet_stat)))
- return -EFAULT;
-
- return 0;
-}
-
-static int
-lstcon_ndlist_stat(struct list_head *ndlist,
- int timeout, struct list_head __user *result_up)
-{
- struct list_head head;
- struct lstcon_rpc_trans *trans;
- int rc;
-
- INIT_LIST_HEAD(&head);
-
- rc = lstcon_rpc_trans_ndlist(ndlist, &head,
- LST_TRANS_STATQRY, NULL, NULL, &trans);
- if (rc) {
- CERROR("Can't create transaction: %d\n", rc);
- return rc;
- }
-
- lstcon_rpc_trans_postwait(trans, LST_VALIDATE_TIMEOUT(timeout));
-
- rc = lstcon_rpc_trans_interpreter(trans, result_up,
- lstcon_statrpc_readent);
- lstcon_rpc_trans_destroy(trans);
-
- return rc;
-}
-
-int
-lstcon_group_stat(char *grp_name, int timeout,
- struct list_head __user *result_up)
-{
- struct lstcon_group *grp;
- int rc;
-
- rc = lstcon_group_find(grp_name, &grp);
- if (rc) {
- CDEBUG(D_NET, "Can't find group %s\n", grp_name);
- return rc;
- }
-
- rc = lstcon_ndlist_stat(&grp->grp_ndl_list, timeout, result_up);
-
- lstcon_group_decref(grp);
-
- return rc;
-}
-
-int
-lstcon_nodes_stat(int count, struct lnet_process_id __user *ids_up,
- int timeout, struct list_head __user *result_up)
-{
- struct lstcon_ndlink *ndl;
- struct lstcon_group *tmp;
- struct lnet_process_id id;
- int i;
- int rc;
-
- rc = lstcon_group_alloc(NULL, &tmp);
- if (rc) {
- CERROR("Out of memory\n");
- return -ENOMEM;
- }
-
- for (i = 0 ; i < count; i++) {
- if (copy_from_user(&id, &ids_up[i], sizeof(id))) {
- rc = -EFAULT;
- break;
- }
-
- /* add to tmp group */
- rc = lstcon_group_ndlink_find(tmp, id, &ndl, 2);
- if (rc) {
- CDEBUG((rc == -ENOMEM) ? D_ERROR : D_NET,
- "Failed to find or create %s: %d\n",
- libcfs_id2str(id), rc);
- break;
- }
- }
-
- if (rc) {
- lstcon_group_decref(tmp);
- return rc;
- }
-
- rc = lstcon_ndlist_stat(&tmp->grp_ndl_list, timeout, result_up);
-
- lstcon_group_decref(tmp);
-
- return rc;
-}
-
-static int
-lstcon_debug_ndlist(struct list_head *ndlist,
- struct list_head *translist,
- int timeout, struct list_head __user *result_up)
-{
- struct lstcon_rpc_trans *trans;
- int rc;
-
- rc = lstcon_rpc_trans_ndlist(ndlist, translist, LST_TRANS_SESQRY,
- NULL, lstcon_sesrpc_condition, &trans);
- if (rc) {
- CERROR("Can't create transaction: %d\n", rc);
- return rc;
- }
-
- lstcon_rpc_trans_postwait(trans, LST_VALIDATE_TIMEOUT(timeout));
-
- rc = lstcon_rpc_trans_interpreter(trans, result_up,
- lstcon_sesrpc_readent);
- lstcon_rpc_trans_destroy(trans);
-
- return rc;
-}
-
-int
-lstcon_session_debug(int timeout, struct list_head __user *result_up)
-{
- return lstcon_debug_ndlist(&console_session.ses_ndl_list,
- NULL, timeout, result_up);
-}
-
-int
-lstcon_batch_debug(int timeout, char *name,
- int client, struct list_head __user *result_up)
-{
- struct lstcon_batch *bat;
- int rc;
-
- rc = lstcon_batch_find(name, &bat);
- if (rc)
- return -ENOENT;
-
- rc = lstcon_debug_ndlist(client ? &bat->bat_cli_list :
- &bat->bat_srv_list,
- NULL, timeout, result_up);
-
- return rc;
-}
-
-int
-lstcon_group_debug(int timeout, char *name,
- struct list_head __user *result_up)
-{
- struct lstcon_group *grp;
- int rc;
-
- rc = lstcon_group_find(name, &grp);
- if (rc)
- return -ENOENT;
-
- rc = lstcon_debug_ndlist(&grp->grp_ndl_list, NULL,
- timeout, result_up);
- lstcon_group_decref(grp);
-
- return rc;
-}
-
-int
-lstcon_nodes_debug(int timeout, int count,
- struct lnet_process_id __user *ids_up,
- struct list_head __user *result_up)
-{
- struct lnet_process_id id;
- struct lstcon_ndlink *ndl;
- struct lstcon_group *grp;
- int i;
- int rc;
-
- rc = lstcon_group_alloc(NULL, &grp);
- if (rc) {
- CDEBUG(D_NET, "Out of memory\n");
- return rc;
- }
-
- for (i = 0; i < count; i++) {
- if (copy_from_user(&id, &ids_up[i], sizeof(id))) {
- rc = -EFAULT;
- break;
- }
-
- /* node is added to tmp group */
- rc = lstcon_group_ndlink_find(grp, id, &ndl, 1);
- if (rc) {
- CERROR("Can't create node link\n");
- break;
- }
- }
-
- if (rc) {
- lstcon_group_decref(grp);
- return rc;
- }
-
- rc = lstcon_debug_ndlist(&grp->grp_ndl_list, NULL,
- timeout, result_up);
-
- lstcon_group_decref(grp);
-
- return rc;
-}
-
-int
-lstcon_session_match(struct lst_sid sid)
-{
- return (console_session.ses_id.ses_nid == sid.ses_nid &&
- console_session.ses_id.ses_stamp == sid.ses_stamp) ? 1 : 0;
-}
-
-static void
-lstcon_new_session_id(struct lst_sid *sid)
-{
- struct lnet_process_id id;
-
- LASSERT(console_session.ses_state == LST_SESSION_NONE);
-
- LNetGetId(1, &id);
- sid->ses_nid = id.nid;
- sid->ses_stamp = cfs_time_current();
-}
-
-int
-lstcon_session_new(char *name, int key, unsigned int feats,
- int timeout, int force, struct lst_sid __user *sid_up)
-{
- int rc = 0;
- int i;
-
- if (console_session.ses_state != LST_SESSION_NONE) {
- /* session exists */
- if (!force) {
- CNETERR("Session %s already exists\n",
- console_session.ses_name);
- return -EEXIST;
- }
-
- rc = lstcon_session_end();
-
- /* lstcon_session_end() only return local error */
- if (rc)
- return rc;
- }
-
- if (feats & ~LST_FEATS_MASK) {
- CNETERR("Unknown session features %x\n",
- (feats & ~LST_FEATS_MASK));
- return -EINVAL;
- }
-
- for (i = 0; i < LST_GLOBAL_HASHSIZE; i++)
- LASSERT(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;
-
- if (strlen(name) > sizeof(console_session.ses_name) - 1)
- return -E2BIG;
- strlcpy(console_session.ses_name, name,
- sizeof(console_session.ses_name));
-
- rc = lstcon_batch_add(LST_DEFAULT_BATCH);
- if (rc)
- return rc;
-
- rc = lstcon_rpc_pinger_start();
- if (rc) {
- struct lstcon_batch *bat = NULL;
-
- lstcon_batch_find(LST_DEFAULT_BATCH, &bat);
- lstcon_batch_destroy(bat);
-
- return rc;
- }
-
- if (!copy_to_user(sid_up, &console_session.ses_id,
- sizeof(struct lst_sid)))
- return rc;
-
- lstcon_session_end();
-
- return -EFAULT;
-}
-
-int
-lstcon_session_info(struct lst_sid __user *sid_up, int __user *key_up,
- unsigned __user *featp,
- struct lstcon_ndlist_ent __user *ndinfo_up,
- char __user *name_up, int len)
-{
- struct lstcon_ndlist_ent *entp;
- struct lstcon_ndlink *ndl;
- int rc = 0;
-
- if (console_session.ses_state != LST_SESSION_ACTIVE)
- return -ESRCH;
-
- entp = kzalloc(sizeof(*entp), GFP_NOFS);
- if (!entp)
- return -ENOMEM;
-
- list_for_each_entry(ndl, &console_session.ses_ndl_list, ndl_link)
- LST_NODE_STATE_COUNTER(ndl->ndl_node, entp);
-
- if (copy_to_user(sid_up, &console_session.ses_id,
- sizeof(*sid_up)) ||
- copy_to_user(key_up, &console_session.ses_key,
- sizeof(*key_up)) ||
- copy_to_user(featp, &console_session.ses_features,
- sizeof(*featp)) ||
- copy_to_user(ndinfo_up, entp, sizeof(*entp)) ||
- copy_to_user(name_up, console_session.ses_name, len))
- rc = -EFAULT;
-
- kfree(entp);
-
- return rc;
-}
-
-int
-lstcon_session_end(void)
-{
- struct lstcon_rpc_trans *trans;
- struct lstcon_group *grp;
- struct lstcon_batch *bat;
- int rc = 0;
-
- LASSERT(console_session.ses_state == LST_SESSION_ACTIVE);
-
- rc = lstcon_rpc_trans_ndlist(&console_session.ses_ndl_list,
- NULL, LST_TRANS_SESEND, NULL,
- lstcon_sesrpc_condition, &trans);
- if (rc) {
- CERROR("Can't create transaction: %d\n", rc);
- return rc;
- }
-
- console_session.ses_shutdown = 1;
-
- lstcon_rpc_pinger_stop();
-
- lstcon_rpc_trans_postwait(trans, LST_TRANS_TIMEOUT);
-
- lstcon_rpc_trans_destroy(trans);
- /* User can do nothing even rpc failed, so go on */
-
- /* waiting for orphan rpcs to die */
- lstcon_rpc_cleanup_wait();
-
- console_session.ses_id = LST_INVALID_SID;
- 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 (!list_empty(&console_session.ses_bat_list)) {
- bat = list_entry(console_session.ses_bat_list.next,
- struct lstcon_batch, bat_link);
-
- lstcon_batch_destroy(bat);
- }
-
- /* destroy all groups */
- while (!list_empty(&console_session.ses_grp_list)) {
- grp = list_entry(console_session.ses_grp_list.next,
- struct lstcon_group, grp_link);
- LASSERT(grp->grp_ref == 1);
-
- lstcon_group_decref(grp);
- }
-
- /* all nodes should be released */
- LASSERT(list_empty(&console_session.ses_ndl_list));
-
- console_session.ses_shutdown = 0;
- console_session.ses_expired = 0;
-
- return rc;
-}
-
-int
-lstcon_session_feats_check(unsigned int feats)
-{
- int rc = 0;
-
- if (feats & ~LST_FEATS_MASK) {
- CERROR("Can't support these features: %x\n",
- (feats & ~LST_FEATS_MASK));
- return -EPROTO;
- }
-
- 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;
-
- spin_unlock(&console_session.ses_rpc_lock);
-
- if (rc) {
- 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(struct srpc_server_rpc *rpc)
-{
- struct srpc_msg *rep = &rpc->srpc_replymsg;
- struct srpc_msg *req = &rpc->srpc_reqstbuf->buf_msg;
- struct srpc_join_reqst *jreq = &req->msg_body.join_reqst;
- struct srpc_join_reply *jrep = &rep->msg_body.join_reply;
- struct lstcon_group *grp = NULL;
- struct lstcon_ndlink *ndl;
- int rc = 0;
-
- sfw_unpack_message(req);
-
- mutex_lock(&console_session.ses_mutex);
-
- jrep->join_sid = console_session.ses_id;
-
- if (console_session.ses_id.ses_nid == LNET_NID_ANY) {
- jrep->join_status = ESRCH;
- goto out;
- }
-
- if (lstcon_session_feats_check(req->msg_ses_feats)) {
- 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;
- goto out;
- }
-
- if (lstcon_group_find(jreq->join_group, &grp)) {
- rc = lstcon_group_alloc(jreq->join_group, &grp);
- if (rc) {
- CERROR("Out of memory\n");
- goto out;
- }
-
- list_add_tail(&grp->grp_link,
- &console_session.ses_grp_list);
- lstcon_group_addref(grp);
- }
-
- if (grp->grp_ref > 2) {
- /* Group in using */
- jrep->join_status = EBUSY;
- goto out;
- }
-
- rc = lstcon_group_ndlink_find(grp, rpc->srpc_peer, &ndl, 0);
- if (!rc) {
- jrep->join_status = EEXIST;
- goto out;
- }
-
- rc = lstcon_group_ndlink_find(grp, rpc->srpc_peer, &ndl, 1);
- if (rc) {
- CERROR("Out of memory\n");
- goto out;
- }
-
- ndl->ndl_node->nd_state = LST_NODE_ACTIVE;
- ndl->ndl_node->nd_timeout = console_session.ses_timeout;
-
- if (!grp->grp_userland)
- grp->grp_userland = 1;
-
- strlcpy(jrep->join_session, console_session.ses_name,
- sizeof(jrep->join_session));
- jrep->join_timeout = console_session.ses_timeout;
- jrep->join_status = 0;
-
-out:
- rep->msg_ses_feats = console_session.ses_features;
- if (grp)
- lstcon_group_decref(grp);
-
- mutex_unlock(&console_session.ses_mutex);
-
- return rc;
-}
-
-static struct srpc_service lstcon_acceptor_service;
-
-static void lstcon_init_acceptor_service(void)
-{
- /* initialize selftest console acceptor service table */
- lstcon_acceptor_service.sv_name = "join session";
- lstcon_acceptor_service.sv_handler = lstcon_acceptor_handle;
- lstcon_acceptor_service.sv_id = SRPC_SERVICE_JOIN;
- lstcon_acceptor_service.sv_wi_total = SFW_FRWK_WI_MAX;
-}
-
-static DECLARE_IOCTL_HANDLER(lstcon_ioctl_handler, lstcon_ioctl_entry);
-
-/* initialize console */
-int
-lstcon_console_init(void)
-{
- int i;
- int rc;
-
- memset(&console_session, 0, sizeof(struct lstcon_session));
-
- 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 = ktime_get_real_seconds();
-
- mutex_init(&console_session.ses_mutex);
-
- INIT_LIST_HEAD(&console_session.ses_ndl_list);
- INIT_LIST_HEAD(&console_session.ses_grp_list);
- INIT_LIST_HEAD(&console_session.ses_bat_list);
- INIT_LIST_HEAD(&console_session.ses_trans_list);
-
- console_session.ses_ndl_hash =
- kmalloc(sizeof(struct list_head) * LST_GLOBAL_HASHSIZE, GFP_KERNEL);
- if (!console_session.ses_ndl_hash)
- return -ENOMEM;
-
- for (i = 0; i < LST_GLOBAL_HASHSIZE; i++)
- INIT_LIST_HEAD(&console_session.ses_ndl_hash[i]);
-
- /* initialize acceptor service table */
- lstcon_init_acceptor_service();
-
- rc = srpc_add_service(&lstcon_acceptor_service);
- LASSERT(rc != -EBUSY);
- if (rc) {
- kfree(console_session.ses_ndl_hash);
- return rc;
- }
-
- rc = srpc_service_add_buffers(&lstcon_acceptor_service,
- lstcon_acceptor_service.sv_wi_total);
- if (rc) {
- rc = -ENOMEM;
- goto out;
- }
-
- rc = libcfs_register_ioctl(&lstcon_ioctl_handler);
-
- if (!rc) {
- lstcon_rpc_module_init();
- return 0;
- }
-
-out:
- srpc_shutdown_service(&lstcon_acceptor_service);
- srpc_remove_service(&lstcon_acceptor_service);
-
- kfree(console_session.ses_ndl_hash);
-
- srpc_wait_service_shutdown(&lstcon_acceptor_service);
-
- return rc;
-}
-
-int
-lstcon_console_fini(void)
-{
- int i;
-
- libcfs_deregister_ioctl(&lstcon_ioctl_handler);
-
- mutex_lock(&console_session.ses_mutex);
-
- srpc_shutdown_service(&lstcon_acceptor_service);
- srpc_remove_service(&lstcon_acceptor_service);
-
- if (console_session.ses_state != LST_SESSION_NONE)
- lstcon_session_end();
-
- lstcon_rpc_module_fini();
-
- mutex_unlock(&console_session.ses_mutex);
-
- LASSERT(list_empty(&console_session.ses_ndl_list));
- LASSERT(list_empty(&console_session.ses_grp_list));
- LASSERT(list_empty(&console_session.ses_bat_list));
- LASSERT(list_empty(&console_session.ses_trans_list));
-
- for (i = 0; i < LST_NODE_HASHSIZE; i++)
- LASSERT(list_empty(&console_session.ses_ndl_hash[i]));
-
- kfree(console_session.ses_ndl_hash);
-
- srpc_wait_service_shutdown(&lstcon_acceptor_service);
-
- return 0;
-}
diff --git a/drivers/staging/lustre/lnet/selftest/console.h b/drivers/staging/lustre/lnet/selftest/console.h
deleted file mode 100644
index 3933ed4cca93..000000000000
--- a/drivers/staging/lustre/lnet/selftest/console.h
+++ /dev/null
@@ -1,244 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * GPL HEADER START
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 only,
- * as published by the Free Software Foundation.
- *
- * This program 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 version 2 for more details (a copy is included
- * in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2011, 2012, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * lnet/selftest/console.h
- *
- * kernel structure for LST console
- *
- * Author: Liang Zhen <liangzhen@clusterfs.com>
- */
-
-#ifndef __LST_CONSOLE_H__
-#define __LST_CONSOLE_H__
-
-#include <linux/libcfs/libcfs.h>
-#include <linux/lnet/lib-types.h>
-#include <uapi/linux/lnet/lnetst.h>
-#include "selftest.h"
-#include "conrpc.h"
-
-/* node descriptor */
-struct lstcon_node {
- struct lnet_process_id nd_id; /* id of the node */
- int nd_ref; /* reference count */
- int nd_state; /* state of the node */
- int nd_timeout; /* session timeout */
- unsigned long nd_stamp; /* timestamp of last replied RPC */
- struct lstcon_rpc nd_ping; /* ping rpc */
-};
-
-/* node link descriptor */
-struct lstcon_ndlink {
- struct list_head ndl_link; /* chain on list */
- struct list_head ndl_hlink; /* chain on hash */
- struct lstcon_node *ndl_node; /* pointer to node */
-};
-
-/* (alias of nodes) group descriptor */
-struct lstcon_group {
- struct list_head grp_link; /* chain on global group list
- */
- int grp_ref; /* reference count */
- int grp_userland; /* has userland nodes */
- int grp_nnode; /* # of nodes */
- char grp_name[LST_NAME_SIZE]; /* group name */
-
- struct list_head grp_trans_list; /* transaction list */
- struct list_head grp_ndl_list; /* nodes list */
- struct list_head grp_ndl_hash[0]; /* hash table for nodes */
-};
-
-#define LST_BATCH_IDLE 0xB0 /* idle batch */
-#define LST_BATCH_RUNNING 0xB1 /* running batch */
-
-struct lstcon_tsb_hdr {
- struct lst_bid tsb_id; /* batch ID */
- int tsb_index; /* test index */
-};
-
-/* (tests ) batch descriptor */
-struct lstcon_batch {
- struct lstcon_tsb_hdr bat_hdr; /* test_batch header */
- struct list_head bat_link; /* chain on session's batches list */
- int bat_ntest; /* # of test */
- int bat_state; /* state of the batch */
- int bat_arg; /* parameter for run|stop, timeout
- * for run, force for stop
- */
- char bat_name[LST_NAME_SIZE];/* name of batch */
-
- struct list_head bat_test_list; /* list head of tests (struct lstcon_test)
- */
- struct list_head bat_trans_list; /* list head of transaction */
- struct list_head bat_cli_list; /* list head of client nodes
- * (struct lstcon_node)
- */
- struct list_head *bat_cli_hash; /* hash table of client nodes */
- struct list_head bat_srv_list; /* list head of server nodes */
- struct list_head *bat_srv_hash; /* hash table of server nodes */
-};
-
-/* a single test descriptor */
-struct lstcon_test {
- struct lstcon_tsb_hdr tes_hdr; /* test batch header */
- struct list_head tes_link; /* chain on batch's tests list */
- struct lstcon_batch *tes_batch; /* pointer to batch */
-
- int tes_type; /* type of the test, i.e: bulk, ping */
- int tes_stop_onerr; /* stop on error */
- int tes_oneside; /* one-sided test */
- int tes_concur; /* concurrency */
- int tes_loop; /* loop count */
- int tes_dist; /* nodes distribution of target group */
- int tes_span; /* nodes span of target group */
- int tes_cliidx; /* client index, used for RPC creating */
-
- struct list_head tes_trans_list; /* transaction list */
- struct lstcon_group *tes_src_grp; /* group run the test */
- struct lstcon_group *tes_dst_grp; /* target group */
-
- int tes_paramlen; /* test parameter length */
- char tes_param[0]; /* test parameter */
-};
-
-#define LST_GLOBAL_HASHSIZE 503 /* global nodes hash table size */
-#define LST_NODE_HASHSIZE 239 /* node hash table (for batch or group) */
-
-#define LST_SESSION_NONE 0x0 /* no session */
-#define LST_SESSION_ACTIVE 0x1 /* working session */
-
-#define LST_CONSOLE_TIMEOUT 300 /* default console timeout */
-
-struct lstcon_session {
- struct mutex ses_mutex; /* only 1 thread in session */
- struct lst_sid ses_id; /* global session id */
- int ses_key; /* local session key */
- int ses_state; /* state of session */
- int ses_timeout; /* timeout in seconds */
- time64_t ses_laststamp; /* last operation stamp (seconds)
- */
- unsigned int ses_features; /* tests features of the session
- */
- unsigned int ses_feats_updated:1; /* features are synced with
- * remote test nodes
- */
- unsigned int ses_force:1; /* force creating */
- unsigned int ses_shutdown:1; /* session is shutting down */
- unsigned int ses_expired:1; /* console is timedout */
- __u64 ses_id_cookie; /* batch id cookie */
- char ses_name[LST_NAME_SIZE];/* session name */
- struct lstcon_rpc_trans *ses_ping; /* session pinger */
- struct stt_timer ses_ping_timer; /* timer for pinger */
- struct lstcon_trans_stat ses_trans_stat; /* transaction stats */
-
- struct list_head ses_trans_list; /* global list of transaction */
- struct list_head ses_grp_list; /* global list of groups */
- struct list_head ses_bat_list; /* global list of batches */
- struct list_head ses_ndl_list; /* global list of nodes */
- struct list_head *ses_ndl_hash; /* hash table of nodes */
-
- spinlock_t ses_rpc_lock; /* serialize */
- atomic_t ses_rpc_counter; /* # of initialized RPCs */
- struct list_head ses_rpc_freelist; /* idle console rpc */
-}; /* session descriptor */
-
-extern struct lstcon_session console_session;
-
-static inline struct lstcon_trans_stat *
-lstcon_trans_stat(void)
-{
- return &console_session.ses_trans_stat;
-}
-
-static inline struct list_head *
-lstcon_id2hash(struct lnet_process_id id, struct list_head *hash)
-{
- unsigned int idx = LNET_NIDADDR(id.nid) % LST_NODE_HASHSIZE;
-
- return &hash[idx];
-}
-
-int lstcon_ioctl_entry(unsigned int cmd, struct libcfs_ioctl_hdr *hdr);
-int lstcon_console_init(void);
-int lstcon_console_fini(void);
-int lstcon_session_match(struct lst_sid sid);
-int lstcon_session_new(char *name, int key, unsigned int version,
- int timeout, int flags, struct lst_sid __user *sid_up);
-int lstcon_session_info(struct lst_sid __user *sid_up, int __user *key,
- unsigned __user *verp, struct lstcon_ndlist_ent __user *entp,
- char __user *name_up, int len);
-int lstcon_session_end(void);
-int lstcon_session_debug(int timeout, struct list_head __user *result_up);
-int lstcon_session_feats_check(unsigned int feats);
-int lstcon_batch_debug(int timeout, char *name,
- int client, struct list_head __user *result_up);
-int lstcon_group_debug(int timeout, char *name,
- struct list_head __user *result_up);
-int lstcon_nodes_debug(int timeout, int nnd,
- struct lnet_process_id __user *nds_up,
- struct list_head __user *result_up);
-int lstcon_group_add(char *name);
-int lstcon_group_del(char *name);
-int lstcon_group_clean(char *name, int args);
-int lstcon_group_refresh(char *name, struct list_head __user *result_up);
-int lstcon_nodes_add(char *name, int nnd, struct lnet_process_id __user *nds_up,
- unsigned int *featp, struct list_head __user *result_up);
-int lstcon_nodes_remove(char *name, int nnd,
- struct lnet_process_id __user *nds_up,
- struct list_head __user *result_up);
-int lstcon_group_info(char *name, struct lstcon_ndlist_ent __user *gent_up,
- int *index_p, int *ndent_p,
- struct lstcon_node_ent __user *ndents_up);
-int lstcon_group_list(int idx, int len, char __user *name_up);
-int lstcon_batch_add(char *name);
-int lstcon_batch_run(char *name, int timeout,
- struct list_head __user *result_up);
-int lstcon_batch_stop(char *name, int force,
- struct list_head __user *result_up);
-int lstcon_test_batch_query(char *name, int testidx,
- int client, int timeout,
- struct list_head __user *result_up);
-int lstcon_batch_del(char *name);
-int lstcon_batch_list(int idx, int namelen, char __user *name_up);
-int lstcon_batch_info(char *name, struct lstcon_test_batch_ent __user *ent_up,
- int server, int testidx, int *index_p,
- int *ndent_p, struct lstcon_node_ent __user *dents_up);
-int lstcon_group_stat(char *grp_name, int timeout,
- struct list_head __user *result_up);
-int lstcon_nodes_stat(int count, struct lnet_process_id __user *ids_up,
- int timeout, struct list_head __user *result_up);
-int lstcon_test_add(char *batch_name, int type, int loop,
- int concur, int dist, int span,
- char *src_name, char *dst_name,
- void *param, int paramlen, int *retp,
- struct list_head __user *result_up);
-#endif
diff --git a/drivers/staging/lustre/lnet/selftest/framework.c b/drivers/staging/lustre/lnet/selftest/framework.c
deleted file mode 100644
index 0ca1e3a780ca..000000000000
--- a/drivers/staging/lustre/lnet/selftest/framework.c
+++ /dev/null
@@ -1,1786 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * GPL HEADER START
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 only,
- * as published by the Free Software Foundation.
- *
- * This program 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 version 2 for more details (a copy is included
- * in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2012, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * lnet/selftest/framework.c
- *
- * Author: Isaac Huang <isaac@clusterfs.com>
- * Author: Liang Zhen <liangzhen@clusterfs.com>
- */
-
-#define DEBUG_SUBSYSTEM S_LNET
-
-#include "selftest.h"
-
-struct lst_sid LST_INVALID_SID = {LNET_NID_ANY, -1};
-
-static int session_timeout = 100;
-module_param(session_timeout, int, 0444);
-MODULE_PARM_DESC(session_timeout, "test session timeout in seconds (100 by default, 0 == never)");
-
-static int rpc_timeout = 64;
-module_param(rpc_timeout, int, 0644);
-MODULE_PARM_DESC(rpc_timeout, "rpc timeout in seconds (64 by default, 0 == never)");
-
-#define sfw_unpack_id(id) \
-do { \
- __swab64s(&(id).nid); \
- __swab32s(&(id).pid); \
-} while (0)
-
-#define sfw_unpack_sid(sid) \
-do { \
- __swab64s(&(sid).ses_nid); \
- __swab64s(&(sid).ses_stamp); \
-} while (0)
-
-#define sfw_unpack_fw_counters(fc) \
-do { \
- __swab32s(&(fc).running_ms); \
- __swab32s(&(fc).active_batches); \
- __swab32s(&(fc).zombie_sessions); \
- __swab32s(&(fc).brw_errors); \
- __swab32s(&(fc).ping_errors); \
-} while (0)
-
-#define sfw_unpack_rpc_counters(rc) \
-do { \
- __swab32s(&(rc).errors); \
- __swab32s(&(rc).rpcs_sent); \
- __swab32s(&(rc).rpcs_rcvd); \
- __swab32s(&(rc).rpcs_dropped); \
- __swab32s(&(rc).rpcs_expired); \
- __swab64s(&(rc).bulk_get); \
- __swab64s(&(rc).bulk_put); \
-} while (0)
-
-#define sfw_unpack_lnet_counters(lc) \
-do { \
- __swab32s(&(lc).errors); \
- __swab32s(&(lc).msgs_max); \
- __swab32s(&(lc).msgs_alloc); \
- __swab32s(&(lc).send_count); \
- __swab32s(&(lc).recv_count); \
- __swab32s(&(lc).drop_count); \
- __swab32s(&(lc).route_count); \
- __swab64s(&(lc).send_length); \
- __swab64s(&(lc).recv_length); \
- __swab64s(&(lc).drop_length); \
- __swab64s(&(lc).route_length); \
-} while (0)
-
-#define sfw_test_active(t) (atomic_read(&(t)->tsi_nactive))
-#define sfw_batch_active(b) (atomic_read(&(b)->bat_nactive))
-
-static struct smoketest_framework {
- struct list_head fw_zombie_rpcs; /* RPCs to be recycled */
- struct list_head fw_zombie_sessions; /* stopping sessions */
- struct list_head fw_tests; /* registered test cases */
- atomic_t fw_nzombies; /* # zombie sessions */
- spinlock_t fw_lock; /* serialise */
- struct sfw_session *fw_session; /* _the_ session */
- int fw_shuttingdown; /* shutdown in progress */
- struct srpc_server_rpc *fw_active_srpc;/* running RPC */
-} sfw_data;
-
-/* forward ref's */
-int sfw_stop_batch(struct sfw_batch *tsb, int force);
-void sfw_destroy_session(struct sfw_session *sn);
-
-static inline struct sfw_test_case *
-sfw_find_test_case(int id)
-{
- struct sfw_test_case *tsc;
-
- LASSERT(id <= SRPC_SERVICE_MAX_ID);
- LASSERT(id > SRPC_FRAMEWORK_SERVICE_MAX_ID);
-
- list_for_each_entry(tsc, &sfw_data.fw_tests, tsc_list) {
- if (tsc->tsc_srv_service->sv_id == id)
- return tsc;
- }
-
- return NULL;
-}
-
-static int
-sfw_register_test(struct srpc_service *service,
- struct sfw_test_client_ops *cliops)
-{
- struct sfw_test_case *tsc;
-
- if (sfw_find_test_case(service->sv_id)) {
- CERROR("Failed to register test %s (%d)\n",
- service->sv_name, service->sv_id);
- return -EEXIST;
- }
-
- tsc = kzalloc(sizeof(struct sfw_test_case), GFP_NOFS);
- if (!tsc)
- return -ENOMEM;
-
- tsc->tsc_cli_ops = cliops;
- tsc->tsc_srv_service = service;
-
- list_add_tail(&tsc->tsc_list, &sfw_data.fw_tests);
- return 0;
-}
-
-static void
-sfw_add_session_timer(void)
-{
- struct sfw_session *sn = sfw_data.fw_session;
- struct stt_timer *timer = &sn->sn_timer;
-
- LASSERT(!sfw_data.fw_shuttingdown);
-
- if (!sn || !sn->sn_timeout)
- return;
-
- LASSERT(!sn->sn_timer_active);
-
- sn->sn_timer_active = 1;
- timer->stt_expires = ktime_get_real_seconds() + sn->sn_timeout;
- stt_add_timer(timer);
-}
-
-static int
-sfw_del_session_timer(void)
-{
- struct sfw_session *sn = sfw_data.fw_session;
-
- if (!sn || !sn->sn_timer_active)
- return 0;
-
- LASSERT(sn->sn_timeout);
-
- if (stt_del_timer(&sn->sn_timer)) { /* timer defused */
- sn->sn_timer_active = 0;
- return 0;
- }
-
- return -EBUSY; /* racing with sfw_session_expired() */
-}
-
-static void
-sfw_deactivate_session(void)
-__must_hold(&sfw_data.fw_lock)
-{
- struct sfw_session *sn = sfw_data.fw_session;
- int nactive = 0;
- struct sfw_batch *tsb;
- struct sfw_test_case *tsc;
-
- if (!sn)
- return;
-
- LASSERT(!sn->sn_timer_active);
-
- sfw_data.fw_session = NULL;
- atomic_inc(&sfw_data.fw_nzombies);
- list_add(&sn->sn_list, &sfw_data.fw_zombie_sessions);
-
- spin_unlock(&sfw_data.fw_lock);
-
- list_for_each_entry(tsc, &sfw_data.fw_tests, tsc_list) {
- srpc_abort_service(tsc->tsc_srv_service);
- }
-
- spin_lock(&sfw_data.fw_lock);
-
- list_for_each_entry(tsb, &sn->sn_batches, bat_list) {
- if (sfw_batch_active(tsb)) {
- nactive++;
- sfw_stop_batch(tsb, 1);
- }
- }
-
- if (nactive)
- return; /* wait for active batches to stop */
-
- list_del_init(&sn->sn_list);
- spin_unlock(&sfw_data.fw_lock);
-
- sfw_destroy_session(sn);
-
- spin_lock(&sfw_data.fw_lock);
-}
-
-static void
-sfw_session_expired(void *data)
-{
- struct sfw_session *sn = data;
-
- spin_lock(&sfw_data.fw_lock);
-
- LASSERT(sn->sn_timer_active);
- LASSERT(sn == sfw_data.fw_session);
-
- CWARN("Session expired! sid: %s-%llu, name: %s\n",
- libcfs_nid2str(sn->sn_id.ses_nid),
- sn->sn_id.ses_stamp, &sn->sn_name[0]);
-
- sn->sn_timer_active = 0;
- sfw_deactivate_session();
-
- spin_unlock(&sfw_data.fw_lock);
-}
-
-static inline void
-sfw_init_session(struct sfw_session *sn, struct lst_sid sid,
- unsigned int features, const char *name)
-{
- struct stt_timer *timer = &sn->sn_timer;
-
- memset(sn, 0, sizeof(struct sfw_session));
- INIT_LIST_HEAD(&sn->sn_list);
- INIT_LIST_HEAD(&sn->sn_batches);
- atomic_set(&sn->sn_refcount, 1); /* +1 for caller */
- atomic_set(&sn->sn_brw_errors, 0);
- atomic_set(&sn->sn_ping_errors, 0);
- strlcpy(&sn->sn_name[0], name, sizeof(sn->sn_name));
-
- sn->sn_timer_active = 0;
- sn->sn_id = sid;
- sn->sn_features = features;
- sn->sn_timeout = session_timeout;
- sn->sn_started = cfs_time_current();
-
- timer->stt_data = sn;
- timer->stt_func = sfw_session_expired;
- INIT_LIST_HEAD(&timer->stt_list);
-}
-
-/* completion handler for incoming framework RPCs */
-static void
-sfw_server_rpc_done(struct srpc_server_rpc *rpc)
-{
- struct srpc_service *sv = rpc->srpc_scd->scd_svc;
- int status = rpc->srpc_status;
-
- CDEBUG(D_NET, "Incoming framework RPC done: service %s, peer %s, status %s:%d\n",
- sv->sv_name, libcfs_id2str(rpc->srpc_peer),
- swi_state2str(rpc->srpc_wi.swi_state),
- status);
-
- if (rpc->srpc_bulk)
- sfw_free_pages(rpc);
-}
-
-static void
-sfw_client_rpc_fini(struct srpc_client_rpc *rpc)
-{
- LASSERT(!rpc->crpc_bulk.bk_niov);
- LASSERT(list_empty(&rpc->crpc_list));
- LASSERT(!atomic_read(&rpc->crpc_refcount));
-
- CDEBUG(D_NET, "Outgoing framework RPC done: service %d, peer %s, status %s:%d:%d\n",
- rpc->crpc_service, libcfs_id2str(rpc->crpc_dest),
- swi_state2str(rpc->crpc_wi.swi_state),
- rpc->crpc_aborted, rpc->crpc_status);
-
- spin_lock(&sfw_data.fw_lock);
-
- /* my callers must finish all RPCs before shutting me down */
- LASSERT(!sfw_data.fw_shuttingdown);
- list_add(&rpc->crpc_list, &sfw_data.fw_zombie_rpcs);
-
- spin_unlock(&sfw_data.fw_lock);
-}
-
-static struct sfw_batch *
-sfw_find_batch(struct lst_bid bid)
-{
- struct sfw_session *sn = sfw_data.fw_session;
- struct sfw_batch *bat;
-
- LASSERT(sn);
-
- list_for_each_entry(bat, &sn->sn_batches, bat_list) {
- if (bat->bat_id.bat_id == bid.bat_id)
- return bat;
- }
-
- return NULL;
-}
-
-static struct sfw_batch *
-sfw_bid2batch(struct lst_bid bid)
-{
- struct sfw_session *sn = sfw_data.fw_session;
- struct sfw_batch *bat;
-
- LASSERT(sn);
-
- bat = sfw_find_batch(bid);
- if (bat)
- return bat;
-
- bat = kzalloc(sizeof(struct sfw_batch), GFP_NOFS);
- if (!bat)
- return NULL;
-
- bat->bat_error = 0;
- bat->bat_session = sn;
- bat->bat_id = bid;
- atomic_set(&bat->bat_nactive, 0);
- INIT_LIST_HEAD(&bat->bat_tests);
-
- list_add_tail(&bat->bat_list, &sn->sn_batches);
- return bat;
-}
-
-static int
-sfw_get_stats(struct srpc_stat_reqst *request, struct srpc_stat_reply *reply)
-{
- struct sfw_session *sn = sfw_data.fw_session;
- struct sfw_counters *cnt = &reply->str_fw;
- struct sfw_batch *bat;
-
- reply->str_sid = !sn ? LST_INVALID_SID : sn->sn_id;
-
- if (request->str_sid.ses_nid == LNET_NID_ANY) {
- reply->str_status = EINVAL;
- return 0;
- }
-
- if (!sn || !sfw_sid_equal(request->str_sid, sn->sn_id)) {
- reply->str_status = ESRCH;
- return 0;
- }
-
- lnet_counters_get(&reply->str_lnet);
- srpc_get_counters(&reply->str_rpc);
-
- /*
- * send over the msecs since the session was started
- * with 32 bits to send, this is ~49 days
- */
- cnt->running_ms = jiffies_to_msecs(jiffies - sn->sn_started);
- cnt->brw_errors = atomic_read(&sn->sn_brw_errors);
- cnt->ping_errors = atomic_read(&sn->sn_ping_errors);
- cnt->zombie_sessions = atomic_read(&sfw_data.fw_nzombies);
-
- cnt->active_batches = 0;
- list_for_each_entry(bat, &sn->sn_batches, bat_list) {
- if (atomic_read(&bat->bat_nactive) > 0)
- cnt->active_batches++;
- }
-
- reply->str_status = 0;
- return 0;
-}
-
-int
-sfw_make_session(struct srpc_mksn_reqst *request, struct srpc_mksn_reply *reply)
-{
- struct sfw_session *sn = sfw_data.fw_session;
- struct srpc_msg *msg = container_of(request, struct srpc_msg,
- msg_body.mksn_reqst);
- int cplen = 0;
-
- if (request->mksn_sid.ses_nid == LNET_NID_ANY) {
- reply->mksn_sid = !sn ? LST_INVALID_SID : sn->sn_id;
- reply->mksn_status = EINVAL;
- return 0;
- }
-
- if (sn) {
- reply->mksn_status = 0;
- reply->mksn_sid = sn->sn_id;
- reply->mksn_timeout = sn->sn_timeout;
-
- if (sfw_sid_equal(request->mksn_sid, sn->sn_id)) {
- atomic_inc(&sn->sn_refcount);
- return 0;
- }
-
- if (!request->mksn_force) {
- reply->mksn_status = EBUSY;
- cplen = strlcpy(&reply->mksn_name[0], &sn->sn_name[0],
- sizeof(reply->mksn_name));
- if (cplen >= sizeof(reply->mksn_name))
- return -E2BIG;
- return 0;
- }
- }
-
- /*
- * reject the request if it requires unknown features
- * NB: old version will always accept all features because it's not
- * aware of srpc_msg::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) {
- reply->mksn_status = EPROTO;
- return 0;
- }
-
- /* brand new or create by force */
- sn = kzalloc(sizeof(struct sfw_session), GFP_NOFS);
- if (!sn) {
- CERROR("dropping RPC mksn under memory pressure\n");
- return -ENOMEM;
- }
-
- sfw_init_session(sn, request->mksn_sid,
- msg->msg_ses_feats, &request->mksn_name[0]);
-
- spin_lock(&sfw_data.fw_lock);
-
- sfw_deactivate_session();
- LASSERT(!sfw_data.fw_session);
- sfw_data.fw_session = sn;
-
- spin_unlock(&sfw_data.fw_lock);
-
- reply->mksn_status = 0;
- reply->mksn_sid = sn->sn_id;
- reply->mksn_timeout = sn->sn_timeout;
- return 0;
-}
-
-static int
-sfw_remove_session(struct srpc_rmsn_reqst *request,
- struct srpc_rmsn_reply *reply)
-{
- struct sfw_session *sn = sfw_data.fw_session;
-
- reply->rmsn_sid = !sn ? LST_INVALID_SID : sn->sn_id;
-
- if (request->rmsn_sid.ses_nid == LNET_NID_ANY) {
- reply->rmsn_status = EINVAL;
- return 0;
- }
-
- if (!sn || !sfw_sid_equal(request->rmsn_sid, sn->sn_id)) {
- reply->rmsn_status = !sn ? ESRCH : EBUSY;
- return 0;
- }
-
- if (!atomic_dec_and_test(&sn->sn_refcount)) {
- reply->rmsn_status = 0;
- return 0;
- }
-
- spin_lock(&sfw_data.fw_lock);
- sfw_deactivate_session();
- spin_unlock(&sfw_data.fw_lock);
-
- reply->rmsn_status = 0;
- reply->rmsn_sid = LST_INVALID_SID;
- LASSERT(!sfw_data.fw_session);
- return 0;
-}
-
-static int
-sfw_debug_session(struct srpc_debug_reqst *request,
- struct srpc_debug_reply *reply)
-{
- struct sfw_session *sn = sfw_data.fw_session;
-
- if (!sn) {
- reply->dbg_status = ESRCH;
- reply->dbg_sid = LST_INVALID_SID;
- return 0;
- }
-
- reply->dbg_status = 0;
- reply->dbg_sid = sn->sn_id;
- reply->dbg_timeout = sn->sn_timeout;
- if (strlcpy(reply->dbg_name, &sn->sn_name[0], sizeof(reply->dbg_name))
- >= sizeof(reply->dbg_name))
- return -E2BIG;
-
- return 0;
-}
-
-static void
-sfw_test_rpc_fini(struct srpc_client_rpc *rpc)
-{
- struct sfw_test_unit *tsu = rpc->crpc_priv;
- struct sfw_test_instance *tsi = tsu->tsu_instance;
-
- /* Called with hold of tsi->tsi_lock */
- LASSERT(list_empty(&rpc->crpc_list));
- list_add(&rpc->crpc_list, &tsi->tsi_free_rpcs);
-}
-
-static inline int
-sfw_test_buffers(struct sfw_test_instance *tsi)
-{
- struct sfw_test_case *tsc;
- struct srpc_service *svc;
- int nbuf;
-
- LASSERT(tsi);
- tsc = sfw_find_test_case(tsi->tsi_service);
- LASSERT(tsc);
- svc = tsc->tsc_srv_service;
- LASSERT(svc);
-
- nbuf = min(svc->sv_wi_total, tsi->tsi_loop) / svc->sv_ncpts;
- return max(SFW_TEST_WI_MIN, nbuf + SFW_TEST_WI_EXTRA);
-}
-
-static int
-sfw_load_test(struct sfw_test_instance *tsi)
-{
- struct sfw_test_case *tsc;
- struct srpc_service *svc;
- int nbuf;
- int rc;
-
- LASSERT(tsi);
- tsc = sfw_find_test_case(tsi->tsi_service);
- nbuf = sfw_test_buffers(tsi);
- LASSERT(tsc);
- svc = tsc->tsc_srv_service;
-
- if (tsi->tsi_is_client) {
- tsi->tsi_ops = tsc->tsc_cli_ops;
- return 0;
- }
-
- rc = srpc_service_add_buffers(svc, nbuf);
- if (rc) {
- CWARN("Failed to reserve enough buffers: service %s, %d needed: %d\n",
- svc->sv_name, nbuf, rc);
- /*
- * NB: this error handler is not strictly correct, because
- * it may release more buffers than already allocated,
- * but it doesn't matter because request portal should
- * be lazy portal and will grow buffers if necessary.
- */
- srpc_service_remove_buffers(svc, nbuf);
- return -ENOMEM;
- }
-
- CDEBUG(D_NET, "Reserved %d buffers for test %s\n",
- nbuf * (srpc_serv_is_framework(svc) ?
- 2 : cfs_cpt_number(cfs_cpt_table)), svc->sv_name);
- return 0;
-}
-
-static void
-sfw_unload_test(struct sfw_test_instance *tsi)
-{
- struct sfw_test_case *tsc;
-
- LASSERT(tsi);
- tsc = sfw_find_test_case(tsi->tsi_service);
- LASSERT(tsc);
-
- if (tsi->tsi_is_client)
- return;
-
- /*
- * shrink buffers, because request portal is lazy portal
- * which can grow buffers at runtime so we may leave
- * some buffers behind, but never mind...
- */
- srpc_service_remove_buffers(tsc->tsc_srv_service,
- sfw_test_buffers(tsi));
-}
-
-static void
-sfw_destroy_test_instance(struct sfw_test_instance *tsi)
-{
- struct srpc_client_rpc *rpc;
- struct sfw_test_unit *tsu;
-
- if (!tsi->tsi_is_client)
- goto clean;
-
- tsi->tsi_ops->tso_fini(tsi);
-
- LASSERT(!tsi->tsi_stopping);
- LASSERT(list_empty(&tsi->tsi_active_rpcs));
- LASSERT(!sfw_test_active(tsi));
-
- while (!list_empty(&tsi->tsi_units)) {
- tsu = list_entry(tsi->tsi_units.next,
- struct sfw_test_unit, tsu_list);
- list_del(&tsu->tsu_list);
- kfree(tsu);
- }
-
- while (!list_empty(&tsi->tsi_free_rpcs)) {
- rpc = list_entry(tsi->tsi_free_rpcs.next,
- struct srpc_client_rpc, crpc_list);
- list_del(&rpc->crpc_list);
- kfree(rpc);
- }
-
-clean:
- sfw_unload_test(tsi);
- kfree(tsi);
-}
-
-static void
-sfw_destroy_batch(struct sfw_batch *tsb)
-{
- struct sfw_test_instance *tsi;
-
- LASSERT(!sfw_batch_active(tsb));
- LASSERT(list_empty(&tsb->bat_list));
-
- while (!list_empty(&tsb->bat_tests)) {
- tsi = list_entry(tsb->bat_tests.next,
- struct sfw_test_instance, tsi_list);
- list_del_init(&tsi->tsi_list);
- sfw_destroy_test_instance(tsi);
- }
-
- kfree(tsb);
-}
-
-void
-sfw_destroy_session(struct sfw_session *sn)
-{
- struct sfw_batch *batch;
-
- LASSERT(list_empty(&sn->sn_list));
- LASSERT(sn != sfw_data.fw_session);
-
- while (!list_empty(&sn->sn_batches)) {
- batch = list_entry(sn->sn_batches.next,
- struct sfw_batch, bat_list);
- list_del_init(&batch->bat_list);
- sfw_destroy_batch(batch);
- }
-
- kfree(sn);
- atomic_dec(&sfw_data.fw_nzombies);
-}
-
-static void
-sfw_unpack_addtest_req(struct srpc_msg *msg)
-{
- struct srpc_test_reqst *req = &msg->msg_body.tes_reqst;
-
- LASSERT(msg->msg_type == SRPC_MSG_TEST_REQST);
- LASSERT(req->tsr_is_client);
-
- if (msg->msg_magic == SRPC_MSG_MAGIC)
- return; /* no flipping needed */
-
- LASSERT(msg->msg_magic == __swab32(SRPC_MSG_MAGIC));
-
- if (req->tsr_service == SRPC_SERVICE_BRW) {
- if (!(msg->msg_ses_feats & LST_FEAT_BULK_LEN)) {
- struct test_bulk_req *bulk = &req->tsr_u.bulk_v0;
-
- __swab32s(&bulk->blk_opc);
- __swab32s(&bulk->blk_npg);
- __swab32s(&bulk->blk_flags);
-
- } else {
- struct test_bulk_req_v1 *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) {
- struct test_ping_req *ping = &req->tsr_u.ping;
-
- __swab32s(&ping->png_size);
- __swab32s(&ping->png_flags);
- return;
- }
-
- LBUG();
-}
-
-static int
-sfw_add_test_instance(struct sfw_batch *tsb, struct srpc_server_rpc *rpc)
-{
- struct srpc_msg *msg = &rpc->srpc_reqstbuf->buf_msg;
- struct srpc_test_reqst *req = &msg->msg_body.tes_reqst;
- struct srpc_bulk *bk = rpc->srpc_bulk;
- int ndest = req->tsr_ndest;
- struct sfw_test_unit *tsu;
- struct sfw_test_instance *tsi;
- int i;
- int rc;
-
- tsi = kzalloc(sizeof(*tsi), GFP_NOFS);
- if (!tsi) {
- CERROR("Can't allocate test instance for batch: %llu\n",
- tsb->bat_id.bat_id);
- return -ENOMEM;
- }
-
- spin_lock_init(&tsi->tsi_lock);
- atomic_set(&tsi->tsi_nactive, 0);
- INIT_LIST_HEAD(&tsi->tsi_units);
- INIT_LIST_HEAD(&tsi->tsi_free_rpcs);
- INIT_LIST_HEAD(&tsi->tsi_active_rpcs);
-
- tsi->tsi_stopping = 0;
- tsi->tsi_batch = tsb;
- tsi->tsi_loop = req->tsr_loop;
- tsi->tsi_concur = req->tsr_concur;
- tsi->tsi_service = req->tsr_service;
- tsi->tsi_is_client = !!(req->tsr_is_client);
- tsi->tsi_stoptsu_onerr = !!(req->tsr_stop_onerr);
-
- rc = sfw_load_test(tsi);
- if (rc) {
- kfree(tsi);
- return rc;
- }
-
- LASSERT(!sfw_batch_active(tsb));
-
- if (!tsi->tsi_is_client) {
- /* it's test server, just add it to tsb */
- list_add_tail(&tsi->tsi_list, &tsb->bat_tests);
- return 0;
- }
-
- LASSERT(bk);
- LASSERT(bk->bk_niov * SFW_ID_PER_PAGE >= (unsigned int)ndest);
- LASSERT((unsigned int)bk->bk_len >=
- sizeof(struct lnet_process_id_packed) * ndest);
-
- sfw_unpack_addtest_req(msg);
- memcpy(&tsi->tsi_u, &req->tsr_u, sizeof(tsi->tsi_u));
-
- for (i = 0; i < ndest; i++) {
- struct lnet_process_id_packed *dests;
- struct lnet_process_id_packed id;
- int j;
-
- dests = page_address(bk->bk_iovs[i / SFW_ID_PER_PAGE].bv_page);
- LASSERT(dests); /* my pages are within KVM always */
- id = dests[i % SFW_ID_PER_PAGE];
- if (msg->msg_magic != SRPC_MSG_MAGIC)
- sfw_unpack_id(id);
-
- for (j = 0; j < tsi->tsi_concur; j++) {
- tsu = kzalloc(sizeof(struct sfw_test_unit), GFP_NOFS);
- if (!tsu) {
- rc = -ENOMEM;
- CERROR("Can't allocate tsu for %d\n",
- tsi->tsi_service);
- goto error;
- }
-
- tsu->tsu_dest.nid = id.nid;
- tsu->tsu_dest.pid = id.pid;
- tsu->tsu_instance = tsi;
- tsu->tsu_private = NULL;
- list_add_tail(&tsu->tsu_list, &tsi->tsi_units);
- }
- }
-
- rc = tsi->tsi_ops->tso_init(tsi);
- if (!rc) {
- list_add_tail(&tsi->tsi_list, &tsb->bat_tests);
- return 0;
- }
-
-error:
- LASSERT(rc);
- sfw_destroy_test_instance(tsi);
- return rc;
-}
-
-static void
-sfw_test_unit_done(struct sfw_test_unit *tsu)
-{
- struct sfw_test_instance *tsi = tsu->tsu_instance;
- struct sfw_batch *tsb = tsi->tsi_batch;
- struct sfw_session *sn = tsb->bat_session;
-
- LASSERT(sfw_test_active(tsi));
-
- if (!atomic_dec_and_test(&tsi->tsi_nactive))
- return;
-
- /* the test instance is done */
- spin_lock(&tsi->tsi_lock);
-
- tsi->tsi_stopping = 0;
-
- spin_unlock(&tsi->tsi_lock);
-
- spin_lock(&sfw_data.fw_lock);
-
- if (!atomic_dec_and_test(&tsb->bat_nactive) || /* tsb still active */
- sn == sfw_data.fw_session) { /* sn also active */
- spin_unlock(&sfw_data.fw_lock);
- return;
- }
-
- LASSERT(!list_empty(&sn->sn_list)); /* I'm a zombie! */
-
- list_for_each_entry(tsb, &sn->sn_batches, bat_list) {
- if (sfw_batch_active(tsb)) {
- spin_unlock(&sfw_data.fw_lock);
- return;
- }
- }
-
- list_del_init(&sn->sn_list);
- spin_unlock(&sfw_data.fw_lock);
-
- sfw_destroy_session(sn);
-}
-
-static void
-sfw_test_rpc_done(struct srpc_client_rpc *rpc)
-{
- struct sfw_test_unit *tsu = rpc->crpc_priv;
- struct sfw_test_instance *tsi = tsu->tsu_instance;
- int done = 0;
-
- tsi->tsi_ops->tso_done_rpc(tsu, rpc);
-
- spin_lock(&tsi->tsi_lock);
-
- LASSERT(sfw_test_active(tsi));
- LASSERT(!list_empty(&rpc->crpc_list));
-
- list_del_init(&rpc->crpc_list);
-
- /* batch is stopping or loop is done or get error */
- if (tsi->tsi_stopping || !tsu->tsu_loop ||
- (rpc->crpc_status && tsi->tsi_stoptsu_onerr))
- done = 1;
-
- /* dec ref for poster */
- srpc_client_rpc_decref(rpc);
-
- spin_unlock(&tsi->tsi_lock);
-
- if (!done) {
- swi_schedule_workitem(&tsu->tsu_worker);
- return;
- }
-
- sfw_test_unit_done(tsu);
-}
-
-int
-sfw_create_test_rpc(struct sfw_test_unit *tsu, struct lnet_process_id peer,
- unsigned int features, int nblk, int blklen,
- struct srpc_client_rpc **rpcpp)
-{
- struct srpc_client_rpc *rpc = NULL;
- struct sfw_test_instance *tsi = tsu->tsu_instance;
-
- spin_lock(&tsi->tsi_lock);
-
- LASSERT(sfw_test_active(tsi));
- /* pick request from buffer */
- rpc = list_first_entry_or_null(&tsi->tsi_free_rpcs,
- struct srpc_client_rpc, crpc_list);
- if (rpc) {
- LASSERT(nblk == rpc->crpc_bulk.bk_niov);
- list_del_init(&rpc->crpc_list);
- }
-
- spin_unlock(&tsi->tsi_lock);
-
- if (!rpc) {
- rpc = srpc_create_client_rpc(peer, tsi->tsi_service, nblk,
- blklen, sfw_test_rpc_done,
- sfw_test_rpc_fini, tsu);
- } else {
- srpc_init_client_rpc(rpc, peer, tsi->tsi_service, nblk,
- blklen, sfw_test_rpc_done,
- sfw_test_rpc_fini, tsu);
- }
-
- if (!rpc) {
- CERROR("Can't create rpc for test %d\n", tsi->tsi_service);
- return -ENOMEM;
- }
-
- rpc->crpc_reqstmsg.msg_ses_feats = features;
- *rpcpp = rpc;
-
- return 0;
-}
-
-static void
-sfw_run_test(struct swi_workitem *wi)
-{
- struct sfw_test_unit *tsu = container_of(wi, struct sfw_test_unit, tsu_worker);
- struct sfw_test_instance *tsi = tsu->tsu_instance;
- struct srpc_client_rpc *rpc = NULL;
-
- if (tsi->tsi_ops->tso_prep_rpc(tsu, tsu->tsu_dest, &rpc)) {
- LASSERT(!rpc);
- goto test_done;
- }
-
- LASSERT(rpc);
-
- spin_lock(&tsi->tsi_lock);
-
- if (tsi->tsi_stopping) {
- list_add(&rpc->crpc_list, &tsi->tsi_free_rpcs);
- spin_unlock(&tsi->tsi_lock);
- goto test_done;
- }
-
- if (tsu->tsu_loop > 0)
- tsu->tsu_loop--;
-
- list_add_tail(&rpc->crpc_list, &tsi->tsi_active_rpcs);
- spin_unlock(&tsi->tsi_lock);
-
- spin_lock(&rpc->crpc_lock);
- rpc->crpc_timeout = rpc_timeout;
- srpc_post_rpc(rpc);
- spin_unlock(&rpc->crpc_lock);
- return;
-
-test_done:
- /*
- * No one can schedule me now since:
- * - previous RPC, if any, has done and
- * - no new RPC is initiated.
- * - my batch is still active; no one can run it again now.
- * Cancel pending schedules and prevent future schedule attempts:
- */
- sfw_test_unit_done(tsu);
-}
-
-static int
-sfw_run_batch(struct sfw_batch *tsb)
-{
- struct swi_workitem *wi;
- struct sfw_test_unit *tsu;
- struct sfw_test_instance *tsi;
-
- if (sfw_batch_active(tsb)) {
- CDEBUG(D_NET, "Batch already active: %llu (%d)\n",
- tsb->bat_id.bat_id, atomic_read(&tsb->bat_nactive));
- return 0;
- }
-
- list_for_each_entry(tsi, &tsb->bat_tests, tsi_list) {
- if (!tsi->tsi_is_client) /* skip server instances */
- continue;
-
- LASSERT(!tsi->tsi_stopping);
- LASSERT(!sfw_test_active(tsi));
-
- atomic_inc(&tsb->bat_nactive);
-
- list_for_each_entry(tsu, &tsi->tsi_units, tsu_list) {
- atomic_inc(&tsi->tsi_nactive);
- tsu->tsu_loop = tsi->tsi_loop;
- wi = &tsu->tsu_worker;
- swi_init_workitem(wi, sfw_run_test,
- lst_test_wq[lnet_cpt_of_nid(tsu->tsu_dest.nid)]);
- swi_schedule_workitem(wi);
- }
- }
-
- return 0;
-}
-
-int
-sfw_stop_batch(struct sfw_batch *tsb, int force)
-{
- struct sfw_test_instance *tsi;
- struct srpc_client_rpc *rpc;
-
- if (!sfw_batch_active(tsb)) {
- CDEBUG(D_NET, "Batch %llu inactive\n", tsb->bat_id.bat_id);
- return 0;
- }
-
- list_for_each_entry(tsi, &tsb->bat_tests, tsi_list) {
- spin_lock(&tsi->tsi_lock);
-
- if (!tsi->tsi_is_client ||
- !sfw_test_active(tsi) || tsi->tsi_stopping) {
- spin_unlock(&tsi->tsi_lock);
- continue;
- }
-
- tsi->tsi_stopping = 1;
-
- if (!force) {
- spin_unlock(&tsi->tsi_lock);
- continue;
- }
-
- /* abort launched rpcs in the test */
- list_for_each_entry(rpc, &tsi->tsi_active_rpcs, crpc_list) {
- spin_lock(&rpc->crpc_lock);
-
- srpc_abort_rpc(rpc, -EINTR);
-
- spin_unlock(&rpc->crpc_lock);
- }
-
- spin_unlock(&tsi->tsi_lock);
- }
-
- return 0;
-}
-
-static int
-sfw_query_batch(struct sfw_batch *tsb, int testidx,
- struct srpc_batch_reply *reply)
-{
- struct sfw_test_instance *tsi;
-
- if (testidx < 0)
- return -EINVAL;
-
- if (!testidx) {
- reply->bar_active = atomic_read(&tsb->bat_nactive);
- return 0;
- }
-
- list_for_each_entry(tsi, &tsb->bat_tests, tsi_list) {
- if (testidx-- > 1)
- continue;
-
- reply->bar_active = atomic_read(&tsi->tsi_nactive);
- return 0;
- }
-
- return -ENOENT;
-}
-
-void
-sfw_free_pages(struct srpc_server_rpc *rpc)
-{
- srpc_free_bulk(rpc->srpc_bulk);
- rpc->srpc_bulk = NULL;
-}
-
-int
-sfw_alloc_pages(struct srpc_server_rpc *rpc, int cpt, int npages, int len,
- int sink)
-{
- LASSERT(!rpc->srpc_bulk);
- LASSERT(npages > 0 && npages <= LNET_MAX_IOV);
-
- rpc->srpc_bulk = srpc_alloc_bulk(cpt, 0, npages, len, sink);
- if (!rpc->srpc_bulk)
- return -ENOMEM;
-
- return 0;
-}
-
-static int
-sfw_add_test(struct srpc_server_rpc *rpc)
-{
- struct sfw_session *sn = sfw_data.fw_session;
- struct srpc_test_reply *reply = &rpc->srpc_replymsg.msg_body.tes_reply;
- struct srpc_test_reqst *request;
- int rc;
- struct sfw_batch *bat;
-
- request = &rpc->srpc_reqstbuf->buf_msg.msg_body.tes_reqst;
- reply->tsr_sid = !sn ? LST_INVALID_SID : sn->sn_id;
-
- if (!request->tsr_loop ||
- !request->tsr_concur ||
- request->tsr_sid.ses_nid == LNET_NID_ANY ||
- request->tsr_ndest > SFW_MAX_NDESTS ||
- (request->tsr_is_client && !request->tsr_ndest) ||
- request->tsr_concur > SFW_MAX_CONCUR ||
- request->tsr_service > SRPC_SERVICE_MAX_ID ||
- request->tsr_service <= SRPC_FRAMEWORK_SERVICE_MAX_ID) {
- reply->tsr_status = EINVAL;
- return 0;
- }
-
- if (!sn || !sfw_sid_equal(request->tsr_sid, sn->sn_id) ||
- !sfw_find_test_case(request->tsr_service)) {
- reply->tsr_status = ENOENT;
- return 0;
- }
-
- bat = sfw_bid2batch(request->tsr_bid);
- if (!bat) {
- CERROR("dropping RPC %s from %s under memory pressure\n",
- rpc->srpc_scd->scd_svc->sv_name,
- libcfs_id2str(rpc->srpc_peer));
- return -ENOMEM;
- }
-
- if (sfw_batch_active(bat)) {
- reply->tsr_status = EBUSY;
- return 0;
- }
-
- if (request->tsr_is_client && !rpc->srpc_bulk) {
- /* rpc will be resumed later in sfw_bulk_ready */
- int npg = sfw_id_pages(request->tsr_ndest);
- int len;
-
- if (!(sn->sn_features & LST_FEAT_BULK_LEN)) {
- len = npg * PAGE_SIZE;
-
- } else {
- len = sizeof(struct lnet_process_id_packed) *
- request->tsr_ndest;
- }
-
- return sfw_alloc_pages(rpc, CFS_CPT_ANY, npg, len, 1);
- }
-
- rc = sfw_add_test_instance(bat, rpc);
- CDEBUG(!rc ? D_NET : D_WARNING,
- "%s test: sv %d %s, loop %d, concur %d, ndest %d\n",
- !rc ? "Added" : "Failed to add", request->tsr_service,
- request->tsr_is_client ? "client" : "server",
- request->tsr_loop, request->tsr_concur, request->tsr_ndest);
-
- reply->tsr_status = (rc < 0) ? -rc : rc;
- return 0;
-}
-
-static int
-sfw_control_batch(struct srpc_batch_reqst *request,
- struct srpc_batch_reply *reply)
-{
- struct sfw_session *sn = sfw_data.fw_session;
- int rc = 0;
- struct sfw_batch *bat;
-
- reply->bar_sid = !sn ? LST_INVALID_SID : sn->sn_id;
-
- if (!sn || !sfw_sid_equal(request->bar_sid, sn->sn_id)) {
- reply->bar_status = ESRCH;
- return 0;
- }
-
- bat = sfw_find_batch(request->bar_bid);
- if (!bat) {
- reply->bar_status = ENOENT;
- return 0;
- }
-
- switch (request->bar_opc) {
- case SRPC_BATCH_OPC_RUN:
- rc = sfw_run_batch(bat);
- break;
-
- case SRPC_BATCH_OPC_STOP:
- rc = sfw_stop_batch(bat, request->bar_arg);
- break;
-
- case SRPC_BATCH_OPC_QUERY:
- rc = sfw_query_batch(bat, request->bar_testidx, reply);
- break;
-
- default:
- return -EINVAL; /* drop it */
- }
-
- reply->bar_status = (rc < 0) ? -rc : rc;
- return 0;
-}
-
-static int
-sfw_handle_server_rpc(struct srpc_server_rpc *rpc)
-{
- struct srpc_service *sv = rpc->srpc_scd->scd_svc;
- struct srpc_msg *reply = &rpc->srpc_replymsg;
- struct srpc_msg *request = &rpc->srpc_reqstbuf->buf_msg;
- unsigned int features = LST_FEATS_MASK;
- int rc = 0;
-
- LASSERT(!sfw_data.fw_active_srpc);
- LASSERT(sv->sv_id <= SRPC_FRAMEWORK_SERVICE_MAX_ID);
-
- spin_lock(&sfw_data.fw_lock);
-
- if (sfw_data.fw_shuttingdown) {
- spin_unlock(&sfw_data.fw_lock);
- return -ESHUTDOWN;
- }
-
- /* Remove timer to avoid racing with it or expiring active session */
- if (sfw_del_session_timer()) {
- CERROR("dropping RPC %s from %s: racing with expiry timer\n",
- sv->sv_name, libcfs_id2str(rpc->srpc_peer));
- spin_unlock(&sfw_data.fw_lock);
- return -EAGAIN;
- }
-
- sfw_data.fw_active_srpc = rpc;
- spin_unlock(&sfw_data.fw_lock);
-
- 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) {
- struct sfw_session *sn = sfw_data.fw_session;
-
- if (sn &&
- 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) {
- /*
- * 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();
- case SRPC_SERVICE_TEST:
- rc = sfw_add_test(rpc);
- break;
-
- case SRPC_SERVICE_BATCH:
- rc = sfw_control_batch(&request->msg_body.bat_reqst,
- &reply->msg_body.bat_reply);
- break;
-
- case SRPC_SERVICE_QUERY_STAT:
- rc = sfw_get_stats(&request->msg_body.stat_reqst,
- &reply->msg_body.stat_reply);
- break;
-
- case SRPC_SERVICE_DEBUG:
- rc = sfw_debug_session(&request->msg_body.dbg_reqst,
- &reply->msg_body.dbg_reply);
- break;
-
- case SRPC_SERVICE_MAKE_SESSION:
- rc = sfw_make_session(&request->msg_body.mksn_reqst,
- &reply->msg_body.mksn_reply);
- break;
-
- case SRPC_SERVICE_REMOVE_SESSION:
- rc = sfw_remove_session(&request->msg_body.rmsn_reqst,
- &reply->msg_body.rmsn_reply);
- break;
- }
-
- if (sfw_data.fw_session)
- features = sfw_data.fw_session->sn_features;
- out:
- reply->msg_ses_feats = features;
- rpc->srpc_done = sfw_server_rpc_done;
- spin_lock(&sfw_data.fw_lock);
-
- if (!sfw_data.fw_shuttingdown)
- sfw_add_session_timer();
-
- sfw_data.fw_active_srpc = NULL;
- spin_unlock(&sfw_data.fw_lock);
- return rc;
-}
-
-static int
-sfw_bulk_ready(struct srpc_server_rpc *rpc, int status)
-{
- struct srpc_service *sv = rpc->srpc_scd->scd_svc;
- int rc;
-
- LASSERT(rpc->srpc_bulk);
- LASSERT(sv->sv_id == SRPC_SERVICE_TEST);
- LASSERT(!sfw_data.fw_active_srpc);
- LASSERT(rpc->srpc_reqstbuf->buf_msg.msg_body.tes_reqst.tsr_is_client);
-
- spin_lock(&sfw_data.fw_lock);
-
- if (status) {
- CERROR("Bulk transfer failed for RPC: service %s, peer %s, status %d\n",
- sv->sv_name, libcfs_id2str(rpc->srpc_peer), status);
- spin_unlock(&sfw_data.fw_lock);
- return -EIO;
- }
-
- if (sfw_data.fw_shuttingdown) {
- spin_unlock(&sfw_data.fw_lock);
- return -ESHUTDOWN;
- }
-
- if (sfw_del_session_timer()) {
- CERROR("dropping RPC %s from %s: racing with expiry timer\n",
- sv->sv_name, libcfs_id2str(rpc->srpc_peer));
- spin_unlock(&sfw_data.fw_lock);
- return -EAGAIN;
- }
-
- sfw_data.fw_active_srpc = rpc;
- spin_unlock(&sfw_data.fw_lock);
-
- rc = sfw_add_test(rpc);
-
- spin_lock(&sfw_data.fw_lock);
-
- if (!sfw_data.fw_shuttingdown)
- sfw_add_session_timer();
-
- sfw_data.fw_active_srpc = NULL;
- spin_unlock(&sfw_data.fw_lock);
- return rc;
-}
-
-struct srpc_client_rpc *
-sfw_create_rpc(struct lnet_process_id peer, int service,
- unsigned int features, int nbulkiov, int bulklen,
- void (*done)(struct srpc_client_rpc *), void *priv)
-{
- struct srpc_client_rpc *rpc = NULL;
-
- spin_lock(&sfw_data.fw_lock);
-
- LASSERT(!sfw_data.fw_shuttingdown);
- LASSERT(service <= SRPC_FRAMEWORK_SERVICE_MAX_ID);
-
- if (!nbulkiov && !list_empty(&sfw_data.fw_zombie_rpcs)) {
- rpc = list_entry(sfw_data.fw_zombie_rpcs.next,
- struct srpc_client_rpc, crpc_list);
- list_del(&rpc->crpc_list);
-
- srpc_init_client_rpc(rpc, peer, service, 0, 0,
- done, sfw_client_rpc_fini, priv);
- }
-
- spin_unlock(&sfw_data.fw_lock);
-
- if (!rpc) {
- rpc = srpc_create_client_rpc(peer, service,
- nbulkiov, bulklen, done,
- nbulkiov ? NULL :
- sfw_client_rpc_fini,
- priv);
- }
-
- if (rpc) /* "session" is concept in framework */
- rpc->crpc_reqstmsg.msg_ses_feats = features;
-
- return rpc;
-}
-
-void
-sfw_unpack_message(struct srpc_msg *msg)
-{
- 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));
-
- if (msg->msg_type == SRPC_MSG_STAT_REQST) {
- struct srpc_stat_reqst *req = &msg->msg_body.stat_reqst;
-
- __swab32s(&req->str_type);
- __swab64s(&req->str_rpyid);
- sfw_unpack_sid(req->str_sid);
- return;
- }
-
- if (msg->msg_type == SRPC_MSG_STAT_REPLY) {
- struct srpc_stat_reply *rep = &msg->msg_body.stat_reply;
-
- __swab32s(&rep->str_status);
- sfw_unpack_sid(rep->str_sid);
- sfw_unpack_fw_counters(rep->str_fw);
- sfw_unpack_rpc_counters(rep->str_rpc);
- sfw_unpack_lnet_counters(rep->str_lnet);
- return;
- }
-
- if (msg->msg_type == SRPC_MSG_MKSN_REQST) {
- struct srpc_mksn_reqst *req = &msg->msg_body.mksn_reqst;
-
- __swab64s(&req->mksn_rpyid);
- __swab32s(&req->mksn_force);
- sfw_unpack_sid(req->mksn_sid);
- return;
- }
-
- if (msg->msg_type == SRPC_MSG_MKSN_REPLY) {
- struct srpc_mksn_reply *rep = &msg->msg_body.mksn_reply;
-
- __swab32s(&rep->mksn_status);
- __swab32s(&rep->mksn_timeout);
- sfw_unpack_sid(rep->mksn_sid);
- return;
- }
-
- if (msg->msg_type == SRPC_MSG_RMSN_REQST) {
- struct srpc_rmsn_reqst *req = &msg->msg_body.rmsn_reqst;
-
- __swab64s(&req->rmsn_rpyid);
- sfw_unpack_sid(req->rmsn_sid);
- return;
- }
-
- if (msg->msg_type == SRPC_MSG_RMSN_REPLY) {
- struct srpc_rmsn_reply *rep = &msg->msg_body.rmsn_reply;
-
- __swab32s(&rep->rmsn_status);
- sfw_unpack_sid(rep->rmsn_sid);
- return;
- }
-
- if (msg->msg_type == SRPC_MSG_DEBUG_REQST) {
- struct srpc_debug_reqst *req = &msg->msg_body.dbg_reqst;
-
- __swab64s(&req->dbg_rpyid);
- __swab32s(&req->dbg_flags);
- sfw_unpack_sid(req->dbg_sid);
- return;
- }
-
- if (msg->msg_type == SRPC_MSG_DEBUG_REPLY) {
- struct srpc_debug_reply *rep = &msg->msg_body.dbg_reply;
-
- __swab32s(&rep->dbg_nbatch);
- __swab32s(&rep->dbg_timeout);
- sfw_unpack_sid(rep->dbg_sid);
- return;
- }
-
- if (msg->msg_type == SRPC_MSG_BATCH_REQST) {
- struct srpc_batch_reqst *req = &msg->msg_body.bat_reqst;
-
- __swab32s(&req->bar_opc);
- __swab64s(&req->bar_rpyid);
- __swab32s(&req->bar_testidx);
- __swab32s(&req->bar_arg);
- sfw_unpack_sid(req->bar_sid);
- __swab64s(&req->bar_bid.bat_id);
- return;
- }
-
- if (msg->msg_type == SRPC_MSG_BATCH_REPLY) {
- struct srpc_batch_reply *rep = &msg->msg_body.bat_reply;
-
- __swab32s(&rep->bar_status);
- sfw_unpack_sid(rep->bar_sid);
- return;
- }
-
- if (msg->msg_type == SRPC_MSG_TEST_REQST) {
- struct srpc_test_reqst *req = &msg->msg_body.tes_reqst;
-
- __swab64s(&req->tsr_rpyid);
- __swab64s(&req->tsr_bulkid);
- __swab32s(&req->tsr_loop);
- __swab32s(&req->tsr_ndest);
- __swab32s(&req->tsr_concur);
- __swab32s(&req->tsr_service);
- sfw_unpack_sid(req->tsr_sid);
- __swab64s(&req->tsr_bid.bat_id);
- return;
- }
-
- if (msg->msg_type == SRPC_MSG_TEST_REPLY) {
- struct srpc_test_reply *rep = &msg->msg_body.tes_reply;
-
- __swab32s(&rep->tsr_status);
- sfw_unpack_sid(rep->tsr_sid);
- return;
- }
-
- if (msg->msg_type == SRPC_MSG_JOIN_REQST) {
- struct srpc_join_reqst *req = &msg->msg_body.join_reqst;
-
- __swab64s(&req->join_rpyid);
- sfw_unpack_sid(req->join_sid);
- return;
- }
-
- if (msg->msg_type == SRPC_MSG_JOIN_REPLY) {
- struct srpc_join_reply *rep = &msg->msg_body.join_reply;
-
- __swab32s(&rep->join_status);
- __swab32s(&rep->join_timeout);
- sfw_unpack_sid(rep->join_sid);
- return;
- }
-
- LBUG();
-}
-
-void
-sfw_abort_rpc(struct srpc_client_rpc *rpc)
-{
- LASSERT(atomic_read(&rpc->crpc_refcount) > 0);
- LASSERT(rpc->crpc_service <= SRPC_FRAMEWORK_SERVICE_MAX_ID);
-
- spin_lock(&rpc->crpc_lock);
- srpc_abort_rpc(rpc, -EINTR);
- spin_unlock(&rpc->crpc_lock);
-}
-
-void
-sfw_post_rpc(struct srpc_client_rpc *rpc)
-{
- spin_lock(&rpc->crpc_lock);
-
- LASSERT(!rpc->crpc_closed);
- LASSERT(!rpc->crpc_aborted);
- LASSERT(list_empty(&rpc->crpc_list));
- LASSERT(!sfw_data.fw_shuttingdown);
-
- rpc->crpc_timeout = rpc_timeout;
- srpc_post_rpc(rpc);
-
- spin_unlock(&rpc->crpc_lock);
-}
-
-static struct srpc_service sfw_services[] = {
- {
- /* sv_id */ SRPC_SERVICE_DEBUG,
- /* sv_name */ "debug",
- 0
- },
- {
- /* sv_id */ SRPC_SERVICE_QUERY_STAT,
- /* sv_name */ "query stats",
- 0
- },
- {
- /* sv_id */ SRPC_SERVICE_MAKE_SESSION,
- /* sv_name */ "make session",
- 0
- },
- {
- /* sv_id */ SRPC_SERVICE_REMOVE_SESSION,
- /* sv_name */ "remove session",
- 0
- },
- {
- /* sv_id */ SRPC_SERVICE_BATCH,
- /* sv_name */ "batch service",
- 0
- },
- {
- /* sv_id */ SRPC_SERVICE_TEST,
- /* sv_name */ "test service",
- 0
- },
- {
- /* sv_id */ 0,
- /* sv_name */ NULL,
- 0
- }
-};
-
-int
-sfw_startup(void)
-{
- int i;
- int rc;
- int error;
- struct srpc_service *sv;
- struct sfw_test_case *tsc;
-
- if (session_timeout < 0) {
- CERROR("Session timeout must be non-negative: %d\n",
- session_timeout);
- return -EINVAL;
- }
-
- if (rpc_timeout < 0) {
- CERROR("RPC timeout must be non-negative: %d\n",
- rpc_timeout);
- return -EINVAL;
- }
-
- if (!session_timeout)
- CWARN("Zero session_timeout specified - test sessions never expire.\n");
-
- if (!rpc_timeout)
- CWARN("Zero rpc_timeout specified - test RPC never expire.\n");
-
- memset(&sfw_data, 0, sizeof(struct smoketest_framework));
-
- sfw_data.fw_session = NULL;
- sfw_data.fw_active_srpc = NULL;
- spin_lock_init(&sfw_data.fw_lock);
- atomic_set(&sfw_data.fw_nzombies, 0);
- INIT_LIST_HEAD(&sfw_data.fw_tests);
- INIT_LIST_HEAD(&sfw_data.fw_zombie_rpcs);
- INIT_LIST_HEAD(&sfw_data.fw_zombie_sessions);
-
- brw_init_test_client();
- brw_init_test_service();
- rc = sfw_register_test(&brw_test_service, &brw_test_client);
- LASSERT(!rc);
-
- ping_init_test_client();
- ping_init_test_service();
- rc = sfw_register_test(&ping_test_service, &ping_test_client);
- LASSERT(!rc);
-
- error = 0;
- list_for_each_entry(tsc, &sfw_data.fw_tests, tsc_list) {
- sv = tsc->tsc_srv_service;
-
- rc = srpc_add_service(sv);
- LASSERT(rc != -EBUSY);
- if (rc) {
- CWARN("Failed to add %s service: %d\n",
- sv->sv_name, rc);
- error = rc;
- }
- }
-
- for (i = 0; ; i++) {
- sv = &sfw_services[i];
- if (!sv->sv_name)
- break;
-
- sv->sv_bulk_ready = NULL;
- sv->sv_handler = sfw_handle_server_rpc;
- sv->sv_wi_total = SFW_FRWK_WI_MAX;
- if (sv->sv_id == SRPC_SERVICE_TEST)
- sv->sv_bulk_ready = sfw_bulk_ready;
-
- rc = srpc_add_service(sv);
- LASSERT(rc != -EBUSY);
- if (rc) {
- CWARN("Failed to add %s service: %d\n",
- sv->sv_name, rc);
- error = rc;
- }
-
- /* about to sfw_shutdown, no need to add buffer */
- if (error)
- continue;
-
- rc = srpc_service_add_buffers(sv, sv->sv_wi_total);
- if (rc) {
- CWARN("Failed to reserve enough buffers: service %s, %d needed: %d\n",
- sv->sv_name, sv->sv_wi_total, rc);
- error = -ENOMEM;
- }
- }
-
- if (error)
- sfw_shutdown();
- return error;
-}
-
-void
-sfw_shutdown(void)
-{
- struct srpc_service *sv;
- struct sfw_test_case *tsc;
- int i;
-
- spin_lock(&sfw_data.fw_lock);
-
- sfw_data.fw_shuttingdown = 1;
- lst_wait_until(!sfw_data.fw_active_srpc, sfw_data.fw_lock,
- "waiting for active RPC to finish.\n");
-
- if (sfw_del_session_timer())
- lst_wait_until(!sfw_data.fw_session, sfw_data.fw_lock,
- "waiting for session timer to explode.\n");
-
- sfw_deactivate_session();
- lst_wait_until(!atomic_read(&sfw_data.fw_nzombies),
- sfw_data.fw_lock,
- "waiting for %d zombie sessions to die.\n",
- atomic_read(&sfw_data.fw_nzombies));
-
- spin_unlock(&sfw_data.fw_lock);
-
- for (i = 0; ; i++) {
- sv = &sfw_services[i];
- if (!sv->sv_name)
- break;
-
- srpc_shutdown_service(sv);
- srpc_remove_service(sv);
- }
-
- list_for_each_entry(tsc, &sfw_data.fw_tests, tsc_list) {
- sv = tsc->tsc_srv_service;
- srpc_shutdown_service(sv);
- srpc_remove_service(sv);
- }
-
- while (!list_empty(&sfw_data.fw_zombie_rpcs)) {
- struct srpc_client_rpc *rpc;
-
- rpc = list_entry(sfw_data.fw_zombie_rpcs.next,
- struct srpc_client_rpc, crpc_list);
- list_del(&rpc->crpc_list);
-
- kfree(rpc);
- }
-
- for (i = 0; ; i++) {
- sv = &sfw_services[i];
- if (!sv->sv_name)
- break;
-
- srpc_wait_service_shutdown(sv);
- }
-
- while (!list_empty(&sfw_data.fw_tests)) {
- tsc = list_entry(sfw_data.fw_tests.next,
- struct sfw_test_case, tsc_list);
-
- srpc_wait_service_shutdown(tsc->tsc_srv_service);
-
- list_del(&tsc->tsc_list);
- kfree(tsc);
- }
-}
diff --git a/drivers/staging/lustre/lnet/selftest/module.c b/drivers/staging/lustre/lnet/selftest/module.c
deleted file mode 100644
index 7359aa56d9b3..000000000000
--- a/drivers/staging/lustre/lnet/selftest/module.c
+++ /dev/null
@@ -1,165 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * GPL HEADER START
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 only,
- * as published by the Free Software Foundation.
- *
- * This program 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 version 2 for more details (a copy is included
- * in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2012, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- */
-
-#define DEBUG_SUBSYSTEM S_LNET
-
-#include "selftest.h"
-#include "console.h"
-
-enum {
- LST_INIT_NONE = 0,
- LST_INIT_WI_SERIAL,
- LST_INIT_WI_TEST,
- LST_INIT_RPC,
- LST_INIT_FW,
- LST_INIT_CONSOLE
-};
-
-static int lst_init_step = LST_INIT_NONE;
-
-struct workqueue_struct *lst_serial_wq;
-struct workqueue_struct **lst_test_wq;
-
-static void
-lnet_selftest_exit(void)
-{
- int i;
-
- switch (lst_init_step) {
- case LST_INIT_CONSOLE:
- lstcon_console_fini();
- /* fall through */
- case LST_INIT_FW:
- sfw_shutdown();
- /* fall through */
- case LST_INIT_RPC:
- srpc_shutdown();
- /* fall through */
- case LST_INIT_WI_TEST:
- for (i = 0;
- i < cfs_cpt_number(lnet_cpt_table()); i++) {
- if (!lst_test_wq[i])
- continue;
- destroy_workqueue(lst_test_wq[i]);
- }
- kvfree(lst_test_wq);
- lst_test_wq = NULL;
- /* fall through */
- case LST_INIT_WI_SERIAL:
- destroy_workqueue(lst_serial_wq);
- lst_serial_wq = NULL;
- case LST_INIT_NONE:
- break;
- default:
- LBUG();
- }
-}
-
-static int
-lnet_selftest_init(void)
-{
- int nscheds;
- int rc = -ENOMEM;
- int i;
-
- lst_serial_wq = alloc_ordered_workqueue("lst_s", 0);
- if (!lst_serial_wq) {
- CERROR("Failed to create serial WI scheduler for LST\n");
- return -ENOMEM;
- }
- lst_init_step = LST_INIT_WI_SERIAL;
-
- nscheds = cfs_cpt_number(lnet_cpt_table());
- lst_test_wq = kvmalloc_array(nscheds, sizeof(lst_test_wq[0]),
- GFP_KERNEL | __GFP_ZERO);
- if (!lst_test_wq) {
- rc = -ENOMEM;
- goto error;
- }
-
- lst_init_step = LST_INIT_WI_TEST;
- for (i = 0; i < nscheds; i++) {
- int nthrs = cfs_cpt_weight(lnet_cpt_table(), i);
- struct workqueue_attrs attrs = {0};
- cpumask_var_t *mask = cfs_cpt_cpumask(lnet_cpt_table(), i);
-
- /* reserve at least one CPU for LND */
- nthrs = max(nthrs - 1, 1);
- lst_test_wq[i] = alloc_workqueue("lst_t", WQ_UNBOUND, nthrs);
- if (!lst_test_wq[i]) {
- CWARN("Failed to create CPU partition affinity WI scheduler %d for LST\n",
- i);
- rc = -ENOMEM;
- goto error;
- }
-
- if (mask && alloc_cpumask_var(&attrs.cpumask, GFP_KERNEL)) {
- cpumask_copy(attrs.cpumask, *mask);
- apply_workqueue_attrs(lst_test_wq[i], &attrs);
- free_cpumask_var(attrs.cpumask);
- }
- }
-
- rc = srpc_startup();
- if (rc) {
- CERROR("LST can't startup rpc\n");
- goto error;
- }
- lst_init_step = LST_INIT_RPC;
-
- rc = sfw_startup();
- if (rc) {
- CERROR("LST can't startup framework\n");
- goto error;
- }
- lst_init_step = LST_INIT_FW;
-
- rc = lstcon_console_init();
- if (rc) {
- CERROR("LST can't startup console\n");
- goto error;
- }
- lst_init_step = LST_INIT_CONSOLE;
- return 0;
-error:
- lnet_selftest_exit();
- return rc;
-}
-
-MODULE_AUTHOR("OpenSFS, Inc. <http://www.lustre.org/>");
-MODULE_DESCRIPTION("LNet Selftest");
-MODULE_VERSION("2.7.0");
-MODULE_LICENSE("GPL");
-
-module_init(lnet_selftest_init);
-module_exit(lnet_selftest_exit);
diff --git a/drivers/staging/lustre/lnet/selftest/ping_test.c b/drivers/staging/lustre/lnet/selftest/ping_test.c
deleted file mode 100644
index f54bd630dbf8..000000000000
--- a/drivers/staging/lustre/lnet/selftest/ping_test.c
+++ /dev/null
@@ -1,228 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * GPL HEADER START
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 only,
- * as published by the Free Software Foundation.
- *
- * This program 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 version 2 for more details (a copy is included
- * in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2012, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * lnet/selftest/conctl.c
- *
- * Test client & Server
- *
- * Author: Liang Zhen <liangzhen@clusterfs.com>
- */
-
-#include "selftest.h"
-
-#define LST_PING_TEST_MAGIC 0xbabeface
-
-static int ping_srv_workitems = SFW_TEST_WI_MAX;
-module_param(ping_srv_workitems, int, 0644);
-MODULE_PARM_DESC(ping_srv_workitems, "# PING server workitems");
-
-struct lst_ping_data {
- spinlock_t pnd_lock; /* serialize */
- int pnd_counter; /* sequence counter */
-};
-
-static struct lst_ping_data lst_ping_data;
-
-static int
-ping_client_init(struct sfw_test_instance *tsi)
-{
- struct sfw_session *sn = tsi->tsi_batch->bat_session;
-
- LASSERT(tsi->tsi_is_client);
- LASSERT(sn && !(sn->sn_features & ~LST_FEATS_MASK));
-
- spin_lock_init(&lst_ping_data.pnd_lock);
- lst_ping_data.pnd_counter = 0;
-
- return 0;
-}
-
-static void
-ping_client_fini(struct sfw_test_instance *tsi)
-{
- struct sfw_session *sn = tsi->tsi_batch->bat_session;
- int errors;
-
- LASSERT(sn);
- LASSERT(tsi->tsi_is_client);
-
- errors = atomic_read(&sn->sn_ping_errors);
- if (errors)
- CWARN("%d pings have failed.\n", errors);
- else
- CDEBUG(D_NET, "Ping test finished OK.\n");
-}
-
-static int
-ping_client_prep_rpc(struct sfw_test_unit *tsu, struct lnet_process_id dest,
- struct srpc_client_rpc **rpc)
-{
- struct srpc_ping_reqst *req;
- struct sfw_test_instance *tsi = tsu->tsu_instance;
- struct sfw_session *sn = tsi->tsi_batch->bat_session;
- struct timespec64 ts;
- int rc;
-
- LASSERT(sn);
- LASSERT(!(sn->sn_features & ~LST_FEATS_MASK));
-
- rc = sfw_create_test_rpc(tsu, dest, sn->sn_features, 0, 0, rpc);
- if (rc)
- return rc;
-
- req = &(*rpc)->crpc_reqstmsg.msg_body.ping_reqst;
-
- req->pnr_magic = LST_PING_TEST_MAGIC;
-
- spin_lock(&lst_ping_data.pnd_lock);
- req->pnr_seq = lst_ping_data.pnd_counter++;
- spin_unlock(&lst_ping_data.pnd_lock);
-
- ktime_get_real_ts64(&ts);
- req->pnr_time_sec = ts.tv_sec;
- req->pnr_time_usec = ts.tv_nsec / NSEC_PER_USEC;
-
- return rc;
-}
-
-static void
-ping_client_done_rpc(struct sfw_test_unit *tsu, struct srpc_client_rpc *rpc)
-{
- struct sfw_test_instance *tsi = tsu->tsu_instance;
- struct sfw_session *sn = tsi->tsi_batch->bat_session;
- struct srpc_ping_reqst *reqst = &rpc->crpc_reqstmsg.msg_body.ping_reqst;
- struct srpc_ping_reply *reply = &rpc->crpc_replymsg.msg_body.ping_reply;
- struct timespec64 ts;
-
- LASSERT(sn);
-
- if (rpc->crpc_status) {
- if (!tsi->tsi_stopping) /* rpc could have been aborted */
- atomic_inc(&sn->sn_ping_errors);
- CERROR("Unable to ping %s (%d): %d\n",
- 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;
- atomic_inc(&sn->sn_ping_errors);
- CERROR("Bad magic %u from %s, %u expected.\n",
- reply->pnr_magic, libcfs_id2str(rpc->crpc_dest),
- LST_PING_TEST_MAGIC);
- return;
- }
-
- if (reply->pnr_seq != reqst->pnr_seq) {
- rpc->crpc_status = -EBADMSG;
- atomic_inc(&sn->sn_ping_errors);
- CERROR("Bad seq %u from %s, %u expected.\n",
- reply->pnr_seq, libcfs_id2str(rpc->crpc_dest),
- reqst->pnr_seq);
- return;
- }
-
- ktime_get_real_ts64(&ts);
- CDEBUG(D_NET, "%d reply in %u usec\n", reply->pnr_seq,
- (unsigned int)((ts.tv_sec - reqst->pnr_time_sec) * 1000000 +
- (ts.tv_nsec / NSEC_PER_USEC - reqst->pnr_time_usec)));
-}
-
-static int
-ping_server_handle(struct srpc_server_rpc *rpc)
-{
- struct srpc_service *sv = rpc->srpc_scd->scd_svc;
- struct srpc_msg *reqstmsg = &rpc->srpc_reqstbuf->buf_msg;
- struct srpc_msg *replymsg = &rpc->srpc_replymsg;
- struct srpc_ping_reqst *req = &reqstmsg->msg_body.ping_reqst;
- struct srpc_ping_reply *rep = &rpc->srpc_replymsg.msg_body.ping_reply;
-
- LASSERT(sv->sv_id == SRPC_SERVICE_PING);
-
- if (reqstmsg->msg_magic != SRPC_MSG_MAGIC) {
- LASSERT(reqstmsg->msg_magic == __swab32(SRPC_MSG_MAGIC));
-
- __swab32s(&req->pnr_seq);
- __swab32s(&req->pnr_magic);
- __swab64s(&req->pnr_time_sec);
- __swab64s(&req->pnr_time_usec);
- }
- LASSERT(reqstmsg->msg_type == srpc_service2request(sv->sv_id));
-
- if (req->pnr_magic != LST_PING_TEST_MAGIC) {
- CERROR("Unexpected magic %08x from %s\n",
- req->pnr_magic, libcfs_id2str(rpc->srpc_peer));
- return -EINVAL;
- }
-
- rep->pnr_seq = req->pnr_seq;
- rep->pnr_magic = LST_PING_TEST_MAGIC;
-
- if (reqstmsg->msg_ses_feats & ~LST_FEATS_MASK) {
- 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;
-}
-
-struct sfw_test_client_ops ping_test_client;
-
-void ping_init_test_client(void)
-{
- ping_test_client.tso_init = ping_client_init;
- ping_test_client.tso_fini = ping_client_fini;
- ping_test_client.tso_prep_rpc = ping_client_prep_rpc;
- ping_test_client.tso_done_rpc = ping_client_done_rpc;
-}
-
-struct srpc_service ping_test_service;
-
-void ping_init_test_service(void)
-{
- ping_test_service.sv_id = SRPC_SERVICE_PING;
- ping_test_service.sv_name = "ping_test";
- ping_test_service.sv_handler = ping_server_handle;
- ping_test_service.sv_wi_total = ping_srv_workitems;
-}
diff --git a/drivers/staging/lustre/lnet/selftest/rpc.c b/drivers/staging/lustre/lnet/selftest/rpc.c
deleted file mode 100644
index 9613b0a77007..000000000000
--- a/drivers/staging/lustre/lnet/selftest/rpc.c
+++ /dev/null
@@ -1,1682 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * GPL HEADER START
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 only,
- * as published by the Free Software Foundation.
- *
- * This program 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 version 2 for more details (a copy is included
- * in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2012, 2015, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * lnet/selftest/rpc.c
- *
- * Author: Isaac Huang <isaac@clusterfs.com>
- *
- * 2012-05-13: Liang Zhen <liang@whamcloud.com>
- * - percpt data for service to improve smp performance
- * - code cleanup
- */
-
-#define DEBUG_SUBSYSTEM S_LNET
-
-#include "selftest.h"
-
-enum srpc_state {
- SRPC_STATE_NONE,
- SRPC_STATE_NI_INIT,
- SRPC_STATE_EQ_INIT,
- SRPC_STATE_RUNNING,
- SRPC_STATE_STOPPING,
-};
-
-static struct smoketest_rpc {
- spinlock_t rpc_glock; /* global lock */
- struct srpc_service *rpc_services[SRPC_SERVICE_MAX_ID + 1];
- struct lnet_handle_eq rpc_lnet_eq; /* _the_ LNet event queue */
- enum srpc_state rpc_state;
- struct srpc_counters rpc_counters;
- __u64 rpc_matchbits; /* matchbits counter */
-} srpc_data;
-
-static inline int
-srpc_serv_portal(int svc_id)
-{
- return svc_id < SRPC_FRAMEWORK_SERVICE_MAX_ID ?
- SRPC_FRAMEWORK_REQUEST_PORTAL : SRPC_REQUEST_PORTAL;
-}
-
-/* forward ref's */
-void srpc_handle_rpc(struct swi_workitem *wi);
-
-void srpc_get_counters(struct srpc_counters *cnt)
-{
- spin_lock(&srpc_data.rpc_glock);
- *cnt = srpc_data.rpc_counters;
- spin_unlock(&srpc_data.rpc_glock);
-}
-
-void srpc_set_counters(const struct srpc_counters *cnt)
-{
- spin_lock(&srpc_data.rpc_glock);
- srpc_data.rpc_counters = *cnt;
- spin_unlock(&srpc_data.rpc_glock);
-}
-
-static int
-srpc_add_bulk_page(struct srpc_bulk *bk, struct page *pg, int i, int off,
- int nob)
-{
- LASSERT(off < PAGE_SIZE);
- LASSERT(nob > 0 && nob <= PAGE_SIZE);
-
- bk->bk_iovs[i].bv_offset = off;
- bk->bk_iovs[i].bv_page = pg;
- bk->bk_iovs[i].bv_len = nob;
- return nob;
-}
-
-void
-srpc_free_bulk(struct srpc_bulk *bk)
-{
- int i;
- struct page *pg;
-
- LASSERT(bk);
-
- for (i = 0; i < bk->bk_niov; i++) {
- pg = bk->bk_iovs[i].bv_page;
- if (!pg)
- break;
-
- __free_page(pg);
- }
-
- kfree(bk);
-}
-
-struct srpc_bulk *
-srpc_alloc_bulk(int cpt, unsigned int bulk_off, unsigned int bulk_npg,
- unsigned int bulk_len, int sink)
-{
- struct srpc_bulk *bk;
- int i;
-
- LASSERT(bulk_npg > 0 && bulk_npg <= LNET_MAX_IOV);
-
- bk = kzalloc_cpt(offsetof(struct srpc_bulk, bk_iovs[bulk_npg]),
- GFP_KERNEL, cpt);
- if (!bk) {
- CERROR("Can't allocate descriptor for %d pages\n", bulk_npg);
- return NULL;
- }
-
- memset(bk, 0, offsetof(struct srpc_bulk, bk_iovs[bulk_npg]));
- bk->bk_sink = sink;
- bk->bk_len = bulk_len;
- bk->bk_niov = bulk_npg;
-
- for (i = 0; i < bulk_npg; i++) {
- struct page *pg;
- int nob;
-
- pg = alloc_pages_node(cfs_cpt_spread_node(lnet_cpt_table(), cpt),
- GFP_KERNEL, 0);
- if (!pg) {
- CERROR("Can't allocate page %d of %d\n", i, bulk_npg);
- srpc_free_bulk(bk);
- return NULL;
- }
-
- nob = min_t(unsigned int, bulk_off + bulk_len, PAGE_SIZE) -
- bulk_off;
- srpc_add_bulk_page(bk, pg, i, bulk_off, nob);
- bulk_len -= nob;
- bulk_off = 0;
- }
-
- return bk;
-}
-
-static inline __u64
-srpc_next_id(void)
-{
- __u64 id;
-
- spin_lock(&srpc_data.rpc_glock);
- id = srpc_data.rpc_matchbits++;
- spin_unlock(&srpc_data.rpc_glock);
- return id;
-}
-
-static void
-srpc_init_server_rpc(struct srpc_server_rpc *rpc,
- struct srpc_service_cd *scd,
- struct srpc_buffer *buffer)
-{
- memset(rpc, 0, sizeof(*rpc));
- swi_init_workitem(&rpc->srpc_wi, srpc_handle_rpc,
- srpc_serv_is_framework(scd->scd_svc) ?
- lst_serial_wq : lst_test_wq[scd->scd_cpt]);
-
- rpc->srpc_ev.ev_fired = 1; /* no event expected now */
-
- rpc->srpc_scd = scd;
- rpc->srpc_reqstbuf = buffer;
- rpc->srpc_peer = buffer->buf_peer;
- rpc->srpc_self = buffer->buf_self;
- LNetInvalidateMDHandle(&rpc->srpc_replymdh);
-}
-
-static void
-srpc_service_fini(struct srpc_service *svc)
-{
- struct srpc_service_cd *scd;
- struct srpc_server_rpc *rpc;
- struct srpc_buffer *buf;
- struct list_head *q;
- int i;
-
- if (!svc->sv_cpt_data)
- return;
-
- cfs_percpt_for_each(scd, i, svc->sv_cpt_data) {
- while (1) {
- if (!list_empty(&scd->scd_buf_posted))
- q = &scd->scd_buf_posted;
- else if (!list_empty(&scd->scd_buf_blocked))
- q = &scd->scd_buf_blocked;
- else
- break;
-
- while (!list_empty(q)) {
- buf = list_entry(q->next, struct srpc_buffer,
- buf_list);
- list_del(&buf->buf_list);
- kfree(buf);
- }
- }
-
- LASSERT(list_empty(&scd->scd_rpc_active));
-
- while (!list_empty(&scd->scd_rpc_free)) {
- rpc = list_entry(scd->scd_rpc_free.next,
- struct srpc_server_rpc,
- srpc_list);
- list_del(&rpc->srpc_list);
- kfree(rpc);
- }
- }
-
- cfs_percpt_free(svc->sv_cpt_data);
- svc->sv_cpt_data = NULL;
-}
-
-static int
-srpc_service_nrpcs(struct srpc_service *svc)
-{
- int nrpcs = svc->sv_wi_total / svc->sv_ncpts;
-
- return srpc_serv_is_framework(svc) ?
- max(nrpcs, SFW_FRWK_WI_MIN) : max(nrpcs, SFW_TEST_WI_MIN);
-}
-
-void srpc_add_buffer(struct swi_workitem *wi);
-
-static int
-srpc_service_init(struct srpc_service *svc)
-{
- struct srpc_service_cd *scd;
- struct srpc_server_rpc *rpc;
- int nrpcs;
- int i;
- int j;
-
- svc->sv_shuttingdown = 0;
-
- svc->sv_cpt_data = cfs_percpt_alloc(lnet_cpt_table(),
- sizeof(**svc->sv_cpt_data));
- if (!svc->sv_cpt_data)
- return -ENOMEM;
-
- svc->sv_ncpts = srpc_serv_is_framework(svc) ?
- 1 : cfs_cpt_number(lnet_cpt_table());
- nrpcs = srpc_service_nrpcs(svc);
-
- cfs_percpt_for_each(scd, i, svc->sv_cpt_data) {
- scd->scd_cpt = i;
- scd->scd_svc = svc;
- spin_lock_init(&scd->scd_lock);
- INIT_LIST_HEAD(&scd->scd_rpc_free);
- INIT_LIST_HEAD(&scd->scd_rpc_active);
- INIT_LIST_HEAD(&scd->scd_buf_posted);
- INIT_LIST_HEAD(&scd->scd_buf_blocked);
-
- scd->scd_ev.ev_data = scd;
- scd->scd_ev.ev_type = SRPC_REQUEST_RCVD;
-
- /*
- * NB: don't use lst_serial_wq for adding buffer,
- * see details in srpc_service_add_buffers()
- */
- swi_init_workitem(&scd->scd_buf_wi,
- srpc_add_buffer, lst_test_wq[i]);
-
- if (i && srpc_serv_is_framework(svc)) {
- /*
- * NB: framework service only needs srpc_service_cd for
- * one partition, but we allocate for all to make
- * it easier to implement, it will waste a little
- * memory but nobody should care about this
- */
- continue;
- }
-
- for (j = 0; j < nrpcs; j++) {
- rpc = kzalloc_cpt(sizeof(*rpc), GFP_NOFS, i);
- if (!rpc) {
- srpc_service_fini(svc);
- return -ENOMEM;
- }
- list_add(&rpc->srpc_list, &scd->scd_rpc_free);
- }
- }
-
- return 0;
-}
-
-int
-srpc_add_service(struct srpc_service *sv)
-{
- int id = sv->sv_id;
-
- LASSERT(0 <= id && id <= SRPC_SERVICE_MAX_ID);
-
- if (srpc_service_init(sv))
- return -ENOMEM;
-
- spin_lock(&srpc_data.rpc_glock);
-
- LASSERT(srpc_data.rpc_state == SRPC_STATE_RUNNING);
-
- if (srpc_data.rpc_services[id]) {
- spin_unlock(&srpc_data.rpc_glock);
- goto failed;
- }
-
- srpc_data.rpc_services[id] = sv;
- spin_unlock(&srpc_data.rpc_glock);
-
- CDEBUG(D_NET, "Adding service: id %d, name %s\n", id, sv->sv_name);
- return 0;
-
- failed:
- srpc_service_fini(sv);
- return -EBUSY;
-}
-
-int
-srpc_remove_service(struct srpc_service *sv)
-{
- int id = sv->sv_id;
-
- spin_lock(&srpc_data.rpc_glock);
-
- if (srpc_data.rpc_services[id] != sv) {
- spin_unlock(&srpc_data.rpc_glock);
- return -ENOENT;
- }
-
- srpc_data.rpc_services[id] = NULL;
- spin_unlock(&srpc_data.rpc_glock);
- return 0;
-}
-
-static int
-srpc_post_passive_rdma(int portal, int local, __u64 matchbits, void *buf,
- int len, int options, struct lnet_process_id peer,
- struct lnet_handle_md *mdh, struct srpc_event *ev)
-{
- int rc;
- struct lnet_md md;
- struct lnet_handle_me meh;
-
- rc = LNetMEAttach(portal, peer, matchbits, 0, LNET_UNLINK,
- local ? LNET_INS_LOCAL : LNET_INS_AFTER, &meh);
- if (rc) {
- CERROR("LNetMEAttach failed: %d\n", rc);
- LASSERT(rc == -ENOMEM);
- return -ENOMEM;
- }
-
- md.threshold = 1;
- md.user_ptr = ev;
- md.start = buf;
- md.length = len;
- md.options = options;
- md.eq_handle = srpc_data.rpc_lnet_eq;
-
- rc = LNetMDAttach(meh, md, LNET_UNLINK, mdh);
- if (rc) {
- CERROR("LNetMDAttach failed: %d\n", rc);
- LASSERT(rc == -ENOMEM);
-
- rc = LNetMEUnlink(meh);
- LASSERT(!rc);
- return -ENOMEM;
- }
-
- CDEBUG(D_NET, "Posted passive RDMA: peer %s, portal %d, matchbits %#llx\n",
- libcfs_id2str(peer), portal, matchbits);
- return 0;
-}
-
-static int
-srpc_post_active_rdma(int portal, __u64 matchbits, void *buf, int len,
- int options, struct lnet_process_id peer,
- lnet_nid_t self, struct lnet_handle_md *mdh,
- struct srpc_event *ev)
-{
- int rc;
- struct lnet_md md;
-
- md.user_ptr = ev;
- md.start = buf;
- md.length = len;
- md.eq_handle = srpc_data.rpc_lnet_eq;
- md.threshold = options & LNET_MD_OP_GET ? 2 : 1;
- md.options = options & ~(LNET_MD_OP_PUT | LNET_MD_OP_GET);
-
- rc = LNetMDBind(md, LNET_UNLINK, mdh);
- if (rc) {
- CERROR("LNetMDBind failed: %d\n", rc);
- LASSERT(rc == -ENOMEM);
- return -ENOMEM;
- }
-
- /*
- * this is kind of an abuse of the LNET_MD_OP_{PUT,GET} options.
- * they're only meaningful for MDs attached to an ME (i.e. passive
- * buffers...
- */
- if (options & LNET_MD_OP_PUT) {
- rc = LNetPut(self, *mdh, LNET_NOACK_REQ, peer,
- portal, matchbits, 0, 0);
- } else {
- LASSERT(options & LNET_MD_OP_GET);
-
- rc = LNetGet(self, *mdh, peer, portal, matchbits, 0);
- }
-
- if (rc) {
- CERROR("LNet%s(%s, %d, %lld) failed: %d\n",
- options & LNET_MD_OP_PUT ? "Put" : "Get",
- libcfs_id2str(peer), portal, matchbits, rc);
-
- /*
- * The forthcoming unlink event will complete this operation
- * with failure, so fall through and return success here.
- */
- rc = LNetMDUnlink(*mdh);
- LASSERT(!rc);
- } else {
- CDEBUG(D_NET, "Posted active RDMA: peer %s, portal %u, matchbits %#llx\n",
- libcfs_id2str(peer), portal, matchbits);
- }
- return 0;
-}
-
-static int
-srpc_post_passive_rqtbuf(int service, int local, void *buf, int len,
- struct lnet_handle_md *mdh, struct srpc_event *ev)
-{
- struct lnet_process_id any = { 0 };
-
- any.nid = LNET_NID_ANY;
- any.pid = LNET_PID_ANY;
-
- return srpc_post_passive_rdma(srpc_serv_portal(service),
- local, service, buf, len,
- LNET_MD_OP_PUT, any, mdh, ev);
-}
-
-static int
-srpc_service_post_buffer(struct srpc_service_cd *scd, struct srpc_buffer *buf)
-__must_hold(&scd->scd_lock)
-{
- struct srpc_service *sv = scd->scd_svc;
- struct srpc_msg *msg = &buf->buf_msg;
- int rc;
-
- LNetInvalidateMDHandle(&buf->buf_mdh);
- list_add(&buf->buf_list, &scd->scd_buf_posted);
- scd->scd_buf_nposted++;
- spin_unlock(&scd->scd_lock);
-
- rc = srpc_post_passive_rqtbuf(sv->sv_id,
- !srpc_serv_is_framework(sv),
- msg, sizeof(*msg), &buf->buf_mdh,
- &scd->scd_ev);
-
- /*
- * At this point, a RPC (new or delayed) may have arrived in
- * msg and its event handler has been called. So we must add
- * buf to scd_buf_posted _before_ dropping scd_lock
- */
- spin_lock(&scd->scd_lock);
-
- if (!rc) {
- if (!sv->sv_shuttingdown)
- return 0;
-
- spin_unlock(&scd->scd_lock);
- /*
- * srpc_shutdown_service might have tried to unlink me
- * when my buf_mdh was still invalid
- */
- LNetMDUnlink(buf->buf_mdh);
- spin_lock(&scd->scd_lock);
- return 0;
- }
-
- scd->scd_buf_nposted--;
- if (sv->sv_shuttingdown)
- return rc; /* don't allow to change scd_buf_posted */
-
- list_del(&buf->buf_list);
- spin_unlock(&scd->scd_lock);
-
- kfree(buf);
-
- spin_lock(&scd->scd_lock);
- return rc;
-}
-
-void
-srpc_add_buffer(struct swi_workitem *wi)
-{
- struct srpc_service_cd *scd = container_of(wi, struct srpc_service_cd, scd_buf_wi);
- struct srpc_buffer *buf;
- int rc = 0;
-
- /*
- * it's called by workitem scheduler threads, these threads
- * should have been set CPT affinity, so buffers will be posted
- * on CPT local list of Portal
- */
- spin_lock(&scd->scd_lock);
-
- while (scd->scd_buf_adjust > 0 &&
- !scd->scd_svc->sv_shuttingdown) {
- scd->scd_buf_adjust--; /* consume it */
- scd->scd_buf_posting++;
-
- spin_unlock(&scd->scd_lock);
-
- buf = kzalloc(sizeof(*buf), GFP_NOFS);
- if (!buf) {
- CERROR("Failed to add new buf to service: %s\n",
- scd->scd_svc->sv_name);
- spin_lock(&scd->scd_lock);
- rc = -ENOMEM;
- break;
- }
-
- spin_lock(&scd->scd_lock);
- if (scd->scd_svc->sv_shuttingdown) {
- spin_unlock(&scd->scd_lock);
- kfree(buf);
-
- spin_lock(&scd->scd_lock);
- rc = -ESHUTDOWN;
- break;
- }
-
- rc = srpc_service_post_buffer(scd, buf);
- if (rc)
- break; /* buf has been freed inside */
-
- LASSERT(scd->scd_buf_posting > 0);
- scd->scd_buf_posting--;
- scd->scd_buf_total++;
- scd->scd_buf_low = max(2, scd->scd_buf_total / 4);
- }
-
- if (rc) {
- scd->scd_buf_err_stamp = ktime_get_real_seconds();
- scd->scd_buf_err = rc;
-
- LASSERT(scd->scd_buf_posting > 0);
- scd->scd_buf_posting--;
- }
-
- spin_unlock(&scd->scd_lock);
-}
-
-int
-srpc_service_add_buffers(struct srpc_service *sv, int nbuffer)
-{
- struct srpc_service_cd *scd;
- int rc = 0;
- int i;
-
- LASSERTF(nbuffer > 0, "nbuffer must be positive: %d\n", nbuffer);
-
- cfs_percpt_for_each(scd, i, sv->sv_cpt_data) {
- spin_lock(&scd->scd_lock);
-
- scd->scd_buf_err = 0;
- scd->scd_buf_err_stamp = 0;
- scd->scd_buf_posting = 0;
- scd->scd_buf_adjust = nbuffer;
- /* start to post buffers */
- swi_schedule_workitem(&scd->scd_buf_wi);
- spin_unlock(&scd->scd_lock);
-
- /* framework service only post buffer for one partition */
- if (srpc_serv_is_framework(sv))
- break;
- }
-
- cfs_percpt_for_each(scd, i, sv->sv_cpt_data) {
- spin_lock(&scd->scd_lock);
- /*
- * NB: srpc_service_add_buffers() can be called inside
- * thread context of lst_serial_wq, and we don't normally
- * allow to sleep inside thread context of WI scheduler
- * because it will block current scheduler thread from doing
- * anything else, even worse, it could deadlock if it's
- * waiting on result from another WI of the same scheduler.
- * However, it's safe at here because scd_buf_wi is scheduled
- * by thread in a different WI scheduler (lst_test_wq),
- * so we don't have any risk of deadlock, though this could
- * block all WIs pending on lst_serial_wq for a moment
- * which is not good but not fatal.
- */
- lst_wait_until(scd->scd_buf_err ||
- (!scd->scd_buf_adjust &&
- !scd->scd_buf_posting),
- scd->scd_lock, "waiting for adding buffer\n");
-
- if (scd->scd_buf_err && !rc)
- rc = scd->scd_buf_err;
-
- spin_unlock(&scd->scd_lock);
- }
-
- return rc;
-}
-
-void
-srpc_service_remove_buffers(struct srpc_service *sv, int nbuffer)
-{
- struct srpc_service_cd *scd;
- int num;
- int i;
-
- LASSERT(!sv->sv_shuttingdown);
-
- cfs_percpt_for_each(scd, i, sv->sv_cpt_data) {
- spin_lock(&scd->scd_lock);
-
- num = scd->scd_buf_total + scd->scd_buf_posting;
- scd->scd_buf_adjust -= min(nbuffer, num);
-
- spin_unlock(&scd->scd_lock);
- }
-}
-
-/* returns 1 if sv has finished, otherwise 0 */
-int
-srpc_finish_service(struct srpc_service *sv)
-{
- struct srpc_service_cd *scd;
- struct srpc_server_rpc *rpc;
- int i;
-
- LASSERT(sv->sv_shuttingdown); /* srpc_shutdown_service called */
-
- cfs_percpt_for_each(scd, i, sv->sv_cpt_data) {
- swi_cancel_workitem(&scd->scd_buf_wi);
-
- spin_lock(&scd->scd_lock);
-
- if (scd->scd_buf_nposted > 0) {
- CDEBUG(D_NET, "waiting for %d posted buffers to unlink\n",
- scd->scd_buf_nposted);
- spin_unlock(&scd->scd_lock);
- return 0;
- }
-
- if (list_empty(&scd->scd_rpc_active)) {
- spin_unlock(&scd->scd_lock);
- continue;
- }
-
- rpc = list_entry(scd->scd_rpc_active.next,
- struct srpc_server_rpc, srpc_list);
- CNETERR("Active RPC %p on shutdown: sv %s, peer %s, wi %s, ev fired %d type %d status %d lnet %d\n",
- rpc, sv->sv_name, libcfs_id2str(rpc->srpc_peer),
- swi_state2str(rpc->srpc_wi.swi_state),
- rpc->srpc_ev.ev_fired, rpc->srpc_ev.ev_type,
- rpc->srpc_ev.ev_status, rpc->srpc_ev.ev_lnet);
- spin_unlock(&scd->scd_lock);
- return 0;
- }
-
- /* no lock needed from now on */
- srpc_service_fini(sv);
- return 1;
-}
-
-/* called with sv->sv_lock held */
-static void
-srpc_service_recycle_buffer(struct srpc_service_cd *scd,
- struct srpc_buffer *buf)
-__must_hold(&scd->scd_lock)
-{
- if (!scd->scd_svc->sv_shuttingdown && scd->scd_buf_adjust >= 0) {
- if (srpc_service_post_buffer(scd, buf)) {
- CWARN("Failed to post %s buffer\n",
- scd->scd_svc->sv_name);
- }
- return;
- }
-
- /* service is shutting down, or we want to recycle some buffers */
- scd->scd_buf_total--;
-
- if (scd->scd_buf_adjust < 0) {
- scd->scd_buf_adjust++;
- if (scd->scd_buf_adjust < 0 &&
- !scd->scd_buf_total && !scd->scd_buf_posting) {
- CDEBUG(D_INFO,
- "Try to recycle %d buffers but nothing left\n",
- scd->scd_buf_adjust);
- scd->scd_buf_adjust = 0;
- }
- }
-
- spin_unlock(&scd->scd_lock);
- kfree(buf);
- spin_lock(&scd->scd_lock);
-}
-
-void
-srpc_abort_service(struct srpc_service *sv)
-{
- struct srpc_service_cd *scd;
- struct srpc_server_rpc *rpc;
- int i;
-
- CDEBUG(D_NET, "Aborting service: id %d, name %s\n",
- sv->sv_id, sv->sv_name);
-
- cfs_percpt_for_each(scd, i, sv->sv_cpt_data) {
- spin_lock(&scd->scd_lock);
-
- /*
- * schedule in-flight RPCs to notice the abort, NB:
- * racing with incoming RPCs; complete fix should make test
- * RPCs carry session ID in its headers
- */
- list_for_each_entry(rpc, &scd->scd_rpc_active, srpc_list) {
- rpc->srpc_aborted = 1;
- swi_schedule_workitem(&rpc->srpc_wi);
- }
-
- spin_unlock(&scd->scd_lock);
- }
-}
-
-void
-srpc_shutdown_service(struct srpc_service *sv)
-{
- struct srpc_service_cd *scd;
- struct srpc_server_rpc *rpc;
- struct srpc_buffer *buf;
- int i;
-
- CDEBUG(D_NET, "Shutting down service: id %d, name %s\n",
- sv->sv_id, sv->sv_name);
-
- cfs_percpt_for_each(scd, i, sv->sv_cpt_data)
- spin_lock(&scd->scd_lock);
-
- sv->sv_shuttingdown = 1; /* i.e. no new active RPC */
-
- cfs_percpt_for_each(scd, i, sv->sv_cpt_data)
- spin_unlock(&scd->scd_lock);
-
- cfs_percpt_for_each(scd, i, sv->sv_cpt_data) {
- spin_lock(&scd->scd_lock);
-
- /* schedule in-flight RPCs to notice the shutdown */
- list_for_each_entry(rpc, &scd->scd_rpc_active, srpc_list)
- swi_schedule_workitem(&rpc->srpc_wi);
-
- spin_unlock(&scd->scd_lock);
-
- /*
- * OK to traverse scd_buf_posted without lock, since no one
- * touches scd_buf_posted now
- */
- list_for_each_entry(buf, &scd->scd_buf_posted, buf_list)
- LNetMDUnlink(buf->buf_mdh);
- }
-}
-
-static int
-srpc_send_request(struct srpc_client_rpc *rpc)
-{
- struct srpc_event *ev = &rpc->crpc_reqstev;
- int rc;
-
- ev->ev_fired = 0;
- ev->ev_data = rpc;
- ev->ev_type = SRPC_REQUEST_SENT;
-
- rc = srpc_post_active_rdma(srpc_serv_portal(rpc->crpc_service),
- rpc->crpc_service, &rpc->crpc_reqstmsg,
- sizeof(struct srpc_msg), LNET_MD_OP_PUT,
- rpc->crpc_dest, LNET_NID_ANY,
- &rpc->crpc_reqstmdh, ev);
- if (rc) {
- LASSERT(rc == -ENOMEM);
- ev->ev_fired = 1; /* no more event expected */
- }
- return rc;
-}
-
-static int
-srpc_prepare_reply(struct srpc_client_rpc *rpc)
-{
- struct srpc_event *ev = &rpc->crpc_replyev;
- __u64 *id = &rpc->crpc_reqstmsg.msg_body.reqst.rpyid;
- int rc;
-
- ev->ev_fired = 0;
- ev->ev_data = rpc;
- ev->ev_type = SRPC_REPLY_RCVD;
-
- *id = srpc_next_id();
-
- rc = srpc_post_passive_rdma(SRPC_RDMA_PORTAL, 0, *id,
- &rpc->crpc_replymsg,
- sizeof(struct srpc_msg),
- LNET_MD_OP_PUT, rpc->crpc_dest,
- &rpc->crpc_replymdh, ev);
- if (rc) {
- LASSERT(rc == -ENOMEM);
- ev->ev_fired = 1; /* no more event expected */
- }
- return rc;
-}
-
-static int
-srpc_prepare_bulk(struct srpc_client_rpc *rpc)
-{
- struct srpc_bulk *bk = &rpc->crpc_bulk;
- struct srpc_event *ev = &rpc->crpc_bulkev;
- __u64 *id = &rpc->crpc_reqstmsg.msg_body.reqst.bulkid;
- int rc;
- int opt;
-
- LASSERT(bk->bk_niov <= LNET_MAX_IOV);
-
- if (!bk->bk_niov)
- return 0; /* nothing to do */
-
- opt = bk->bk_sink ? LNET_MD_OP_PUT : LNET_MD_OP_GET;
- opt |= LNET_MD_KIOV;
-
- ev->ev_fired = 0;
- ev->ev_data = rpc;
- ev->ev_type = SRPC_BULK_REQ_RCVD;
-
- *id = srpc_next_id();
-
- rc = srpc_post_passive_rdma(SRPC_RDMA_PORTAL, 0, *id,
- &bk->bk_iovs[0], bk->bk_niov, opt,
- rpc->crpc_dest, &bk->bk_mdh, ev);
- if (rc) {
- LASSERT(rc == -ENOMEM);
- ev->ev_fired = 1; /* no more event expected */
- }
- return rc;
-}
-
-static int
-srpc_do_bulk(struct srpc_server_rpc *rpc)
-{
- struct srpc_event *ev = &rpc->srpc_ev;
- struct srpc_bulk *bk = rpc->srpc_bulk;
- __u64 id = rpc->srpc_reqstbuf->buf_msg.msg_body.reqst.bulkid;
- int rc;
- int opt;
-
- LASSERT(bk);
-
- opt = bk->bk_sink ? LNET_MD_OP_GET : LNET_MD_OP_PUT;
- opt |= LNET_MD_KIOV;
-
- ev->ev_fired = 0;
- ev->ev_data = rpc;
- ev->ev_type = bk->bk_sink ? SRPC_BULK_GET_RPLD : SRPC_BULK_PUT_SENT;
-
- rc = srpc_post_active_rdma(SRPC_RDMA_PORTAL, id,
- &bk->bk_iovs[0], bk->bk_niov, opt,
- rpc->srpc_peer, rpc->srpc_self,
- &bk->bk_mdh, ev);
- if (rc)
- ev->ev_fired = 1; /* no more event expected */
- return rc;
-}
-
-/* only called from srpc_handle_rpc */
-static void
-srpc_server_rpc_done(struct srpc_server_rpc *rpc, int status)
-{
- struct srpc_service_cd *scd = rpc->srpc_scd;
- struct srpc_service *sv = scd->scd_svc;
- struct srpc_buffer *buffer;
-
- LASSERT(status || rpc->srpc_wi.swi_state == SWI_STATE_DONE);
-
- rpc->srpc_status = status;
-
- CDEBUG_LIMIT(!status ? D_NET : D_NETERROR,
- "Server RPC %p done: service %s, peer %s, status %s:%d\n",
- rpc, sv->sv_name, libcfs_id2str(rpc->srpc_peer),
- swi_state2str(rpc->srpc_wi.swi_state), status);
-
- if (status) {
- spin_lock(&srpc_data.rpc_glock);
- srpc_data.rpc_counters.rpcs_dropped++;
- spin_unlock(&srpc_data.rpc_glock);
- }
-
- if (rpc->srpc_done)
- (*rpc->srpc_done) (rpc);
- LASSERT(!rpc->srpc_bulk);
-
- spin_lock(&scd->scd_lock);
-
- if (rpc->srpc_reqstbuf) {
- /*
- * NB might drop sv_lock in srpc_service_recycle_buffer, but
- * sv won't go away for scd_rpc_active must not be empty
- */
- srpc_service_recycle_buffer(scd, rpc->srpc_reqstbuf);
- rpc->srpc_reqstbuf = NULL;
- }
-
- list_del(&rpc->srpc_list); /* from scd->scd_rpc_active */
-
- /*
- * No one can schedule me now since:
- * - I'm not on scd_rpc_active.
- * - all LNet events have been fired.
- * Cancel pending schedules and prevent future schedule attempts:
- */
- LASSERT(rpc->srpc_ev.ev_fired);
-
- if (!sv->sv_shuttingdown && !list_empty(&scd->scd_buf_blocked)) {
- buffer = list_entry(scd->scd_buf_blocked.next,
- struct srpc_buffer, buf_list);
- list_del(&buffer->buf_list);
-
- srpc_init_server_rpc(rpc, scd, buffer);
- list_add_tail(&rpc->srpc_list, &scd->scd_rpc_active);
- swi_schedule_workitem(&rpc->srpc_wi);
- } else {
- list_add(&rpc->srpc_list, &scd->scd_rpc_free);
- }
-
- spin_unlock(&scd->scd_lock);
-}
-
-/* handles an incoming RPC */
-void
-srpc_handle_rpc(struct swi_workitem *wi)
-{
- struct srpc_server_rpc *rpc = container_of(wi, struct srpc_server_rpc, srpc_wi);
- struct srpc_service_cd *scd = rpc->srpc_scd;
- struct srpc_service *sv = scd->scd_svc;
- struct srpc_event *ev = &rpc->srpc_ev;
- int rc = 0;
-
- LASSERT(wi == &rpc->srpc_wi);
-
- spin_lock(&scd->scd_lock);
-
- if (sv->sv_shuttingdown || rpc->srpc_aborted) {
- spin_unlock(&scd->scd_lock);
-
- if (rpc->srpc_bulk)
- LNetMDUnlink(rpc->srpc_bulk->bk_mdh);
- LNetMDUnlink(rpc->srpc_replymdh);
-
- if (ev->ev_fired) { /* no more event, OK to finish */
- srpc_server_rpc_done(rpc, -ESHUTDOWN);
- }
- return;
- }
-
- spin_unlock(&scd->scd_lock);
-
- switch (wi->swi_state) {
- default:
- LBUG();
- case SWI_STATE_NEWBORN: {
- struct srpc_msg *msg;
- struct srpc_generic_reply *reply;
-
- msg = &rpc->srpc_reqstbuf->buf_msg;
- reply = &rpc->srpc_replymsg.msg_body.reply;
-
- if (!msg->msg_magic) {
- /* moaned already in srpc_lnet_ev_handler */
- srpc_server_rpc_done(rpc, EBADMSG);
- return;
- }
-
- 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 || !rpc->srpc_bulk);
- if (rc) {
- srpc_server_rpc_done(rpc, rc);
- return;
- }
- }
-
- wi->swi_state = SWI_STATE_BULK_STARTED;
-
- if (rpc->srpc_bulk) {
- rc = srpc_do_bulk(rpc);
- if (!rc)
- return; /* wait for bulk */
-
- LASSERT(ev->ev_fired);
- ev->ev_status = rc;
- }
- }
- /* fall through */
- case SWI_STATE_BULK_STARTED:
- LASSERT(!rpc->srpc_bulk || ev->ev_fired);
-
- if (rpc->srpc_bulk) {
- rc = ev->ev_status;
-
- if (sv->sv_bulk_ready)
- rc = (*sv->sv_bulk_ready) (rpc, rc);
-
- if (rc) {
- srpc_server_rpc_done(rpc, rc);
- return;
- }
- }
-
- wi->swi_state = SWI_STATE_REPLY_SUBMITTED;
- rc = srpc_send_reply(rpc);
- if (!rc)
- return; /* wait for reply */
- srpc_server_rpc_done(rpc, rc);
- return;
-
- case SWI_STATE_REPLY_SUBMITTED:
- if (!ev->ev_fired) {
- CERROR("RPC %p: bulk %p, service %d\n",
- rpc, rpc->srpc_bulk, sv->sv_id);
- CERROR("Event: status %d, type %d, lnet %d\n",
- ev->ev_status, ev->ev_type, ev->ev_lnet);
- LASSERT(ev->ev_fired);
- }
-
- wi->swi_state = SWI_STATE_DONE;
- srpc_server_rpc_done(rpc, ev->ev_status);
- return;
- }
-}
-
-static void
-srpc_client_rpc_expired(void *data)
-{
- struct srpc_client_rpc *rpc = data;
-
- CWARN("Client RPC expired: service %d, peer %s, timeout %d.\n",
- rpc->crpc_service, libcfs_id2str(rpc->crpc_dest),
- rpc->crpc_timeout);
-
- spin_lock(&rpc->crpc_lock);
-
- rpc->crpc_timeout = 0;
- srpc_abort_rpc(rpc, -ETIMEDOUT);
-
- spin_unlock(&rpc->crpc_lock);
-
- spin_lock(&srpc_data.rpc_glock);
- srpc_data.rpc_counters.rpcs_expired++;
- spin_unlock(&srpc_data.rpc_glock);
-}
-
-static void
-srpc_add_client_rpc_timer(struct srpc_client_rpc *rpc)
-{
- struct stt_timer *timer = &rpc->crpc_timer;
-
- if (!rpc->crpc_timeout)
- return;
-
- INIT_LIST_HEAD(&timer->stt_list);
- timer->stt_data = rpc;
- timer->stt_func = srpc_client_rpc_expired;
- timer->stt_expires = ktime_get_real_seconds() + rpc->crpc_timeout;
- stt_add_timer(timer);
-}
-
-/*
- * Called with rpc->crpc_lock held.
- *
- * Upon exit the RPC expiry timer is not queued and the handler is not
- * running on any CPU.
- */
-static void
-srpc_del_client_rpc_timer(struct srpc_client_rpc *rpc)
-{
- /* timer not planted or already exploded */
- if (!rpc->crpc_timeout)
- return;
-
- /* timer successfully defused */
- if (stt_del_timer(&rpc->crpc_timer))
- return;
-
- /* timer detonated, wait for it to explode */
- while (rpc->crpc_timeout) {
- spin_unlock(&rpc->crpc_lock);
-
- schedule();
-
- spin_lock(&rpc->crpc_lock);
- }
-}
-
-static void
-srpc_client_rpc_done(struct srpc_client_rpc *rpc, int status)
-{
- struct swi_workitem *wi = &rpc->crpc_wi;
-
- LASSERT(status || wi->swi_state == SWI_STATE_DONE);
-
- spin_lock(&rpc->crpc_lock);
-
- rpc->crpc_closed = 1;
- if (!rpc->crpc_status)
- rpc->crpc_status = status;
-
- srpc_del_client_rpc_timer(rpc);
-
- CDEBUG_LIMIT(!status ? D_NET : D_NETERROR,
- "Client RPC done: service %d, peer %s, status %s:%d:%d\n",
- rpc->crpc_service, libcfs_id2str(rpc->crpc_dest),
- swi_state2str(wi->swi_state), rpc->crpc_aborted, status);
-
- /*
- * No one can schedule me now since:
- * - RPC timer has been defused.
- * - all LNet events have been fired.
- * - crpc_closed has been set, preventing srpc_abort_rpc from
- * scheduling me.
- * Cancel pending schedules and prevent future schedule attempts:
- */
- LASSERT(!srpc_event_pending(rpc));
-
- spin_unlock(&rpc->crpc_lock);
-
- (*rpc->crpc_done)(rpc);
-}
-
-/* sends an outgoing RPC */
-void
-srpc_send_rpc(struct swi_workitem *wi)
-{
- int rc = 0;
- struct srpc_client_rpc *rpc;
- struct srpc_msg *reply;
- int do_bulk;
-
- LASSERT(wi);
-
- rpc = container_of(wi, struct srpc_client_rpc, crpc_wi);
-
- LASSERT(rpc);
- LASSERT(wi == &rpc->crpc_wi);
-
- reply = &rpc->crpc_replymsg;
- do_bulk = rpc->crpc_bulk.bk_niov > 0;
-
- spin_lock(&rpc->crpc_lock);
-
- if (rpc->crpc_aborted) {
- spin_unlock(&rpc->crpc_lock);
- goto abort;
- }
-
- spin_unlock(&rpc->crpc_lock);
-
- switch (wi->swi_state) {
- default:
- LBUG();
- case SWI_STATE_NEWBORN:
- LASSERT(!srpc_event_pending(rpc));
-
- rc = srpc_prepare_reply(rpc);
- if (rc) {
- srpc_client_rpc_done(rpc, rc);
- return;
- }
-
- rc = srpc_prepare_bulk(rpc);
- if (rc)
- break;
-
- wi->swi_state = SWI_STATE_REQUEST_SUBMITTED;
- rc = srpc_send_request(rpc);
- break;
-
- case SWI_STATE_REQUEST_SUBMITTED:
- /*
- * CAVEAT EMPTOR: rqtev, rpyev, and bulkev may come in any
- * order; however, they're processed in a strict order:
- * rqt, rpy, and bulk.
- */
- if (!rpc->crpc_reqstev.ev_fired)
- break;
-
- rc = rpc->crpc_reqstev.ev_status;
- if (rc)
- break;
-
- wi->swi_state = SWI_STATE_REQUEST_SENT;
- /* perhaps more events */
- /* fall through */
- case SWI_STATE_REQUEST_SENT: {
- enum srpc_msg_type type = srpc_service2reply(rpc->crpc_service);
-
- if (!rpc->crpc_replyev.ev_fired)
- break;
-
- rc = rpc->crpc_replyev.ev_status;
- if (rc)
- break;
-
- srpc_unpack_msg_hdr(reply);
- if (reply->msg_type != type ||
- (reply->msg_magic != SRPC_MSG_MAGIC &&
- reply->msg_magic != __swab32(SRPC_MSG_MAGIC))) {
- CWARN("Bad message from %s: type %u (%d expected), magic %u (%d expected).\n",
- libcfs_id2str(rpc->crpc_dest),
- reply->msg_type, type,
- reply->msg_magic, SRPC_MSG_MAGIC);
- rc = -EBADMSG;
- break;
- }
-
- if (do_bulk && reply->msg_body.reply.status) {
- CWARN("Remote error %d at %s, unlink bulk buffer in case peer didn't initiate bulk transfer\n",
- reply->msg_body.reply.status,
- libcfs_id2str(rpc->crpc_dest));
- LNetMDUnlink(rpc->crpc_bulk.bk_mdh);
- }
-
- wi->swi_state = SWI_STATE_REPLY_RECEIVED;
- }
- /* fall through */
- case SWI_STATE_REPLY_RECEIVED:
- if (do_bulk && !rpc->crpc_bulkev.ev_fired)
- break;
-
- rc = do_bulk ? rpc->crpc_bulkev.ev_status : 0;
-
- /*
- * Bulk buffer was unlinked due to remote error. Clear error
- * since reply buffer still contains valid data.
- * NB rpc->crpc_done shouldn't look into bulk data in case of
- * remote error.
- */
- if (do_bulk && rpc->crpc_bulkev.ev_lnet == LNET_EVENT_UNLINK &&
- !rpc->crpc_status && reply->msg_body.reply.status)
- rc = 0;
-
- wi->swi_state = SWI_STATE_DONE;
- srpc_client_rpc_done(rpc, rc);
- return;
- }
-
- if (rc) {
- spin_lock(&rpc->crpc_lock);
- srpc_abort_rpc(rpc, rc);
- spin_unlock(&rpc->crpc_lock);
- }
-
-abort:
- if (rpc->crpc_aborted) {
- LNetMDUnlink(rpc->crpc_reqstmdh);
- LNetMDUnlink(rpc->crpc_replymdh);
- LNetMDUnlink(rpc->crpc_bulk.bk_mdh);
-
- if (!srpc_event_pending(rpc)) {
- srpc_client_rpc_done(rpc, -EINTR);
- return;
- }
- }
-}
-
-struct srpc_client_rpc *
-srpc_create_client_rpc(struct lnet_process_id peer, int service,
- int nbulkiov, int bulklen,
- void (*rpc_done)(struct srpc_client_rpc *),
- void (*rpc_fini)(struct srpc_client_rpc *), void *priv)
-{
- struct srpc_client_rpc *rpc;
-
- rpc = kzalloc(offsetof(struct srpc_client_rpc,
- crpc_bulk.bk_iovs[nbulkiov]), GFP_KERNEL);
- if (!rpc)
- return NULL;
-
- srpc_init_client_rpc(rpc, peer, service, nbulkiov,
- bulklen, rpc_done, rpc_fini, priv);
- return rpc;
-}
-
-/* called with rpc->crpc_lock held */
-void
-srpc_abort_rpc(struct srpc_client_rpc *rpc, int why)
-{
- LASSERT(why);
-
- if (rpc->crpc_aborted || /* already aborted */
- rpc->crpc_closed) /* callback imminent */
- return;
-
- CDEBUG(D_NET, "Aborting RPC: service %d, peer %s, state %s, why %d\n",
- rpc->crpc_service, libcfs_id2str(rpc->crpc_dest),
- swi_state2str(rpc->crpc_wi.swi_state), why);
-
- rpc->crpc_aborted = 1;
- rpc->crpc_status = why;
- swi_schedule_workitem(&rpc->crpc_wi);
-}
-
-/* called with rpc->crpc_lock held */
-void
-srpc_post_rpc(struct srpc_client_rpc *rpc)
-{
- LASSERT(!rpc->crpc_aborted);
- LASSERT(srpc_data.rpc_state == SRPC_STATE_RUNNING);
-
- CDEBUG(D_NET, "Posting RPC: peer %s, service %d, timeout %d\n",
- libcfs_id2str(rpc->crpc_dest), rpc->crpc_service,
- rpc->crpc_timeout);
-
- srpc_add_client_rpc_timer(rpc);
- swi_schedule_workitem(&rpc->crpc_wi);
-}
-
-int
-srpc_send_reply(struct srpc_server_rpc *rpc)
-{
- struct srpc_event *ev = &rpc->srpc_ev;
- struct srpc_msg *msg = &rpc->srpc_replymsg;
- struct srpc_buffer *buffer = rpc->srpc_reqstbuf;
- struct srpc_service_cd *scd = rpc->srpc_scd;
- struct srpc_service *sv = scd->scd_svc;
- __u64 rpyid;
- int rc;
-
- LASSERT(buffer);
- rpyid = buffer->buf_msg.msg_body.reqst.rpyid;
-
- spin_lock(&scd->scd_lock);
-
- if (!sv->sv_shuttingdown && !srpc_serv_is_framework(sv)) {
- /*
- * Repost buffer before replying since test client
- * might send me another RPC once it gets the reply
- */
- if (srpc_service_post_buffer(scd, buffer))
- CWARN("Failed to repost %s buffer\n", sv->sv_name);
- rpc->srpc_reqstbuf = NULL;
- }
-
- spin_unlock(&scd->scd_lock);
-
- ev->ev_fired = 0;
- ev->ev_data = rpc;
- ev->ev_type = SRPC_REPLY_SENT;
-
- msg->msg_magic = SRPC_MSG_MAGIC;
- msg->msg_version = SRPC_MSG_VERSION;
- msg->msg_type = srpc_service2reply(sv->sv_id);
-
- rc = srpc_post_active_rdma(SRPC_RDMA_PORTAL, rpyid, msg,
- sizeof(*msg), LNET_MD_OP_PUT,
- rpc->srpc_peer, rpc->srpc_self,
- &rpc->srpc_replymdh, ev);
- if (rc)
- ev->ev_fired = 1; /* no more event expected */
- return rc;
-}
-
-/* when in kernel always called with LNET_LOCK() held, and in thread context */
-static void
-srpc_lnet_ev_handler(struct lnet_event *ev)
-{
- struct srpc_service_cd *scd;
- struct srpc_event *rpcev = ev->md.user_ptr;
- struct srpc_client_rpc *crpc;
- struct srpc_server_rpc *srpc;
- struct srpc_buffer *buffer;
- struct srpc_service *sv;
- struct srpc_msg *msg;
- enum srpc_msg_type type;
-
- LASSERT(!in_interrupt());
-
- if (ev->status) {
- __u32 errors;
-
- spin_lock(&srpc_data.rpc_glock);
- if (ev->status != -ECANCELED) /* cancellation is not error */
- srpc_data.rpc_counters.errors++;
- errors = srpc_data.rpc_counters.errors;
- spin_unlock(&srpc_data.rpc_glock);
-
- CNETERR("LNet event status %d type %d, RPC errors %u\n",
- ev->status, ev->type, errors);
- }
-
- rpcev->ev_lnet = ev->type;
-
- switch (rpcev->ev_type) {
- default:
- CERROR("Unknown event: status %d, type %d, lnet %d\n",
- rpcev->ev_status, rpcev->ev_type, rpcev->ev_lnet);
- LBUG();
- case SRPC_REQUEST_SENT:
- if (!ev->status && ev->type != LNET_EVENT_UNLINK) {
- spin_lock(&srpc_data.rpc_glock);
- srpc_data.rpc_counters.rpcs_sent++;
- spin_unlock(&srpc_data.rpc_glock);
- }
- /* fall through */
- case SRPC_REPLY_RCVD:
- case SRPC_BULK_REQ_RCVD:
- crpc = rpcev->ev_data;
-
- if (rpcev != &crpc->crpc_reqstev &&
- rpcev != &crpc->crpc_replyev &&
- rpcev != &crpc->crpc_bulkev) {
- CERROR("rpcev %p, crpc %p, reqstev %p, replyev %p, bulkev %p\n",
- rpcev, crpc, &crpc->crpc_reqstev,
- &crpc->crpc_replyev, &crpc->crpc_bulkev);
- CERROR("Bad event: status %d, type %d, lnet %d\n",
- rpcev->ev_status, rpcev->ev_type, rpcev->ev_lnet);
- LBUG();
- }
-
- spin_lock(&crpc->crpc_lock);
-
- LASSERT(!rpcev->ev_fired);
- rpcev->ev_fired = 1;
- rpcev->ev_status = (ev->type == LNET_EVENT_UNLINK) ?
- -EINTR : ev->status;
- swi_schedule_workitem(&crpc->crpc_wi);
-
- spin_unlock(&crpc->crpc_lock);
- break;
-
- case SRPC_REQUEST_RCVD:
- scd = rpcev->ev_data;
- sv = scd->scd_svc;
-
- LASSERT(rpcev == &scd->scd_ev);
-
- spin_lock(&scd->scd_lock);
-
- LASSERT(ev->unlinked);
- LASSERT(ev->type == LNET_EVENT_PUT ||
- ev->type == LNET_EVENT_UNLINK);
- LASSERT(ev->type != LNET_EVENT_UNLINK ||
- sv->sv_shuttingdown);
-
- buffer = container_of(ev->md.start, struct srpc_buffer, buf_msg);
- buffer->buf_peer = ev->initiator;
- buffer->buf_self = ev->target.nid;
-
- LASSERT(scd->scd_buf_nposted > 0);
- scd->scd_buf_nposted--;
-
- if (sv->sv_shuttingdown) {
- /*
- * Leave buffer on scd->scd_buf_nposted since
- * srpc_finish_service needs to traverse it.
- */
- spin_unlock(&scd->scd_lock);
- break;
- }
-
- if (scd->scd_buf_err_stamp &&
- scd->scd_buf_err_stamp < ktime_get_real_seconds()) {
- /* re-enable adding buffer */
- scd->scd_buf_err_stamp = 0;
- scd->scd_buf_err = 0;
- }
-
- if (!scd->scd_buf_err && /* adding buffer is enabled */
- !scd->scd_buf_adjust &&
- scd->scd_buf_nposted < scd->scd_buf_low) {
- scd->scd_buf_adjust = max(scd->scd_buf_total / 2,
- SFW_TEST_WI_MIN);
- swi_schedule_workitem(&scd->scd_buf_wi);
- }
-
- list_del(&buffer->buf_list); /* from scd->scd_buf_posted */
- msg = &buffer->buf_msg;
- type = srpc_service2request(sv->sv_id);
-
- if (ev->status || ev->mlength != sizeof(*msg) ||
- (msg->msg_type != type &&
- msg->msg_type != __swab32(type)) ||
- (msg->msg_magic != SRPC_MSG_MAGIC &&
- msg->msg_magic != __swab32(SRPC_MSG_MAGIC))) {
- CERROR("Dropping RPC (%s) from %s: status %d mlength %d type %u magic %u.\n",
- sv->sv_name, libcfs_id2str(ev->initiator),
- ev->status, ev->mlength,
- msg->msg_type, msg->msg_magic);
-
- /*
- * NB can't call srpc_service_recycle_buffer here since
- * it may call LNetM[DE]Attach. The invalid magic tells
- * srpc_handle_rpc to drop this RPC
- */
- msg->msg_magic = 0;
- }
-
- if (!list_empty(&scd->scd_rpc_free)) {
- srpc = list_entry(scd->scd_rpc_free.next,
- struct srpc_server_rpc,
- srpc_list);
- list_del(&srpc->srpc_list);
-
- srpc_init_server_rpc(srpc, scd, buffer);
- list_add_tail(&srpc->srpc_list,
- &scd->scd_rpc_active);
- swi_schedule_workitem(&srpc->srpc_wi);
- } else {
- list_add_tail(&buffer->buf_list,
- &scd->scd_buf_blocked);
- }
-
- spin_unlock(&scd->scd_lock);
-
- spin_lock(&srpc_data.rpc_glock);
- srpc_data.rpc_counters.rpcs_rcvd++;
- spin_unlock(&srpc_data.rpc_glock);
- break;
-
- case SRPC_BULK_GET_RPLD:
- LASSERT(ev->type == LNET_EVENT_SEND ||
- ev->type == LNET_EVENT_REPLY ||
- ev->type == LNET_EVENT_UNLINK);
-
- if (!ev->unlinked)
- break; /* wait for final event */
- /* fall through */
- case SRPC_BULK_PUT_SENT:
- if (!ev->status && ev->type != LNET_EVENT_UNLINK) {
- spin_lock(&srpc_data.rpc_glock);
-
- if (rpcev->ev_type == SRPC_BULK_GET_RPLD)
- srpc_data.rpc_counters.bulk_get += ev->mlength;
- else
- srpc_data.rpc_counters.bulk_put += ev->mlength;
-
- spin_unlock(&srpc_data.rpc_glock);
- }
- /* fall through */
- case SRPC_REPLY_SENT:
- srpc = rpcev->ev_data;
- scd = srpc->srpc_scd;
-
- LASSERT(rpcev == &srpc->srpc_ev);
-
- spin_lock(&scd->scd_lock);
-
- rpcev->ev_fired = 1;
- rpcev->ev_status = (ev->type == LNET_EVENT_UNLINK) ?
- -EINTR : ev->status;
- swi_schedule_workitem(&srpc->srpc_wi);
-
- spin_unlock(&scd->scd_lock);
- break;
- }
-}
-
-int
-srpc_startup(void)
-{
- int rc;
-
- memset(&srpc_data, 0, sizeof(struct smoketest_rpc));
- spin_lock_init(&srpc_data.rpc_glock);
-
- /* 1 second pause to avoid timestamp reuse */
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ);
- srpc_data.rpc_matchbits = ((__u64)ktime_get_real_seconds()) << 48;
-
- srpc_data.rpc_state = SRPC_STATE_NONE;
-
- rc = LNetNIInit(LNET_PID_LUSTRE);
- if (rc < 0) {
- CERROR("LNetNIInit() has failed: %d\n", rc);
- return rc;
- }
-
- srpc_data.rpc_state = SRPC_STATE_NI_INIT;
-
- LNetInvalidateEQHandle(&srpc_data.rpc_lnet_eq);
- rc = LNetEQAlloc(0, srpc_lnet_ev_handler, &srpc_data.rpc_lnet_eq);
- if (rc) {
- CERROR("LNetEQAlloc() has failed: %d\n", rc);
- goto bail;
- }
-
- rc = LNetSetLazyPortal(SRPC_FRAMEWORK_REQUEST_PORTAL);
- LASSERT(!rc);
- rc = LNetSetLazyPortal(SRPC_REQUEST_PORTAL);
- LASSERT(!rc);
-
- srpc_data.rpc_state = SRPC_STATE_EQ_INIT;
-
- rc = stt_startup();
-
-bail:
- if (rc)
- srpc_shutdown();
- else
- srpc_data.rpc_state = SRPC_STATE_RUNNING;
-
- return rc;
-}
-
-void
-srpc_shutdown(void)
-{
- int i;
- int rc;
- int state;
-
- state = srpc_data.rpc_state;
- srpc_data.rpc_state = SRPC_STATE_STOPPING;
-
- switch (state) {
- default:
- LBUG();
- case SRPC_STATE_RUNNING:
- spin_lock(&srpc_data.rpc_glock);
-
- for (i = 0; i <= SRPC_SERVICE_MAX_ID; i++) {
- struct srpc_service *sv = srpc_data.rpc_services[i];
-
- LASSERTF(!sv, "service not empty: id %d, name %s\n",
- i, sv->sv_name);
- }
-
- spin_unlock(&srpc_data.rpc_glock);
-
- stt_shutdown();
- /* fall through */
- case SRPC_STATE_EQ_INIT:
- rc = LNetClearLazyPortal(SRPC_FRAMEWORK_REQUEST_PORTAL);
- rc = LNetClearLazyPortal(SRPC_REQUEST_PORTAL);
- LASSERT(!rc);
- rc = LNetEQFree(srpc_data.rpc_lnet_eq);
- LASSERT(!rc); /* the EQ should have no user by now */
- /* fall through */
- case SRPC_STATE_NI_INIT:
- LNetNIFini();
- }
-}
diff --git a/drivers/staging/lustre/lnet/selftest/rpc.h b/drivers/staging/lustre/lnet/selftest/rpc.h
deleted file mode 100644
index 465b5b534423..000000000000
--- a/drivers/staging/lustre/lnet/selftest/rpc.h
+++ /dev/null
@@ -1,295 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * GPL HEADER START
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 only,
- * as published by the Free Software Foundation.
- *
- * This program 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 version 2 for more details (a copy is included
- * in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2012, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- */
-
-#ifndef __SELFTEST_RPC_H__
-#define __SELFTEST_RPC_H__
-
-#include <uapi/linux/lnet/lnetst.h>
-
-/*
- * LST wired structures
- *
- * XXX: *REPLY == *REQST + 1
- */
-enum srpc_msg_type {
- SRPC_MSG_MKSN_REQST = 0,
- SRPC_MSG_MKSN_REPLY = 1,
- SRPC_MSG_RMSN_REQST = 2,
- SRPC_MSG_RMSN_REPLY = 3,
- SRPC_MSG_BATCH_REQST = 4,
- SRPC_MSG_BATCH_REPLY = 5,
- SRPC_MSG_STAT_REQST = 6,
- SRPC_MSG_STAT_REPLY = 7,
- SRPC_MSG_TEST_REQST = 8,
- SRPC_MSG_TEST_REPLY = 9,
- SRPC_MSG_DEBUG_REQST = 10,
- SRPC_MSG_DEBUG_REPLY = 11,
- SRPC_MSG_BRW_REQST = 12,
- SRPC_MSG_BRW_REPLY = 13,
- SRPC_MSG_PING_REQST = 14,
- SRPC_MSG_PING_REPLY = 15,
- SRPC_MSG_JOIN_REQST = 16,
- SRPC_MSG_JOIN_REPLY = 17,
-};
-
-/* CAVEAT EMPTOR:
- * All srpc_*_reqst_t's 1st field must be matchbits of reply buffer,
- * and 2nd field matchbits of bulk buffer if any.
- *
- * All srpc_*_reply_t's 1st field must be a __u32 status, and 2nd field
- * session id if needed.
- */
-struct srpc_generic_reqst {
- __u64 rpyid; /* reply buffer matchbits */
- __u64 bulkid; /* bulk buffer matchbits */
-} WIRE_ATTR;
-
-struct srpc_generic_reply {
- __u32 status;
- struct lst_sid sid;
-} WIRE_ATTR;
-
-/* FRAMEWORK RPCs */
-struct srpc_mksn_reqst {
- __u64 mksn_rpyid; /* reply buffer matchbits */
- struct lst_sid mksn_sid; /* session id */
- __u32 mksn_force; /* use brute force */
- char mksn_name[LST_NAME_SIZE];
-} WIRE_ATTR; /* make session request */
-
-struct srpc_mksn_reply {
- __u32 mksn_status; /* session status */
- struct lst_sid mksn_sid; /* session id */
- __u32 mksn_timeout; /* session timeout */
- char mksn_name[LST_NAME_SIZE];
-} WIRE_ATTR; /* make session reply */
-
-struct srpc_rmsn_reqst {
- __u64 rmsn_rpyid; /* reply buffer matchbits */
- struct lst_sid rmsn_sid; /* session id */
-} WIRE_ATTR; /* remove session request */
-
-struct srpc_rmsn_reply {
- __u32 rmsn_status;
- struct lst_sid rmsn_sid; /* session id */
-} WIRE_ATTR; /* remove session reply */
-
-struct srpc_join_reqst {
- __u64 join_rpyid; /* reply buffer matchbits */
- struct lst_sid join_sid; /* session id to join */
- char join_group[LST_NAME_SIZE]; /* group name */
-} WIRE_ATTR;
-
-struct srpc_join_reply {
- __u32 join_status; /* returned status */
- struct lst_sid join_sid; /* session id */
- __u32 join_timeout; /* # seconds' inactivity to
- * expire
- */
- char join_session[LST_NAME_SIZE]; /* session name */
-} WIRE_ATTR;
-
-struct srpc_debug_reqst {
- __u64 dbg_rpyid; /* reply buffer matchbits */
- struct lst_sid dbg_sid; /* session id */
- __u32 dbg_flags; /* bitmap of debug */
-} WIRE_ATTR;
-
-struct srpc_debug_reply {
- __u32 dbg_status; /* returned code */
- struct lst_sid dbg_sid; /* session id */
- __u32 dbg_timeout; /* session timeout */
- __u32 dbg_nbatch; /* # of batches in the node */
- char dbg_name[LST_NAME_SIZE]; /* session name */
-} WIRE_ATTR;
-
-#define SRPC_BATCH_OPC_RUN 1
-#define SRPC_BATCH_OPC_STOP 2
-#define SRPC_BATCH_OPC_QUERY 3
-
-struct srpc_batch_reqst {
- __u64 bar_rpyid; /* reply buffer matchbits */
- struct lst_sid bar_sid; /* session id */
- struct lst_bid bar_bid; /* batch id */
- __u32 bar_opc; /* create/start/stop batch */
- __u32 bar_testidx; /* index of test */
- __u32 bar_arg; /* parameters */
-} WIRE_ATTR;
-
-struct srpc_batch_reply {
- __u32 bar_status; /* status of request */
- struct lst_sid bar_sid; /* session id */
- __u32 bar_active; /* # of active tests in batch/test */
- __u32 bar_time; /* remained time */
-} WIRE_ATTR;
-
-struct srpc_stat_reqst {
- __u64 str_rpyid; /* reply buffer matchbits */
- struct lst_sid str_sid; /* session id */
- __u32 str_type; /* type of stat */
-} WIRE_ATTR;
-
-struct srpc_stat_reply {
- __u32 str_status;
- struct lst_sid str_sid;
- struct sfw_counters str_fw;
- struct srpc_counters str_rpc;
- struct lnet_counters str_lnet;
-} WIRE_ATTR;
-
-struct test_bulk_req {
- __u32 blk_opc; /* bulk operation code */
- __u32 blk_npg; /* # of pages */
- __u32 blk_flags; /* reserved flags */
-} WIRE_ATTR;
-
-struct test_bulk_req_v1 {
- __u16 blk_opc; /* bulk operation code */
- __u16 blk_flags; /* data check flags */
- __u32 blk_len; /* data length */
- __u32 blk_offset; /* offset */
-} WIRE_ATTR;
-
-struct test_ping_req {
- __u32 png_size; /* size of ping message */
- __u32 png_flags; /* reserved flags */
-} WIRE_ATTR;
-
-struct srpc_test_reqst {
- __u64 tsr_rpyid; /* reply buffer matchbits */
- __u64 tsr_bulkid; /* bulk buffer matchbits */
- struct lst_sid tsr_sid; /* session id */
- struct lst_bid tsr_bid; /* batch id */
- __u32 tsr_service; /* test type: bulk|ping|... */
- __u32 tsr_loop; /* test client loop count or
- * # server buffers needed
- */
- __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 {
- struct test_ping_req ping;
- struct test_bulk_req bulk_v0;
- struct test_bulk_req_v1 bulk_v1;
- } tsr_u;
-} WIRE_ATTR;
-
-struct srpc_test_reply {
- __u32 tsr_status; /* returned code */
- struct lst_sid tsr_sid;
-} WIRE_ATTR;
-
-/* TEST RPCs */
-struct srpc_ping_reqst {
- __u64 pnr_rpyid;
- __u32 pnr_magic;
- __u32 pnr_seq;
- __u64 pnr_time_sec;
- __u64 pnr_time_usec;
-} WIRE_ATTR;
-
-struct srpc_ping_reply {
- __u32 pnr_status;
- __u32 pnr_magic;
- __u32 pnr_seq;
-} WIRE_ATTR;
-
-struct srpc_brw_reqst {
- __u64 brw_rpyid; /* reply buffer matchbits */
- __u64 brw_bulkid; /* bulk buffer matchbits */
- __u32 brw_rw; /* read or write */
- __u32 brw_len; /* bulk data len */
- __u32 brw_flags; /* bulk data patterns */
-} WIRE_ATTR; /* bulk r/w request */
-
-struct srpc_brw_reply {
- __u32 brw_status;
-} WIRE_ATTR; /* bulk r/w reply */
-
-#define SRPC_MSG_MAGIC 0xeeb0f00d
-#define SRPC_MSG_VERSION 1
-
-struct srpc_msg {
- __u32 msg_magic; /* magic number */
- __u32 msg_version; /* message version number */
- __u32 msg_type; /* type of message body: srpc_msg_type */
- __u32 msg_reserved0;
- __u32 msg_reserved1;
- __u32 msg_ses_feats; /* test session features */
- union {
- struct srpc_generic_reqst reqst;
- struct srpc_generic_reply reply;
-
- struct srpc_mksn_reqst mksn_reqst;
- struct srpc_mksn_reply mksn_reply;
- struct srpc_rmsn_reqst rmsn_reqst;
- struct srpc_rmsn_reply rmsn_reply;
- struct srpc_debug_reqst dbg_reqst;
- struct srpc_debug_reply dbg_reply;
- struct srpc_batch_reqst bat_reqst;
- struct srpc_batch_reply bat_reply;
- struct srpc_stat_reqst stat_reqst;
- struct srpc_stat_reply stat_reply;
- struct srpc_test_reqst tes_reqst;
- struct srpc_test_reply tes_reply;
- struct srpc_join_reqst join_reqst;
- struct srpc_join_reply join_reply;
-
- struct srpc_ping_reqst ping_reqst;
- struct srpc_ping_reply ping_reply;
- struct srpc_brw_reqst brw_reqst;
- struct srpc_brw_reply brw_reply;
- } msg_body;
-} WIRE_ATTR;
-
-static inline void
-srpc_unpack_msg_hdr(struct srpc_msg *msg)
-{
- if (msg->msg_magic == SRPC_MSG_MAGIC)
- return; /* no flipping needed */
-
- /*
- * We do not swap the magic number here as it is needed to
- * determine whether the body needs to be swapped.
- */
- /* __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__ */
diff --git a/drivers/staging/lustre/lnet/selftest/selftest.h b/drivers/staging/lustre/lnet/selftest/selftest.h
deleted file mode 100644
index 05466b85e1c0..000000000000
--- a/drivers/staging/lustre/lnet/selftest/selftest.h
+++ /dev/null
@@ -1,623 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * GPL HEADER START
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 only,
- * as published by the Free Software Foundation.
- *
- * This program 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 version 2 for more details (a copy is included
- * in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2012, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * lnet/selftest/selftest.h
- *
- * Author: Isaac Huang <isaac@clusterfs.com>
- */
-#ifndef __SELFTEST_SELFTEST_H__
-#define __SELFTEST_SELFTEST_H__
-
-#define LNET_ONLY
-
-#include <linux/libcfs/libcfs.h>
-#include <linux/lnet/lib-lnet.h>
-#include <linux/lnet/lib-types.h>
-#include <uapi/linux/lnet/lnetst.h>
-
-#include "rpc.h"
-#include "timer.h"
-
-#ifndef MADE_WITHOUT_COMPROMISE
-#define MADE_WITHOUT_COMPROMISE
-#endif
-
-#define SWI_STATE_NEWBORN 0
-#define SWI_STATE_REPLY_SUBMITTED 1
-#define SWI_STATE_REPLY_SENT 2
-#define SWI_STATE_REQUEST_SUBMITTED 3
-#define SWI_STATE_REQUEST_SENT 4
-#define SWI_STATE_REPLY_RECEIVED 5
-#define SWI_STATE_BULK_STARTED 6
-#define SWI_STATE_DONE 10
-
-/* forward refs */
-struct srpc_service;
-struct srpc_service_cd;
-struct sfw_test_unit;
-struct sfw_test_instance;
-
-/* services below SRPC_FRAMEWORK_SERVICE_MAX_ID are framework
- * services, e.g. create/modify session.
- */
-#define SRPC_SERVICE_DEBUG 0
-#define SRPC_SERVICE_MAKE_SESSION 1
-#define SRPC_SERVICE_REMOVE_SESSION 2
-#define SRPC_SERVICE_BATCH 3
-#define SRPC_SERVICE_TEST 4
-#define SRPC_SERVICE_QUERY_STAT 5
-#define SRPC_SERVICE_JOIN 6
-#define SRPC_FRAMEWORK_SERVICE_MAX_ID 10
-/* other services start from SRPC_FRAMEWORK_SERVICE_MAX_ID+1 */
-#define SRPC_SERVICE_BRW 11
-#define SRPC_SERVICE_PING 12
-#define SRPC_SERVICE_MAX_ID 12
-
-#define SRPC_REQUEST_PORTAL 50
-/* a lazy portal for framework RPC requests */
-#define SRPC_FRAMEWORK_REQUEST_PORTAL 51
-/* all reply/bulk RDMAs go to this portal */
-#define SRPC_RDMA_PORTAL 52
-
-static inline enum srpc_msg_type
-srpc_service2request(int service)
-{
- switch (service) {
- default:
- LBUG();
- case SRPC_SERVICE_DEBUG:
- return SRPC_MSG_DEBUG_REQST;
-
- case SRPC_SERVICE_MAKE_SESSION:
- return SRPC_MSG_MKSN_REQST;
-
- case SRPC_SERVICE_REMOVE_SESSION:
- return SRPC_MSG_RMSN_REQST;
-
- case SRPC_SERVICE_BATCH:
- return SRPC_MSG_BATCH_REQST;
-
- case SRPC_SERVICE_TEST:
- return SRPC_MSG_TEST_REQST;
-
- case SRPC_SERVICE_QUERY_STAT:
- return SRPC_MSG_STAT_REQST;
-
- case SRPC_SERVICE_BRW:
- return SRPC_MSG_BRW_REQST;
-
- case SRPC_SERVICE_PING:
- return SRPC_MSG_PING_REQST;
-
- case SRPC_SERVICE_JOIN:
- return SRPC_MSG_JOIN_REQST;
- }
-}
-
-static inline enum srpc_msg_type
-srpc_service2reply(int service)
-{
- return srpc_service2request(service) + 1;
-}
-
-enum srpc_event_type {
- SRPC_BULK_REQ_RCVD = 1, /* passive bulk request(PUT sink/GET source)
- * received
- */
- SRPC_BULK_PUT_SENT = 2, /* active bulk PUT sent (source) */
- SRPC_BULK_GET_RPLD = 3, /* active bulk GET replied (sink) */
- SRPC_REPLY_RCVD = 4, /* incoming reply received */
- SRPC_REPLY_SENT = 5, /* outgoing reply sent */
- SRPC_REQUEST_RCVD = 6, /* incoming request received */
- SRPC_REQUEST_SENT = 7, /* outgoing request sent */
-};
-
-/* RPC event */
-struct srpc_event {
- enum srpc_event_type ev_type; /* what's up */
- enum lnet_event_kind ev_lnet; /* LNet event type */
- int ev_fired; /* LNet event fired? */
- int ev_status; /* LNet event status */
- void *ev_data; /* owning server/client RPC */
-};
-
-/* bulk descriptor */
-struct srpc_bulk {
- int bk_len; /* len of bulk data */
- struct lnet_handle_md bk_mdh;
- int bk_sink; /* sink/source */
- int bk_niov; /* # iov in bk_iovs */
- struct bio_vec bk_iovs[0];
-};
-
-/* message buffer descriptor */
-struct srpc_buffer {
- struct list_head buf_list; /* chain on srpc_service::*_msgq */
- struct srpc_msg buf_msg;
- struct lnet_handle_md buf_mdh;
- lnet_nid_t buf_self;
- struct lnet_process_id buf_peer;
-};
-
-struct swi_workitem;
-typedef void (*swi_action_t) (struct swi_workitem *);
-
-struct swi_workitem {
- struct workqueue_struct *swi_wq;
- struct work_struct swi_work;
- swi_action_t swi_action;
- int swi_state;
-};
-
-/* server-side state of a RPC */
-struct srpc_server_rpc {
- /* chain on srpc_service::*_rpcq */
- struct list_head srpc_list;
- struct srpc_service_cd *srpc_scd;
- struct swi_workitem srpc_wi;
- struct srpc_event srpc_ev; /* bulk/reply event */
- lnet_nid_t srpc_self;
- struct lnet_process_id srpc_peer;
- struct srpc_msg srpc_replymsg;
- struct lnet_handle_md srpc_replymdh;
- struct srpc_buffer *srpc_reqstbuf;
- struct srpc_bulk *srpc_bulk;
-
- unsigned int srpc_aborted; /* being given up */
- int srpc_status;
- void (*srpc_done)(struct srpc_server_rpc *);
-};
-
-/* client-side state of a RPC */
-struct srpc_client_rpc {
- struct list_head crpc_list; /* chain on user's lists */
- spinlock_t crpc_lock; /* serialize */
- int crpc_service;
- atomic_t crpc_refcount;
- int crpc_timeout; /* # seconds to wait for reply */
- struct stt_timer crpc_timer;
- struct swi_workitem crpc_wi;
- struct lnet_process_id crpc_dest;
-
- void (*crpc_done)(struct srpc_client_rpc *);
- void (*crpc_fini)(struct srpc_client_rpc *);
- int crpc_status; /* completion status */
- void *crpc_priv; /* caller data */
-
- /* state flags */
- unsigned int crpc_aborted:1; /* being given up */
- unsigned int crpc_closed:1; /* completed */
-
- /* RPC events */
- struct srpc_event crpc_bulkev; /* bulk event */
- struct srpc_event crpc_reqstev; /* request event */
- struct srpc_event crpc_replyev; /* reply event */
-
- /* bulk, request(reqst), and reply exchanged on wire */
- struct srpc_msg crpc_reqstmsg;
- struct srpc_msg crpc_replymsg;
- struct lnet_handle_md crpc_reqstmdh;
- struct lnet_handle_md crpc_replymdh;
- struct srpc_bulk crpc_bulk;
-};
-
-#define srpc_client_rpc_size(rpc) \
-offsetof(struct srpc_client_rpc, crpc_bulk.bk_iovs[(rpc)->crpc_bulk.bk_niov])
-
-#define srpc_client_rpc_addref(rpc) \
-do { \
- CDEBUG(D_NET, "RPC[%p] -> %s (%d)++\n", \
- (rpc), libcfs_id2str((rpc)->crpc_dest), \
- atomic_read(&(rpc)->crpc_refcount)); \
- LASSERT(atomic_read(&(rpc)->crpc_refcount) > 0); \
- atomic_inc(&(rpc)->crpc_refcount); \
-} while (0)
-
-#define srpc_client_rpc_decref(rpc) \
-do { \
- CDEBUG(D_NET, "RPC[%p] -> %s (%d)--\n", \
- (rpc), libcfs_id2str((rpc)->crpc_dest), \
- atomic_read(&(rpc)->crpc_refcount)); \
- LASSERT(atomic_read(&(rpc)->crpc_refcount) > 0); \
- if (atomic_dec_and_test(&(rpc)->crpc_refcount)) \
- srpc_destroy_client_rpc(rpc); \
-} while (0)
-
-#define srpc_event_pending(rpc) (!(rpc)->crpc_bulkev.ev_fired || \
- !(rpc)->crpc_reqstev.ev_fired || \
- !(rpc)->crpc_replyev.ev_fired)
-
-/* CPU partition data of srpc service */
-struct srpc_service_cd {
- /** serialize */
- spinlock_t scd_lock;
- /** backref to service */
- struct srpc_service *scd_svc;
- /** event buffer */
- struct srpc_event scd_ev;
- /** free RPC descriptors */
- struct list_head scd_rpc_free;
- /** in-flight RPCs */
- struct list_head scd_rpc_active;
- /** workitem for posting buffer */
- struct swi_workitem scd_buf_wi;
- /** CPT id */
- int scd_cpt;
- /** error code for scd_buf_wi */
- int scd_buf_err;
- /** timestamp for scd_buf_err */
- time64_t scd_buf_err_stamp;
- /** total # request buffers */
- int scd_buf_total;
- /** # posted request buffers */
- int scd_buf_nposted;
- /** in progress of buffer posting */
- int scd_buf_posting;
- /** allocate more buffers if scd_buf_nposted < scd_buf_low */
- int scd_buf_low;
- /** increase/decrease some buffers */
- int scd_buf_adjust;
- /** posted message buffers */
- struct list_head scd_buf_posted;
- /** blocked for RPC descriptor */
- struct list_head scd_buf_blocked;
-};
-
-/* number of server workitems (mini-thread) for testing service */
-#define SFW_TEST_WI_MIN 256
-#define SFW_TEST_WI_MAX 2048
-/* extra buffers for tolerating buggy peers, or unbalanced number
- * of peers between partitions
- */
-#define SFW_TEST_WI_EXTRA 64
-
-/* number of server workitems (mini-thread) for framework service */
-#define SFW_FRWK_WI_MIN 16
-#define SFW_FRWK_WI_MAX 256
-
-struct srpc_service {
- int sv_id; /* service id */
- const char *sv_name; /* human readable name */
- int sv_wi_total; /* total server workitems */
- int sv_shuttingdown;
- int sv_ncpts;
- /* percpt data for srpc_service */
- struct srpc_service_cd **sv_cpt_data;
- /* Service callbacks:
- * - sv_handler: process incoming RPC request
- * - sv_bulk_ready: notify bulk data
- */
- int (*sv_handler)(struct srpc_server_rpc *);
- int (*sv_bulk_ready)(struct srpc_server_rpc *, int);
-};
-
-struct sfw_session {
- struct list_head sn_list; /* chain on fw_zombie_sessions */
- struct lst_sid sn_id; /* unique identifier */
- unsigned int sn_timeout; /* # seconds' inactivity to expire */
- int sn_timer_active;
- unsigned int sn_features;
- struct stt_timer sn_timer;
- struct list_head sn_batches; /* list of batches */
- char sn_name[LST_NAME_SIZE];
- atomic_t sn_refcount;
- atomic_t sn_brw_errors;
- atomic_t sn_ping_errors;
- unsigned long sn_started;
-};
-
-#define sfw_sid_equal(sid0, sid1) ((sid0).ses_nid == (sid1).ses_nid && \
- (sid0).ses_stamp == (sid1).ses_stamp)
-
-struct sfw_batch {
- struct list_head bat_list; /* chain on sn_batches */
- struct lst_bid bat_id; /* batch id */
- int bat_error; /* error code of batch */
- struct sfw_session *bat_session; /* batch's session */
- atomic_t bat_nactive; /* # of active tests */
- struct list_head bat_tests; /* test instances */
-};
-
-struct sfw_test_client_ops {
- int (*tso_init)(struct sfw_test_instance *tsi); /* initialize test
- * client
- */
- void (*tso_fini)(struct sfw_test_instance *tsi); /* finalize test
- * client
- */
- int (*tso_prep_rpc)(struct sfw_test_unit *tsu,
- struct lnet_process_id dest,
- struct srpc_client_rpc **rpc); /* prep a tests rpc */
- void (*tso_done_rpc)(struct sfw_test_unit *tsu,
- struct srpc_client_rpc *rpc); /* done a test rpc */
-};
-
-struct sfw_test_instance {
- struct list_head tsi_list; /* chain on batch */
- int tsi_service; /* test type */
- struct sfw_batch *tsi_batch; /* batch */
- struct sfw_test_client_ops *tsi_ops; /* test client operation
- */
-
- /* public parameter for all test units */
- unsigned int tsi_is_client:1; /* is test client */
- unsigned int tsi_stoptsu_onerr:1; /* stop tsu on error */
- int tsi_concur; /* concurrency */
- int tsi_loop; /* loop count */
-
- /* status of test instance */
- spinlock_t tsi_lock; /* serialize */
- unsigned int tsi_stopping:1; /* test is stopping */
- atomic_t tsi_nactive; /* # of active test
- * unit
- */
- struct list_head tsi_units; /* test units */
- struct list_head tsi_free_rpcs; /* free rpcs */
- struct list_head tsi_active_rpcs; /* active rpcs */
-
- union {
- struct test_ping_req ping; /* ping parameter */
- struct test_bulk_req bulk_v0; /* bulk parameter */
- struct test_bulk_req_v1 bulk_v1; /* bulk v1 parameter */
- } tsi_u;
-};
-
-/*
- * XXX: trailing (PAGE_SIZE % sizeof(struct lnet_process_id)) bytes at the end
- * of pages are not used
- */
-#define SFW_MAX_CONCUR LST_MAX_CONCUR
-#define SFW_ID_PER_PAGE (PAGE_SIZE / sizeof(struct lnet_process_id_packed))
-#define SFW_MAX_NDESTS (LNET_MAX_IOV * SFW_ID_PER_PAGE)
-#define sfw_id_pages(n) (((n) + SFW_ID_PER_PAGE - 1) / SFW_ID_PER_PAGE)
-
-struct sfw_test_unit {
- struct list_head tsu_list; /* chain on lst_test_instance */
- struct lnet_process_id tsu_dest; /* id of dest node */
- int tsu_loop; /* loop count of the test */
- struct sfw_test_instance *tsu_instance; /* pointer to test instance */
- void *tsu_private; /* private data */
- struct swi_workitem tsu_worker; /* workitem of the test unit */
-};
-
-struct sfw_test_case {
- struct list_head tsc_list; /* chain on fw_tests */
- struct srpc_service *tsc_srv_service; /* test service */
- struct sfw_test_client_ops *tsc_cli_ops; /* ops of test client */
-};
-
-struct srpc_client_rpc *
-sfw_create_rpc(struct lnet_process_id peer, int service,
- unsigned int features, int nbulkiov, int bulklen,
- void (*done)(struct srpc_client_rpc *), void *priv);
-int sfw_create_test_rpc(struct sfw_test_unit *tsu,
- struct lnet_process_id peer, unsigned int features,
- int nblk, int blklen, struct srpc_client_rpc **rpc);
-void sfw_abort_rpc(struct srpc_client_rpc *rpc);
-void sfw_post_rpc(struct srpc_client_rpc *rpc);
-void sfw_client_rpc_done(struct srpc_client_rpc *rpc);
-void sfw_unpack_message(struct srpc_msg *msg);
-void sfw_free_pages(struct srpc_server_rpc *rpc);
-void sfw_add_bulk_page(struct srpc_bulk *bk, struct page *pg, int i);
-int sfw_alloc_pages(struct srpc_server_rpc *rpc, int cpt, int npages, int len,
- int sink);
-int sfw_make_session(struct srpc_mksn_reqst *request,
- struct srpc_mksn_reply *reply);
-
-struct srpc_client_rpc *
-srpc_create_client_rpc(struct lnet_process_id peer, int service,
- int nbulkiov, int bulklen,
- void (*rpc_done)(struct srpc_client_rpc *),
- void (*rpc_fini)(struct srpc_client_rpc *), void *priv);
-void srpc_post_rpc(struct srpc_client_rpc *rpc);
-void srpc_abort_rpc(struct srpc_client_rpc *rpc, int why);
-void srpc_free_bulk(struct srpc_bulk *bk);
-struct srpc_bulk *srpc_alloc_bulk(int cpt, unsigned int off,
- unsigned int bulk_npg, unsigned int bulk_len,
- int sink);
-void srpc_send_rpc(struct swi_workitem *wi);
-int srpc_send_reply(struct srpc_server_rpc *rpc);
-int srpc_add_service(struct srpc_service *sv);
-int srpc_remove_service(struct srpc_service *sv);
-void srpc_shutdown_service(struct srpc_service *sv);
-void srpc_abort_service(struct srpc_service *sv);
-int srpc_finish_service(struct srpc_service *sv);
-int srpc_service_add_buffers(struct srpc_service *sv, int nbuffer);
-void srpc_service_remove_buffers(struct srpc_service *sv, int nbuffer);
-void srpc_get_counters(struct srpc_counters *cnt);
-void srpc_set_counters(const struct srpc_counters *cnt);
-
-extern struct workqueue_struct *lst_serial_wq;
-extern struct workqueue_struct **lst_test_wq;
-
-static inline int
-srpc_serv_is_framework(struct srpc_service *svc)
-{
- return svc->sv_id < SRPC_FRAMEWORK_SERVICE_MAX_ID;
-}
-
-static void
-swi_wi_action(struct work_struct *wi)
-{
- struct swi_workitem *swi;
-
- swi = container_of(wi, struct swi_workitem, swi_work);
-
- swi->swi_action(swi);
-}
-
-static inline void
-swi_init_workitem(struct swi_workitem *swi,
- swi_action_t action, struct workqueue_struct *wq)
-{
- swi->swi_wq = wq;
- swi->swi_action = action;
- swi->swi_state = SWI_STATE_NEWBORN;
- INIT_WORK(&swi->swi_work, swi_wi_action);
-}
-
-static inline void
-swi_schedule_workitem(struct swi_workitem *wi)
-{
- queue_work(wi->swi_wq, &wi->swi_work);
-}
-
-static inline int
-swi_cancel_workitem(struct swi_workitem *swi)
-{
- return cancel_work_sync(&swi->swi_work);
-}
-
-int sfw_startup(void);
-int srpc_startup(void);
-void sfw_shutdown(void);
-void srpc_shutdown(void);
-
-static inline void
-srpc_destroy_client_rpc(struct srpc_client_rpc *rpc)
-{
- LASSERT(rpc);
- LASSERT(!srpc_event_pending(rpc));
- LASSERT(!atomic_read(&rpc->crpc_refcount));
-
- if (!rpc->crpc_fini)
- kfree(rpc);
- else
- (*rpc->crpc_fini)(rpc);
-}
-
-static inline void
-srpc_init_client_rpc(struct srpc_client_rpc *rpc, struct lnet_process_id peer,
- int service, int nbulkiov, int bulklen,
- void (*rpc_done)(struct srpc_client_rpc *),
- void (*rpc_fini)(struct srpc_client_rpc *), void *priv)
-{
- LASSERT(nbulkiov <= LNET_MAX_IOV);
-
- memset(rpc, 0, offsetof(struct srpc_client_rpc,
- crpc_bulk.bk_iovs[nbulkiov]));
-
- INIT_LIST_HEAD(&rpc->crpc_list);
- swi_init_workitem(&rpc->crpc_wi, srpc_send_rpc,
- lst_test_wq[lnet_cpt_of_nid(peer.nid)]);
- spin_lock_init(&rpc->crpc_lock);
- atomic_set(&rpc->crpc_refcount, 1); /* 1 ref for caller */
-
- rpc->crpc_dest = peer;
- rpc->crpc_priv = priv;
- rpc->crpc_service = service;
- rpc->crpc_bulk.bk_len = bulklen;
- rpc->crpc_bulk.bk_niov = nbulkiov;
- rpc->crpc_done = rpc_done;
- rpc->crpc_fini = rpc_fini;
- LNetInvalidateMDHandle(&rpc->crpc_reqstmdh);
- LNetInvalidateMDHandle(&rpc->crpc_replymdh);
- LNetInvalidateMDHandle(&rpc->crpc_bulk.bk_mdh);
-
- /* no event is expected at this point */
- rpc->crpc_bulkev.ev_fired = 1;
- rpc->crpc_reqstev.ev_fired = 1;
- rpc->crpc_replyev.ev_fired = 1;
-
- rpc->crpc_reqstmsg.msg_magic = SRPC_MSG_MAGIC;
- rpc->crpc_reqstmsg.msg_version = SRPC_MSG_VERSION;
- rpc->crpc_reqstmsg.msg_type = srpc_service2request(service);
-}
-
-static inline const char *
-swi_state2str(int state)
-{
-#define STATE2STR(x) case x: return #x
- switch (state) {
- default:
- LBUG();
- STATE2STR(SWI_STATE_NEWBORN);
- STATE2STR(SWI_STATE_REPLY_SUBMITTED);
- STATE2STR(SWI_STATE_REPLY_SENT);
- STATE2STR(SWI_STATE_REQUEST_SUBMITTED);
- STATE2STR(SWI_STATE_REQUEST_SENT);
- STATE2STR(SWI_STATE_REPLY_RECEIVED);
- STATE2STR(SWI_STATE_BULK_STARTED);
- STATE2STR(SWI_STATE_DONE);
- }
-#undef STATE2STR
-}
-
-#define selftest_wait_events() \
- do { \
- set_current_state(TASK_UNINTERRUPTIBLE); \
- schedule_timeout(HZ / 10); \
- } while (0)
-
-#define lst_wait_until(cond, lock, fmt, ...) \
-do { \
- int __I = 2; \
- while (!(cond)) { \
- CDEBUG(is_power_of_2(++__I) ? D_WARNING : D_NET, \
- fmt, ## __VA_ARGS__); \
- spin_unlock(&(lock)); \
- \
- selftest_wait_events(); \
- \
- spin_lock(&(lock)); \
- } \
-} while (0)
-
-static inline void
-srpc_wait_service_shutdown(struct srpc_service *sv)
-{
- int i = 2;
-
- LASSERT(sv->sv_shuttingdown);
-
- while (!srpc_finish_service(sv)) {
- i++;
- CDEBUG(((i & -i) == i) ? D_WARNING : D_NET,
- "Waiting for %s service to shutdown...\n",
- sv->sv_name);
- selftest_wait_events();
- }
-}
-
-extern struct sfw_test_client_ops brw_test_client;
-void brw_init_test_client(void);
-
-extern struct srpc_service brw_test_service;
-void brw_init_test_service(void);
-
-extern struct sfw_test_client_ops ping_test_client;
-void ping_init_test_client(void);
-
-extern struct srpc_service ping_test_service;
-void ping_init_test_service(void);
-
-#endif /* __SELFTEST_SELFTEST_H__ */
diff --git a/drivers/staging/lustre/lnet/selftest/timer.c b/drivers/staging/lustre/lnet/selftest/timer.c
deleted file mode 100644
index 1b2c5fc81358..000000000000
--- a/drivers/staging/lustre/lnet/selftest/timer.c
+++ /dev/null
@@ -1,244 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * GPL HEADER START
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 only,
- * as published by the Free Software Foundation.
- *
- * This program 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 version 2 for more details (a copy is included
- * in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- *
- * Copyright (c) 2011, 2012, Intel Corporation.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * lnet/selftest/timer.c
- *
- * Author: Isaac Huang <isaac@clusterfs.com>
- */
-
-#define DEBUG_SUBSYSTEM S_LNET
-
-#include "selftest.h"
-
-/*
- * Timers are implemented as a sorted queue of expiry times. The queue
- * is slotted, with each slot holding timers which expire in a
- * 2**STTIMER_MINPOLL (8) second period. The timers in each slot are
- * sorted by increasing expiry time. The number of slots is 2**7 (128),
- * to cover a time period of 1024 seconds into the future before wrapping.
- */
-#define STTIMER_MINPOLL 3 /* log2 min poll interval (8 s) */
-#define STTIMER_SLOTTIME BIT(STTIMER_MINPOLL)
-#define STTIMER_SLOTTIMEMASK (~(STTIMER_SLOTTIME - 1))
-#define STTIMER_NSLOTS BIT(7)
-#define STTIMER_SLOT(t) (&stt_data.stt_hash[(((t) >> STTIMER_MINPOLL) & \
- (STTIMER_NSLOTS - 1))])
-
-static struct st_timer_data {
- spinlock_t stt_lock;
- unsigned long stt_prev_slot; /* start time of the slot processed
- * previously
- */
- struct list_head stt_hash[STTIMER_NSLOTS];
- int stt_shuttingdown;
- wait_queue_head_t stt_waitq;
- int stt_nthreads;
-} stt_data;
-
-void
-stt_add_timer(struct stt_timer *timer)
-{
- struct list_head *pos;
-
- spin_lock(&stt_data.stt_lock);
-
- LASSERT(stt_data.stt_nthreads > 0);
- LASSERT(!stt_data.stt_shuttingdown);
- LASSERT(timer->stt_func);
- LASSERT(list_empty(&timer->stt_list));
- LASSERT(timer->stt_expires > ktime_get_real_seconds());
-
- /* a simple insertion sort */
- list_for_each_prev(pos, STTIMER_SLOT(timer->stt_expires)) {
- struct stt_timer *old = list_entry(pos, struct stt_timer,
- stt_list);
-
- if (timer->stt_expires >= old->stt_expires)
- break;
- }
- list_add(&timer->stt_list, pos);
-
- spin_unlock(&stt_data.stt_lock);
-}
-
-/*
- * The function returns whether it has deactivated a pending timer or not.
- * (ie. del_timer() of an inactive timer returns 0, del_timer() of an
- * active timer returns 1.)
- *
- * CAVEAT EMPTOR:
- * When 0 is returned, it is possible that timer->stt_func _is_ running on
- * another CPU.
- */
-int
-stt_del_timer(struct stt_timer *timer)
-{
- int ret = 0;
-
- spin_lock(&stt_data.stt_lock);
-
- LASSERT(stt_data.stt_nthreads > 0);
- LASSERT(!stt_data.stt_shuttingdown);
-
- if (!list_empty(&timer->stt_list)) {
- ret = 1;
- list_del_init(&timer->stt_list);
- }
-
- spin_unlock(&stt_data.stt_lock);
- return ret;
-}
-
-/* called with stt_data.stt_lock held */
-static int
-stt_expire_list(struct list_head *slot, time64_t now)
-{
- int expired = 0;
- struct stt_timer *timer;
-
- while (!list_empty(slot)) {
- timer = list_entry(slot->next, struct stt_timer, stt_list);
-
- if (timer->stt_expires > now)
- break;
-
- list_del_init(&timer->stt_list);
- spin_unlock(&stt_data.stt_lock);
-
- expired++;
- (*timer->stt_func) (timer->stt_data);
-
- spin_lock(&stt_data.stt_lock);
- }
-
- return expired;
-}
-
-static int
-stt_check_timers(unsigned long *last)
-{
- int expired = 0;
- time64_t now;
- unsigned long this_slot;
-
- now = ktime_get_real_seconds();
- this_slot = now & STTIMER_SLOTTIMEMASK;
-
- spin_lock(&stt_data.stt_lock);
-
- while (cfs_time_aftereq(this_slot, *last)) {
- expired += stt_expire_list(STTIMER_SLOT(this_slot), now);
- this_slot = cfs_time_sub(this_slot, STTIMER_SLOTTIME);
- }
-
- *last = now & STTIMER_SLOTTIMEMASK;
- spin_unlock(&stt_data.stt_lock);
- return expired;
-}
-
-static int
-stt_timer_main(void *arg)
-{
- int rc = 0;
-
- while (!stt_data.stt_shuttingdown) {
- stt_check_timers(&stt_data.stt_prev_slot);
-
- rc = wait_event_timeout(stt_data.stt_waitq,
- stt_data.stt_shuttingdown,
- STTIMER_SLOTTIME * HZ);
- }
-
- spin_lock(&stt_data.stt_lock);
- stt_data.stt_nthreads--;
- spin_unlock(&stt_data.stt_lock);
- return rc;
-}
-
-static int
-stt_start_timer_thread(void)
-{
- struct task_struct *task;
-
- LASSERT(!stt_data.stt_shuttingdown);
-
- task = kthread_run(stt_timer_main, NULL, "st_timer");
- if (IS_ERR(task))
- return PTR_ERR(task);
-
- spin_lock(&stt_data.stt_lock);
- stt_data.stt_nthreads++;
- spin_unlock(&stt_data.stt_lock);
- return 0;
-}
-
-int
-stt_startup(void)
-{
- int rc = 0;
- int i;
-
- stt_data.stt_shuttingdown = 0;
- stt_data.stt_prev_slot = ktime_get_real_seconds() & STTIMER_SLOTTIMEMASK;
-
- spin_lock_init(&stt_data.stt_lock);
- for (i = 0; i < STTIMER_NSLOTS; i++)
- INIT_LIST_HEAD(&stt_data.stt_hash[i]);
-
- stt_data.stt_nthreads = 0;
- init_waitqueue_head(&stt_data.stt_waitq);
- rc = stt_start_timer_thread();
- if (rc)
- CERROR("Can't spawn timer thread: %d\n", rc);
-
- return rc;
-}
-
-void
-stt_shutdown(void)
-{
- int i;
-
- spin_lock(&stt_data.stt_lock);
-
- for (i = 0; i < STTIMER_NSLOTS; i++)
- LASSERT(list_empty(&stt_data.stt_hash[i]));
-
- stt_data.stt_shuttingdown = 1;
-
- wake_up(&stt_data.stt_waitq);
- lst_wait_until(!stt_data.stt_nthreads, stt_data.stt_lock,
- "waiting for %d threads to terminate\n",
- stt_data.stt_nthreads);
-
- spin_unlock(&stt_data.stt_lock);
-}
diff --git a/drivers/staging/lustre/lnet/selftest/timer.h b/drivers/staging/lustre/lnet/selftest/timer.h
deleted file mode 100644
index 7f0ef9bd0cda..000000000000
--- a/drivers/staging/lustre/lnet/selftest/timer.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * GPL HEADER START
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 only,
- * as published by the Free Software Foundation.
- *
- * This program 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 version 2 for more details (a copy is included
- * in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU General Public License
- * version 2 along with this program; If not, see
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * GPL HEADER END
- */
-/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Use is subject to license terms.
- */
-/*
- * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
- *
- * lnet/selftest/timer.h
- *
- * Author: Isaac Huang <isaac@clusterfs.com>
- */
-#ifndef __SELFTEST_TIMER_H__
-#define __SELFTEST_TIMER_H__
-
-struct stt_timer {
- struct list_head stt_list;
- time64_t stt_expires;
- void (*stt_func)(void *);
- void *stt_data;
-};
-
-void stt_add_timer(struct stt_timer *timer);
-int stt_del_timer(struct stt_timer *timer);
-int stt_startup(void);
-void stt_shutdown(void);
-
-#endif /* __SELFTEST_TIMER_H__ */