Whamcloud - gitweb
- the start of moving things from portals.o to libcfs.o. the 2.4 kernel
authorzab <zab>
Tue, 2 Mar 2004 01:34:28 +0000 (01:34 +0000)
committerzab <zab>
Tue, 2 Mar 2004 01:34:28 +0000 (01:34 +0000)
  build still works though others probably don't.

lnet/include/linux/libcfs.h [new file with mode: 0644]
lnet/include/linux/list.h [new file with mode: 0644]
lnet/lnet/module.c [new file with mode: 0644]
lustre/portals/include/linux/libcfs.h [new file with mode: 0644]
lustre/portals/include/linux/list.h [new file with mode: 0644]
lustre/portals/portals/module.c [new file with mode: 0644]

diff --git a/lnet/include/linux/libcfs.h b/lnet/include/linux/libcfs.h
new file mode 100644 (file)
index 0000000..6a1f071
--- /dev/null
@@ -0,0 +1,217 @@
+/* -*- 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 */
diff --git a/lnet/include/linux/list.h b/lnet/include/linux/list.h
new file mode 100644 (file)
index 0000000..9cab047
--- /dev/null
@@ -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 (file)
index 0000000..7137efc
--- /dev/null
@@ -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 <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);
diff --git a/lustre/portals/include/linux/libcfs.h b/lustre/portals/include/linux/libcfs.h
new file mode 100644 (file)
index 0000000..6a1f071
--- /dev/null
@@ -0,0 +1,217 @@
+/* -*- 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 */
diff --git a/lustre/portals/include/linux/list.h b/lustre/portals/include/linux/list.h
new file mode 100644 (file)
index 0000000..9cab047
--- /dev/null
@@ -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 (file)
index 0000000..7137efc
--- /dev/null
@@ -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 <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);