X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=blobdiff_plain;f=lnet%2Fselftest%2Fconrpc.c;h=b00b80ad5e3b27baaaf29a29f1c2380d4e29473c;hp=028bdc1d3aded7f7c3b3c36751ff3b35fbfa6e8c;hb=f8b4e51fb85c078ae48c3c14472c520e850a2a2d;hpb=776615e6825e2c90c2635c8b55e7bb02da33726c diff --git a/lnet/selftest/conrpc.c b/lnet/selftest/conrpc.c index 028bdc1..b00b80a 100644 --- a/lnet/selftest/conrpc.c +++ b/lnet/selftest/conrpc.c @@ -1,13 +1,45 @@ -/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- - * vim:expandtab:shiftwidth=8:tabstop=8: - * - * Author: Liang Zhen +/* + * GPL HEADER START * - * This file is part of Lustre, http://www.lustre.org + * 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, 2014, 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 */ -#ifdef __KERNEL__ + #include #include @@ -15,104 +47,96 @@ #include "conrpc.h" #include "console.h" -void lstcon_rpc_stat_reply(int, srpc_msg_t *, - lstcon_node_t *, lstcon_trans_stat_t *); +void lstcon_rpc_stat_reply(lstcon_rpc_trans_t *, srpc_msg_t *, + lstcon_node_t *, lstcon_trans_stat_t *); static void lstcon_rpc_done(srpc_client_rpc_t *rpc) { - lstcon_rpc_t *crpc = (lstcon_rpc_t *)rpc->crpc_priv; + lstcon_rpc_t *crpc = (lstcon_rpc_t *)rpc->crpc_priv; - LASSERT (!list_empty(&crpc->crp_link)); - LASSERT (crpc != NULL && rpc == crpc->crp_rpc); - LASSERT (crpc->crp_posted && !crpc->crp_finished); + LASSERT(crpc != NULL && rpc == crpc->crp_rpc); + LASSERT(crpc->crp_posted && !crpc->crp_finished); - spin_lock(&rpc->crpc_lock); + spin_lock(&rpc->crpc_lock); - if (crpc->crp_trans == NULL) { - /* orphan RPC */ - spin_lock(&console_session.ses_rpc_lock); + if (crpc->crp_trans == NULL) { + /* Orphan RPC is not in any transaction, + * I'm just a poor body and nobody loves me */ + spin_unlock(&rpc->crpc_lock); - /* delete from orphan rpcs list */ - console_session.ses_rpc_pending --; - list_del_init(&crpc->crp_link); + /* release it */ + lstcon_rpc_put(crpc); + return; + } - spin_unlock(&console_session.ses_rpc_lock); + /* not an orphan RPC */ + crpc->crp_finished = 1; - spin_unlock(&rpc->crpc_lock); + if (crpc->crp_stamp == 0) { + /* not aborted */ + LASSERT (crpc->crp_status == 0); - /* release it */ - lstcon_rpc_put(crpc); - return; - } + crpc->crp_stamp = cfs_time_current(); + crpc->crp_status = rpc->crpc_status; + } - /* not an orphan RPC */ - crpc->crp_finished = 1; + /* 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); - if (crpc->crp_stamp == 0) { - /* not aborted */ - LASSERT (crpc->crp_status == 0); - - crpc->crp_stamp = cfs_time_current(); - crpc->crp_status = rpc->crpc_status; - } - - /* wakeup thread waiting on the group if - * it's the last rpc in the group */ - if (atomic_dec_and_test(&crpc->crp_trans->tas_remaining)) - cfs_waitq_signal(&crpc->crp_trans->tas_waitq); - - spin_unlock(&rpc->crpc_lock); + spin_unlock(&rpc->crpc_lock); } -int -lstcon_rpc_init(lstcon_node_t *nd, int service, - int npg, int cached, lstcon_rpc_t *crpc) +static int +lstcon_rpc_init(lstcon_node_t *nd, int service, unsigned feats, + int bulk_npg, int bulk_len, int embedded, lstcon_rpc_t *crpc) { - - crpc->crp_rpc = sfw_create_rpc(nd->nd_id, service, - npg, npg * CFS_PAGE_SIZE, - lstcon_rpc_done, (void *)crpc); - if (crpc->crp_rpc == NULL) - 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_static = !cached; - CFS_INIT_LIST_HEAD(&crpc->crp_link); - - return 0; + crpc->crp_rpc = sfw_create_rpc(nd->nd_id, service, + feats, bulk_npg, bulk_len, + lstcon_rpc_done, (void *)crpc); + if (crpc->crp_rpc == NULL) + return -ENOMEM; + + crpc->crp_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; } -int -lstcon_rpc_prep(lstcon_node_t *nd, int service, - int npg, lstcon_rpc_t **crpcpp) +static int +lstcon_rpc_prep(lstcon_node_t *nd, int service, unsigned feats, + int bulk_npg, int bulk_len, lstcon_rpc_t **crpcpp) { - lstcon_rpc_t *crpc = NULL; - int rc; + lstcon_rpc_t *crpc = NULL; + int rc; - spin_lock(&console_session.ses_rpc_lock); + spin_lock(&console_session.ses_rpc_lock); - if (!list_empty(&console_session.ses_rpc_freelist)) { - crpc = list_entry(console_session.ses_rpc_freelist.next, - lstcon_rpc_t, crp_link); - list_del(&crpc->crp_link); - } + if (!list_empty(&console_session.ses_rpc_freelist)) { + crpc = list_entry(console_session.ses_rpc_freelist.next, + lstcon_rpc_t, crp_link); + list_del_init(&crpc->crp_link); + } - spin_unlock(&console_session.ses_rpc_lock); + spin_unlock(&console_session.ses_rpc_lock); - if (crpc == NULL) { - LIBCFS_ALLOC(crpc, sizeof(*crpc)); - if (crpc == NULL) - return -ENOMEM; - } + if (crpc == NULL) { + LIBCFS_ALLOC(crpc, sizeof(*crpc)); + if (crpc == NULL) + return -ENOMEM; + } - rc = lstcon_rpc_init(nd, service, npg, 1, crpc); + rc = lstcon_rpc_init(nd, service, feats, bulk_npg, bulk_len, 0, crpc); if (rc == 0) { *crpcpp = crpc; return 0; @@ -126,41 +150,46 @@ lstcon_rpc_prep(lstcon_node_t *nd, int service, void lstcon_rpc_put(lstcon_rpc_t *crpc) { - srpc_bulk_t *bulk = &crpc->crp_rpc->crpc_bulk; - int i; + srpc_bulk_t *bulk = &crpc->crp_rpc->crpc_bulk; + int i; - LASSERT (list_empty(&crpc->crp_link)); + LASSERT(list_empty(&crpc->crp_link)); - for (i = 0; i < bulk->bk_niov; i++) { - if (bulk->bk_iovs[i].kiov_page == NULL) - continue; + for (i = 0; i < bulk->bk_niov; i++) { + if (bulk->bk_iovs[i].kiov_page == NULL) + continue; - cfs_free_page(bulk->bk_iovs[i].kiov_page); - } + __free_page(bulk->bk_iovs[i].kiov_page); + } - srpc_client_rpc_decref(crpc->crp_rpc); + srpc_client_rpc_decref(crpc->crp_rpc); - if (crpc->crp_static) { - memset(crpc, 0, sizeof(*crpc)); - crpc->crp_static = 1; - return; - } + 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); - spin_lock(&console_session.ses_rpc_lock); + list_add(&crpc->crp_link, + &console_session.ses_rpc_freelist); - list_add(&crpc->crp_link, &console_session.ses_rpc_freelist); + spin_unlock(&console_session.ses_rpc_lock); + } - spin_unlock(&console_session.ses_rpc_lock); + /* RPC is not alive now */ + atomic_dec(&console_session.ses_rpc_counter); } -void +static void lstcon_rpc_post(lstcon_rpc_t *crpc) { lstcon_rpc_trans_t *trans = crpc->crp_trans; LASSERT (trans != NULL); - atomic_inc(&trans->tas_remaining); + atomic_inc(&trans->tas_remaining); crpc->crp_posted = 1; sfw_post_rpc(crpc->crp_rpc); @@ -206,133 +235,140 @@ lstcon_rpc_trans_name(int transop) } int -lstcon_rpc_trans_prep(struct list_head *translist, - int transop, lstcon_rpc_trans_t **transpp) +lstcon_rpc_trans_prep(struct list_head *translist, int transop, + lstcon_rpc_trans_t **transpp) { - lstcon_rpc_trans_t *trans; + lstcon_rpc_trans_t *trans; - if (translist != NULL) { - 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; - } - } + if (translist != NULL) { + 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 */ - LIBCFS_ALLOC(trans, sizeof(*trans)); - if (trans == NULL) - return -ENOMEM; - - trans->tas_opc = transop; + /* create a trans group */ + LIBCFS_ALLOC(trans, sizeof(*trans)); + if (trans == NULL) + return -ENOMEM; - if (translist == NULL) - CFS_INIT_LIST_HEAD(&trans->tas_olink); - else - list_add_tail(&trans->tas_olink, translist); + trans->tas_opc = transop; - list_add_tail(&trans->tas_link, &console_session.ses_trans_list); + if (translist == NULL) + INIT_LIST_HEAD(&trans->tas_olink); + else + list_add_tail(&trans->tas_olink, translist); - CFS_INIT_LIST_HEAD(&trans->tas_rpcs_list); - atomic_set(&trans->tas_remaining, 0); - cfs_waitq_init(&trans->tas_waitq); + list_add_tail(&trans->tas_link, &console_session.ses_trans_list); - *transpp = trans; + INIT_LIST_HEAD(&trans->tas_rpcs_list); + atomic_set(&trans->tas_remaining, 0); + init_waitqueue_head(&trans->tas_waitq); - return 0; + 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(lstcon_rpc_trans_t *trans, lstcon_rpc_t *crpc) { - list_add_tail(&crpc->crp_link, &trans->tas_rpcs_list); - crpc->crp_trans = trans; + list_add_tail(&crpc->crp_link, &trans->tas_rpcs_list); + crpc->crp_trans = trans; } void lstcon_rpc_trans_abort(lstcon_rpc_trans_t *trans, int error) { - srpc_client_rpc_t *rpc; - lstcon_rpc_t *crpc; - lstcon_node_t *nd; + srpc_client_rpc_t *rpc; + lstcon_rpc_t *crpc; + lstcon_node_t *nd; - list_for_each_entry (crpc, &trans->tas_rpcs_list, crp_link) { - rpc = crpc->crp_rpc; + list_for_each_entry(crpc, &trans->tas_rpcs_list, crp_link) { + rpc = crpc->crp_rpc; - spin_lock(&rpc->crpc_lock); + spin_lock(&rpc->crpc_lock); - if (!crpc->crp_posted || crpc->crp_stamp != 0) { - /* rpc done or aborted already */ - spin_unlock(&rpc->crpc_lock); - continue; - } + if (!crpc->crp_posted || /* not posted */ + crpc->crp_stamp != 0) { /* rpc done or aborted already */ + if (crpc->crp_stamp == 0) { + 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; + crpc->crp_stamp = cfs_time_current(); + crpc->crp_status = error; - spin_unlock(&rpc->crpc_lock); + spin_unlock(&rpc->crpc_lock); - sfw_abort_rpc(rpc); + sfw_abort_rpc(rpc); - if (error != ETIMEDOUT) - continue; + if (error != -ETIMEDOUT) + continue; - nd = crpc->crp_node; - if (cfs_time_after(nd->nd_stamp, crpc->crp_stamp)) - 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; - } + nd->nd_stamp = crpc->crp_stamp; + nd->nd_state = LST_NODE_DOWN; + } } static int lstcon_rpc_trans_check(lstcon_rpc_trans_t *trans) { - if (console_session.ses_shutdown && - !list_empty(&trans->tas_olink)) /* It's not an end session RPC */ - return 1; + if (console_session.ses_shutdown && + !list_empty(&trans->tas_olink)) /* Not an end session RPC */ + return 1; - return (atomic_read(&trans->tas_remaining) == 0) ? 1: 0; + return (atomic_read(&trans->tas_remaining) == 0) ? 1: 0; } int lstcon_rpc_trans_postwait(lstcon_rpc_trans_t *trans, int timeout) { - lstcon_rpc_t *crpc; - int rc; + lstcon_rpc_t *crpc; + int rc; - if (list_empty(&trans->tas_rpcs_list)) + if (list_empty(&trans->tas_rpcs_list)) return 0; - if (timeout < LST_TRANS_MIN_TIMEOUT) - timeout = LST_TRANS_MIN_TIMEOUT; + 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)); + 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); + /* post all requests */ + list_for_each_entry(crpc, &trans->tas_rpcs_list, crp_link) { + LASSERT(!crpc->crp_posted); - lstcon_rpc_post(crpc); - } + lstcon_rpc_post(crpc); + } - mutex_up(&console_session.ses_mutex); + mutex_unlock(&console_session.ses_mutex); - rc = wait_event_interruptible_timeout(trans->tas_waitq, - lstcon_rpc_trans_check(trans), - timeout * HZ); + rc = wait_event_interruptible_timeout(trans->tas_waitq, + lstcon_rpc_trans_check(trans), + cfs_time_seconds(timeout)); rc = (rc > 0)? 0: ((rc < 0)? -EINTR: -ETIMEDOUT); - mutex_down(&console_session.ses_mutex); + mutex_lock(&console_session.ses_mutex); if (console_session.ses_shutdown) rc = -ESHUTDOWN; - if (rc != 0) { + if (rc != 0 || atomic_read(&trans->tas_remaining) != 0) { /* treat short timeout as canceled */ if (rc == -ETIMEDOUT && timeout < LST_TRANS_MIN_TIMEOUT * 2) rc = -EINTR; @@ -348,7 +384,7 @@ lstcon_rpc_trans_postwait(lstcon_rpc_trans_t *trans, int timeout) return rc; } -int +static int lstcon_rpc_get_reply(lstcon_rpc_t *crpc, srpc_msg_t **msgpp) { lstcon_node_t *nd = crpc->crp_node; @@ -368,7 +404,7 @@ lstcon_rpc_get_reply(lstcon_rpc_t *crpc, srpc_msg_t **msgpp) sfw_unpack_message(*msgpp); crpc->crp_unpacked = 1; } - + if (cfs_time_after(nd->nd_stamp, crpc->crp_stamp)) return 0; @@ -388,21 +424,18 @@ lstcon_rpc_get_reply(lstcon_rpc_t *crpc, srpc_msg_t **msgpp) void lstcon_rpc_trans_stat(lstcon_rpc_trans_t *trans, lstcon_trans_stat_t *stat) { - lstcon_rpc_t *crpc; - srpc_client_rpc_t *rpc; - srpc_msg_t *rep; - int error; + lstcon_rpc_t *crpc; + srpc_msg_t *rep; + int error; - LASSERT (stat != NULL); + LASSERT(stat != NULL); - memset(stat, 0, sizeof(*stat)); + memset(stat, 0, sizeof(*stat)); - list_for_each_entry(crpc, &trans->tas_rpcs_list, crp_link) { - lstcon_rpc_stat_total(stat, 1); + list_for_each_entry(crpc, &trans->tas_rpcs_list, crp_link) { + lstcon_rpc_stat_total(stat, 1); - rpc = crpc->crp_rpc; - - LASSERT (crpc->crp_stamp != 0); + LASSERT(crpc->crp_stamp != 0); error = lstcon_rpc_get_reply(crpc, &rep); if (error != 0) { @@ -415,11 +448,15 @@ lstcon_rpc_trans_stat(lstcon_rpc_trans_t *trans, lstcon_trans_stat_t *stat) lstcon_rpc_stat_success(stat, 1); - lstcon_rpc_stat_reply(trans->tas_opc, rep, - crpc->crp_node, stat); + lstcon_rpc_stat_reply(trans, rep, crpc->crp_node, stat); + } + + if (trans->tas_opc == LST_TRANS_SESNEW && stat->trs_fwk_errno == 0) { + stat->trs_fwk_errno = + lstcon_session_feats_check(trans->tas_features); } - CDEBUG(D_NET, "transaction %s success, %d failure, %d total %d, " + 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), @@ -432,14 +469,13 @@ lstcon_rpc_trans_stat(lstcon_rpc_trans_t *trans, lstcon_trans_stat_t *stat) int lstcon_rpc_trans_interpreter(lstcon_rpc_trans_t *trans, - struct list_head *head_up, - lstcon_rpc_readent_func_t readent) + struct list_head __user *head_up, + lstcon_rpc_readent_func_t readent) { - struct list_head tmp; - struct list_head *next; + struct list_head tmp; + struct list_head __user *next; lstcon_rpc_ent_t *ent; srpc_generic_reply_t *rep; - srpc_client_rpc_t *rpc; lstcon_rpc_t *crpc; srpc_msg_t *msg; lstcon_node_t *nd; @@ -447,127 +483,121 @@ lstcon_rpc_trans_interpreter(lstcon_rpc_trans_t *trans, struct timeval tv; int error; - LASSERT (head_up != NULL); + LASSERT(head_up != NULL); - next = 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; + list_for_each_entry(crpc, &trans->tas_rpcs_list, crp_link) { + if (copy_from_user(&tmp, next, + sizeof(struct list_head))) + return -EFAULT; - if (tmp.next == head_up) - return 0; + if (tmp.next == head_up) + return 0; - next = tmp.next; + next = tmp.next; - ent = list_entry(next, lstcon_rpc_ent_t, rpe_link); + ent = list_entry(next, lstcon_rpc_ent_t, rpe_link); - rpc = crpc->crp_rpc; - - LASSERT (crpc->crp_stamp != 0); + LASSERT(crpc->crp_stamp != 0); error = lstcon_rpc_get_reply(crpc, &msg); nd = crpc->crp_node; - dur = cfs_time_sub(crpc->crp_stamp, - console_session.ses_id.ses_stamp); + dur = (cfs_duration_t)cfs_time_sub(crpc->crp_stamp, + (cfs_time_t)console_session.ses_id.ses_stamp); cfs_duration_usec(dur, &tv); - if (copy_to_user(&ent->rpe_peer, - &nd->nd_id, sizeof(lnet_process_id_t)) || - 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 (copy_to_user(&ent->rpe_peer, + &nd->nd_id, sizeof(lnet_process_id_t)) || + 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 != 0) - continue; + if (error != 0) + continue; - /* RPC is done */ - rep = (srpc_generic_reply_t *)&msg->msg_body.reply; + /* RPC is done */ + rep = (srpc_generic_reply_t *)&msg->msg_body.reply; - if (copy_to_user(&ent->rpe_sid, - &rep->sid, sizeof(lst_sid_t)) || - copy_to_user(&ent->rpe_fwk_errno, - &rep->status, sizeof(rep->status))) - return -EFAULT; + if (copy_to_user(&ent->rpe_sid, + &rep->sid, sizeof(lst_sid_t)) || + copy_to_user(&ent->rpe_fwk_errno, + &rep->status, sizeof(rep->status))) + return -EFAULT; - if (readent == NULL) - continue; + if (readent == NULL) + continue; - if ((error = readent(trans->tas_opc, msg, ent)) != 0) - return error; - } + error = readent(trans->tas_opc, msg, ent); + if (error != 0) + return error; + } - return 0; + return 0; } void lstcon_rpc_trans_destroy(lstcon_rpc_trans_t *trans) { - srpc_client_rpc_t *rpc; - lstcon_rpc_t *crpc; - lstcon_rpc_t *tmp; - int count = 0; - - list_for_each_entry_safe(crpc, tmp, - &trans->tas_rpcs_list, crp_link) { - rpc = crpc->crp_rpc; + srpc_client_rpc_t *rpc; + lstcon_rpc_t *crpc; + lstcon_rpc_t *tmp; + int count = 0; - spin_lock(&rpc->crpc_lock); + list_for_each_entry_safe(crpc, tmp, &trans->tas_rpcs_list, crp_link) { + rpc = crpc->crp_rpc; - /* free it if not posted or finished already */ - if (!crpc->crp_posted || crpc->crp_finished) { - spin_unlock(&rpc->crpc_lock); + spin_lock(&rpc->crpc_lock); - list_del_init(&crpc->crp_link); - lstcon_rpc_put(crpc); + /* free it if not posted or finished already */ + if (!crpc->crp_posted || crpc->crp_finished) { + spin_unlock(&rpc->crpc_lock); - continue; - } + list_del_init(&crpc->crp_link); + lstcon_rpc_put(crpc); - /* rpcs can be still not callbacked (even LNetMDUnlink is called) - * because huge timeout for inaccessible network, don't make - * user wait for them, just put rpcs in orphan list */ + continue; + } - LASSERT (crpc->crp_status != 0); + /* 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 */ - crpc->crp_node = NULL; - crpc->crp_trans = NULL; - list_del(&crpc->crp_link); + LASSERT(crpc->crp_status != 0); - spin_lock(&console_session.ses_rpc_lock); + crpc->crp_node = NULL; + crpc->crp_trans = NULL; + list_del_init(&crpc->crp_link); + count++; - count ++; - /* add to orphan list */ - console_session.ses_rpc_pending ++; - list_add_tail(&crpc->crp_link, &console_session.ses_rpc_list); + spin_unlock(&rpc->crpc_lock); - spin_unlock(&console_session.ses_rpc_lock); + atomic_dec(&trans->tas_remaining); + } - spin_unlock(&rpc->crpc_lock); + LASSERT(atomic_read(&trans->tas_remaining) == 0); - atomic_dec(&trans->tas_remaining); - } - - LASSERT (atomic_read(&trans->tas_remaining) == 0); + list_del(&trans->tas_link); + if (!list_empty(&trans->tas_olink)) + list_del(&trans->tas_olink); - 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); - CDEBUG(D_NET, "Transaction %s destroyed with %d pending RPCs\n", - lstcon_rpc_trans_name(trans->tas_opc), count); + LIBCFS_FREE(trans, sizeof(*trans)); - LIBCFS_FREE(trans, sizeof(*trans)); - - return; + return; } int -lstcon_sesrpc_prep(lstcon_node_t *nd, int transop, lstcon_rpc_t **crpc) +lstcon_sesrpc_prep(lstcon_node_t *nd, int transop, + unsigned feats, lstcon_rpc_t **crpc) { srpc_mksn_reqst_t *msrq; srpc_rmsn_reqst_t *rsrq; @@ -575,19 +605,21 @@ lstcon_sesrpc_prep(lstcon_node_t *nd, int transop, lstcon_rpc_t **crpc) switch (transop) { case LST_TRANS_SESNEW: - rc = lstcon_rpc_prep(nd, SRPC_SERVICE_MAKE_SESSION, 0, crpc); + rc = lstcon_rpc_prep(nd, SRPC_SERVICE_MAKE_SESSION, + feats, 0, 0, crpc); if (rc != 0) return rc; msrq = &(*crpc)->crp_rpc->crpc_reqstmsg.msg_body.mksn_reqst; msrq->mksn_sid = console_session.ses_id; msrq->mksn_force = console_session.ses_force; - strncpy(msrq->mksn_name, console_session.ses_name, - strlen(console_session.ses_name)); + 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, 0, crpc); + rc = lstcon_rpc_prep(nd, SRPC_SERVICE_REMOVE_SESSION, + feats, 0, 0, crpc); if (rc != 0) return rc; @@ -603,12 +635,12 @@ lstcon_sesrpc_prep(lstcon_node_t *nd, int transop, lstcon_rpc_t **crpc) } int -lstcon_dbgrpc_prep(lstcon_node_t *nd, lstcon_rpc_t **crpc) +lstcon_dbgrpc_prep(lstcon_node_t *nd, unsigned feats, lstcon_rpc_t **crpc) { - srpc_debug_reqst_t *drq; - int rc; + srpc_debug_reqst_t *drq; + int rc; - rc = lstcon_rpc_prep(nd, SRPC_SERVICE_DEBUG, 0, crpc); + rc = lstcon_rpc_prep(nd, SRPC_SERVICE_DEBUG, feats, 0, 0, crpc); if (rc != 0) return rc; @@ -616,19 +648,19 @@ lstcon_dbgrpc_prep(lstcon_node_t *nd, lstcon_rpc_t **crpc) drq->dbg_sid = console_session.ses_id; drq->dbg_flags = 0; - + return rc; } int -lstcon_batrpc_prep(lstcon_node_t *nd, int transop, - lstcon_tsb_hdr_t *tsb, lstcon_rpc_t **crpc) +lstcon_batrpc_prep(lstcon_node_t *nd, int transop, unsigned feats, + lstcon_tsb_hdr_t *tsb, lstcon_rpc_t **crpc) { - lstcon_batch_t *batch; - srpc_batch_reqst_t *brq; - int rc; + lstcon_batch_t *batch; + srpc_batch_reqst_t *brq; + int rc; - rc = lstcon_rpc_prep(nd, SRPC_SERVICE_BATCH, 0, crpc); + rc = lstcon_rpc_prep(nd, SRPC_SERVICE_BATCH, feats, 0, 0, crpc); if (rc != 0) return rc; @@ -649,17 +681,17 @@ lstcon_batrpc_prep(lstcon_node_t *nd, int transop, batch = (lstcon_batch_t *)tsb; brq->bar_arg = batch->bat_arg; - + return 0; } int -lstcon_statrpc_prep(lstcon_node_t *nd, lstcon_rpc_t **crpc) +lstcon_statrpc_prep(lstcon_node_t *nd, unsigned feats, lstcon_rpc_t **crpc) { - srpc_stat_reqst_t *srq; - int rc; + srpc_stat_reqst_t *srq; + int rc; - rc = lstcon_rpc_prep(nd, SRPC_SERVICE_QUERY_STAT, 0, crpc); + rc = lstcon_rpc_prep(nd, SRPC_SERVICE_QUERY_STAT, feats, 0, 0, crpc); if (rc != 0) return rc; @@ -671,31 +703,31 @@ lstcon_statrpc_prep(lstcon_node_t *nd, lstcon_rpc_t **crpc) return 0; } -lnet_process_id_t * +static lnet_process_id_packed_t * lstcon_next_id(int idx, int nkiov, lnet_kiov_t *kiov) { - lnet_process_id_t *pid; - int i; + lnet_process_id_packed_t *pid; + int i; + + i = idx / SFW_ID_PER_PAGE; - i = idx / (CFS_PAGE_SIZE / sizeof(lnet_process_id_t)); - LASSERT (i < nkiov); - pid = (lnet_process_id_t *)cfs_page_address(kiov[i].kiov_page); + pid = (lnet_process_id_packed_t *)page_address(kiov[i].kiov_page); - return &pid[idx % (CFS_PAGE_SIZE / sizeof(lnet_process_id_t))]; + return &pid[idx % SFW_ID_PER_PAGE]; } -int +static int lstcon_dstnodes_prep(lstcon_group_t *grp, int idx, int dist, int span, int nkiov, lnet_kiov_t *kiov) { - lnet_process_id_t *pid; - lstcon_ndlink_t *ndl; - lstcon_node_t *nd; - int start; - int end; - int i = 0; + lnet_process_id_packed_t *pid; + lstcon_ndlink_t *ndl; + lstcon_node_t *nd; + int start; + int end; + int i = 0; LASSERT (dist >= 1); LASSERT (span >= 1); @@ -707,62 +739,78 @@ lstcon_dstnodes_prep(lstcon_group_t *grp, int idx, 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 = nd->nd_id; - 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 = nd->nd_id; - i++; - } - - return 0; + 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; } -int +static int lstcon_pingrpc_prep(lst_test_ping_param_t *param, srpc_test_reqst_t *req) { test_ping_req_t *prq = &req->tsr_u.ping; - + prq->png_size = param->png_size; prq->png_flags = param->png_flags; /* TODO dest */ return 0; } -int -lstcon_bulkrpc_prep(lst_test_bulk_param_t *param, srpc_test_reqst_t *req) +static int +lstcon_bulkrpc_v0_prep(lst_test_bulk_param_t *param, srpc_test_reqst_t *req) { - test_bulk_req_t *brq = &req->tsr_u.bulk; + test_bulk_req_t *brq = &req->tsr_u.bulk_v0; - brq->blk_opc = param->blk_opc; - brq->blk_npg = param->blk_npg; - brq->blk_flags = param->blk_flags; + brq->blk_opc = param->blk_opc; + brq->blk_npg = (param->blk_size + PAGE_CACHE_SIZE - 1) / + PAGE_CACHE_SIZE; + brq->blk_flags = param->blk_flags; - return 0; + return 0; +} + +static int +lstcon_bulkrpc_v1_prep(lst_test_bulk_param_t *param, srpc_test_reqst_t *req) +{ + test_bulk_req_v1_t *brq = &req->tsr_u.bulk_v1; + + brq->blk_opc = param->blk_opc; + brq->blk_flags = param->blk_flags; + brq->blk_len = param->blk_size; + brq->blk_offset = 0; /* reserved */ + + return 0; } int -lstcon_testrpc_prep(lstcon_node_t *nd, int transop, +lstcon_testrpc_prep(lstcon_node_t *nd, int transop, unsigned feats, lstcon_test_t *test, lstcon_rpc_t **crpc) { lstcon_group_t *sgrp = test->tes_src_grp; @@ -770,14 +818,19 @@ lstcon_testrpc_prep(lstcon_node_t *nd, int transop, srpc_test_reqst_t *trq; srpc_bulk_t *bulk; int i; - int n = 0; - int rc = 0; - - if (transop == LST_TRANS_TSBCLIADD) - n = sfw_id_pages(test->tes_span); - - rc = lstcon_rpc_prep(nd, SRPC_SERVICE_TEST, n, crpc); - if (rc != 0) + int npg = 0; + int nob = 0; + int rc = 0; + + if (transop == LST_TRANS_TSBCLIADD) { + npg = sfw_id_pages(test->tes_span); + nob = (feats & LST_FEAT_BULK_LEN) == 0 ? + npg * PAGE_CACHE_SIZE : + sizeof(lnet_process_id_packed_t) * test->tes_span; + } + + rc = lstcon_rpc_prep(nd, SRPC_SERVICE_TEST, feats, npg, nob, crpc); + if (rc != 0) return rc; trq = &(*crpc)->crp_rpc->crpc_reqstmsg.msg_body.tes_reqst; @@ -793,16 +846,24 @@ lstcon_testrpc_prep(lstcon_node_t *nd, int transop, } else { bulk = &(*crpc)->crp_rpc->crpc_bulk; - for (i = 0; i < n; i++) { - bulk->bk_iovs[i].kiov_offset = 0; - bulk->bk_iovs[i].kiov_len = CFS_PAGE_SIZE; - bulk->bk_iovs[i].kiov_page = cfs_alloc_page(CFS_ALLOC_STD); + for (i = 0; i < npg; i++) { + int len; - if (bulk->bk_iovs[i].kiov_page != NULL) - continue; + LASSERT(nob > 0); - lstcon_rpc_put(*crpc); - return -ENOMEM; + len = (feats & LST_FEAT_BULK_LEN) == 0 ? + PAGE_CACHE_SIZE : min_t(int, nob, PAGE_CACHE_SIZE); + nob -= len; + + bulk->bk_iovs[i].kiov_offset = 0; + bulk->bk_iovs[i].kiov_len = len; + bulk->bk_iovs[i].kiov_page = + alloc_page(GFP_KERNEL); + + if (bulk->bk_iovs[i].kiov_page == NULL) { + lstcon_rpc_put(*crpc); + return -ENOMEM; + } } bulk->bk_sink = 0; @@ -810,8 +871,10 @@ lstcon_testrpc_prep(lstcon_node_t *nd, int transop, LASSERT (transop == LST_TRANS_TSBCLIADD); rc = lstcon_dstnodes_prep(test->tes_dst_grp, - test->tes_cliidx++, test->tes_dist, - test->tes_span, n, &bulk->bk_iovs[0]); + test->tes_cliidx++, + test->tes_dist, + test->tes_span, + npg, &bulk->bk_iovs[0]); if (rc != 0) { lstcon_rpc_put(*crpc); return rc; @@ -819,22 +882,31 @@ lstcon_testrpc_prep(lstcon_node_t *nd, int transop, 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; + 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((lst_test_ping_param_t *)&test->tes_param[0], trq); - break; - case LST_TEST_BULK: - trq->tsr_service = SRPC_SERVICE_BRW; - rc = lstcon_bulkrpc_prep((lst_test_bulk_param_t *)&test->tes_param[0], trq); + rc = lstcon_pingrpc_prep((lst_test_ping_param_t *) + &test->tes_param[0], trq); + break; + + case LST_TEST_BULK: + trq->tsr_service = SRPC_SERVICE_BRW; + if ((feats & LST_FEAT_BULK_LEN) == 0) { + rc = lstcon_bulkrpc_v0_prep((lst_test_bulk_param_t *) + &test->tes_param[0], trq); + } else { + rc = lstcon_bulkrpc_v1_prep((lst_test_bulk_param_t *) + &test->tes_param[0], trq); + } + break; default: LBUG(); @@ -844,34 +916,73 @@ lstcon_testrpc_prep(lstcon_node_t *nd, int transop, return rc; } +static int +lstcon_sesnew_stat_reply(lstcon_rpc_trans_t *trans, + lstcon_node_t *nd, srpc_msg_t *reply) +{ + srpc_mksn_reply_t *mksn_rep = &reply->msg_body.mksn_reply; + int status = mksn_rep->mksn_status; + + if (status == 0 && + (reply->msg_ses_feats & ~LST_FEATS_MASK) != 0) { + mksn_rep->mksn_status = EPROTO; + status = EPROTO; + } + + if (status == EPROTO) { + CNETERR("session protocol error from %s: %u\n", + libcfs_nid2str(nd->nd_id.nid), + reply->msg_ses_feats); + } + + if (status != 0) + return status; + + if (!trans->tas_feats_updated) { + 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); + status = mksn_rep->mksn_status = EPROTO; + } + + if (status == 0) { + /* session timeout on remote node */ + nd->nd_timeout = mksn_rep->mksn_timeout; + } + + return status; +} + void -lstcon_rpc_stat_reply(int transop, srpc_msg_t *msg, +lstcon_rpc_stat_reply(lstcon_rpc_trans_t *trans, srpc_msg_t *msg, lstcon_node_t *nd, lstcon_trans_stat_t *stat) { - srpc_mksn_reply_t *mksn_rep; srpc_rmsn_reply_t *rmsn_rep; srpc_debug_reply_t *dbg_rep; srpc_batch_reply_t *bat_rep; srpc_test_reply_t *test_rep; srpc_stat_reply_t *stat_rep; - int errno = 0; - - switch (transop) { - case LST_TRANS_SESNEW: - mksn_rep = &msg->msg_body.mksn_reply; + int rc = 0; - if (mksn_rep->mksn_status == 0) { + switch (trans->tas_opc) { + case LST_TRANS_SESNEW: + rc = lstcon_sesnew_stat_reply(trans, nd, msg); + if (rc == 0) { lstcon_sesop_stat_success(stat, 1); - /* session timeout on remote node */ - nd->nd_timeout = mksn_rep->mksn_timeout; return; } - LASSERT (mksn_rep->mksn_status == EBUSY || - mksn_rep->mksn_status == EINVAL); - lstcon_sesop_stat_failure(stat, 1); - errno = mksn_rep->mksn_status; break; case LST_TRANS_SESEND: @@ -883,11 +994,8 @@ lstcon_rpc_stat_reply(int transop, srpc_msg_t *msg, return; } - LASSERT (rmsn_rep->rmsn_status == EBUSY || - rmsn_rep->rmsn_status == EINVAL); - lstcon_sesop_stat_failure(stat, 1); - errno = rmsn_rep->rmsn_status; + rc = rmsn_rep->rmsn_status; break; case LST_TRANS_SESQRY: @@ -897,9 +1005,7 @@ lstcon_rpc_stat_reply(int transop, srpc_msg_t *msg, if (dbg_rep->dbg_status == ESRCH) { lstcon_sesqry_stat_unknown(stat, 1); return; - } - - LASSERT (dbg_rep->dbg_status == 0); + } if (lstcon_session_match(dbg_rep->dbg_sid)) lstcon_sesqry_stat_active(stat, 1); @@ -916,30 +1022,30 @@ lstcon_rpc_stat_reply(int transop, srpc_msg_t *msg, return; } - if (bat_rep->bar_status == EPERM && - transop == LST_TRANS_TSBSTOP) { + 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); - errno = bat_rep->bar_status; + 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 != 0) + if (bat_rep->bar_active != 0) lstcon_tsbqry_stat_run(stat, 1); else lstcon_tsbqry_stat_idle(stat, 1); - if (bat_rep->bar_status == 0) + if (bat_rep->bar_status == 0) return; lstcon_tsbqry_stat_failure(stat, 1); - errno = bat_rep->bar_status; + rc = bat_rep->bar_status; break; case LST_TRANS_TSBCLIADD: @@ -952,7 +1058,7 @@ lstcon_rpc_stat_reply(int transop, srpc_msg_t *msg, } lstcon_tsbop_stat_failure(stat, 1); - errno = test_rep->tsr_status; + rc = test_rep->tsr_status; break; case LST_TRANS_STATQRY: @@ -964,7 +1070,7 @@ lstcon_rpc_stat_reply(int transop, srpc_msg_t *msg, } lstcon_statqry_stat_failure(stat, 1); - errno = stat_rep->str_status; + rc = stat_rep->str_status; break; default: @@ -972,20 +1078,22 @@ lstcon_rpc_stat_reply(int transop, srpc_msg_t *msg, } if (stat->trs_fwk_errno == 0) - stat->trs_fwk_errno = errno; + stat->trs_fwk_errno = rc; return; } int lstcon_rpc_trans_ndlist(struct list_head *ndlist, - struct list_head *translist, int transop, void *arg, - lstcon_rpc_cond_func_t condition, lstcon_rpc_trans_t **transpp) + struct list_head *translist, int transop, + void *arg, lstcon_rpc_cond_func_t condition, + lstcon_rpc_trans_t **transpp) { lstcon_rpc_trans_t *trans; lstcon_ndlink_t *ndl; lstcon_node_t *nd; lstcon_rpc_t *rpc; + unsigned feats; int rc; /* Creating session RPG for list of nodes */ @@ -996,7 +1104,8 @@ lstcon_rpc_trans_ndlist(struct list_head *ndlist, return rc; } - list_for_each_entry(ndl, ndlist, ndl_link) { + feats = trans->tas_features; + list_for_each_entry(ndl, ndlist, ndl_link) { rc = condition == NULL ? 1 : condition(transop, ndl->ndl_node, arg); @@ -1014,26 +1123,26 @@ lstcon_rpc_trans_ndlist(struct list_head *ndlist, switch (transop) { case LST_TRANS_SESNEW: case LST_TRANS_SESEND: - rc = lstcon_sesrpc_prep(nd, transop, &rpc); - break; - case LST_TRANS_SESQRY: - case LST_TRANS_SESPING: - rc = lstcon_dbgrpc_prep(nd, &rpc); - break; - case LST_TRANS_TSBCLIADD: - case LST_TRANS_TSBSRVADD: - rc = lstcon_testrpc_prep(nd, transop, - (lstcon_test_t *)arg, &rpc); - break; - case LST_TRANS_TSBRUN: - case LST_TRANS_TSBSTOP: - case LST_TRANS_TSBCLIQRY: - case LST_TRANS_TSBSRVQRY: - rc = lstcon_batrpc_prep(nd, transop, - (lstcon_tsb_hdr_t *)arg, &rpc); - break; - case LST_TRANS_STATQRY: - rc = lstcon_statrpc_prep(nd, &rpc); + rc = lstcon_sesrpc_prep(nd, transop, feats, &rpc); + break; + case LST_TRANS_SESQRY: + case LST_TRANS_SESPING: + rc = lstcon_dbgrpc_prep(nd, feats, &rpc); + break; + case LST_TRANS_TSBCLIADD: + case LST_TRANS_TSBSRVADD: + rc = lstcon_testrpc_prep(nd, transop, feats, + (lstcon_test_t *)arg, &rpc); + break; + case LST_TRANS_TSBRUN: + case LST_TRANS_TSBSTOP: + case LST_TRANS_TSBCLIQRY: + case LST_TRANS_TSBSRVQRY: + rc = lstcon_batrpc_prep(nd, transop, feats, + (lstcon_tsb_hdr_t *)arg, &rpc); + break; + case LST_TRANS_STATQRY: + rc = lstcon_statrpc_prep(nd, feats, &rpc); break; default: rc = -EINVAL; @@ -1045,7 +1154,7 @@ lstcon_rpc_trans_ndlist(struct list_head *ndlist, lstcon_rpc_trans_name(transop), rc); break; } - + lstcon_rpc_trans_addreq(trans, rpc); } @@ -1059,7 +1168,7 @@ lstcon_rpc_trans_ndlist(struct list_head *ndlist, return rc; } -void +static void lstcon_rpc_pinger(void *arg) { stt_timer_t *ptimer = (stt_timer_t *)arg; @@ -1076,31 +1185,32 @@ lstcon_rpc_pinger(void *arg) /* RPC pinger is a special case of transaction, * it's called by timer at 8 seconds interval. */ - mutex_down(&console_session.ses_mutex); + mutex_lock(&console_session.ses_mutex); if (console_session.ses_shutdown || console_session.ses_expired) { - mutex_up(&console_session.ses_mutex); + mutex_unlock(&console_session.ses_mutex); return; } if (!console_session.ses_expired && cfs_time_current_sec() - console_session.ses_laststamp > - console_session.ses_timeout) + (time_t)console_session.ses_timeout) console_session.ses_expired = 1; - trans = console_session.ses_ping; + trans = console_session.ses_ping; - LASSERT (trans != NULL); + LASSERT(trans != NULL); - list_for_each_entry(ndl, &console_session.ses_ndl_list, ndl_link) { - nd = ndl->ndl_node; + 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, &crpc); + rc = lstcon_sesrpc_prep(nd, LST_TRANS_SESEND, + trans->tas_features, &crpc); if (rc != 0) { CERROR("Out of memory\n"); break; @@ -1114,38 +1224,39 @@ lstcon_rpc_pinger(void *arg) crpc = &nd->nd_ping; - if (crpc->crp_rpc != NULL) { - LASSERT (crpc->crp_trans == trans); - LASSERT (!list_empty(&crpc->crp_link)); + if (crpc->crp_rpc != NULL) { + LASSERT(crpc->crp_trans == trans); + LASSERT(!list_empty(&crpc->crp_link)); - spin_lock(&crpc->crp_rpc->crpc_lock); + spin_lock(&crpc->crp_rpc->crpc_lock); - LASSERT (crpc->crp_posted); + LASSERT(crpc->crp_posted); - if (!crpc->crp_finished) { - /* in flight */ - spin_unlock(&crpc->crp_rpc->crpc_lock); - continue; - } + if (!crpc->crp_finished) { + /* in flight */ + spin_unlock(&crpc->crp_rpc->crpc_lock); + continue; + } - spin_unlock(&crpc->crp_rpc->crpc_lock); + spin_unlock(&crpc->crp_rpc->crpc_lock); - lstcon_rpc_get_reply(crpc, &rep); + lstcon_rpc_get_reply(crpc, &rep); - list_del_init(&crpc->crp_link); - - lstcon_rpc_put(crpc); - } + list_del_init(&crpc->crp_link); + + lstcon_rpc_put(crpc); + } if (nd->nd_state != LST_NODE_ACTIVE) continue; intv = cfs_duration_sec(cfs_time_sub(cfs_time_current(), nd->nd_stamp)); - if (intv < nd->nd_timeout / 2) + if (intv < (time_t)nd->nd_timeout / 2) continue; - rc = lstcon_rpc_init(nd, SRPC_SERVICE_DEBUG, 0, 0, crpc); + rc = lstcon_rpc_init(nd, SRPC_SERVICE_DEBUG, + trans->tas_features, 0, 0, 1, crpc); if (rc != 0) { CERROR("Out of memory\n"); break; @@ -1159,31 +1270,30 @@ lstcon_rpc_pinger(void *arg) lstcon_rpc_trans_addreq(trans, crpc); lstcon_rpc_post(crpc); - count ++; + count++; } if (console_session.ses_expired) { - mutex_up(&console_session.ses_mutex); + mutex_unlock(&console_session.ses_mutex); return; } CDEBUG(D_NET, "Ping %d nodes in session\n", count); - ptimer->stt_expires = cfs_time_current_sec() + LST_PING_INTERVAL; + ptimer->stt_expires = (cfs_time_t)(cfs_time_current_sec() + LST_PING_INTERVAL); stt_add_timer(ptimer); - mutex_up(&console_session.ses_mutex); + mutex_unlock(&console_session.ses_mutex); } int lstcon_rpc_pinger_start(void) { - stt_timer_t *ptimer; - int rc; + stt_timer_t *ptimer; + int rc; - LASSERT (console_session.ses_rpc_pending == 0); - LASSERT (list_empty(&console_session.ses_rpc_list)); - LASSERT (list_empty(&console_session.ses_rpc_freelist)); + LASSERT(list_empty(&console_session.ses_rpc_freelist)); + LASSERT(atomic_read(&console_session.ses_rpc_counter) == 0); rc = lstcon_rpc_trans_prep(NULL, LST_TRANS_SESPING, &console_session.ses_ping); @@ -1193,7 +1303,7 @@ lstcon_rpc_pinger_start(void) } ptimer = &console_session.ses_ping_timer; - ptimer->stt_expires = cfs_time_current_sec() + LST_PING_INTERVAL; + ptimer->stt_expires = (cfs_time_t)(cfs_time_current_sec() + LST_PING_INTERVAL); stt_add_timer(ptimer); @@ -1219,75 +1329,77 @@ lstcon_rpc_pinger_stop(void) void lstcon_rpc_cleanup_wait(void) { - lstcon_rpc_trans_t *trans; - lstcon_rpc_t *crpc; - struct list_head *pacer; - struct list_head zlist; + lstcon_rpc_trans_t *trans; + lstcon_rpc_t *crpc; + struct list_head *pacer; + struct list_head zlist; - LASSERT (console_session.ses_shutdown); + /* Called with hold of global mutex */ - while (!list_empty(&console_session.ses_trans_list)) { - list_for_each(pacer, &console_session.ses_trans_list) { - trans = list_entry(pacer, lstcon_rpc_trans_t, tas_link); - cfs_waitq_signal(&trans->tas_waitq); + LASSERT(console_session.ses_shutdown); - CDEBUG(D_NET, "Session closed, wakeup transaction %s\n", - lstcon_rpc_trans_name(trans->tas_opc)); - } + while (!list_empty(&console_session.ses_trans_list)) { + list_for_each(pacer, &console_session.ses_trans_list) { + trans = list_entry(pacer, lstcon_rpc_trans_t, + tas_link); - mutex_up(&console_session.ses_mutex); + CDEBUG(D_NET, "Session closed, wakeup transaction %s\n", + lstcon_rpc_trans_name(trans->tas_opc)); - CWARN("Session is shutting down, close all transactions\n"); - cfs_pause(cfs_time_seconds(1)); + wake_up(&trans->tas_waitq); + } - mutex_down(&console_session.ses_mutex); - } + mutex_unlock(&console_session.ses_mutex); + + CWARN("Session is shutting down, " + "waiting for termination of transactions\n"); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(cfs_time_seconds(1)); + + mutex_lock(&console_session.ses_mutex); + } - spin_lock(&console_session.ses_rpc_lock); + spin_lock(&console_session.ses_rpc_lock); - lst_wait_until(list_empty(&console_session.ses_rpc_list), + lst_wait_until((atomic_read(&console_session.ses_rpc_counter) == 0), console_session.ses_rpc_lock, "Network is not accessable or target is down, " - "waiting for %d console rpcs to die\n", - console_session.ses_rpc_pending); + "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); + list_add(&zlist, &console_session.ses_rpc_freelist); + list_del_init(&console_session.ses_rpc_freelist); - spin_unlock(&console_session.ses_rpc_lock); + spin_unlock(&console_session.ses_rpc_lock); - LASSERT (console_session.ses_rpc_pending == 0); + while (!list_empty(&zlist)) { + crpc = list_entry(zlist.next, lstcon_rpc_t, crp_link); - while (!list_empty(&zlist)) { - crpc = list_entry(zlist.next, lstcon_rpc_t, crp_link); - - list_del(&crpc->crp_link); - LIBCFS_FREE(crpc, sizeof(lstcon_rpc_t)); - } + list_del(&crpc->crp_link); + LIBCFS_FREE(crpc, sizeof(lstcon_rpc_t)); + } } int lstcon_rpc_module_init(void) { - CFS_INIT_LIST_HEAD(&console_session.ses_ping_timer.stt_list); + 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; - console_session.ses_rpc_pending = 0; - spin_lock_init(&console_session.ses_rpc_lock); - CFS_INIT_LIST_HEAD(&console_session.ses_rpc_list); - CFS_INIT_LIST_HEAD(&console_session.ses_rpc_freelist); - return 0; + 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 (console_session.ses_rpc_pending == 0); - LASSERT (list_empty(&console_session.ses_rpc_list)); - LASSERT (list_empty(&console_session.ses_rpc_freelist)); + LASSERT(list_empty(&console_session.ses_rpc_freelist)); + LASSERT(atomic_read(&console_session.ses_rpc_counter) == 0); } -#endif