📄 console.c
字号:
/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- * vim:expandtab:shiftwidth=8:tabstop=8: * * Author: Liang Zhen <liangzhen@clusterfs.com> * * This file is part of Lustre, http://www.lustre.org * * Infrastructure of LST console */#ifdef __KERNEL__#include <libcfs/libcfs.h>#include <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)lstcon_session_t console_session;voidlstcon_node_get(lstcon_node_t *nd){ LASSERT (nd->nd_ref >= 1); nd->nd_ref++;}static intlstcon_node_find(lnet_process_id_t id, lstcon_node_t **ndpp, int create){ lstcon_ndlink_t *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; LIBCFS_ALLOC(*ndpp, sizeof(lstcon_node_t) + sizeof(lstcon_ndlink_t)); if (*ndpp == NULL) return -ENOMEM; ndl = (lstcon_ndlink_t *)(*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(lstcon_rpc_t)); /* 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;}voidlstcon_node_put(lstcon_node_t *nd){ lstcon_ndlink_t *ndl; LASSERT (nd->nd_ref > 0); if (--nd->nd_ref > 0) return; ndl = (lstcon_ndlink_t *)(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); LIBCFS_FREE(nd, sizeof(lstcon_node_t) + sizeof(lstcon_ndlink_t));}static intlstcon_ndlink_find(struct list_head *hash, lnet_process_id_t id, lstcon_ndlink_t **ndlpp, int create){ unsigned int idx = LNET_NIDADDR(id.nid) % LST_NODE_HASHSIZE; lstcon_ndlink_t *ndl; lstcon_node_t *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 == 0) return -ENOENT; /* find or create in session hash */ rc = lstcon_node_find(id, &nd, (create == 1) ? 1 : 0); if (rc != 0) return rc; LIBCFS_ALLOC(ndl, sizeof(lstcon_ndlink_t)); if (ndl == NULL) { lstcon_node_put(nd); return -ENOMEM; } *ndlpp = ndl; ndl->ndl_node = nd; CFS_INIT_LIST_HEAD(&ndl->ndl_link); list_add_tail(&ndl->ndl_hlink, &hash[idx]); return 0;}static voidlstcon_ndlink_release(lstcon_ndlink_t *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); LIBCFS_FREE(ndl, sizeof(*ndl));}static intlstcon_group_alloc(char *name, lstcon_group_t **grpp){ lstcon_group_t *grp; int i; LIBCFS_ALLOC(grp, offsetof(lstcon_group_t, grp_ndl_hash[LST_NODE_HASHSIZE])); if (grp == NULL) return -ENOMEM; memset(grp, 0, offsetof(lstcon_group_t, grp_ndl_hash[LST_NODE_HASHSIZE])); grp->grp_ref = 1; if (name != NULL) strcpy(grp->grp_name, name); CFS_INIT_LIST_HEAD(&grp->grp_link); CFS_INIT_LIST_HEAD(&grp->grp_ndl_list); CFS_INIT_LIST_HEAD(&grp->grp_trans_list); for (i = 0; i < LST_NODE_HASHSIZE; i++) CFS_INIT_LIST_HEAD(&grp->grp_ndl_hash[i]); *grpp = grp; return 0;}static voidlstcon_group_addref(lstcon_group_t *grp){ grp->grp_ref ++;}static void lstcon_group_ndlink_release(lstcon_group_t *, lstcon_ndlink_t *);static voidlstcon_group_drain(lstcon_group_t *grp, int keep){ lstcon_ndlink_t *ndl; lstcon_ndlink_t *tmp; list_for_each_entry_safe(ndl, tmp, &grp->grp_ndl_list, ndl_link) { if ((ndl->ndl_node->nd_state & keep) == 0) lstcon_group_ndlink_release(grp, ndl); }}static voidlstcon_group_decref(lstcon_group_t *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])); } LIBCFS_FREE(grp, offsetof(lstcon_group_t, grp_ndl_hash[LST_NODE_HASHSIZE]));}static intlstcon_group_find(char *name, lstcon_group_t **grpp){ lstcon_group_t *grp; list_for_each_entry(grp, &console_session.ses_grp_list, grp_link) { if (strncmp(grp->grp_name, name, LST_NAME_SIZE) != 0) continue; lstcon_group_addref(grp); /* +1 ref for caller */ *grpp = grp; return 0; } return -ENOENT;}static voidlstcon_group_put(lstcon_group_t *grp){ lstcon_group_decref(grp);}static intlstcon_group_ndlink_find(lstcon_group_t *grp, lnet_process_id_t id, lstcon_ndlink_t **ndlpp, int create){ int rc; rc = lstcon_ndlink_find(&grp->grp_ndl_hash[0], id, ndlpp, create); if (rc != 0) 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 voidlstcon_group_ndlink_release(lstcon_group_t *grp, lstcon_ndlink_t *ndl){ list_del_init(&ndl->ndl_link); lstcon_ndlink_release(ndl); grp->grp_nnode --;}static voidlstcon_group_ndlink_move(lstcon_group_t *old, lstcon_group_t *new, lstcon_ndlink_t *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 ++; return;}static voidlstcon_group_move(lstcon_group_t *old, lstcon_group_t *new){ lstcon_ndlink_t *ndl; while (!list_empty(&old->grp_ndl_list)) { ndl = list_entry(old->grp_ndl_list.next, lstcon_ndlink_t, ndl_link); lstcon_group_ndlink_move(old, new, ndl); }}intlstcon_sesrpc_condition(int transop, lstcon_node_t *nd, void *arg){ lstcon_group_t *grp = (lstcon_group_t *)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 != NULL && nd->nd_ref > 1) return 0; break; case LST_TRANS_SESQRY: break; default: LBUG(); } return 1;}intlstcon_sesrpc_readent(int transop, srpc_msg_t *msg, lstcon_rpc_ent_t *ent_up){ srpc_debug_reply_t *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 intlstcon_group_nodes_add(lstcon_group_t *grp, int count, lnet_process_id_t *ids_up, struct list_head *result_up){ lstcon_rpc_trans_t *trans; lstcon_ndlink_t *ndl; lstcon_group_t *tmp; lnet_process_id_t id; int i; int rc; rc = lstcon_group_alloc(NULL, &tmp); if (rc != 0) { 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 == 0) continue; /* add to tmp group */ rc = lstcon_group_ndlink_find(tmp, id, &ndl, 1); if (rc != 0) { CERROR("Can't create ndlink, out of memory\n"); break; } } if (rc != 0) { lstcon_group_put(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 != 0) { CERROR("Can't create transaction: %d\n", rc); lstcon_group_put(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); /* destroy all RPGs */ lstcon_rpc_trans_destroy(trans); lstcon_group_move(tmp, grp); lstcon_group_put(tmp); return rc;}static intlstcon_group_nodes_remove(lstcon_group_t *grp, int count, lnet_process_id_t *ids_up, struct list_head *result_up){ lstcon_rpc_trans_t *trans; lstcon_ndlink_t *ndl; lstcon_group_t *tmp; lnet_process_id_t id; int rc; int i; /* End session and remove node from the group */ rc = lstcon_group_alloc(NULL, &tmp); if (rc != 0) { 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) == 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 != 0) { 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_put(tmp); return rc;error: lstcon_group_move(tmp, grp); lstcon_group_put(tmp); return rc;}intlstcon_group_add(char *name){ lstcon_group_t *grp; int rc;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -