/*
 * 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.sun.com/software/products/lustre/docs/GPLv2.pdf
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 *
 * 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/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");

static void
brw_client_fini(sfw_test_instance_t *tsi)
{
	srpc_bulk_t     *bulk;
	sfw_test_unit_t *tsu;

	LASSERT(tsi->tsi_is_client);

	list_for_each_entry(tsu, &tsi->tsi_units, tsu_list) {
		bulk = tsu->tsu_private;
		if (bulk == NULL)
			continue;

		srpc_free_bulk(bulk);
		tsu->tsu_private = NULL;
	}
}

int
brw_client_init(sfw_test_instance_t *tsi)
{
	sfw_session_t	 *sn = tsi->tsi_batch->bat_session;
	int		  flags;
	int		  npg;
	int		  len;
	int		  opc;
	srpc_bulk_t	 *bulk;
	sfw_test_unit_t	 *tsu;

	LASSERT(sn != NULL);
	LASSERT(tsi->tsi_is_client);

	if ((sn->sn_features & LST_FEAT_BULK_LEN) == 0) {
		test_bulk_req_t  *breq = &tsi->tsi_u.bulk_v0;

		opc   = breq->blk_opc;
		flags = breq->blk_flags;
		npg   = breq->blk_npg;
		/* NB: this is not going to work for variable page size,
		 * but we have to keep it for compatibility */
		len   = npg * PAGE_CACHE_SIZE;

	} else {
		test_bulk_req_v1_t  *breq = &tsi->tsi_u.bulk_v1;

		/* I should never get this step if it's unknown feature
		 * because make_session will reject unknown feature */
		LASSERT((sn->sn_features & ~LST_FEATS_MASK) == 0);

		opc   = breq->blk_opc;
		flags = breq->blk_flags;
		len   = breq->blk_len;
		npg   = (len + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
	}

	if (npg > LNET_MAX_IOV || npg <= 0)
		return -EINVAL;

	if (opc != LST_BRW_READ && opc != LST_BRW_WRITE)
		return -EINVAL;

	if (flags != LST_BRW_CHECK_NONE &&
	    flags != LST_BRW_CHECK_FULL && flags != LST_BRW_CHECK_SIMPLE)
		return -EINVAL;

	list_for_each_entry(tsu, &tsi->tsi_units, tsu_list) {
		bulk = srpc_alloc_bulk(lnet_cpt_of_nid(tsu->tsu_dest.nid),
				       npg, len, opc == LST_BRW_READ);
		if (bulk == NULL) {
			brw_client_fini(tsi);
			return -ENOMEM;
		}

		tsu->tsu_private = bulk;
	}

	return 0;
}

#define BRW_POISON      0xbeefbeefbeefbeefULL
#define BRW_MAGIC       0xeeb0eeb1eeb2eeb3ULL
#define BRW_MSIZE       sizeof(__u64)

int
brw_inject_one_error(void)
{
	struct timeval tv;

	if (brw_inject_errors <= 0)
		return 0;

	do_gettimeofday(&tv);

	if ((tv.tv_usec & 1) == 0)
		return 0;

	return brw_inject_errors--;
}

void
brw_fill_page(struct page *pg, int pattern, __u64 magic)
{
	char *addr = page_address(pg);
	int   i;

	LASSERT(addr != NULL);

	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);
		addr += PAGE_CACHE_SIZE - BRW_MSIZE;
		memcpy(addr, &magic, BRW_MSIZE);
		return;
	}

	if (pattern == LST_BRW_CHECK_FULL) {
		for (i = 0; i < PAGE_CACHE_SIZE / BRW_MSIZE; i++)
			memcpy(addr + i * BRW_MSIZE, &magic, BRW_MSIZE);
		return;
	}

	LBUG();
	return;
}

