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 rwlock_t proc_route_rwlock;
35 } kpr_read_routes_data;
37 /* nal2name support re-used from utils/portals.c */
52 static struct name2num *name2num_lookup_num(struct name2num *table, int num)
54 while (table->name != NULL)
55 if (num == table->num)
62 static char *nal2name(int nal)
64 struct name2num *e = name2num_lookup_num(nalnames, nal);
65 return ((e == NULL) ? "???" : e->name);
69 static int kpr_proc_router_read(char *page, char **start, off_t off,
70 int count, int *eof, void *data)
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);
82 len = sprintf(page, "%Ld %ld %ld %d\n", bytes, packets, errors, qdepth);
88 static int kpr_proc_router_write(struct file *file, const char *ubuffer,
89 unsigned long count, void *data)
91 /* Ignore what we've been asked to write, and just zero the stats */
99 static int kpr_proc_routes_read(char *page, char **start, off_t off,
100 int count, int *eof, void *data)
102 struct proc_route_data *prd = data;
103 kpr_route_entry_t *re;
104 kpr_gateway_entry_t *ge;
113 write_lock(&(prd->proc_route_rwlock));
115 if (prd->curr == NULL) {
117 goto routes_read_exit;
119 /* First pass, initialize our private data */
120 prd->curr = kpr_routes.next;
121 prd->generation = kpr_routes_generation;
124 /* Abort route list generation change */
125 if (prd->generation != kpr_routes_generation) {
127 rc = sprintf(page, "\nError: Routes Changed\n");
128 goto routes_read_exit;
131 /* All the routes have been walked */
132 if (prd->curr == &kpr_routes) {
134 goto routes_read_exit;
138 read_lock(&kpr_rwlock);
139 *start = page + prd->skip;
140 user_len = -prd->skip;
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;
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;
154 /* Abort the route list changed */
155 if (prd->curr->next == NULL) {
157 read_unlock(&kpr_rwlock);
158 rc = sprintf(page, "\nError: Routes Changed\n");
159 goto routes_read_exit;
162 prd->curr = prd->curr->next;
164 /* The route table will exceed one page, break the while loop
165 * so the function can be re-called with a new page.
167 if ((chunk_len > (PAGE_SIZE - 80)) || (user_len > count))
173 /* Caller received only a portion of the last entry, the
174 * remaining will be delivered in the next page if asked for.
176 if (user_len > count) {
177 prd->curr = prd->curr->prev;
178 prd->skip = line_len - (user_len - count);
179 read_unlock(&kpr_rwlock);
181 goto routes_read_exit;
184 /* Not enough data to entirely satify callers request */
186 read_unlock(&kpr_rwlock);
190 write_unlock(&(prd->proc_route_rwlock));
194 static int kpr_proc_routes_write(struct file *file, const char *ubuffer,
195 unsigned long count, void *data)
197 /* no-op; lctl should be used to adjust the routes */
201 void kpr_proc_init(void)
203 struct proc_dir_entry *router_entry;
204 struct proc_dir_entry *routes_entry;
206 /* Initialize KPR_PROC_ROUTER */
207 router_entry = create_proc_entry (KPR_PROC_ROUTER,
208 S_IFREG | S_IRUGO | S_IWUSR, NULL);
210 if (router_entry == NULL) {
211 CERROR("couldn't create proc entry %s\n", KPR_PROC_ROUTER);
215 router_entry->data = NULL;
216 router_entry->read_proc = kpr_proc_router_read;
217 router_entry->write_proc = kpr_proc_router_write;
219 /* Initialize KPR_PROC_ROUTES */
220 routes_entry = create_proc_entry (KPR_PROC_ROUTES,
221 S_IFREG | S_IRUGO | S_IWUSR, NULL);
223 if (routes_entry == NULL) {
224 CERROR("couldn't create proc entry %s\n", KPR_PROC_ROUTES);
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;
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;
238 void kpr_proc_fini(void)
240 remove_proc_entry(KPR_PROC_ROUTER, 0);
241 remove_proc_entry(KPR_PROC_ROUTES, 0);