From 2aaec18ac09a7bbff62c5fe245dac20579c2df49 Mon Sep 17 00:00:00 2001 From: zab Date: Tue, 2 Mar 2004 01:34:28 +0000 Subject: [PATCH] - the start of moving things from portals.o to libcfs.o. the 2.4 kernel build still works though others probably don't. --- lnet/include/linux/libcfs.h | 217 +++++++++++++++ lnet/include/linux/list.h | 249 ++++++++++++++++++ lnet/lnet/module.c | 478 ++++++++++++++++++++++++++++++++++ lustre/portals/include/linux/libcfs.h | 217 +++++++++++++++ lustre/portals/include/linux/list.h | 249 ++++++++++++++++++ lustre/portals/portals/module.c | 478 ++++++++++++++++++++++++++++++++++ 6 files changed, 1888 insertions(+) create mode 100644 lnet/include/linux/libcfs.h create mode 100644 lnet/include/linux/list.h create mode 100644 lnet/lnet/module.c create mode 100644 lustre/portals/include/linux/libcfs.h create mode 100644 lustre/portals/include/linux/list.h create mode 100644 lustre/portals/portals/module.c diff --git a/lnet/include/linux/libcfs.h b/lnet/include/linux/libcfs.h new file mode 100644 index 0000000..6a1f071 --- /dev/null +++ b/lnet/include/linux/libcfs.h @@ -0,0 +1,217 @@ +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- + * vim:expandtab:shiftwidth=8:tabstop=8: + */ +#ifndef _LIBCFS_H + +#include + +#define PORTAL_DEBUG + +#ifndef offsetof +# define offsetof(typ,memb) ((int)((char *)&(((typ *)0)->memb))) +#endif + +#define LOWEST_BIT_SET(x) ((x) & ~((x) - 1)) + +/* + * Debugging + */ +extern unsigned int portal_subsystem_debug; +extern unsigned int portal_stack; +extern unsigned int portal_debug; +extern unsigned int portal_printk; +extern unsigned int portal_cerror; +/* Debugging subsystems (32 bits, non-overlapping) */ +#define S_UNDEFINED (1 << 0) +#define S_MDC (1 << 1) +#define S_MDS (1 << 2) +#define S_OSC (1 << 3) +#define S_OST (1 << 4) +#define S_CLASS (1 << 5) +#define S_LOG (1 << 6) +#define S_LLITE (1 << 7) +#define S_RPC (1 << 8) +#define S_MGMT (1 << 9) +#define S_PORTALS (1 << 10) +#define S_SOCKNAL (1 << 11) +#define S_QSWNAL (1 << 12) +#define S_PINGER (1 << 13) +#define S_FILTER (1 << 14) +#define S_PTLBD (1 << 15) +#define S_ECHO (1 << 16) +#define S_LDLM (1 << 17) +#define S_LOV (1 << 18) +#define S_GMNAL (1 << 19) +#define S_PTLROUTER (1 << 20) +#define S_COBD (1 << 21) +#define S_IBNAL (1 << 22) + +/* If you change these values, please keep portals/utils/debug.c + * up to date! */ + +/* Debugging masks (32 bits, non-overlapping) */ +#define D_TRACE (1 << 0) /* ENTRY/EXIT markers */ +#define D_INODE (1 << 1) +#define D_SUPER (1 << 2) +#define D_EXT2 (1 << 3) /* anything from ext2_debug */ +#define D_MALLOC (1 << 4) /* print malloc, free information */ +#define D_CACHE (1 << 5) /* cache-related items */ +#define D_INFO (1 << 6) /* general information */ +#define D_IOCTL (1 << 7) /* ioctl related information */ +#define D_BLOCKS (1 << 8) /* ext2 block allocation */ +#define D_NET (1 << 9) /* network communications */ +#define D_WARNING (1 << 10) /* CWARN(...) == CDEBUG (D_WARNING, ...) */ +#define D_BUFFS (1 << 11) +#define D_OTHER (1 << 12) +#define D_DENTRY (1 << 13) +#define D_PORTALS (1 << 14) /* ENTRY/EXIT markers */ +#define D_PAGE (1 << 15) /* bulk page handling */ +#define D_DLMTRACE (1 << 16) +#define D_ERROR (1 << 17) /* CERROR(...) == CDEBUG (D_ERROR, ...) */ +#define D_EMERG (1 << 18) /* CEMERG(...) == CDEBUG (D_EMERG, ...) */ +#define D_HA (1 << 19) /* recovery and failover */ +#define D_RPCTRACE (1 << 20) /* for distributed debugging */ +#define D_VFSTRACE (1 << 21) +#define D_READA (1 << 22) /* read-ahead */ + +#ifdef __KERNEL__ +# include /* THREAD_SIZE */ +#else +# ifndef THREAD_SIZE /* x86_64 has THREAD_SIZE in userspace */ +# define THREAD_SIZE 8192 +# endif +#endif + +#define LUSTRE_TRACE_SIZE (THREAD_SIZE >> 5) + +#ifdef __KERNEL__ +# ifdef __ia64__ +# define CDEBUG_STACK (THREAD_SIZE - \ + ((unsigned long)__builtin_dwarf_cfa() & \ + (THREAD_SIZE - 1))) +# else +# define CDEBUG_STACK (THREAD_SIZE - \ + ((unsigned long)__builtin_frame_address(0) & \ + (THREAD_SIZE - 1))) +# endif + +#define CHECK_STACK(stack) \ + do { \ + if ((stack) > 3*THREAD_SIZE/4 && (stack) > portal_stack) { \ + portals_debug_msg(DEBUG_SUBSYSTEM, D_WARNING, \ + __FILE__, __FUNCTION__, __LINE__, \ + (stack),"maximum lustre stack %u\n",\ + portal_stack = (stack)); \ + /*panic("LBUG");*/ \ + } \ + } while (0) +#else /* __KERNEL__ */ +#define CHECK_STACK(stack) do { } while(0) +#define CDEBUG_STACK (0L) +#endif /* __KERNEL__ */ + +#if 1 +#define CDEBUG(mask, format, a...) \ +do { \ + if (portal_cerror == 0) \ + break; \ + CHECK_STACK(CDEBUG_STACK); \ + if (((mask) & (D_ERROR | D_EMERG | D_WARNING)) || \ + (portal_debug & (mask) && \ + portal_subsystem_debug & DEBUG_SUBSYSTEM)) \ + portals_debug_msg(DEBUG_SUBSYSTEM, mask, \ + __FILE__, __FUNCTION__, __LINE__, \ + CDEBUG_STACK, format, ## a); \ +} while (0) + +#define CWARN(format, a...) CDEBUG(D_WARNING, format, ## a) +#define CERROR(format, a...) CDEBUG(D_ERROR, format, ## a) +#define CEMERG(format, a...) CDEBUG(D_EMERG, format, ## a) + +#define GOTO(label, rc) \ +do { \ + long GOTO__ret = (long)(rc); \ + CDEBUG(D_TRACE,"Process leaving via %s (rc=%lu : %ld : %lx)\n", \ + #label, (unsigned long)GOTO__ret, (signed long)GOTO__ret,\ + (signed long)GOTO__ret); \ + goto label; \ +} while (0) + +#define RETURN(rc) \ +do { \ + typeof(rc) RETURN__ret = (rc); \ + CDEBUG(D_TRACE, "Process leaving (rc=%lu : %ld : %lx)\n", \ + (long)RETURN__ret, (long)RETURN__ret, (long)RETURN__ret);\ + return RETURN__ret; \ +} while (0) + +#define ENTRY \ +do { \ + CDEBUG(D_TRACE, "Process entered\n"); \ +} while (0) + +#define EXIT \ +do { \ + CDEBUG(D_TRACE, "Process leaving\n"); \ +} while(0) +#else +#define CDEBUG(mask, format, a...) do { } while (0) +#define CWARN(format, a...) do { } while (0) +#define CERROR(format, a...) printk("<3>" format, ## a) +#define CEMERG(format, a...) printk("<0>" format, ## a) +#define GOTO(label, rc) do { (void)(rc); goto label; } while (0) +#define RETURN(rc) return (rc) +#define ENTRY do { } while (0) +#define EXIT do { } while (0) +#endif + +struct portal_ioctl_data { + __u32 ioc_len; + __u32 ioc_version; + __u64 ioc_nid; + __u64 ioc_nid2; + __u64 ioc_nid3; + __u32 ioc_count; + __u32 ioc_nal; + __u32 ioc_nal_cmd; + __u32 ioc_fd; + __u32 ioc_id; + + __u32 ioc_flags; + __u32 ioc_size; + + __u32 ioc_wait; + __u32 ioc_timeout; + __u32 ioc_misc; + + __u32 ioc_inllen1; + char *ioc_inlbuf1; + __u32 ioc_inllen2; + char *ioc_inlbuf2; + + __u32 ioc_plen1; /* buffers in userspace */ + char *ioc_pbuf1; + __u32 ioc_plen2; /* buffers in userspace */ + char *ioc_pbuf2; + + char ioc_bulk[0]; +}; + +struct libcfs_ioctl_handler { + struct list_head item; + int (*handle_ioctl)(struct portal_ioctl_data *data, + unsigned int cmd, unsigned long args); +}; + +#define DECLARE_IOCTL_HANDLER(ident, func) \ + struct libcfs_ioctl_handler ident = { \ + .item = LIST_HEAD_INIT(ident.item), \ + .handle_ioctl = func \ + } + +int libcfs_register_ioctl(struct libcfs_ioctl_handler *hand); +int libcfs_deregister_ioctl(struct libcfs_ioctl_handler *hand); + +#define _LIBCFS_H + +#endif /* _LIBCFS_H */ diff --git a/lnet/include/linux/list.h b/lnet/include/linux/list.h new file mode 100644 index 0000000..9cab047 --- /dev/null +++ b/lnet/include/linux/list.h @@ -0,0 +1,249 @@ +#ifndef _LINUX_LIST_H +/* + * Simple doubly linked list implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole lists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + */ + +#define prefetch(a) ((void)a) + +struct list_head { + struct list_head *next, *prev; +}; + +typedef struct list_head list_t; + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +#define INIT_LIST_HEAD(ptr) do { \ + (ptr)->next = (ptr); (ptr)->prev = (ptr); \ +} while (0) + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_add(struct list_head * new, + struct list_head * prev, + struct list_head * next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} + +/** + * list_add - add a new entry + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +static inline void list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} + +/** + * list_add_tail - add a new entry + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static inline void list_add_tail(struct list_head *new, struct list_head *head) +{ + __list_add(new, head->prev, head); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_del(struct list_head * prev, struct list_head * next) +{ + next->prev = prev; + prev->next = next; +} + +/** + * list_del - deletes entry from list. + * @entry: the element to delete from the list. + * Note: list_empty on entry does not return true after this, the entry is in an undefined state. + */ +static inline void list_del(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); +} + +/** + * list_del_init - deletes entry from list and reinitialize it. + * @entry: the element to delete from the list. + */ +static inline void list_del_init(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + INIT_LIST_HEAD(entry); +} +#endif + +#ifndef list_for_each_entry +/** + * list_move - delete from one list and add as another's head + * @list: the entry to move + * @head: the head that will precede our entry + */ +static inline void list_move(struct list_head *list, struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add(list, head); +} + +/** + * list_move_tail - delete from one list and add as another's tail + * @list: the entry to move + * @head: the head that will follow our entry + */ +static inline void list_move_tail(struct list_head *list, + struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add_tail(list, head); +} +#endif + +#ifndef _LINUX_LIST_H +#define _LINUX_LIST_H +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static inline int list_empty(struct list_head *head) +{ + return head->next == head; +} + +static inline void __list_splice(struct list_head *list, + struct list_head *head) +{ + struct list_head *first = list->next; + struct list_head *last = list->prev; + struct list_head *at = head->next; + + first->prev = head; + head->next = first; + + last->next = at; + at->prev = last; +} + +/** + * list_splice - join two lists + * @list: the new list to add. + * @head: the place to add it in the first list. + */ +static inline void list_splice(struct list_head *list, struct list_head *head) +{ + if (!list_empty(list)) + __list_splice(list, head); +} + +/** + * list_splice_init - join two lists and reinitialise the emptied list. + * @list: the new list to add. + * @head: the place to add it in the first list. + * + * The list at @list is reinitialised + */ +static inline void list_splice_init(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) { + __list_splice(list, head); + INIT_LIST_HEAD(list); + } +} + +/** + * list_entry - get the struct for this entry + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + */ +#define list_entry(ptr, type, member) \ + ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) + +/** + * list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + */ +#define list_for_each(pos, head) \ + for (pos = (head)->next, prefetch(pos->next); pos != (head); \ + pos = pos->next, prefetch(pos->next)) + +/** + * list_for_each_prev - iterate over a list in reverse order + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + */ +#define list_for_each_prev(pos, head) \ + for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \ + pos = pos->prev, prefetch(pos->prev)) + +/** + * list_for_each_safe - iterate over a list safe against removal of list entry + * @pos: the &struct list_head to use as a loop counter. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, n = pos->next) + +#endif + +#ifndef list_for_each_entry +/** + * list_for_each_entry - iterate over list of given type + * @pos: the type * to use as a loop counter. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry(pos, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + prefetch(pos->member.next); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member), \ + prefetch(pos->member.next)) +#endif + +#ifndef list_for_each_entry_safe +/** + * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @pos: the type * to use as a loop counter. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_safe(pos, n, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) +#endif diff --git a/lnet/lnet/module.c b/lnet/lnet/module.c new file mode 100644 index 0000000..7137efc --- /dev/null +++ b/lnet/lnet/module.c @@ -0,0 +1,478 @@ +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- + * vim:expandtab:shiftwidth=8:tabstop=8: + * + * Copyright (C) 2001, 2002 Cluster File Systems, Inc. + * + * This file is part of Lustre, http://www.lustre.org. + * + * Lustre is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * Lustre 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 for more details. + * + * You should have received a copy of the GNU General Public License + * along with Lustre; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef EXPORT_SYMTAB +# define EXPORT_SYMTAB +#endif +#define DEBUG_SUBSYSTEM S_PORTALS + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +extern void (kping_client)(struct portal_ioctl_data *); + +struct nal_cmd_handler { + nal_cmd_handler_t nch_handler; + void * nch_private; +}; + +static struct nal_cmd_handler nal_cmd[NAL_MAX_NR + 1]; +static DECLARE_MUTEX(nal_cmd_sem); + + +static int +kportal_add_route(int gateway_nalid, ptl_nid_t gateway_nid, + ptl_nid_t lo_nid, ptl_nid_t hi_nid) +{ + int rc; + kpr_control_interface_t *ci; + + ci = (kpr_control_interface_t *) PORTAL_SYMBOL_GET (kpr_control_interface); + if (ci == NULL) + return (-ENODEV); + + rc = ci->kprci_add_route (gateway_nalid, gateway_nid, lo_nid, hi_nid); + + PORTAL_SYMBOL_PUT(kpr_control_interface); + return (rc); +} + +static int +kportal_del_route(int gw_nalid, ptl_nid_t gw_nid, + ptl_nid_t lo, ptl_nid_t hi) +{ + int rc; + kpr_control_interface_t *ci; + + ci = (kpr_control_interface_t *)PORTAL_SYMBOL_GET(kpr_control_interface); + if (ci == NULL) + return (-ENODEV); + + rc = ci->kprci_del_route (gw_nalid, gw_nid, lo, hi); + + PORTAL_SYMBOL_PUT(kpr_control_interface); + return (rc); +} + +static int +kportal_notify_router (int gw_nalid, ptl_nid_t gw_nid, + int alive, time_t when) +{ + int rc; + kpr_control_interface_t *ci; + + /* No error if router not preset. Sysadmin is allowed to notify + * _everywhere_ when a NID boots or crashes, even if they know + * nothing of the peer. */ + ci = (kpr_control_interface_t *)PORTAL_SYMBOL_GET(kpr_control_interface); + if (ci == NULL) + return (0); + + rc = ci->kprci_notify (gw_nalid, gw_nid, alive, when); + + PORTAL_SYMBOL_PUT(kpr_control_interface); + return (rc); +} + +static int +kportal_get_route(int index, __u32 *gateway_nalidp, ptl_nid_t *gateway_nidp, + ptl_nid_t *lo_nidp, ptl_nid_t *hi_nidp, int *alivep) +{ + int gateway_nalid; + ptl_nid_t gateway_nid; + ptl_nid_t lo_nid; + ptl_nid_t hi_nid; + int alive; + int rc; + kpr_control_interface_t *ci; + + ci = (kpr_control_interface_t *) PORTAL_SYMBOL_GET(kpr_control_interface); + if (ci == NULL) + return (-ENODEV); + + rc = ci->kprci_get_route(index, &gateway_nalid, &gateway_nid, + &lo_nid, &hi_nid, &alive); + + if (rc == 0) { + CDEBUG(D_IOCTL, "got route [%d] %d "LPX64":"LPX64" - "LPX64", %s\n", + index, gateway_nalid, gateway_nid, lo_nid, hi_nid, + alive ? "up" : "down"); + + *gateway_nalidp = (__u32)gateway_nalid; + *gateway_nidp = gateway_nid; + *lo_nidp = lo_nid; + *hi_nidp = hi_nid; + *alivep = alive; + } + + PORTAL_SYMBOL_PUT (kpr_control_interface); + return (rc); +} + +static int +kportal_router_cmd(struct portals_cfg *pcfg, void * private) +{ + int err = -EINVAL; + ENTRY; + + switch(pcfg->pcfg_command) { + default: + CDEBUG(D_IOCTL, "Inappropriate cmd: %d\n", pcfg->pcfg_command); + break; + + case NAL_CMD_ADD_ROUTE: + CDEBUG(D_IOCTL, "Adding route: [%d] "LPU64" : "LPU64" - "LPU64"\n", + pcfg->pcfg_nal, pcfg->pcfg_nid, + pcfg->pcfg_nid2, pcfg->pcfg_nid3); + err = kportal_add_route(pcfg->pcfg_gw_nal, pcfg->pcfg_nid, + pcfg->pcfg_nid2, pcfg->pcfg_nid3); + break; + + case NAL_CMD_DEL_ROUTE: + CDEBUG (D_IOCTL, "Removing routes via [%d] "LPU64" : "LPU64" - "LPU64"\n", + pcfg->pcfg_gw_nal, pcfg->pcfg_nid, + pcfg->pcfg_nid2, pcfg->pcfg_nid3); + err = kportal_del_route (pcfg->pcfg_gw_nal, pcfg->pcfg_nid, + pcfg->pcfg_nid2, pcfg->pcfg_nid3); + break; + + case NAL_CMD_NOTIFY_ROUTER: { + CDEBUG (D_IOCTL, "Notifying peer [%d] "LPU64" %s @ %ld\n", + pcfg->pcfg_gw_nal, pcfg->pcfg_nid, + pcfg->pcfg_flags ? "Enabling" : "Disabling", + (time_t)pcfg->pcfg_nid3); + + err = kportal_notify_router (pcfg->pcfg_gw_nal, pcfg->pcfg_nid, + pcfg->pcfg_flags, + (time_t)pcfg->pcfg_nid3); + break; + } + + case NAL_CMD_GET_ROUTE: + CDEBUG (D_IOCTL, "Getting route [%d]\n", pcfg->pcfg_count); + err = kportal_get_route(pcfg->pcfg_count, &pcfg->pcfg_gw_nal, + &pcfg->pcfg_nid, + &pcfg->pcfg_nid2, &pcfg->pcfg_nid3, + &pcfg->pcfg_flags); + break; + } + RETURN(err); +} + +int +kportal_nal_cmd(struct portals_cfg *pcfg) +{ + __u32 nal = pcfg->pcfg_nal; + int rc = -EINVAL; + + ENTRY; + + down(&nal_cmd_sem); + if (nal > 0 && nal <= NAL_MAX_NR && nal_cmd[nal].nch_handler) { + CDEBUG(D_IOCTL, "calling handler nal: %d, cmd: %d\n", nal, + pcfg->pcfg_command); + rc = nal_cmd[nal].nch_handler(pcfg, nal_cmd[nal].nch_private); + } + up(&nal_cmd_sem); + RETURN(rc); +} + +ptl_handle_ni_t * +kportal_get_ni (int nal) +{ + + switch (nal) + { + case QSWNAL: + return (PORTAL_SYMBOL_GET(kqswnal_ni)); + case SOCKNAL: + return (PORTAL_SYMBOL_GET(ksocknal_ni)); + case GMNAL: + return (PORTAL_SYMBOL_GET(kgmnal_ni)); + case IBNAL: + return (PORTAL_SYMBOL_GET(kibnal_ni)); + case TCPNAL: + /* userspace NAL */ + return (NULL); + case SCIMACNAL: + return (PORTAL_SYMBOL_GET(kscimacnal_ni)); + default: + /* A warning to a naive caller */ + CERROR ("unknown nal: %d\n", nal); + return (NULL); + } +} + +void +kportal_put_ni (int nal) +{ + + switch (nal) + { + case QSWNAL: + PORTAL_SYMBOL_PUT(kqswnal_ni); + break; + case SOCKNAL: + PORTAL_SYMBOL_PUT(ksocknal_ni); + break; + case GMNAL: + PORTAL_SYMBOL_PUT(kgmnal_ni); + break; + case IBNAL: + PORTAL_SYMBOL_PUT(kibnal_ni); + break; + case TCPNAL: + /* A lesson to a malicious caller */ + LBUG (); + case SCIMACNAL: + PORTAL_SYMBOL_PUT(kscimacnal_ni); + break; + default: + CERROR ("unknown nal: %d\n", nal); + } +} + +int +kportal_nal_register(int nal, nal_cmd_handler_t handler, void * private) +{ + int rc = 0; + + CDEBUG(D_IOCTL, "Register NAL %d, handler: %p\n", nal, handler); + + if (nal > 0 && nal <= NAL_MAX_NR) { + down(&nal_cmd_sem); + if (nal_cmd[nal].nch_handler != NULL) + rc = -EBUSY; + else { + nal_cmd[nal].nch_handler = handler; + nal_cmd[nal].nch_private = private; + } + up(&nal_cmd_sem); + } + return rc; +} + +int +kportal_nal_unregister(int nal) +{ + int rc = 0; + + CDEBUG(D_IOCTL, "Unregister NAL %d\n", nal); + + if (nal > 0 && nal <= NAL_MAX_NR) { + down(&nal_cmd_sem); + nal_cmd[nal].nch_handler = NULL; + nal_cmd[nal].nch_private = NULL; + up(&nal_cmd_sem); + } + return rc; +} + +static int kportal_ioctl(struct portal_ioctl_data *data, + unsigned int cmd, unsigned long arg) +{ + int err = 0; + char str[PTL_NALFMT_SIZE]; + ENTRY; + + switch (cmd) { + case IOC_PORTAL_PING: { + void (*ping)(struct portal_ioctl_data *); + + CDEBUG(D_IOCTL, "doing %d pings to nid "LPX64" (%s)\n", + data->ioc_count, data->ioc_nid, + portals_nid2str(data->ioc_nal, data->ioc_nid, str)); + ping = PORTAL_SYMBOL_GET(kping_client); + if (!ping) + CERROR("PORTAL_SYMBOL_GET failed\n"); + else { + ping(data); + PORTAL_SYMBOL_PUT(kping_client); + } + RETURN(0); + } + + case IOC_PORTAL_GET_NID: { + const ptl_handle_ni_t *nip; + ptl_process_id_t pid; + + CDEBUG (D_IOCTL, "Getting nid for nal [%d]\n", data->ioc_nal); + + nip = kportal_get_ni (data->ioc_nal); + if (nip == NULL) + RETURN (-EINVAL); + + err = PtlGetId (*nip, &pid); + LASSERT (err == PTL_OK); + kportal_put_ni (data->ioc_nal); + + data->ioc_nid = pid.nid; + if (copy_to_user ((char *)arg, data, sizeof (*data))) + err = -EFAULT; + break; + } + + case IOC_PORTAL_NAL_CMD: { + struct portals_cfg pcfg; + + LASSERT (data->ioc_plen1 == sizeof(pcfg)); + err = copy_from_user(&pcfg, (void *)data->ioc_pbuf1, + sizeof(pcfg)); + if ( err ) { + EXIT; + return err; + } + + CDEBUG (D_IOCTL, "nal command nal %d cmd %d\n", pcfg.pcfg_nal, + pcfg.pcfg_command); + err = kportal_nal_cmd(&pcfg); + if (err == 0) { + if (copy_to_user((char *)data->ioc_pbuf1, &pcfg, + sizeof (pcfg))) + err = -EFAULT; + if (copy_to_user((char *)arg, data, sizeof (*data))) + err = -EFAULT; + } + break; + } + case IOC_PORTAL_FAIL_NID: { + const ptl_handle_ni_t *nip; + + CDEBUG (D_IOCTL, "fail nid: [%d] "LPU64" count %d\n", + data->ioc_nal, data->ioc_nid, data->ioc_count); + + nip = kportal_get_ni (data->ioc_nal); + if (nip == NULL) + return (-EINVAL); + + err = PtlFailNid (*nip, data->ioc_nid, data->ioc_count); + kportal_put_ni (data->ioc_nal); + break; + } + default: + err = -EINVAL; + break; + } + + RETURN(err); +} + +DECLARE_IOCTL_HANDLER(kportal_ioctl_handler, kportal_ioctl); + +static int init_kportals_module(void) +{ + int rc; + ENTRY; + + rc = PtlInit(); + if (rc) { + CERROR("PtlInit: error %d\n", rc); + RETURN(rc); + } + + rc = kportal_nal_register(ROUTER, kportal_router_cmd, NULL); + if (rc) { + PtlFini(); + CERROR("kportal_nal_registre: ROUTER error %d\n", rc); + } + + if (rc == 0) + libcfs_register_ioctl(&kportal_ioctl_handler); + + RETURN(rc); +} + +static void exit_kportals_module(void) +{ + libcfs_deregister_ioctl(&kportal_ioctl_handler); + kportal_nal_unregister(ROUTER); + PtlFini(); +} + +EXPORT_SYMBOL(kportal_nal_register); +EXPORT_SYMBOL(kportal_nal_unregister); +EXPORT_SYMBOL(kportal_get_ni); +EXPORT_SYMBOL(kportal_put_ni); +EXPORT_SYMBOL(kportal_nal_cmd); + +EXPORT_SYMBOL(ptl_err_str); +EXPORT_SYMBOL(lib_dispatch); +EXPORT_SYMBOL(PtlMEAttach); +EXPORT_SYMBOL(PtlMEInsert); +EXPORT_SYMBOL(PtlMEUnlink); +EXPORT_SYMBOL(PtlEQAlloc); +EXPORT_SYMBOL(PtlMDAttach); +EXPORT_SYMBOL(PtlMDUnlink); +EXPORT_SYMBOL(PtlNIInit); +EXPORT_SYMBOL(PtlNIFini); +EXPORT_SYMBOL(PtlNIDebug); +EXPORT_SYMBOL(PtlInit); +EXPORT_SYMBOL(PtlFini); +EXPORT_SYMBOL(PtlSnprintHandle); +EXPORT_SYMBOL(PtlPut); +EXPORT_SYMBOL(PtlGet); +EXPORT_SYMBOL(PtlEQWait); +EXPORT_SYMBOL(PtlEQFree); +EXPORT_SYMBOL(PtlEQGet); +EXPORT_SYMBOL(PtlGetId); +EXPORT_SYMBOL(PtlMDBind); +EXPORT_SYMBOL(lib_iov_nob); +EXPORT_SYMBOL(lib_copy_iov2buf); +EXPORT_SYMBOL(lib_copy_buf2iov); +EXPORT_SYMBOL(lib_extract_iov); +EXPORT_SYMBOL(lib_kiov_nob); +EXPORT_SYMBOL(lib_copy_kiov2buf); +EXPORT_SYMBOL(lib_copy_buf2kiov); +EXPORT_SYMBOL(lib_extract_kiov); +EXPORT_SYMBOL(lib_finalize); +EXPORT_SYMBOL(lib_parse); +EXPORT_SYMBOL(lib_create_reply_msg); +EXPORT_SYMBOL(lib_init); +EXPORT_SYMBOL(lib_fini); +EXPORT_SYMBOL(dispatch_name); + +MODULE_AUTHOR("Peter J. Braam "); +MODULE_DESCRIPTION("Portals v3.1"); +MODULE_LICENSE("GPL"); +module_init(init_kportals_module); +module_exit(exit_kportals_module); diff --git a/lustre/portals/include/linux/libcfs.h b/lustre/portals/include/linux/libcfs.h new file mode 100644 index 0000000..6a1f071 --- /dev/null +++ b/lustre/portals/include/linux/libcfs.h @@ -0,0 +1,217 @@ +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- + * vim:expandtab:shiftwidth=8:tabstop=8: + */ +#ifndef _LIBCFS_H + +#include + +#define PORTAL_DEBUG + +#ifndef offsetof +# define offsetof(typ,memb) ((int)((char *)&(((typ *)0)->memb))) +#endif + +#define LOWEST_BIT_SET(x) ((x) & ~((x) - 1)) + +/* + * Debugging + */ +extern unsigned int portal_subsystem_debug; +extern unsigned int portal_stack; +extern unsigned int portal_debug; +extern unsigned int portal_printk; +extern unsigned int portal_cerror; +/* Debugging subsystems (32 bits, non-overlapping) */ +#define S_UNDEFINED (1 << 0) +#define S_MDC (1 << 1) +#define S_MDS (1 << 2) +#define S_OSC (1 << 3) +#define S_OST (1 << 4) +#define S_CLASS (1 << 5) +#define S_LOG (1 << 6) +#define S_LLITE (1 << 7) +#define S_RPC (1 << 8) +#define S_MGMT (1 << 9) +#define S_PORTALS (1 << 10) +#define S_SOCKNAL (1 << 11) +#define S_QSWNAL (1 << 12) +#define S_PINGER (1 << 13) +#define S_FILTER (1 << 14) +#define S_PTLBD (1 << 15) +#define S_ECHO (1 << 16) +#define S_LDLM (1 << 17) +#define S_LOV (1 << 18) +#define S_GMNAL (1 << 19) +#define S_PTLROUTER (1 << 20) +#define S_COBD (1 << 21) +#define S_IBNAL (1 << 22) + +/* If you change these values, please keep portals/utils/debug.c + * up to date! */ + +/* Debugging masks (32 bits, non-overlapping) */ +#define D_TRACE (1 << 0) /* ENTRY/EXIT markers */ +#define D_INODE (1 << 1) +#define D_SUPER (1 << 2) +#define D_EXT2 (1 << 3) /* anything from ext2_debug */ +#define D_MALLOC (1 << 4) /* print malloc, free information */ +#define D_CACHE (1 << 5) /* cache-related items */ +#define D_INFO (1 << 6) /* general information */ +#define D_IOCTL (1 << 7) /* ioctl related information */ +#define D_BLOCKS (1 << 8) /* ext2 block allocation */ +#define D_NET (1 << 9) /* network communications */ +#define D_WARNING (1 << 10) /* CWARN(...) == CDEBUG (D_WARNING, ...) */ +#define D_BUFFS (1 << 11) +#define D_OTHER (1 << 12) +#define D_DENTRY (1 << 13) +#define D_PORTALS (1 << 14) /* ENTRY/EXIT markers */ +#define D_PAGE (1 << 15) /* bulk page handling */ +#define D_DLMTRACE (1 << 16) +#define D_ERROR (1 << 17) /* CERROR(...) == CDEBUG (D_ERROR, ...) */ +#define D_EMERG (1 << 18) /* CEMERG(...) == CDEBUG (D_EMERG, ...) */ +#define D_HA (1 << 19) /* recovery and failover */ +#define D_RPCTRACE (1 << 20) /* for distributed debugging */ +#define D_VFSTRACE (1 << 21) +#define D_READA (1 << 22) /* read-ahead */ + +#ifdef __KERNEL__ +# include /* THREAD_SIZE */ +#else +# ifndef THREAD_SIZE /* x86_64 has THREAD_SIZE in userspace */ +# define THREAD_SIZE 8192 +# endif +#endif + +#define LUSTRE_TRACE_SIZE (THREAD_SIZE >> 5) + +#ifdef __KERNEL__ +# ifdef __ia64__ +# define CDEBUG_STACK (THREAD_SIZE - \ + ((unsigned long)__builtin_dwarf_cfa() & \ + (THREAD_SIZE - 1))) +# else +# define CDEBUG_STACK (THREAD_SIZE - \ + ((unsigned long)__builtin_frame_address(0) & \ + (THREAD_SIZE - 1))) +# endif + +#define CHECK_STACK(stack) \ + do { \ + if ((stack) > 3*THREAD_SIZE/4 && (stack) > portal_stack) { \ + portals_debug_msg(DEBUG_SUBSYSTEM, D_WARNING, \ + __FILE__, __FUNCTION__, __LINE__, \ + (stack),"maximum lustre stack %u\n",\ + portal_stack = (stack)); \ + /*panic("LBUG");*/ \ + } \ + } while (0) +#else /* __KERNEL__ */ +#define CHECK_STACK(stack) do { } while(0) +#define CDEBUG_STACK (0L) +#endif /* __KERNEL__ */ + +#if 1 +#define CDEBUG(mask, format, a...) \ +do { \ + if (portal_cerror == 0) \ + break; \ + CHECK_STACK(CDEBUG_STACK); \ + if (((mask) & (D_ERROR | D_EMERG | D_WARNING)) || \ + (portal_debug & (mask) && \ + portal_subsystem_debug & DEBUG_SUBSYSTEM)) \ + portals_debug_msg(DEBUG_SUBSYSTEM, mask, \ + __FILE__, __FUNCTION__, __LINE__, \ + CDEBUG_STACK, format, ## a); \ +} while (0) + +#define CWARN(format, a...) CDEBUG(D_WARNING, format, ## a) +#define CERROR(format, a...) CDEBUG(D_ERROR, format, ## a) +#define CEMERG(format, a...) CDEBUG(D_EMERG, format, ## a) + +#define GOTO(label, rc) \ +do { \ + long GOTO__ret = (long)(rc); \ + CDEBUG(D_TRACE,"Process leaving via %s (rc=%lu : %ld : %lx)\n", \ + #label, (unsigned long)GOTO__ret, (signed long)GOTO__ret,\ + (signed long)GOTO__ret); \ + goto label; \ +} while (0) + +#define RETURN(rc) \ +do { \ + typeof(rc) RETURN__ret = (rc); \ + CDEBUG(D_TRACE, "Process leaving (rc=%lu : %ld : %lx)\n", \ + (long)RETURN__ret, (long)RETURN__ret, (long)RETURN__ret);\ + return RETURN__ret; \ +} while (0) + +#define ENTRY \ +do { \ + CDEBUG(D_TRACE, "Process entered\n"); \ +} while (0) + +#define EXIT \ +do { \ + CDEBUG(D_TRACE, "Process leaving\n"); \ +} while(0) +#else +#define CDEBUG(mask, format, a...) do { } while (0) +#define CWARN(format, a...) do { } while (0) +#define CERROR(format, a...) printk("<3>" format, ## a) +#define CEMERG(format, a...) printk("<0>" format, ## a) +#define GOTO(label, rc) do { (void)(rc); goto label; } while (0) +#define RETURN(rc) return (rc) +#define ENTRY do { } while (0) +#define EXIT do { } while (0) +#endif + +struct portal_ioctl_data { + __u32 ioc_len; + __u32 ioc_version; + __u64 ioc_nid; + __u64 ioc_nid2; + __u64 ioc_nid3; + __u32 ioc_count; + __u32 ioc_nal; + __u32 ioc_nal_cmd; + __u32 ioc_fd; + __u32 ioc_id; + + __u32 ioc_flags; + __u32 ioc_size; + + __u32 ioc_wait; + __u32 ioc_timeout; + __u32 ioc_misc; + + __u32 ioc_inllen1; + char *ioc_inlbuf1; + __u32 ioc_inllen2; + char *ioc_inlbuf2; + + __u32 ioc_plen1; /* buffers in userspace */ + char *ioc_pbuf1; + __u32 ioc_plen2; /* buffers in userspace */ + char *ioc_pbuf2; + + char ioc_bulk[0]; +}; + +struct libcfs_ioctl_handler { + struct list_head item; + int (*handle_ioctl)(struct portal_ioctl_data *data, + unsigned int cmd, unsigned long args); +}; + +#define DECLARE_IOCTL_HANDLER(ident, func) \ + struct libcfs_ioctl_handler ident = { \ + .item = LIST_HEAD_INIT(ident.item), \ + .handle_ioctl = func \ + } + +int libcfs_register_ioctl(struct libcfs_ioctl_handler *hand); +int libcfs_deregister_ioctl(struct libcfs_ioctl_handler *hand); + +#define _LIBCFS_H + +#endif /* _LIBCFS_H */ diff --git a/lustre/portals/include/linux/list.h b/lustre/portals/include/linux/list.h new file mode 100644 index 0000000..9cab047 --- /dev/null +++ b/lustre/portals/include/linux/list.h @@ -0,0 +1,249 @@ +#ifndef _LINUX_LIST_H +/* + * Simple doubly linked list implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole lists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + */ + +#define prefetch(a) ((void)a) + +struct list_head { + struct list_head *next, *prev; +}; + +typedef struct list_head list_t; + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +#define INIT_LIST_HEAD(ptr) do { \ + (ptr)->next = (ptr); (ptr)->prev = (ptr); \ +} while (0) + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_add(struct list_head * new, + struct list_head * prev, + struct list_head * next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} + +/** + * list_add - add a new entry + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +static inline void list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} + +/** + * list_add_tail - add a new entry + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static inline void list_add_tail(struct list_head *new, struct list_head *head) +{ + __list_add(new, head->prev, head); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_del(struct list_head * prev, struct list_head * next) +{ + next->prev = prev; + prev->next = next; +} + +/** + * list_del - deletes entry from list. + * @entry: the element to delete from the list. + * Note: list_empty on entry does not return true after this, the entry is in an undefined state. + */ +static inline void list_del(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); +} + +/** + * list_del_init - deletes entry from list and reinitialize it. + * @entry: the element to delete from the list. + */ +static inline void list_del_init(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + INIT_LIST_HEAD(entry); +} +#endif + +#ifndef list_for_each_entry +/** + * list_move - delete from one list and add as another's head + * @list: the entry to move + * @head: the head that will precede our entry + */ +static inline void list_move(struct list_head *list, struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add(list, head); +} + +/** + * list_move_tail - delete from one list and add as another's tail + * @list: the entry to move + * @head: the head that will follow our entry + */ +static inline void list_move_tail(struct list_head *list, + struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add_tail(list, head); +} +#endif + +#ifndef _LINUX_LIST_H +#define _LINUX_LIST_H +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static inline int list_empty(struct list_head *head) +{ + return head->next == head; +} + +static inline void __list_splice(struct list_head *list, + struct list_head *head) +{ + struct list_head *first = list->next; + struct list_head *last = list->prev; + struct list_head *at = head->next; + + first->prev = head; + head->next = first; + + last->next = at; + at->prev = last; +} + +/** + * list_splice - join two lists + * @list: the new list to add. + * @head: the place to add it in the first list. + */ +static inline void list_splice(struct list_head *list, struct list_head *head) +{ + if (!list_empty(list)) + __list_splice(list, head); +} + +/** + * list_splice_init - join two lists and reinitialise the emptied list. + * @list: the new list to add. + * @head: the place to add it in the first list. + * + * The list at @list is reinitialised + */ +static inline void list_splice_init(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) { + __list_splice(list, head); + INIT_LIST_HEAD(list); + } +} + +/** + * list_entry - get the struct for this entry + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + */ +#define list_entry(ptr, type, member) \ + ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) + +/** + * list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + */ +#define list_for_each(pos, head) \ + for (pos = (head)->next, prefetch(pos->next); pos != (head); \ + pos = pos->next, prefetch(pos->next)) + +/** + * list_for_each_prev - iterate over a list in reverse order + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + */ +#define list_for_each_prev(pos, head) \ + for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \ + pos = pos->prev, prefetch(pos->prev)) + +/** + * list_for_each_safe - iterate over a list safe against removal of list entry + * @pos: the &struct list_head to use as a loop counter. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, n = pos->next) + +#endif + +#ifndef list_for_each_entry +/** + * list_for_each_entry - iterate over list of given type + * @pos: the type * to use as a loop counter. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry(pos, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + prefetch(pos->member.next); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member), \ + prefetch(pos->member.next)) +#endif + +#ifndef list_for_each_entry_safe +/** + * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @pos: the type * to use as a loop counter. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_safe(pos, n, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) +#endif diff --git a/lustre/portals/portals/module.c b/lustre/portals/portals/module.c new file mode 100644 index 0000000..7137efc --- /dev/null +++ b/lustre/portals/portals/module.c @@ -0,0 +1,478 @@ +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- + * vim:expandtab:shiftwidth=8:tabstop=8: + * + * Copyright (C) 2001, 2002 Cluster File Systems, Inc. + * + * This file is part of Lustre, http://www.lustre.org. + * + * Lustre is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * Lustre 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 for more details. + * + * You should have received a copy of the GNU General Public License + * along with Lustre; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef EXPORT_SYMTAB +# define EXPORT_SYMTAB +#endif +#define DEBUG_SUBSYSTEM S_PORTALS + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +extern void (kping_client)(struct portal_ioctl_data *); + +struct nal_cmd_handler { + nal_cmd_handler_t nch_handler; + void * nch_private; +}; + +static struct nal_cmd_handler nal_cmd[NAL_MAX_NR + 1]; +static DECLARE_MUTEX(nal_cmd_sem); + + +static int +kportal_add_route(int gateway_nalid, ptl_nid_t gateway_nid, + ptl_nid_t lo_nid, ptl_nid_t hi_nid) +{ + int rc; + kpr_control_interface_t *ci; + + ci = (kpr_control_interface_t *) PORTAL_SYMBOL_GET (kpr_control_interface); + if (ci == NULL) + return (-ENODEV); + + rc = ci->kprci_add_route (gateway_nalid, gateway_nid, lo_nid, hi_nid); + + PORTAL_SYMBOL_PUT(kpr_control_interface); + return (rc); +} + +static int +kportal_del_route(int gw_nalid, ptl_nid_t gw_nid, + ptl_nid_t lo, ptl_nid_t hi) +{ + int rc; + kpr_control_interface_t *ci; + + ci = (kpr_control_interface_t *)PORTAL_SYMBOL_GET(kpr_control_interface); + if (ci == NULL) + return (-ENODEV); + + rc = ci->kprci_del_route (gw_nalid, gw_nid, lo, hi); + + PORTAL_SYMBOL_PUT(kpr_control_interface); + return (rc); +} + +static int +kportal_notify_router (int gw_nalid, ptl_nid_t gw_nid, + int alive, time_t when) +{ + int rc; + kpr_control_interface_t *ci; + + /* No error if router not preset. Sysadmin is allowed to notify + * _everywhere_ when a NID boots or crashes, even if they know + * nothing of the peer. */ + ci = (kpr_control_interface_t *)PORTAL_SYMBOL_GET(kpr_control_interface); + if (ci == NULL) + return (0); + + rc = ci->kprci_notify (gw_nalid, gw_nid, alive, when); + + PORTAL_SYMBOL_PUT(kpr_control_interface); + return (rc); +} + +static int +kportal_get_route(int index, __u32 *gateway_nalidp, ptl_nid_t *gateway_nidp, + ptl_nid_t *lo_nidp, ptl_nid_t *hi_nidp, int *alivep) +{ + int gateway_nalid; + ptl_nid_t gateway_nid; + ptl_nid_t lo_nid; + ptl_nid_t hi_nid; + int alive; + int rc; + kpr_control_interface_t *ci; + + ci = (kpr_control_interface_t *) PORTAL_SYMBOL_GET(kpr_control_interface); + if (ci == NULL) + return (-ENODEV); + + rc = ci->kprci_get_route(index, &gateway_nalid, &gateway_nid, + &lo_nid, &hi_nid, &alive); + + if (rc == 0) { + CDEBUG(D_IOCTL, "got route [%d] %d "LPX64":"LPX64" - "LPX64", %s\n", + index, gateway_nalid, gateway_nid, lo_nid, hi_nid, + alive ? "up" : "down"); + + *gateway_nalidp = (__u32)gateway_nalid; + *gateway_nidp = gateway_nid; + *lo_nidp = lo_nid; + *hi_nidp = hi_nid; + *alivep = alive; + } + + PORTAL_SYMBOL_PUT (kpr_control_interface); + return (rc); +} + +static int +kportal_router_cmd(struct portals_cfg *pcfg, void * private) +{ + int err = -EINVAL; + ENTRY; + + switch(pcfg->pcfg_command) { + default: + CDEBUG(D_IOCTL, "Inappropriate cmd: %d\n", pcfg->pcfg_command); + break; + + case NAL_CMD_ADD_ROUTE: + CDEBUG(D_IOCTL, "Adding route: [%d] "LPU64" : "LPU64" - "LPU64"\n", + pcfg->pcfg_nal, pcfg->pcfg_nid, + pcfg->pcfg_nid2, pcfg->pcfg_nid3); + err = kportal_add_route(pcfg->pcfg_gw_nal, pcfg->pcfg_nid, + pcfg->pcfg_nid2, pcfg->pcfg_nid3); + break; + + case NAL_CMD_DEL_ROUTE: + CDEBUG (D_IOCTL, "Removing routes via [%d] "LPU64" : "LPU64" - "LPU64"\n", + pcfg->pcfg_gw_nal, pcfg->pcfg_nid, + pcfg->pcfg_nid2, pcfg->pcfg_nid3); + err = kportal_del_route (pcfg->pcfg_gw_nal, pcfg->pcfg_nid, + pcfg->pcfg_nid2, pcfg->pcfg_nid3); + break; + + case NAL_CMD_NOTIFY_ROUTER: { + CDEBUG (D_IOCTL, "Notifying peer [%d] "LPU64" %s @ %ld\n", + pcfg->pcfg_gw_nal, pcfg->pcfg_nid, + pcfg->pcfg_flags ? "Enabling" : "Disabling", + (time_t)pcfg->pcfg_nid3); + + err = kportal_notify_router (pcfg->pcfg_gw_nal, pcfg->pcfg_nid, + pcfg->pcfg_flags, + (time_t)pcfg->pcfg_nid3); + break; + } + + case NAL_CMD_GET_ROUTE: + CDEBUG (D_IOCTL, "Getting route [%d]\n", pcfg->pcfg_count); + err = kportal_get_route(pcfg->pcfg_count, &pcfg->pcfg_gw_nal, + &pcfg->pcfg_nid, + &pcfg->pcfg_nid2, &pcfg->pcfg_nid3, + &pcfg->pcfg_flags); + break; + } + RETURN(err); +} + +int +kportal_nal_cmd(struct portals_cfg *pcfg) +{ + __u32 nal = pcfg->pcfg_nal; + int rc = -EINVAL; + + ENTRY; + + down(&nal_cmd_sem); + if (nal > 0 && nal <= NAL_MAX_NR && nal_cmd[nal].nch_handler) { + CDEBUG(D_IOCTL, "calling handler nal: %d, cmd: %d\n", nal, + pcfg->pcfg_command); + rc = nal_cmd[nal].nch_handler(pcfg, nal_cmd[nal].nch_private); + } + up(&nal_cmd_sem); + RETURN(rc); +} + +ptl_handle_ni_t * +kportal_get_ni (int nal) +{ + + switch (nal) + { + case QSWNAL: + return (PORTAL_SYMBOL_GET(kqswnal_ni)); + case SOCKNAL: + return (PORTAL_SYMBOL_GET(ksocknal_ni)); + case GMNAL: + return (PORTAL_SYMBOL_GET(kgmnal_ni)); + case IBNAL: + return (PORTAL_SYMBOL_GET(kibnal_ni)); + case TCPNAL: + /* userspace NAL */ + return (NULL); + case SCIMACNAL: + return (PORTAL_SYMBOL_GET(kscimacnal_ni)); + default: + /* A warning to a naive caller */ + CERROR ("unknown nal: %d\n", nal); + return (NULL); + } +} + +void +kportal_put_ni (int nal) +{ + + switch (nal) + { + case QSWNAL: + PORTAL_SYMBOL_PUT(kqswnal_ni); + break; + case SOCKNAL: + PORTAL_SYMBOL_PUT(ksocknal_ni); + break; + case GMNAL: + PORTAL_SYMBOL_PUT(kgmnal_ni); + break; + case IBNAL: + PORTAL_SYMBOL_PUT(kibnal_ni); + break; + case TCPNAL: + /* A lesson to a malicious caller */ + LBUG (); + case SCIMACNAL: + PORTAL_SYMBOL_PUT(kscimacnal_ni); + break; + default: + CERROR ("unknown nal: %d\n", nal); + } +} + +int +kportal_nal_register(int nal, nal_cmd_handler_t handler, void * private) +{ + int rc = 0; + + CDEBUG(D_IOCTL, "Register NAL %d, handler: %p\n", nal, handler); + + if (nal > 0 && nal <= NAL_MAX_NR) { + down(&nal_cmd_sem); + if (nal_cmd[nal].nch_handler != NULL) + rc = -EBUSY; + else { + nal_cmd[nal].nch_handler = handler; + nal_cmd[nal].nch_private = private; + } + up(&nal_cmd_sem); + } + return rc; +} + +int +kportal_nal_unregister(int nal) +{ + int rc = 0; + + CDEBUG(D_IOCTL, "Unregister NAL %d\n", nal); + + if (nal > 0 && nal <= NAL_MAX_NR) { + down(&nal_cmd_sem); + nal_cmd[nal].nch_handler = NULL; + nal_cmd[nal].nch_private = NULL; + up(&nal_cmd_sem); + } + return rc; +} + +static int kportal_ioctl(struct portal_ioctl_data *data, + unsigned int cmd, unsigned long arg) +{ + int err = 0; + char str[PTL_NALFMT_SIZE]; + ENTRY; + + switch (cmd) { + case IOC_PORTAL_PING: { + void (*ping)(struct portal_ioctl_data *); + + CDEBUG(D_IOCTL, "doing %d pings to nid "LPX64" (%s)\n", + data->ioc_count, data->ioc_nid, + portals_nid2str(data->ioc_nal, data->ioc_nid, str)); + ping = PORTAL_SYMBOL_GET(kping_client); + if (!ping) + CERROR("PORTAL_SYMBOL_GET failed\n"); + else { + ping(data); + PORTAL_SYMBOL_PUT(kping_client); + } + RETURN(0); + } + + case IOC_PORTAL_GET_NID: { + const ptl_handle_ni_t *nip; + ptl_process_id_t pid; + + CDEBUG (D_IOCTL, "Getting nid for nal [%d]\n", data->ioc_nal); + + nip = kportal_get_ni (data->ioc_nal); + if (nip == NULL) + RETURN (-EINVAL); + + err = PtlGetId (*nip, &pid); + LASSERT (err == PTL_OK); + kportal_put_ni (data->ioc_nal); + + data->ioc_nid = pid.nid; + if (copy_to_user ((char *)arg, data, sizeof (*data))) + err = -EFAULT; + break; + } + + case IOC_PORTAL_NAL_CMD: { + struct portals_cfg pcfg; + + LASSERT (data->ioc_plen1 == sizeof(pcfg)); + err = copy_from_user(&pcfg, (void *)data->ioc_pbuf1, + sizeof(pcfg)); + if ( err ) { + EXIT; + return err; + } + + CDEBUG (D_IOCTL, "nal command nal %d cmd %d\n", pcfg.pcfg_nal, + pcfg.pcfg_command); + err = kportal_nal_cmd(&pcfg); + if (err == 0) { + if (copy_to_user((char *)data->ioc_pbuf1, &pcfg, + sizeof (pcfg))) + err = -EFAULT; + if (copy_to_user((char *)arg, data, sizeof (*data))) + err = -EFAULT; + } + break; + } + case IOC_PORTAL_FAIL_NID: { + const ptl_handle_ni_t *nip; + + CDEBUG (D_IOCTL, "fail nid: [%d] "LPU64" count %d\n", + data->ioc_nal, data->ioc_nid, data->ioc_count); + + nip = kportal_get_ni (data->ioc_nal); + if (nip == NULL) + return (-EINVAL); + + err = PtlFailNid (*nip, data->ioc_nid, data->ioc_count); + kportal_put_ni (data->ioc_nal); + break; + } + default: + err = -EINVAL; + break; + } + + RETURN(err); +} + +DECLARE_IOCTL_HANDLER(kportal_ioctl_handler, kportal_ioctl); + +static int init_kportals_module(void) +{ + int rc; + ENTRY; + + rc = PtlInit(); + if (rc) { + CERROR("PtlInit: error %d\n", rc); + RETURN(rc); + } + + rc = kportal_nal_register(ROUTER, kportal_router_cmd, NULL); + if (rc) { + PtlFini(); + CERROR("kportal_nal_registre: ROUTER error %d\n", rc); + } + + if (rc == 0) + libcfs_register_ioctl(&kportal_ioctl_handler); + + RETURN(rc); +} + +static void exit_kportals_module(void) +{ + libcfs_deregister_ioctl(&kportal_ioctl_handler); + kportal_nal_unregister(ROUTER); + PtlFini(); +} + +EXPORT_SYMBOL(kportal_nal_register); +EXPORT_SYMBOL(kportal_nal_unregister); +EXPORT_SYMBOL(kportal_get_ni); +EXPORT_SYMBOL(kportal_put_ni); +EXPORT_SYMBOL(kportal_nal_cmd); + +EXPORT_SYMBOL(ptl_err_str); +EXPORT_SYMBOL(lib_dispatch); +EXPORT_SYMBOL(PtlMEAttach); +EXPORT_SYMBOL(PtlMEInsert); +EXPORT_SYMBOL(PtlMEUnlink); +EXPORT_SYMBOL(PtlEQAlloc); +EXPORT_SYMBOL(PtlMDAttach); +EXPORT_SYMBOL(PtlMDUnlink); +EXPORT_SYMBOL(PtlNIInit); +EXPORT_SYMBOL(PtlNIFini); +EXPORT_SYMBOL(PtlNIDebug); +EXPORT_SYMBOL(PtlInit); +EXPORT_SYMBOL(PtlFini); +EXPORT_SYMBOL(PtlSnprintHandle); +EXPORT_SYMBOL(PtlPut); +EXPORT_SYMBOL(PtlGet); +EXPORT_SYMBOL(PtlEQWait); +EXPORT_SYMBOL(PtlEQFree); +EXPORT_SYMBOL(PtlEQGet); +EXPORT_SYMBOL(PtlGetId); +EXPORT_SYMBOL(PtlMDBind); +EXPORT_SYMBOL(lib_iov_nob); +EXPORT_SYMBOL(lib_copy_iov2buf); +EXPORT_SYMBOL(lib_copy_buf2iov); +EXPORT_SYMBOL(lib_extract_iov); +EXPORT_SYMBOL(lib_kiov_nob); +EXPORT_SYMBOL(lib_copy_kiov2buf); +EXPORT_SYMBOL(lib_copy_buf2kiov); +EXPORT_SYMBOL(lib_extract_kiov); +EXPORT_SYMBOL(lib_finalize); +EXPORT_SYMBOL(lib_parse); +EXPORT_SYMBOL(lib_create_reply_msg); +EXPORT_SYMBOL(lib_init); +EXPORT_SYMBOL(lib_fini); +EXPORT_SYMBOL(dispatch_name); + +MODULE_AUTHOR("Peter J. Braam "); +MODULE_DESCRIPTION("Portals v3.1"); +MODULE_LICENSE("GPL"); +module_init(init_kportals_module); +module_exit(exit_kportals_module); -- 1.8.3.1