build still works though others probably don't.
--- /dev/null
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ */
+#ifndef _LIBCFS_H
+
+#include <linux/list.h>
+
+#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 <linux/sched.h> /* 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 */
--- /dev/null
+#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
--- /dev/null
+/* -*- 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 <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/stat.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/smp_lock.h>
+#include <linux/unistd.h>
+
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+#include <linux/fs.h>
+#include <linux/stat.h>
+#include <asm/uaccess.h>
+#include <asm/segment.h>
+#include <linux/miscdevice.h>
+
+#include <portals/lib-p30.h>
+#include <portals/p30.h>
+#include <linux/kp30.h>
+#include <linux/portals_compat25.h>
+
+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 <braam@clusterfs.com>");
+MODULE_DESCRIPTION("Portals v3.1");
+MODULE_LICENSE("GPL");
+module_init(init_kportals_module);
+module_exit(exit_kportals_module);
--- /dev/null
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ */
+#ifndef _LIBCFS_H
+
+#include <linux/list.h>
+
+#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 <linux/sched.h> /* 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 */
--- /dev/null
+#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
--- /dev/null
+/* -*- 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 <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/stat.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/smp_lock.h>
+#include <linux/unistd.h>
+
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+#include <linux/fs.h>
+#include <linux/stat.h>
+#include <asm/uaccess.h>
+#include <asm/segment.h>
+#include <linux/miscdevice.h>
+
+#include <portals/lib-p30.h>
+#include <portals/p30.h>
+#include <linux/kp30.h>
+#include <linux/portals_compat25.h>
+
+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 <braam@clusterfs.com>");
+MODULE_DESCRIPTION("Portals v3.1");
+MODULE_LICENSE("GPL");
+module_init(init_kportals_module);
+module_exit(exit_kportals_module);