int
brw_check_page(struct page *pg, int pattern, __u64 magic)
{
	char  *addr = page_address(pg);
	__u64  data = 0; /* make compiler happy */
	int    i;

	LASSERT(addr != NULL);

	if (pattern == LST_BRW_CHECK_NONE)
		return 0;

	if (pattern == LST_BRW_CHECK_SIMPLE) {
		data = *((__u64 *) addr);
		if (data != magic)
			goto bad_data;

		addr += PAGE_CACHE_SIZE - BRW_MSIZE;
		data = *((__u64 *) addr);
		if (data != magic)
			goto bad_data;

		return 0;
	}

	if (pattern == LST_BRW_CHECK_FULL) {
		for (i = 0; i < PAGE_CACHE_SIZE / BRW_MSIZE; i++) {
			data = *(((__u64 *) addr) + i);
			if (data != magic)
				goto bad_data;
		}

		return 0;
	}

	LBUG();

bad_data:
	CERROR("Bad data in page %p: "LPX64", "LPX64" expected\n",
		pg, data, magic);
	return 1;
}

void
brw_fill_bulk(srpc_bulk_t *bk, int pattern, __u64 magic)
{
	int	 i;
	struct page *pg;

	for (i = 0; i < bk->bk_niov; i++) {
		pg = bk->bk_iovs[i].kiov_page;
		brw_fill_page(pg, pattern, magic);
	}
}

int
brw_check_bulk(srpc_bulk_t *bk, int pattern, __u64 magic)
{
	int	 i;
	struct page *pg;

	for (i = 0; i < bk->bk_niov; i++) {
		pg = bk->bk_iovs[i].kiov_page;
		if (brw_check_page(pg, pattern, magic) != 0) {
			CERROR("Bulk page %p (%d/%d) is corrupted!\n",
				pg, i, bk->bk_niov);
			return 1;
		}
	}

	return 0;
}

static int
brw_client_prep_rpc(sfw_test_unit_t *tsu,
		     lnet_process_id_t dest, srpc_client_rpc_t **rpcpp)
{
	srpc_bulk_t	 *bulk = tsu->tsu_private;
	sfw_test_instance_t *tsi = tsu->tsu_instance;
	sfw_session_t	    *sn = tsi->tsi_batch->bat_session;
	srpc_client_rpc_t   *rpc;
	srpc_brw_reqst_t    *req;
	int		     flags;
	int		     npg;
	int		     len;
	int		     opc;
	int		     rc;

	LASSERT(sn != NULL);
	LASSERT(bulk != NULL);

	if ((sn->sn_features & LST_FEAT_BULK_LEN) == 0) {
		test_bulk_req_t *breq = &tsi->tsi_u.bulk_v0;

		opc   = breq->blk_opc;
		flags = breq->blk_flags;
		npg   = breq->blk_npg;
		len   = npg * PAGE_CACHE_SIZE;

	} else {
		test_bulk_req_v1_t  *breq = &tsi->tsi_u.bulk_v1;

		/* I should never get this step if it's unknown feature
		 * because make_session will reject unknown feature */
		LASSERT((sn->sn_features & ~LST_FEATS_MASK) == 0);

		opc   = breq->blk_opc;
		flags = breq->blk_flags;
		len   = breq->blk_len;
		npg   = (len + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
	}

	rc = sfw_create_test_rpc(tsu, dest, sn->sn_features, npg, len, &rpc);
	if (rc != 0)
		return rc;

	memcpy(&rpc->crpc_bulk, bulk, offsetof(srpc_bulk_t, bk_iovs[npg]));
	if (opc == LST_BRW_WRITE)
		brw_fill_bulk(&rpc->crpc_bulk, flags, BRW_MAGIC);
	else
		brw_fill_bulk(&rpc->crpc_bulk, flags, BRW_POISON);

	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(sfw_test_unit_t *tsu, srpc_client_rpc_t *rpc)
{
	__u64		magic = BRW_MAGIC;
	sfw_test_instance_t *tsi = tsu->tsu_instance;
	sfw_session_t       *sn = tsi->tsi_batch->bat_session;
	srpc_msg_t	  *msg = &rpc->crpc_replymsg;
	srpc_brw_reply_t    *reply = &msg->msg_body.brw_reply;
	srpc_brw_reqst_t    *reqst = &rpc->crpc_reqstmsg.msg_body.brw_reqst;

	LASSERT(sn != NULL);

	if (rpc->crpc_status != 0) {
		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);
		goto out;
	}

	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 != 0) {
		atomic_inc(&sn->sn_brw_errors);
		rpc->crpc_status = -(int)reply->brw_status;
		goto out;
	}

	if (reqst->brw_rw == LST_BRW_WRITE)
		goto out;

	if (brw_check_bulk(&rpc->crpc_bulk, reqst->brw_flags, magic) != 0) {
		CERROR("Bulk data from %s is corrupted!\n",
			libcfs_id2str(rpc->crpc_dest));
		atomic_inc(&sn->sn_brw_errors);
		rpc->crpc_status = -EBADMSG;
	}

out:
	return;
}

