xref: /dragonfly/sys/dev/raid/vinum/vinummemory.c (revision 0dcae15371ebd5dc7a19d358d01ad6283c2b40c4)
1 /*-
2  * Copyright (c) 1997, 1998
3  *        Nan Yang Computer Services Limited.  All rights reserved.
4  *
5  *  This software is distributed under the so-called ``Berkeley
6  *  License'':
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *        This product includes software developed by Nan Yang Computer
19  *      Services Limited.
20  * 4. Neither the name of the Company nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * This software is provided ``as is'', and any express or implied
25  * warranties, including, but not limited to, the implied warranties of
26  * merchantability and fitness for a particular purpose are disclaimed.
27  * In no event shall the company or contributors be liable for any
28  * direct, indirect, incidental, special, exemplary, or consequential
29  * damages (including, but not limited to, procurement of substitute
30  * goods or services; loss of use, data, or profits; or business
31  * interruption) however caused and on any theory of liability, whether
32  * in contract, strict liability, or tort (including negligence or
33  * otherwise) arising in any way out of the use of this software, even if
34  * advised of the possibility of such damage.
35  *
36  * $Id: vinummemory.c,v 1.25 2000/05/04 01:57:48 grog Exp grog $
37  * $FreeBSD: src/sys/dev/vinum/vinummemory.c,v 1.22.2.1 2000/06/02 04:26:11 grog Exp $
38  */
39 
40 #include "vinumhdr.h"
41 
42 #ifdef VINUMDEBUG
43 
44 #include "request.h"
45 extern struct rqinfo rqinfo[];
46 extern struct rqinfo *rqip;
47 int rqinfo_size = RQINFO_SIZE;                                            /* for debugger */
48 
49 #define LongJmp longjmp                                                   /* just use the kernel function */
50 #endif
51 
52 /* find the base name of a path name */
53 char *
basename(char * file)54 basename(char *file)
55 {
56     char *f = rindex(file, '/');                                /* chop off dirname if present */
57 
58     if (f == NULL)
59           return file;
60     else
61           return ++f;                                                     /* skip the / */
62 }
63 
64 void
expand_table(void ** table,int oldsize,int newsize)65 expand_table(void **table, int oldsize, int newsize)
66 {
67     if (newsize > oldsize) {
68           int *temp;
69 
70           crit_enter();
71           temp = (int *) Malloc(newsize);                                 /* allocate a new table */
72           CHECKALLOC(temp, "vinum: Can't expand table\n");
73           bzero((char *) temp, newsize);                                  /* clean it all out */
74           if (*table != NULL) {                                           /* already something there, */
75               bcopy((char *) *table, (char *) temp, oldsize); /* copy it to the old table */
76               Free(*table);
77           }
78           *table = temp;
79           crit_exit();
80     }
81 }
82 
83 #ifdef VINUMDEBUG                                               /* XXX debug */
84 #define MALLOCENTRIES 16384
85 int malloccount = 0;
86 int highwater = 0;                                              /* highest index ever allocated */
87 struct mc malloced[MALLOCENTRIES];
88 
89 #define FREECOUNT 64
90 int freecount = FREECOUNT;                                      /* for debugger */
91 int lastfree = 0;
92 struct mc freeinfo[FREECOUNT];
93 
94 int total_malloced;
95 static int mallocseq = 0;
96 
97 caddr_t
MMalloc(int size,char * file,int line)98 MMalloc(int size, char *file, int line)
99 {
100     caddr_t result;
101     int i;
102 
103     if (malloccount >= MALLOCENTRIES) {                         /* too many */
104           log(LOG_ERR, "vinum: can't allocate table space to trace memory allocation");
105           return 0;                                             /* can't continue */
106     }
107     /* Wait for malloc if we can */
108     result = kmalloc(size, M_DEVBUF, mycpu->gd_intr_nesting_level == 0 ? M_WAITOK : M_INTWAIT);
109     if (result == NULL)
110           log(LOG_ERR, "vinum: can't allocate %d bytes from %s:%d\n", size, file, line);
111     else {
112           crit_enter();
113           for (i = 0; i < malloccount; i++) {
114               if (((result + size) > malloced[i].address)
115                     && (result < malloced[i].address + malloced[i].size)) /* overlap */
116                     Debugger("Malloc overlap");
117           }
118           if (result) {
119               char *f = basename(file);
120 
121               i = malloccount++;
122               total_malloced += size;
123               microtime(&malloced[i].time);
124               malloced[i].seq = mallocseq++;
125               malloced[i].size = size;
126               malloced[i].line = line;
127               malloced[i].address = result;
128               bcopy(f, malloced[i].file, min(strlen(f), MCFILENAMELEN - 1));
129               malloced[i].file[MCFILENAMELEN - 1] = '\0';
130           }
131           if (malloccount > highwater)
132               highwater = malloccount;
133           crit_exit();
134     }
135     return result;
136 }
137 
138 void
FFree(void * mem,char * file,int line)139 FFree(void *mem, char *file, int line)
140 {
141     int i;
142 
143     crit_enter();
144     for (i = 0; i < malloccount; i++) {
145           if ((caddr_t) mem == malloced[i].address) {           /* found it */
146               bzero(mem, malloced[i].size);                     /* XXX */
147               kfree(mem, M_DEVBUF);
148               malloccount--;
149               total_malloced -= malloced[i].size;
150               if (debug & DEBUG_MEMFREE) {                      /* keep track of recent frees */
151                     char *f = rindex(file, '/');                /* chop off dirname if present */
152 
153                     if (f == NULL)
154                         f = file;
155                     else
156                         f++;                                    /* skip the / */
157 
158                     microtime(&freeinfo[lastfree].time);
159                     freeinfo[lastfree].seq = malloced[i].seq;
160                     freeinfo[lastfree].size = malloced[i].size;
161                     freeinfo[lastfree].line = line;
162                     freeinfo[lastfree].address = mem;
163                     bcopy(f, freeinfo[lastfree].file, min(strlen(f), MCFILENAMELEN - 1));
164                     freeinfo[lastfree].file[MCFILENAMELEN - 1] = '\0';
165                     if (++lastfree == FREECOUNT)
166                         lastfree = 0;
167               }
168               if (i < malloccount)                              /* more coming after */
169                     bcopy(&malloced[i + 1], &malloced[i], (malloccount - i) * sizeof(struct mc));
170               crit_exit();
171               return;
172           }
173     }
174     log(LOG_ERR,
175           "Freeing unallocated data at 0x%p from %s, line %d\n",
176           mem,
177           file,
178           line);
179     Debugger("Free");
180     crit_exit();
181 }
182 
183 void
vinum_meminfo(caddr_t data)184 vinum_meminfo(caddr_t data)
185 {
186     struct meminfo *m = (struct meminfo *) data;
187 
188     m->mallocs = malloccount;
189     m->total_malloced = total_malloced;
190     m->malloced = malloced;
191     m->highwater = highwater;
192 }
193 
194 int
vinum_mallocinfo(caddr_t data)195 vinum_mallocinfo(caddr_t data)
196 {
197     struct mc *m = (struct mc *) data;
198     unsigned int ent = m->seq;                                            /* index of entry to return */
199 
200     if (ent >= malloccount)
201           return ENOENT;
202     m->address = malloced[ent].address;
203     m->size = malloced[ent].size;
204     m->line = malloced[ent].line;
205     m->seq = malloced[ent].seq;
206     bcopy(malloced[ent].file, m->file, MCFILENAMELEN);
207     return 0;
208 }
209 
210 /*
211  * return the nth request trace buffer entry.  This
212  * is indexed back from the current entry (which
213  * has index 0)
214  */
215 int
vinum_rqinfo(caddr_t data)216 vinum_rqinfo(caddr_t data)
217 {
218     struct rqinfo *rq = (struct rqinfo *) data;
219     int ent = *(int *) data;                                    /* 1st word is index */
220     int lastent = rqip - rqinfo;                                /* entry number of current entry */
221 
222     if (ent >= RQINFO_SIZE)                                     /* out of the table */
223           return ENOENT;
224     if ((ent = lastent - ent - 1) < 0)
225           ent += RQINFO_SIZE;                                   /* roll over backwards */
226     bcopy(&rqinfo[ent], rq, sizeof(struct rqinfo));
227     return 0;
228 }
229 #endif
230