Whamcloud - gitweb
- merge 0.7rc1 from b_devel to HEAD (20030612 merge point)
[fs/lustre-release.git] / lustre / portals / knals / socknal / socknal.h
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * Copyright (C) 2001, 2002 Cluster File Systems, Inc.
5  *   Author: Zach Brown <zab@zabbo.net>
6  *   Author: Peter J. Braam <braam@clusterfs.com>
7  *   Author: Phil Schwan <phil@clusterfs.com>
8  *   Author: Eric Barton <eric@bartonsoftware.com>
9  *
10  *   This file is part of Portals, http://www.sf.net/projects/lustre/
11  *
12  *   Portals is free software; you can redistribute it and/or
13  *   modify it under the terms of version 2 of the GNU General Public
14  *   License as published by the Free Software Foundation.
15  *
16  *   Portals is distributed in the hope that it will be useful,
17  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *   GNU General Public License for more details.
20  *
21  *   You should have received a copy of the GNU General Public License
22  *   along with Portals; if not, write to the Free Software
23  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  *
25  */
26
27 #define DEBUG_PORTAL_ALLOC
28 #define EXPORT_SYMTAB
29
30 #include <linux/config.h>
31 #include <linux/module.h>
32 #include <linux/kernel.h>
33 #include <linux/mm.h>
34 #include <linux/string.h>
35 #include <linux/stat.h>
36 #include <linux/errno.h>
37 #include <linux/smp_lock.h>
38 #include <linux/unistd.h>
39 #include <net/sock.h>
40 #include <net/tcp.h>
41 #include <linux/uio.h>
42
43 #include <asm/system.h>
44 #include <asm/uaccess.h>
45
46 #include <linux/fs.h>
47 #include <linux/file.h>
48 #include <linux/stat.h>
49 #include <linux/list.h>
50 #include <linux/kmod.h>
51 #include <asm/uaccess.h>
52 #include <asm/segment.h>
53
54 #define DEBUG_SUBSYSTEM S_SOCKNAL
55
56 #include <linux/kp30.h>
57 #include <portals/p30.h>
58 #include <portals/lib-p30.h>
59
60 #define SOCKNAL_N_SCHED num_online_cpus()       /* # socknal schedulers */
61
62 #if PTL_LARGE_MTU
63 # define SOCKNAL_MAX_FWD_PAYLOAD (256<<10)      /* biggest payload I can forward */
64 #else
65 # define SOCKNAL_MAX_FWD_PAYLOAD (64<<10)       /* biggest payload I can forward */
66 #endif
67
68 #define SOCKNAL_NLTXS           128             /* # normal transmit messages */
69 #define SOCKNAL_NNBLK_LTXS      128             /* # transmit messages reserved if can't block */
70
71 #define SOCKNAL_SMALL_FWD_NMSGS 128             /* # small messages I can be forwarding at any time */
72 #define SOCKNAL_LARGE_FWD_NMSGS 64              /* # large messages I can be forwarding at any time */
73
74 #define SOCKNAL_SMALL_FWD_PAGES 1               /* # pages in a small message fwd buffer */
75
76 #define SOCKNAL_LARGE_FWD_PAGES (PAGE_ALIGN (sizeof (ptl_hdr_t) + SOCKNAL_MAX_FWD_PAYLOAD) >> PAGE_SHIFT)
77                                                 /* # pages in a large message fwd buffer */
78
79 #define SOCKNAL_RESCHED         100             /* # scheduler loops before reschedule */
80
81 #define SOCKNAL_TX_LOW_WATER(sk) (((sk)->sndbuf*8)/10)
82
83 typedef struct                                  /* pool of forwarding buffers */
84 {
85         spinlock_t        fmp_lock;             /* serialise */
86         struct list_head  fmp_idle_fmbs;        /* buffers waiting for a connection */
87         struct list_head  fmp_blocked_conns;    /* connections waiting for a buffer */
88 } ksock_fmb_pool_t;
89
90
91 typedef struct                                  /* per scheduler state */
92 {
93         spinlock_t        kss_lock;             /* serialise */
94         struct list_head  kss_rx_conns;         /* conn waiting to be read */
95         struct list_head  kss_tx_conns;         /* conn waiting to be written */
96 #if SOCKNAL_ZC
97         struct list_head  kss_zctxdone_list;    /* completed ZC transmits */
98 #endif
99         wait_queue_head_t kss_waitq;            /* where scheduler sleeps */
100         int               kss_nconns;           /* # connections assigned to this scheduler */
101 } ksock_sched_t;
102
103 typedef struct {
104         int               ksnd_init;            /* initialisation state */
105         
106         struct list_head  ksnd_socklist;        /* all my connections */
107         rwlock_t          ksnd_socklist_lock;   /* stabilise add/find/remove */
108
109         nal_cb_t         *ksnd_nal_cb;
110         spinlock_t        ksnd_nal_cb_lock;     /* lib cli/sti lock */
111
112         atomic_t          ksnd_nthreads;        /* # live threads */
113         int               ksnd_shuttingdown;    /* tell threads to exit */
114         ksock_sched_t    *ksnd_schedulers;      /* scheduler state */
115         
116         kpr_router_t      ksnd_router;          /* THE router */
117
118         void             *ksnd_fmbs;            /* all the pre-allocated FMBs */
119         ksock_fmb_pool_t  ksnd_small_fmp;       /* small message forwarding buffers */
120         ksock_fmb_pool_t  ksnd_large_fmp;       /* large message forwarding buffers */
121
122         void             *ksnd_ltxs;            /* all the pre-allocated LTXs */
123         spinlock_t        ksnd_idle_ltx_lock;   /* serialise ltx alloc/free */
124         struct list_head  ksnd_idle_ltx_list;   /* where to get an idle LTX */
125         struct list_head  ksnd_idle_nblk_ltx_list; /* where to get an idle LTX if you can't block */
126         wait_queue_head_t ksnd_idle_ltx_waitq;  /* where to block for an idle LTX */
127
128         struct list_head  ksnd_reaper_list;     /* conn waiting to be reaped */
129         wait_queue_head_t ksnd_reaper_waitq;    /* reaper sleeps here */
130         spinlock_t        ksnd_reaper_lock;     /* serialise */
131         unsigned char     ksnd_irq_info[NR_IRQS]; /* irq->scheduler lookup */
132 } ksock_nal_data_t;
133
134 #define SOCKNAL_INIT_NOTHING    0
135 #define SOCKNAL_INIT_DATA       1
136 #define SOCKNAL_INIT_PTL        2
137 #define SOCKNAL_INIT_ALL        3
138
139 #define SOCKNAL_IRQ_BOUND       0x80            /* flag we _did_ bind already */
140 #define SOCKNAL_IRQ_SCHED_MASK  0x7f            /* we assume < 127 CPUs */
141 #define SOCKNAL_IRQ_UNASSIGNED  0xff            /* flag unassigned */
142
143 /* A packet just assembled for transmission is represented by 1 or more
144  * struct iovec fragments and 0 or more ptl_kiov_t fragments.  Forwarded
145  * messages, or messages from an MD with PTL_MD_KIOV _not_ set have 0
146  * ptl_kiov_t fragments.  Messages from an MD with PTL_MD_KIOV set, have 1
147  * struct iovec fragment (the header) and up to PTL_MD_MAX_IOV ptl_kiov_t
148  * fragments.
149  *
150  * On the receive side, initially 1 struct iovec fragment is posted for
151  * receive (the header).  Once the header has been received, if the message
152  * requires forwarding or will be received into mapped memory, up to
153  * PTL_MD_MAX_IOV struct iovec fragments describe the target memory.
154  * Otherwise up to PTL_MD_MAX_IOV ptl_kiov_t fragments are used.
155  */
156
157 typedef struct                                  /* transmit packet */
158 {
159         struct list_head        tx_list;        /* queue on conn for transmission etc */
160         char                    tx_isfwd;       /* forwarding / sourced here */
161         int                     tx_nob;         /* # packet bytes */
162         int                     tx_niov;        /* # packet iovec frags */
163         struct iovec           *tx_iov;         /* packet iovec frags */
164         int                     tx_nkiov;       /* # packet page frags */
165         ptl_kiov_t             *tx_kiov;        /* packet page frags */
166 #if SOCKNAL_ZC        
167         ksock_sched_t          *tx_sched;       /* who to wake on callback */
168         zccd_t                  tx_zccd;        /* zero copy callback descriptor */
169 #endif
170 } ksock_tx_t;
171
172 #define KSOCK_ZCCD_2_TX(ptr)    list_entry (ptr, ksock_tx_t, tx_zccd)
173 /* network zero copy callback descriptor embedded in ksock_tx_t */
174
175 /* space for the tx frag descriptors: hdr is always 1 iovec
176  * and payload is PTL_MD_MAX of either type. */
177 typedef struct
178 {
179         struct iovec            hdr;
180         union {
181                 struct iovec    iov[PTL_MD_MAX_IOV];
182                 ptl_kiov_t      kiov[PTL_MD_MAX_IOV];
183         }                       payload;
184 } ksock_txiovspace_t;
185
186 typedef struct                                  /* locally transmitted packet */
187 {
188         ksock_tx_t              ltx_tx;         /* send info */
189         struct list_head       *ltx_idle;       /* where to put when idle */
190         void                   *ltx_private;    /* lib_finalize() callback arg */
191         void                   *ltx_cookie;     /* lib_finalize() callback arg */
192         ksock_txiovspace_t      ltx_iov_space;  /* where to stash frag descriptors */
193         ptl_hdr_t               ltx_hdr;        /* buffer for packet header */
194 } ksock_ltx_t;
195
196 #define KSOCK_TX_2_KPR_FWD_DESC(ptr)    list_entry ((kprfd_scratch_t *)ptr, kpr_fwd_desc_t, kprfd_scratch)
197 /* forwarded packets (router->socknal) embedded in kpr_fwd_desc_t::kprfd_scratch */
198
199 #define KSOCK_TX_2_KSOCK_LTX(ptr)       list_entry (ptr, ksock_ltx_t, ltx_tx)
200 /* local packets (lib->socknal) embedded in ksock_ltx_t::ltx_tx */
201
202 /* NB list_entry() is used here as convenient macro for calculating a
203  * pointer to a struct from the address of a member.
204  */
205
206 typedef struct                                  /* Kernel portals Socket Forwarding message buffer */
207 {                                               /* (socknal->router) */
208         struct list_head        fmb_list;       /* queue idle */
209         kpr_fwd_desc_t          fmb_fwd;        /* router's descriptor */
210         int                     fmb_npages;     /* # pages allocated */
211         ksock_fmb_pool_t       *fmb_pool;       /* owning pool */
212         struct page            *fmb_pages[SOCKNAL_LARGE_FWD_PAGES];
213         struct iovec            fmb_iov[SOCKNAL_LARGE_FWD_PAGES];
214 } ksock_fmb_t;
215
216 /* space for the rx frag descriptors; we either read a single contiguous
217  * header, or PTL_MD_MAX_IOV frags of payload of either type. */
218 typedef union {
219         struct iovec    iov[PTL_MD_MAX_IOV];
220         ptl_kiov_t      kiov[PTL_MD_MAX_IOV];
221 } ksock_rxiovspace_t;
222
223 #define SOCKNAL_RX_HEADER       1               /* reading header */
224 #define SOCKNAL_RX_BODY         2               /* reading body (to deliver here) */
225 #define SOCKNAL_RX_BODY_FWD     3               /* reading body (to forward) */
226 #define SOCKNAL_RX_SLOP         4               /* skipping body */
227 #define SOCKNAL_RX_GET_FMB      5               /* scheduled for forwarding */
228 #define SOCKNAL_RX_FMB_SLEEP    6               /* blocked waiting for a fwd desc */
229
230 typedef struct 
231
232         struct list_head    ksnc_list;          /* stash on global socket list */
233         struct file        *ksnc_file;          /* socket filp */
234         struct socket      *ksnc_sock;          /* actual socket */
235         void               *ksnc_saved_data_ready; /* socket's original data_ready() callback */
236         void               *ksnc_saved_write_space; /* socket's original write_space() callback */
237         ptl_nid_t           ksnc_peernid;       /* who's on the other end */
238         atomic_t            ksnc_refcount;      /* # users */
239         ksock_sched_t      *ksnc_scheduler;     /* who schedules this connection */
240         
241         /* READER */
242         struct list_head    ksnc_rx_list;       /* where I enq waiting input or a forwarding descriptor */
243         volatile int        ksnc_rx_ready;      /* data ready to read */
244         int                 ksnc_rx_scheduled;  /* being progressed */
245         int                 ksnc_rx_state;      /* what is being read */
246         int                 ksnc_rx_nob_left;   /* # bytes to next hdr/body  */
247         int                 ksnc_rx_nob_wanted; /* bytes actually wanted */
248         int                 ksnc_rx_niov;       /* # iovec frags */
249         struct iovec       *ksnc_rx_iov;        /* the iovec frags */
250         int                 ksnc_rx_nkiov;      /* # page frags */
251         ptl_kiov_t         *ksnc_rx_kiov;       /* the page frags */
252         ksock_rxiovspace_t  ksnc_rx_iov_space;  /* space for frag descriptors */
253         void               *ksnc_cookie;        /* rx lib_finalize passthru arg */
254         ptl_hdr_t           ksnc_hdr;           /* where I read headers into */
255
256         /* WRITER */
257         struct list_head    ksnc_tx_list;       /* where I enq waiting for output space */
258         struct list_head    ksnc_tx_queue;      /* packets waiting to be sent */
259         volatile int        ksnc_tx_ready;      /* write space */
260         int                 ksnc_tx_scheduled;  /* being progressed */
261
262 } ksock_conn_t;
263
264 extern int ksocknal_add_sock (ptl_nid_t nid, int fd, int client);
265 extern int ksocknal_close_sock(ptl_nid_t nid);
266 extern int ksocknal_set_mynid(ptl_nid_t nid);
267 extern int ksocknal_push_sock(ptl_nid_t nid);
268 extern ksock_conn_t *ksocknal_get_conn (ptl_nid_t nid);
269 extern void _ksocknal_put_conn (ksock_conn_t *conn);
270 extern void ksocknal_close_conn (ksock_conn_t *conn);
271
272 static inline void
273 ksocknal_put_conn (ksock_conn_t *conn)
274 {
275         CDEBUG (D_OTHER, "putting conn[%p] -> "LPX64" (%d)\n",
276                 conn, conn->ksnc_peernid, atomic_read (&conn->ksnc_refcount));
277
278         if (atomic_dec_and_test (&conn->ksnc_refcount))
279                 _ksocknal_put_conn (conn);
280 }
281
282 extern int ksocknal_thread_start (int (*fn)(void *arg), void *arg);
283 extern int ksocknal_new_packet (ksock_conn_t *conn, int skip);
284 extern void ksocknal_fwd_packet (void *arg, kpr_fwd_desc_t *fwd);
285 extern int ksocknal_scheduler (void *arg);
286 extern int ksocknal_reaper (void *arg);
287 extern void ksocknal_data_ready(struct sock *sk, int n);
288 extern void ksocknal_write_space(struct sock *sk);
289
290
291 extern nal_cb_t         ksocknal_lib;
292 extern ksock_nal_data_t ksocknal_data;