Whamcloud - gitweb
* removed a diff that crept in somehow
[fs/lustre-release.git] / lustre / portals / router / proc.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * Copyright (C) 2002 Cluster File Systems, Inc.
5  *
6  *   This file is part of Portals
7  *   http://sourceforge.net/projects/sandiaportals/
8  *
9  *   Portals is free software; you can redistribute it and/or
10  *   modify it under the terms of version 2 of the GNU General Public
11  *   License as published by the Free Software Foundation.
12  *
13  *   Portals is distributed in the hope that it will be useful,
14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *   GNU General Public License for more details.
17  *
18  *   You should have received a copy of the GNU General Public License
19  *   along with Portals; if not, write to the Free Software
20  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  *
22  */
23
24 #include "router.h"
25
26 #define KPR_PROC_ROUTER "sys/portals/router"
27 #define KPR_PROC_ROUTES "sys/portals/routes"
28
29 /* Used for multi-page route list book keeping */
30 struct proc_route_data {
31         struct list_head *curr;
32         unsigned int generation;
33         off_t skip;
34         rwlock_t proc_route_rwlock;
35 } kpr_read_routes_data;
36
37 /* nal2name support re-used from utils/portals.c */
38 struct name2num {
39         char *name;
40         int   num;
41 } nalnames[] = {
42         { "any",         0},
43         { "elan",        QSWNAL},
44         { "tcp",         SOCKNAL},
45         { "gm",          GMNAL},
46         { "ib",          OPENIBNAL},
47         { "iib",         IIBNAL},
48         { "lo",          LONAL},
49         { NULL,          -1}
50 };
51
52 static struct name2num *name2num_lookup_num(struct name2num *table, int num)
53 {
54         while (table->name != NULL)
55                 if (num == table->num)
56                         return (table);
57                 else
58                         table++;
59         return (NULL);
60 }
61
62 static char *nal2name(int nal)
63 {
64         struct name2num *e = name2num_lookup_num(nalnames, nal);
65         return ((e == NULL) ? "???" : e->name);
66 }
67
68
69 static int kpr_proc_router_read(char *page, char **start, off_t off,
70                                 int count, int *eof, void *data)
71 {
72         unsigned long long bytes = kpr_fwd_bytes;
73         unsigned long      packets = kpr_fwd_packets;
74         unsigned long      errors = kpr_fwd_errors;
75         unsigned int       qdepth = atomic_read (&kpr_queue_depth);
76         int                len;
77
78         *eof = 1;
79         if (off != 0)
80                 return (0);
81
82         len = sprintf(page, "%Ld %ld %ld %d\n", bytes, packets, errors, qdepth);
83
84         *start = page;
85         return (len);
86 }
87
88 static int kpr_proc_router_write(struct file *file, const char *ubuffer,
89                                  unsigned long count, void *data)
90 {
91         /* Ignore what we've been asked to write, and just zero the stats */
92         kpr_fwd_bytes = 0;
93         kpr_fwd_packets = 0;
94         kpr_fwd_errors = 0;
95
96         return (count);
97 }
98
99 static int kpr_proc_routes_read(char *page, char **start, off_t off,
100                                 int count, int *eof, void *data)
101 {
102         struct proc_route_data  *prd = data;
103         kpr_route_entry_t       *re;
104         kpr_gateway_entry_t     *ge;
105         int                     chunk_len = 0;
106         int                     line_len = 0;
107         int                     user_len = 0;
108         int                     rc = 0;
109
110         *eof = 1;
111         *start = page;
112
113         write_lock(&(prd->proc_route_rwlock));
114
115         if (prd->curr == NULL) {
116                 if (off != 0)
117                         goto routes_read_exit;
118
119                 /* First pass, initialize our private data */
120                 prd->curr = kpr_routes.next;
121                 prd->generation = kpr_routes_generation;
122                 prd->skip = 0;
123         } else {
124                 /* Abort route list generation change */
125                 if (prd->generation != kpr_routes_generation) {
126                         prd->curr = NULL;
127                         rc = sprintf(page, "\nError: Routes Changed\n");
128                         goto routes_read_exit;
129                 }
130
131                 /* All the routes have been walked */
132                 if (prd->curr == &kpr_routes) {
133                         prd->curr = NULL;
134                         goto routes_read_exit;
135                 }
136         }
137
138         read_lock(&kpr_rwlock);
139         *start = page + prd->skip;
140         user_len = -prd->skip;
141
142         while ((prd->curr != NULL) && (prd->curr != &kpr_routes)) {
143                 re = list_entry(prd->curr, kpr_route_entry_t, kpre_list);
144                 ge = re->kpre_gateway;
145
146                 line_len = sprintf(page + chunk_len,
147                         "%12s  "LPX64" : "LPX64" - "LPX64", %s\n",
148                         nal2name(ge->kpge_nalid), ge->kpge_nid,
149                         re->kpre_lo_nid, re->kpre_hi_nid,
150                         ge->kpge_alive ? "up" : "down");
151                 chunk_len += line_len;
152                 user_len += line_len;
153
154                 /* Abort the route list changed */
155                 if (prd->curr->next == NULL) {
156                         prd->curr = NULL;
157                         read_unlock(&kpr_rwlock);
158                         rc = sprintf(page, "\nError: Routes Changed\n");
159                         goto routes_read_exit;
160                 }
161
162                 prd->curr = prd->curr->next;
163
164                 /* The route table will exceed one page, break the while loop
165                  * so the function can be re-called with a new page.
166                  */
167                 if ((chunk_len > (PAGE_SIZE - 80)) || (user_len > count))
168                         break;
169         }
170
171         *eof = 0;
172
173         /* Caller received only a portion of the last entry, the
174          * remaining will be delivered in the next page if asked for.
175          */
176         if (user_len > count) {
177                 prd->curr = prd->curr->prev;
178                 prd->skip = line_len - (user_len - count);
179                 read_unlock(&kpr_rwlock);
180                 rc = count;
181                 goto routes_read_exit;
182         }
183
184         /* Not enough data to entirely satify callers request */
185         prd->skip = 0;
186         read_unlock(&kpr_rwlock);
187         rc = user_len;
188
189 routes_read_exit:
190         write_unlock(&(prd->proc_route_rwlock));
191         return rc;
192 }
193
194 static int kpr_proc_routes_write(struct file *file, const char *ubuffer,
195                                  unsigned long count, void *data)
196 {
197         /* no-op; lctl should be used to adjust the routes */
198         return (count);
199 }
200
201 void kpr_proc_init(void)
202 {
203         struct proc_dir_entry *router_entry;
204         struct proc_dir_entry *routes_entry;
205
206         /* Initialize KPR_PROC_ROUTER */
207         router_entry = create_proc_entry (KPR_PROC_ROUTER,
208                 S_IFREG | S_IRUGO | S_IWUSR, NULL);
209
210         if (router_entry == NULL) {
211                 CERROR("couldn't create proc entry %s\n", KPR_PROC_ROUTER);
212                 return;
213         }
214
215         router_entry->data = NULL;
216         router_entry->read_proc = kpr_proc_router_read;
217         router_entry->write_proc = kpr_proc_router_write;
218
219         /* Initialize KPR_PROC_ROUTES */
220         routes_entry = create_proc_entry (KPR_PROC_ROUTES,
221                 S_IFREG | S_IRUGO | S_IWUSR, NULL);
222
223         if (routes_entry == NULL) {
224                 CERROR("couldn't create proc entry %s\n", KPR_PROC_ROUTES);
225                 return;
226         }
227
228         kpr_read_routes_data.curr = NULL;
229         kpr_read_routes_data.generation = 0;
230         kpr_read_routes_data.skip = 0;
231         kpr_read_routes_data.proc_route_rwlock = RW_LOCK_UNLOCKED;
232
233         routes_entry->data = &kpr_read_routes_data;
234         routes_entry->read_proc = kpr_proc_routes_read;
235         routes_entry->write_proc = kpr_proc_routes_write;
236 }
237
238 void kpr_proc_fini(void)
239 {
240         remove_proc_entry(KPR_PROC_ROUTER, 0);
241         remove_proc_entry(KPR_PROC_ROUTES, 0);
242 }