1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (C) 2002 Cluster File Systems, Inc.
6 * This file is part of Portals
7 * http://sourceforge.net/projects/sandiaportals/
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.
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.
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.
26 #define KPR_PROC_ROUTER "sys/portals/router"
27 #define KPR_PROC_ROUTES "sys/portals/routes"
29 /* Used for multi-page route list book keeping */
30 struct proc_route_data {
31 struct list_head *curr;
32 unsigned int generation;
34 } kpr_read_routes_data;
36 /* nal2name support re-used from utils/portals.c */
49 static struct name2num *name2num_lookup_num(struct name2num *table, int num)
51 while (table->name != NULL)
52 if (num == table->num)
59 static char *nal2name(int nal)
61 struct name2num *e = name2num_lookup_num(nalnames, nal);
62 return ((e == NULL) ? "???" : e->name);
66 static int kpr_proc_router_read(char *page, char **start, off_t off,
67 int count, int *eof, void *data)
69 unsigned long long bytes = kpr_fwd_bytes;
70 unsigned long packets = kpr_fwd_packets;
71 unsigned long errors = kpr_fwd_errors;
72 unsigned int qdepth = atomic_read (&kpr_queue_depth);
79 len = sprintf(page, "%Ld %ld %ld %d\n", bytes, packets, errors, qdepth);
85 static int kpr_proc_router_write(struct file *file, const char *ubuffer,
86 unsigned long count, void *data)
88 /* Ignore what we've been asked to write, and just zero the stats */
96 static int kpr_proc_routes_read(char *page, char **start, off_t off,
97 int count, int *eof, void *data)
99 struct proc_route_data *prd = data;
100 kpr_route_entry_t *re;
101 kpr_gateway_entry_t *ge;
109 if (prd->curr == NULL) {
113 /* First pass, initialize our private data */
114 prd->curr = kpr_routes.next;
115 prd->generation = kpr_routes_generation;
118 /* Abort route list generation change */
119 if (prd->generation != kpr_routes_generation) {
121 return sprintf(page, "\nError: Routes Changed\n");
124 /* All the routes have been walked */
125 if (prd->curr == &kpr_routes) {
131 read_lock(&kpr_rwlock);
132 *start = page + prd->skip;
133 user_len = -prd->skip;
135 while ((prd->curr != NULL) && (prd->curr != &kpr_routes)) {
136 re = list_entry(prd->curr, kpr_route_entry_t, kpre_list);
137 ge = re->kpre_gateway;
139 line_len = sprintf(page + chunk_len,
140 "%12s "LPX64" : "LPX64" - "LPX64", %s\n",
141 nal2name(ge->kpge_nalid), ge->kpge_nid,
142 re->kpre_lo_nid, re->kpre_hi_nid,
143 ge->kpge_alive ? "up" : "down");
144 chunk_len += line_len;
145 user_len += line_len;
147 /* Abort the route list changed */
148 if (prd->curr->next == NULL) {
150 read_unlock(&kpr_rwlock);
151 return sprintf(page, "\nError: Routes Changed\n");
154 prd->curr = prd->curr->next;
156 /* The route table will exceed one page, break the while loop
157 * so the function can be re-called with a new page.
159 if ((chunk_len > (PAGE_SIZE - 80)) || (user_len > count))
165 /* Caller received only a portion of the last entry, the
166 * remaining will be delivered in the next page if asked for.
168 if (user_len > count) {
169 prd->curr = prd->curr->prev;
170 prd->skip = line_len - (user_len - count);
171 read_unlock(&kpr_rwlock);
175 /* Not enough data to entirely satify callers request */
177 read_unlock(&kpr_rwlock);
181 static int kpr_proc_routes_write(struct file *file, const char *ubuffer,
182 unsigned long count, void *data)
184 /* no-op; lctl should be used to adjust the routes */
188 void kpr_proc_init(void)
190 struct proc_dir_entry *router_entry;
191 struct proc_dir_entry *routes_entry;
193 /* Initialize KPR_PROC_ROUTER */
194 router_entry = create_proc_entry (KPR_PROC_ROUTER,
195 S_IFREG | S_IRUGO | S_IWUSR, NULL);
197 if (router_entry == NULL) {
198 CERROR("couldn't create proc entry %s\n", KPR_PROC_ROUTER);
202 router_entry->data = NULL;
203 router_entry->read_proc = kpr_proc_router_read;
204 router_entry->write_proc = kpr_proc_router_write;
206 /* Initialize KPR_PROC_ROUTES */
207 routes_entry = create_proc_entry (KPR_PROC_ROUTES,
208 S_IFREG | S_IRUGO | S_IWUSR, NULL);
210 if (routes_entry == NULL) {
211 CERROR("couldn't create proc entry %s\n", KPR_PROC_ROUTES);
215 kpr_read_routes_data.curr = NULL;
216 kpr_read_routes_data.generation = 0;
217 kpr_read_routes_data.skip = 0;
219 routes_entry->data = &kpr_read_routes_data;
220 routes_entry->read_proc = kpr_proc_routes_read;
221 routes_entry->write_proc = kpr_proc_routes_write;
224 void kpr_proc_fini(void)
226 remove_proc_entry(KPR_PROC_ROUTER, 0);
227 remove_proc_entry(KPR_PROC_ROUTES, 0);