void
brw_server_rpc_done(srpc_server_rpc_t *rpc)
{
	srpc_bulk_t *blk = rpc->srpc_bulk;

	if (blk == NULL)
		return;

	if (rpc->srpc_status != 0)
		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);
}

int
brw_bulk_ready(srpc_server_rpc_t *rpc, int status)
{
	__u64	     magic = BRW_MAGIC;
	srpc_brw_reply_t *reply = &rpc->srpc_replymsg.msg_body.brw_reply;
	srpc_brw_reqst_t *reqst;
	srpc_msg_t       *reqstmsg;

	LASSERT(rpc->srpc_bulk != NULL);
	LASSERT(rpc->srpc_reqstbuf != NULL);

	reqstmsg = &rpc->srpc_reqstbuf->buf_msg;
	reqst = &reqstmsg->msg_body.brw_reqst;

	if (status != 0) {
		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) != 0) {
		CERROR("Bulk data from %s is corrupted!\n",
			libcfs_id2str(rpc->srpc_peer));
		reply->brw_status = EBADMSG;
	}

	return 0;
}

int
brw_server_handle(struct srpc_server_rpc *rpc)
{
	struct srpc_service	*sv = rpc->srpc_scd->scd_svc;
	srpc_msg_t       *replymsg = &rpc->srpc_replymsg;
	srpc_msg_t       *reqstmsg = &rpc->srpc_reqstbuf->buf_msg;
	srpc_brw_reply_t *reply = &replymsg->msg_body.brw_reply;
	srpc_brw_reqst_t *reqst = &reqstmsg->msg_body.brw_reqst;
	int		  npg;
	int	       rc;

	LASSERT(sv->sv_id == SRPC_SERVICE_BRW);

	if (reqstmsg->msg_magic != SRPC_MSG_MAGIC) {
		LASSERT(reqstmsg->msg_magic == __swab32(SRPC_MSG_MAGIC));

		__swab32s(&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) != 0) {
		replymsg->msg_ses_feats = LST_FEATS_MASK;
		reply->brw_status = EPROTO;
		return 0;
	}

	if ((reqstmsg->msg_ses_feats & LST_FEAT_BULK_LEN) == 0) {
		/* compat with old version */
		if ((reqst->brw_len & ~CFS_PAGE_MASK) != 0) {
			reply->brw_status = EINVAL;
			return 0;
		}
		npg = reqst->brw_len >> PAGE_CACHE_SHIFT;

	} else {
		npg = (reqst->brw_len + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
	}

	replymsg->msg_ses_feats = reqstmsg->msg_ses_feats;

	if (reqst->brw_len == 0 || npg > LNET_MAX_IOV) {
		reply->brw_status = EINVAL;
		return 0;
	}

	rc = sfw_alloc_pages(rpc, rpc->srpc_scd->scd_cpt, npg,
			     reqst->brw_len,
			     reqst->brw_rw == LST_BRW_WRITE);
	if (rc != 0)
		return rc;

	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;
}

sfw_test_client_ops_t 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;
};

srpc_service_t 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;
}
