7c15b73947bf4a31340865d4ad9312b2362f20eb
[openafs.git] / src / afs / LINUX / osi_proc.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /*
11  * Linux module support routines.
12  *
13  */
14 #include <afsconfig.h>
15 #include "afs/param.h"
16
17 RCSID
18     ("$Header$");
19
20 #include <linux/module.h> /* early to avoid printf->printk mapping */
21 #include "afs/sysincludes.h"
22 #include "afsincludes.h"
23 #include "afs/nfsclient.h"
24 #include "h/unistd.h"           /* For syscall numbers. */
25 #include "h/mm.h"
26
27 #ifdef AFS_AMD64_LINUX20_ENV
28 #include <asm/ia32_unistd.h>
29 #endif
30
31 #include <linux/proc_fs.h>
32 #include <linux/slab.h>
33 #include <linux/init.h>
34 #include <linux/sched.h>
35 #include <linux/kernel.h>
36
37 #ifdef HAVE_KERNEL_LINUX_SEQ_FILE_H
38 #include <linux/seq_file.h>
39 #endif
40
41 struct proc_dir_entry *openafs_procfs;
42
43 #ifdef HAVE_KERNEL_LINUX_SEQ_FILE_H
44 static void *c_start(struct seq_file *m, loff_t *pos)
45 {
46         struct afs_q *cq, *tq;
47         loff_t n = 0;
48
49         ObtainReadLock(&afs_xcell);
50         for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
51                 tq = QNext(cq);
52
53                 if (n++ == *pos)
54                         break;
55         }
56         if (cq == &CellLRU)
57                 return NULL;
58
59         return cq;
60 }
61
62 static void *c_next(struct seq_file *m, void *p, loff_t *pos)
63 {
64         struct afs_q *cq = p, *tq;
65
66         (*pos)++;
67         tq = QNext(cq);
68
69         if (tq == &CellLRU)
70                 return NULL;
71
72         return tq;
73 }
74
75 static void c_stop(struct seq_file *m, void *p)
76 {
77         ReleaseReadLock(&afs_xcell);
78 }
79
80 static int c_show(struct seq_file *m, void *p)
81 {
82         struct afs_q *cq = p;
83         struct cell *tc = QTOC(cq);
84         int j;
85
86         seq_printf(m, ">%s #(%d/%d)\n", tc->cellName,
87                    tc->cellNum, tc->cellIndex);
88
89         for (j = 0; j < MAXCELLHOSTS; j++) {
90                 afs_uint32 addr;
91
92                 if (!tc->cellHosts[j]) break;
93
94                 addr = tc->cellHosts[j]->addr->sa_ip;
95                 seq_printf(m, "%u.%u.%u.%u #%u.%u.%u.%u\n",
96                            NIPQUAD(addr), NIPQUAD(addr));
97         }
98
99         return 0;
100 }
101
102 static struct seq_operations afs_csdb_op = {
103         .start          = c_start,
104         .next           = c_next,
105         .stop           = c_stop,
106         .show           = c_show,
107 };
108
109 static int afs_csdb_open(struct inode *inode, struct file *file)
110 {
111         return seq_open(file, &afs_csdb_op);
112 }
113
114 static struct file_operations afs_csdb_operations = {
115         .open           = afs_csdb_open,
116         .read           = seq_read,
117         .llseek         = seq_lseek,
118         .release        = seq_release,
119 };
120
121
122 static void *uu_start(struct seq_file *m, loff_t *pos)
123 {
124     struct unixuser *tu;
125     loff_t n = 0;
126     afs_int32 i;
127
128     ObtainReadLock(&afs_xuser);
129     if (!*pos)
130         return (void *)(1);
131
132     for (i = 0; i < NUSERS; i++) {
133         for (tu = afs_users[i]; tu; tu = tu->next) {
134             if (++n == *pos)
135                 return tu;
136         }
137     }
138
139     return NULL;
140 }
141
142 static void *uu_next(struct seq_file *m, void *p, loff_t *pos)
143 {
144     struct unixuser *tu = p;
145     afs_int32 i = 0;
146
147     (*pos)++;
148     if (!p) return NULL;
149
150     if (p != (void *)1) {
151         if (tu->next) return tu->next;
152         i = UHash(tu->uid) + 1;
153     }
154
155     for (; i < NUSERS; i++)
156         if (afs_users[i]) return afs_users[i];
157     return NULL;
158 }
159
160 static void uu_stop(struct seq_file *m, void *p)
161 {
162     ReleaseReadLock(&afs_xuser);
163 }
164
165 static int uu_show(struct seq_file *m, void *p)
166 {
167     struct cell *tc = 0;
168     struct unixuser *tu = p;
169     char *cellname;
170
171     if (p == (void *)1) {
172         seq_printf(m, "%10s %4s %-6s  %-25s %10s",
173                    "UID/PAG", "Refs", "States", "Cell", "ViceID");
174         seq_printf(m, "  %10s %10s %10s %3s",
175                    "Tok Set", "Tok Begin", "Tok Expire", "vno");
176         seq_printf(m, "  %-15s %10s %10s %s\n",
177                    "NFS Client", "UID/PAG", "Client UID", "Sysname(s)");
178
179         return 0;
180     }
181
182     if (tu->cell == -1) {
183         cellname = "<default>";
184     } else {
185         tc = afs_GetCellStale(tu->cell, READ_LOCK);
186         if (tc) cellname = tc->cellName;
187         else cellname = "<unknown>";
188     }
189
190     seq_printf(m, "%10d %4d %04x    %-25s %10d",
191                tu->uid, tu->refCount, tu->states, cellname, tu->vid);
192
193     if (tc) afs_PutCell(tc, READ_LOCK);
194
195     if (tu->states & UHasTokens) {
196         seq_printf(m, "  %10d %10d %10d %3d",
197                    tu->tokenTime, tu->ct.BeginTimestamp, tu->ct.EndTimestamp,
198                    tu->ct.AuthHandle);
199     } else {
200         seq_printf(m, "  %-36s", "Tokens Not Set");
201     }
202
203     if (tu->exporter && tu->exporter->exp_type == EXP_NFS) {
204         struct nfsclientpag *np = (struct nfsclientpag *)(tu->exporter);
205         char ipaddr[16];
206         int i;
207
208         sprintf(ipaddr, "%u.%u.%u.%u", NIPQUAD(np->host));
209         seq_printf(m, "  %-15s %10d %10d", ipaddr, np->uid, np->client_uid);
210         if (np->sysnamecount) {
211             for (i = 0; i < np->sysnamecount; i++)
212                 seq_printf(m, " %s", np->sysname[i]);
213         } else { 
214             seq_printf(m, " <no sysname list>");
215         }
216
217     } else if (tu->exporter) {
218         seq_printf(m, "  Unknown exporter type %d", tu->exporter->exp_type);
219     }
220     seq_printf(m, "\n");
221
222     return 0;
223 }
224
225 static struct seq_operations afs_unixuser_seqop = {
226     .start              = uu_start,
227     .next               = uu_next,
228     .stop               = uu_stop,
229     .show               = uu_show,
230 };
231
232 static int afs_unixuser_open(struct inode *inode, struct file *file)
233 {
234     return seq_open(file, &afs_unixuser_seqop);
235 }
236
237 static struct file_operations afs_unixuser_fops = {
238     .open               = afs_unixuser_open,
239     .read               = seq_read,
240     .llseek             = seq_lseek,
241     .release    = seq_release,
242 };
243
244
245 #else /* HAVE_KERNEL_LINUX_SEQ_FILE_H */
246
247 static int
248 csdbproc_info(char *buffer, char **start, off_t offset, int
249 length)
250 {
251     int len = 0;
252     off_t pos = 0;
253     int cnt;
254     struct afs_q *cq, *tq;
255     struct cell *tc;
256     char tbuffer[16];
257     /* 90 - 64 cellname, 10 for 32 bit num and index, plus
258        decor */
259     char temp[91];
260     afs_uint32 addr;
261     
262     ObtainReadLock(&afs_xcell);
263
264     for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
265         tc = QTOC(cq); tq = QNext(cq);
266
267         pos += 90;
268
269         if (pos <= offset) {
270             len = 0;
271         } else {
272             sprintf(temp, ">%s #(%d/%d)\n", tc->cellName, 
273                     tc->cellNum, tc->cellIndex);
274             sprintf(buffer + len, "%-89s\n", temp);
275             len += 90;
276             if (pos >= offset+length) {
277                 ReleaseReadLock(&afs_xcell);
278                 goto done;
279             }
280         }
281
282         for (cnt = 0; cnt < MAXCELLHOSTS; cnt++) {
283             if (!tc->cellHosts[cnt]) break;
284             pos += 90;
285             if (pos <= offset) {
286                 len = 0;
287             } else {
288                 addr = ntohl(tc->cellHosts[cnt]->addr->sa_ip);
289                 sprintf(tbuffer, "%d.%d.%d.%d", 
290                         (int)((addr>>24) & 0xff),
291 (int)((addr>>16) & 0xff),
292                         (int)((addr>>8)  & 0xff), (int)( addr & 0xff));
293                 sprintf(temp, "%s #%s\n", tbuffer, tbuffer);
294                 sprintf(buffer + len, "%-89s\n", temp);
295                 len += 90;
296                 if (pos >= offset+length) {
297                     ReleaseReadLock(&afs_xcell);
298                     goto done;
299                 }
300             }
301         }
302     }
303
304     ReleaseReadLock(&afs_xcell);
305     
306 done:
307     *start = buffer + len - (pos - offset);
308     len = pos - offset;
309     if (len > length)
310         len = length;
311     return len;
312 }
313
314 #endif /* HAVE_KERNEL_LINUX_SEQ_FILE_H */
315
316 void
317 osi_proc_init(void)
318 {
319     struct proc_dir_entry *entry;
320 #if !defined(EXPORTED_PROC_ROOT_FS)
321     char path[64];
322 #endif
323     
324 #if defined(EXPORTED_PROC_ROOT_FS)
325     openafs_procfs = proc_mkdir(PROC_FSDIRNAME, proc_root_fs);
326 #else
327     sprintf(path, "fs/%s", PROC_FSDIRNAME);
328     openafs_procfs = proc_mkdir(path, NULL);
329 #endif
330 #ifdef HAVE_KERNEL_LINUX_SEQ_FILE_H
331     entry = create_proc_entry("unixusers", 0, openafs_procfs);
332     if (entry) {
333         entry->proc_fops = &afs_unixuser_fops;
334         entry->owner = THIS_MODULE;
335     }
336     entry = create_proc_entry(PROC_CELLSERVDB_NAME, 0, openafs_procfs);
337     if (entry)
338         entry->proc_fops = &afs_csdb_operations;
339 #else
340     entry = create_proc_info_entry(PROC_CELLSERVDB_NAME, (S_IFREG|S_IRUGO), openafs_procfs, csdbproc_info);
341 #endif
342     entry->owner = THIS_MODULE;
343 }
344
345 void
346 osi_proc_clean(void)
347 {
348 #if !defined(EXPORTED_PROC_ROOT_FS)
349     char path[64];
350 #endif
351
352 #if defined(EXPORTED_PROC_ROOT_FS)
353     remove_proc_entry(PROC_FSDIRNAME, proc_root_fs);
354 #else
355     sprintf(path, "fs/%s", PROC_FSDIRNAME);
356     remove_proc_entry(path, NULL);
357 #endif
358     remove_proc_entry(PROC_CELLSERVDB_NAME, openafs_procfs);
359 #ifdef HAVE_KERNEL_LINUX_SEQ_FILE_H
360     remove_proc_entry("unixusers", openafs_procfs);
361 #endif
362 }