nfs3-no-readdirplus-20041108
[openafs.git] / src / afs / afs_osi_alloc.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 #include <afsconfig.h>
11 #include "afs/param.h"
12
13 RCSID
14     ("$Header$");
15
16
17
18 #include "afs/sysincludes.h"    /* Standard vendor system headers */
19 #include "afsincludes.h"        /* Afs-based standard headers */
20 #include "afs/afs_stats.h"      /* afs statistics */
21
22 #ifndef AFS_FBSD_ENV
23 #ifdef AFS_AIX41_ENV
24 #include "sys/lockl.h"
25 #include "sys/sleep.h"
26 #include "sys/syspest.h"
27 #include "sys/lock_def.h"
28 /*lock_t osi_fsplock = LOCK_AVAIL;*/
29 #else
30 afs_lock_t osi_fsplock;
31 #endif
32
33
34
35 static struct osi_packet {
36     struct osi_packet *next;
37 } *freePacketList = NULL, *freeSmallList;
38 afs_lock_t osi_flplock;
39
40
41 afs_int32 afs_preallocs = 512;  /* Reserve space for all small allocs! */
42 void
43 osi_AllocMoreSSpace(register afs_int32 preallocs)
44 {
45     register int i;
46     char *p;
47
48     p = (char *)afs_osi_Alloc(AFS_SMALLOCSIZ * preallocs);
49 #ifdef  KERNEL_HAVE_PIN
50     pin(p, AFS_SMALLOCSIZ * preallocs); /* XXXX */
51 #endif
52     for (i = 0; i < preallocs; i++, p += AFS_SMALLOCSIZ) {
53 #ifdef AFS_AIX32_ENV
54         *p = '\0';              /* page fault it in. */
55 #endif
56         osi_FreeSmallSpace((char *)p);
57     }
58     afs_stats_cmperf.SmallBlocksAlloced += preallocs;
59     afs_stats_cmperf.SmallBlocksActive += preallocs;
60 }
61
62
63
64 /* free space allocated by AllocLargeSpace.  Also called by mclput when freeing
65  * a packet allocated by osi_NetReceive. */
66
67 void
68 osi_FreeLargeSpace(void *adata)
69 {
70
71     AFS_ASSERT_GLOCK();
72
73     AFS_STATCNT(osi_FreeLargeSpace);
74     afs_stats_cmperf.LargeBlocksActive--;
75     MObtainWriteLock(&osi_flplock, 322);
76     ((struct osi_packet *)adata)->next = freePacketList;
77     freePacketList = adata;
78     MReleaseWriteLock(&osi_flplock);
79 }
80
81 void
82 osi_FreeSmallSpace(void *adata)
83 {
84
85 #if     defined(AFS_AIX32_ENV)
86     int x;
87 #endif
88 #if     defined(AFS_HPUX_ENV)
89     ulong_t x;
90 #endif
91
92     AFS_ASSERT_GLOCK();
93
94     AFS_STATCNT(osi_FreeSmallSpace);
95     afs_stats_cmperf.SmallBlocksActive--;
96 #if     defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
97     x = splnet();               /*lockl(&osi_fsplock, LOCK_SHORT); */
98 #else
99     MObtainWriteLock(&osi_fsplock, 323);
100 #endif
101     ((struct osi_packet *)adata)->next = freeSmallList;
102     freeSmallList = adata;
103 #if     defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
104     splx(x);                    /*unlockl(&osi_fsplock); */
105 #else
106     MReleaseWriteLock(&osi_fsplock);
107 #endif
108 }
109
110 #if     defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
111 static struct osi_packet *freeMediumList;
112
113 osi_AllocMoreMSpace(register afs_int32 preallocs)
114 {
115     register int i;
116     char *p;
117
118     p = (char *)afs_osi_Alloc(AFS_MDALLOCSIZ * preallocs);
119 #ifdef  KERNEL_HAVE_PIN
120     pin(p, AFS_MDALLOCSIZ * preallocs); /* XXXX */
121 #endif
122     for (i = 0; i < preallocs; i++, p += AFS_MDALLOCSIZ) {
123 #ifdef AFS_AIX32_ENV
124         *p = '\0';              /* page fault it in. */
125 #endif
126         osi_FreeMediumSpace((char *)p);
127     }
128     afs_stats_cmperf.MediumBlocksAlloced += preallocs;
129     afs_stats_cmperf.MediumBlocksActive += preallocs;
130 }
131
132
133 void *
134 osi_AllocMediumSpace(size_t size)
135 {
136     register struct osi_packet *tp;
137 #if     defined(AFS_AIX32_ENV)
138     int x;
139 #endif
140 #if     defined(AFS_HPUX_ENV)
141     ulong_t x;
142 #endif
143
144     afs_stats_cmperf.MediumBlocksActive++;
145   retry:
146     x = splnet();
147     tp = freeMediumList;
148     if (tp)
149         freeMediumList = tp->next;
150     splx(x);
151     if (!tp) {
152         osi_AllocMoreMSpace(AFS_MALLOC_LOW_WATER);
153         goto retry;
154     }
155     return tp;
156 }
157
158 void
159 osi_FreeMediumSpace(void *adata)
160 {
161
162 #if     defined(AFS_AIX32_ENV)
163     int x;
164 #endif
165 #if     defined(AFS_HPUX_ENV)
166     ulong_t x;
167 #endif
168
169     afs_stats_cmperf.MediumBlocksActive--;
170     x = splnet();
171     ((struct osi_packet *)adata)->next = freeMediumList;
172     freeMediumList = adata;
173     splx(x);
174 }
175 #endif /* defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV) */
176
177
178 /* allocate space for sender */
179 void *
180 osi_AllocLargeSpace(size_t size)
181 {
182     register struct osi_packet *tp;
183
184     AFS_ASSERT_GLOCK();
185
186     AFS_STATCNT(osi_AllocLargeSpace);
187     if (size > AFS_LRALLOCSIZ)
188         osi_Panic("osi_AllocLargeSpace: size=%d\n", size);
189     afs_stats_cmperf.LargeBlocksActive++;
190     if (!freePacketList) {
191         char *p;
192
193         afs_stats_cmperf.LargeBlocksAlloced++;
194         p = (char *)afs_osi_Alloc(AFS_LRALLOCSIZ);
195 #ifdef  KERNEL_HAVE_PIN
196         /*
197          * Need to pin this memory since under heavy conditions this memory
198          * could be swapped out; the problem is that we could inside rx where
199          * interrupts are disabled and thus we would panic if we don't pin it.
200          */
201         pin(p, AFS_LRALLOCSIZ);
202 #endif
203         return p;
204     }
205     MObtainWriteLock(&osi_flplock, 324);
206     tp = freePacketList;
207     if (tp)
208         freePacketList = tp->next;
209     MReleaseWriteLock(&osi_flplock);
210     return (char *)tp;
211 }
212
213 #if     defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
214 /*
215  * XXX We could have used a macro around osi_AllocSmallSpace but it's
216  * probably better like this so that we can remove this at some point.
217  */
218 /* morespace 1 - means we called at splnet level */
219 char *
220 osi_AllocSmall(register afs_int32 size, register afs_int32 morespace)
221 {
222     register struct osi_packet *tp;
223 #if     defined(AFS_AIX32_ENV)
224     int x;
225 #endif
226 #if     defined(AFS_HPUX_ENV)
227     ulong_t x;
228 #endif
229
230     AFS_ASSERT_GLOCK();
231
232     AFS_STATCNT(osi_AllocSmallSpace);
233     if (size > AFS_SMALLOCSIZ)
234         osi_Panic("osi_AllocSmall, size=%d", size);
235     if ((!morespace
236          &&
237          ((afs_stats_cmperf.SmallBlocksAlloced -
238            afs_stats_cmperf.SmallBlocksActive)
239           <= AFS_SALLOC_LOW_WATER))
240         || !freeSmallList) {
241         osi_AllocMoreSSpace(AFS_SALLOC_LOW_WATER * 2);
242     }
243     afs_stats_cmperf.SmallBlocksActive++;
244 #if     defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
245     x = splnet();               /*lockl(&osi_fsplock, LOCK_SHORT); */
246 #else
247     MObtainWriteLock(&osi_fsplock, 325);
248 #endif
249     tp = freeSmallList;
250     if (tp)
251         freeSmallList = tp->next;
252 #if     defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
253     splx(x);                    /*unlockl(&osi_fsplock); */
254 #else
255     MReleaseWriteLock(&osi_fsplock);
256 #endif
257
258     return (char *)tp;
259 }
260
261 int
262 osi_FreeSmall(register struct osi_packet *adata)
263 {
264 #if     defined(AFS_AIX32_ENV)
265     int x;
266 #endif
267 #if     defined(AFS_HPUX_ENV)
268     ulong_t x;
269 #endif
270
271     AFS_STATCNT(osi_FreeSmallSpace);
272     afs_stats_cmperf.SmallBlocksActive--;
273 #if     defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
274     x = splnet();               /*lockl(&osi_fsplock, LOCK_SHORT); */
275 #else
276     MObtainWriteLock(&osi_fsplock, 326);
277 #endif
278     adata->next = freeSmallList;
279     freeSmallList = adata;
280 #if     defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
281     splx(x);                    /*unlockl(&osi_fsplock); */
282 #else
283     MReleaseWriteLock(&osi_fsplock);
284 #endif
285     return 0;
286 }
287 #endif /* AFS_AIX32_ENV || AFS_HPUX_ENV */
288
289 /* allocate space for sender */
290 void *
291 osi_AllocSmallSpace(size_t size)
292 {
293     register struct osi_packet *tp;
294 #if     defined(AFS_AIX32_ENV)
295     int x;
296 #endif
297 #if     defined(AFS_HPUX_ENV)
298     ulong_t x;
299 #endif
300
301     AFS_STATCNT(osi_AllocSmallSpace);
302     if (size > AFS_SMALLOCSIZ)
303         osi_Panic("osi_AllocSmallS: size=%d\n", size);
304
305 #if     defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
306     /* 
307      * We're running out of free blocks (< 50); get some more ourselves so that
308      * when we don't run out of them when called under splnet() (from rx);
309      */
310     if (((afs_stats_cmperf.SmallBlocksAlloced -
311           afs_stats_cmperf.SmallBlocksActive)
312          <= AFS_SALLOC_LOW_WATER) || !freeSmallList) {
313         osi_AllocMoreSSpace(AFS_SALLOC_LOW_WATER * 2);
314     }
315 #else
316     if (!freeSmallList) {
317         afs_stats_cmperf.SmallBlocksAlloced++;
318         afs_stats_cmperf.SmallBlocksActive++;
319         return afs_osi_Alloc(AFS_SMALLOCSIZ);
320     }
321 #endif
322     afs_stats_cmperf.SmallBlocksActive++;
323 #if     defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
324     x = splnet();               /*lockl(&osi_fsplock, LOCK_SHORT); */
325 #else
326     MObtainWriteLock(&osi_fsplock, 327);
327 #endif
328     tp = freeSmallList;
329     if (tp)
330         freeSmallList = tp->next;
331 #if     defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
332     splx(x);                    /*unlockl(&osi_fsplock); */
333 #else
334     MReleaseWriteLock(&osi_fsplock);
335 #endif
336     return (char *)tp;
337 }
338
339
340
341 void
342 shutdown_osinet(void)
343 {
344     extern int afs_cold_shutdown;
345
346     AFS_STATCNT(shutdown_osinet);
347     if (afs_cold_shutdown) {
348         struct osi_packet *tp;
349
350         while ((tp = freePacketList)) {
351             freePacketList = tp->next;
352             afs_osi_Free(tp, AFS_LRALLOCSIZ);
353 #ifdef  KERNEL_HAVE_PIN
354             unpin(tp, AFS_LRALLOCSIZ);
355 #endif
356         }
357
358         while ((tp = freeSmallList)) {
359             freeSmallList = tp->next;
360             afs_osi_Free(tp, AFS_SMALLOCSIZ);
361 #ifdef  KERNEL_HAVE_PIN
362             unpin(tp, AFS_SMALLOCSIZ);
363 #endif
364         }
365         afs_preallocs = 512;
366 #ifndef AFS_AIX32_ENV
367         LOCK_INIT(&osi_fsplock, "osi_fsplock");
368 #endif
369         LOCK_INIT(&osi_flplock, "osi_flplock");
370     }
371 }
372 #endif