openbsd-continues-20021009
[openafs.git] / src / afs / afs_init.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  * afs_init.c - initialize AFS client.
12  *
13  * Implements:
14  */
15
16 #include <afsconfig.h>
17 #include "../afs/param.h"
18
19 RCSID("$Header$");
20
21 #include "../afs/stds.h"
22 #include "../afs/sysincludes.h" /* Standard vendor system headers */
23 #include "../afs/afsincludes.h" /* Afs-based standard headers */
24 #include "../afs/afs_stats.h"   /* afs statistics */
25
26 /* Exported variables */
27 struct osi_dev cacheDev;           /*Cache device*/
28 afs_int32 cacheInfoModTime;                     /*Last time cache info modified*/
29 #if defined(AFS_OSF_ENV) || defined(AFS_DEC_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
30 struct mount *afs_cacheVfsp=0;
31 #elif defined(AFS_LINUX20_ENV)
32 struct super_block *afs_cacheSBp = 0;
33 #else
34 struct vfs *afs_cacheVfsp=0;
35 #endif
36 afs_rwlock_t afs_puttofileLock; /* not used */
37 char *afs_sysname = 0;                  /* So that superuser may change the
38                                          * local value of @sys */
39 char *afs_sysnamelist[MAXNUMSYSNAMES];  /* For support of a list of sysname */
40 int afs_sysnamecount = 0;
41 struct volume *Initialafs_freeVolList;
42 int afs_memvolumes = 0;
43
44 /*
45  * Initialization order is important.  Must first call afs_CacheInit,
46  * then cache file and volume file initialization routines.  Next, the
47  * individual cache entry initialization routines are called.
48  */
49
50
51 /*
52  * afs_CacheInit
53  *
54  * Description:
55  *
56  * Parameters:
57  *      astatSize : The number of stat cache (vnode) entries to
58  *                  allocate.
59  *      afiles    : The number of disk files to allocate to the cache
60  *      ablocks   : The max number of 1 Kbyte blocks that all of
61  *                  the files in the cache may occupy.
62  *      aDentries : Number of dcache entries to allocate.
63  *      aVolumes  : Number of volume cache entries to allocate.
64  *      achunk    : Power of 2 to make the chunks.
65  *      aflags    : Flags passed in.
66  *      inodes    : max inodes to pin down in inode[]
67  *      users     : what should size of per-user access cache be?
68  *
69  * Environment:
70  *      This routine should only be called at initialization time, since
71  *      it reclaims no resources and doesn't sufficiently synchronize
72  *      with other processes.
73  */
74
75 struct cm_initparams cm_initParams;
76 static int afs_cacheinit_flag = 0;
77 int afs_CacheInit(afs_int32 astatSize, afs_int32 afiles, afs_int32 
78         ablocks, afs_int32 aDentries, afs_int32 aVolumes, afs_int32 achunk, 
79         afs_int32 aflags, afs_int32 ninodes, afs_int32 nusers)
80 {
81     register afs_int32 i;
82     register struct volume *tv;
83
84     AFS_STATCNT(afs_CacheInit);
85     /*
86      * Jot down the epoch time, namely when this incarnation of the
87      * Cache Manager started.
88      */
89     afs_stats_cmperf.epoch = pag_epoch = osi_Time();
90 #ifdef SYS_NAME_ID
91     afs_stats_cmperf.sysName_ID = SYS_NAME_ID;
92 #else
93     afs_stats_cmperf.sysName_ID = SYS_NAME_ID_UNDEFINED;
94 #endif /* SYS_NAME_ID */
95
96     printf("Starting AFS cache scan...");
97     if (afs_cacheinit_flag)
98         return 0;
99     afs_cacheinit_flag = 1;
100     cacheInfoModTime = 0;
101     maxIHint = ninodes;
102     nihints = 0;
103     usedihint = 0;
104
105     LOCK_INIT(&afs_ftf, "afs_ftf");
106     RWLOCK_INIT(&afs_xaxs, "afs_xaxs");
107     osi_dnlc_init();
108
109
110 #if     defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
111     {
112         afs_int32 preallocs;
113
114         /*
115          * We want to also reserve space for the gnode struct which is associated
116          * with each vnode (vcache) one; we want to use the pinned pool for them   
117          * since they're referenced at interrupt level.
118          */
119         if (afs_stats_cmperf.SmallBlocksAlloced + astatSize < 3600)
120             preallocs = astatSize;
121         else {
122             preallocs = 3600 - afs_stats_cmperf.SmallBlocksAlloced;
123             if (preallocs <= 0) preallocs = 10;
124         }
125         osi_AllocMoreSSpace(preallocs);
126     }
127 #endif
128     /* 
129      * create volume list structure 
130      */
131     if (aVolumes < 50) aVolumes = 50;
132     else if (aVolumes > 3000) aVolumes = 3000;
133
134     tv = (struct volume *) afs_osi_Alloc(aVolumes * sizeof(struct volume));
135     for (i=0;i<aVolumes-1;i++)
136         tv[i].next = &tv[i+1];
137     tv[aVolumes-1].next = NULL;
138     afs_freeVolList = Initialafs_freeVolList = tv;
139     afs_memvolumes = aVolumes;
140
141     afs_cacheFiles = afiles;
142     afs_cacheStats = astatSize;
143     afs_vcacheInit(astatSize);
144     afs_dcacheInit(afiles, ablocks, aDentries, achunk, aflags);
145 #ifdef AFS_64BIT_CLIENT
146 #ifdef AFS_VM_RDWR_ENV
147     afs_vmMappingEnd = AFS_CHUNKBASE(0x7fffffff);
148 #endif /* AFS_VM_RDWR_ENV */
149 #endif /* AFS_64BIT_CLIENT */
150
151 #if defined(AFS_AIX_ENV) && !defined(AFS_AIX51_ENV)
152     {
153         static void afs_procsize_init(void);
154
155         afs_procsize_init();
156     }
157 #endif
158
159     /* Save the initialization parameters for later pioctl queries. */
160     cm_initParams.cmi_version = CMI_VERSION;
161     cm_initParams.cmi_nChunkFiles = afiles;
162     cm_initParams.cmi_nStatCaches = astatSize;
163     cm_initParams.cmi_nDataCaches = aDentries;
164     cm_initParams.cmi_nVolumeCaches = aVolumes;
165     cm_initParams.cmi_firstChunkSize = AFS_FIRSTCSIZE;
166     cm_initParams.cmi_otherChunkSize = AFS_OTHERCSIZE;
167     cm_initParams.cmi_cacheSize = afs_cacheBlocks;
168     cm_initParams.cmi_setTime = afs_setTime;
169     cm_initParams.cmi_memCache = (aflags & AFSCALL_INIT_MEMCACHE) ? 1 : 0;
170
171     return 0;
172
173 } /*afs_CacheInit*/
174
175
176 /*
177   * afs_ComputeCacheParams
178   *
179   * Description:
180   *     Set some cache parameters.
181   *
182   * Parameters:
183   *     None.
184   */
185
186 void afs_ComputeCacheParms(void)
187 {
188     register afs_int32 i;
189     afs_int32 afs_maxCacheDirty;
190
191     /*
192      * Don't allow more than 2/3 of the files in the cache to be dirty.
193      */
194     afs_maxCacheDirty = (2*afs_cacheFiles) / 3;
195
196     /*
197      * Also, don't allow more than 2/3 of the total space get filled
198      * with dirty chunks.  Compute the total number of chunks required
199      * to fill the cache, make sure we don't set out limit above 2/3 of
200      * that. If the cache size is greater than 1G, avoid overflow at
201      * the expense of precision on the chunk size.
202      */
203     if (afs_cacheBlocks & 0xffe00000) {
204         i = afs_cacheBlocks / (AFS_FIRSTCSIZE >> 10);
205     }
206     else {
207         i = (afs_cacheBlocks << 10) / AFS_FIRSTCSIZE;
208     }
209     i = (2*i) / 3;
210     if (afs_maxCacheDirty > i)
211         afs_maxCacheDirty = i;
212     if (afs_maxCacheDirty < 1)
213         afs_maxCacheDirty = 1;
214     afs_stats_cmperf.cacheMaxDirtyChunks = afs_maxCacheDirty;
215 } /*afs_ComputeCacheParms*/
216
217
218 /*
219  * afs_InitVolumeInfo
220  *
221  * Description:
222  *      Set up the volume info storage file.
223  *
224  * Parameters:
225  *      afile : the file to be declared to be the volume info storage
226  *              file for AFS.  It must be already truncated to 0 length.
227  *
228  * Environment:
229  *      This function is called only during initialization.
230  *
231  *      WARNING: Data will be written to this file over time by AFS.
232  */
233
234 static int LookupInodeByPath(char *filename, ino_t *inode)
235 {
236     afs_int32 code;
237
238 #ifdef AFS_LINUX22_ENV
239     struct dentry *dp;
240     code = gop_lookupname(filename, AFS_UIOSYS, 0, NULL, &dp);
241     if (code) return code;
242     *inode = dp->d_inode->i_ino;
243     dput(dp);
244 #else
245     struct vnode *filevp;
246     code = gop_lookupname(filename, AFS_UIOSYS, 0, NULL, &filevp);
247     if (code) return code;
248     *inode = afs_vnodeToInumber(filevp);
249 #ifdef AFS_DEC_ENV
250     grele(filevp);
251 #else
252     AFS_RELE((struct vnode *)filevp);
253 #endif
254 #endif /* AFS_LINUX22_ENV */
255
256     return 0;
257 }
258
259 int afs_InitCellInfo(char *afile)
260 {
261     ino_t inode;
262     int code;
263
264     code = LookupInodeByPath(afile, &inode);
265     return afs_cellname_init(inode, code);
266 }
267
268 int afs_InitVolumeInfo(char *afile)
269 {
270     int code;
271     struct osi_file *tfile;
272
273     AFS_STATCNT(afs_InitVolumeInfo);
274     code = LookupInodeByPath(afile, &volumeInode);
275     if (code) return code;
276     tfile = afs_CFileOpen(volumeInode);
277     afs_CFileTruncate(tfile, 0);
278     afs_CFileClose(tfile);
279     return 0;
280 }
281
282 /*
283  * afs_InitCacheInfo
284  *
285  * Description:
286  *      Set up the given file as the AFS cache info file.
287  *
288  * Parameters:
289  *      afile : Name of the file assumed to be the cache info file
290  *              for the Cache Manager; it will be used as such.
291  * Side Effects:  This sets afs_fragsize, which is used in the cache usage 
292  *                calculations such as in afs_adjustsize()
293  *
294  * Environment:
295  *      This function is called only during initialization.  The given
296  *      file should NOT be truncated to 0 lenght; its contents descrebe
297  *      what data is really in the cache.
298  *
299  *      WARNING: data will be written to this file over time by AFS.
300  *
301  * NOTE: Starting to use separate osi_InitCacheInfo() routines to clean up
302  * code.
303  *
304  */
305 int afs_InitCacheInfo(register char *afile)
306 {
307     register afs_int32 code;
308     struct osi_stat tstat;
309     register struct osi_file *tfile;
310     struct afs_fheader theader;
311     struct vnode *filevp;
312     int goodFile;
313
314     AFS_STATCNT(afs_InitCacheInfo);
315     if(cacheDiskType != AFS_FCACHE_TYPE_UFS)
316         osi_Panic("afs_InitCacheInfo --- called for non-ufs cache!");
317 #ifdef AFS_LINUX22_ENV
318     code = osi_InitCacheInfo(afile);
319     if (code) return code;
320 #else
321     code = gop_lookupname(afile, AFS_UIOSYS, 0, NULL, &filevp);
322     if (code || !filevp) return ENOENT;
323     {
324 #if     defined(AFS_SUN56_ENV)
325         struct statvfs64 st;
326 #else
327 #if     defined(AFS_HPUX102_ENV)
328         struct k_statvfs st;
329 #else
330 #if     defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) ||defined(AFS_HPUX100_ENV)
331         struct statvfs st;
332 #else 
333 #if defined(AFS_DUX40_ENV)
334         struct nstatfs st;
335 #else
336         struct statfs st;
337 #endif /* DUX40 */
338 #endif /* SUN5 SGI */
339 #endif /* HP 10.20 */
340 #endif /* SUN56 */
341
342 #if     defined(AFS_SGI_ENV)
343 #ifdef AFS_SGI65_ENV
344         VFS_STATVFS(filevp->v_vfsp, &st, NULL, code);
345         if (!code) 
346 #else
347         if (!VFS_STATFS(filevp->v_vfsp, &st, NULL))
348 #endif /* AFS_SGI65_ENV */
349 #else  /* AFS_SGI_ENV */
350 #if     defined(AFS_SUN5_ENV) || defined(AFS_HPUX100_ENV)
351         if (!VFS_STATVFS(filevp->v_vfsp, &st)) 
352 #else
353 #ifdef  AFS_OSF_ENV
354       
355         VFS_STATFS(filevp->v_vfsp, code);
356         /* struct copy */
357         st = filevp->v_vfsp->m_stat;
358         if (code == 0)
359 #else  /* AFS_OSF_ENV */
360 #ifdef AFS_AIX41_ENV
361         if (!VFS_STATFS(filevp->v_vfsp, &st, &afs_osi_cred))
362 #else
363 #ifdef AFS_LINUX20_ENV
364         {
365             KERNEL_SPACE_DECL;
366             TO_USER_SPACE();
367
368             VFS_STATFS(filevp->v_vfsp, &st);
369             TO_KERNEL_SPACE();
370         }
371 #else
372 #if defined(AFS_DARWIN_ENV)
373         if (!VFS_STATFS(filevp->v_mount, &st, current_proc()))
374 #else 
375 #if defined(AFS_XBSD_ENV)
376         if (!VFS_STATFS(filevp->v_mount, &st, curproc))
377 #else 
378         if (!VFS_STATFS(filevp->v_vfsp, &st))  
379 #endif /* AFS_XBSD_ENV */
380 #endif /* AFS_DARWIN_ENV */
381 #endif /* AFS_LINUX20_ENV */
382 #endif /* AIX41 */
383 #endif /* OSF */
384 #endif /* SUN5 HP10 */
385 #endif /* SGI */
386 #if     defined(AFS_SUN5_ENV) || defined(AFS_HPUX100_ENV)
387             afs_fsfragsize = st.f_frsize - 1; 
388 #else
389             afs_fsfragsize = st.f_bsize - 1; 
390 #endif
391     }
392 #ifdef AFS_LINUX20_ENV
393     cacheInode = filevp->i_ino;
394     afs_cacheSBp = filevp->i_sb;
395 #else
396 #ifdef AFS_OBSD_ENV
397     cacheInode = VTOI(filevp)->i_number;
398     cacheDev.mp = filevp->v_mount;
399     cacheDev.held_vnode = filevp;
400     AFS_HOLD(filevp);           /* Make sure mount point stays busy. XXX */
401 #else
402 #if defined(AFS_SGI62_ENV) || defined(AFS_HAVE_VXFS) || defined(AFS_DARWIN_ENV)
403     afs_InitDualFSCacheOps(filevp);
404 #endif
405     cacheInode = afs_vnodeToInumber(filevp);
406     cacheDev.dev = afs_vnodeToDev(filevp);
407     afs_cacheVfsp = filevp->v_vfsp;
408 #endif /* AFS_OBSD_ENV */
409 #endif /* AFS_LINUX20_ENV */
410     AFS_RELE((struct vnode *)filevp);
411 #endif /* AFS_LINUX22_ENV */
412     tfile = osi_UFSOpen(cacheInode);
413     afs_osi_Stat(tfile, &tstat);
414     cacheInfoModTime = tstat.mtime;
415     code = afs_osi_Read(tfile, -1, &theader, sizeof(theader));
416     goodFile = 0;
417     if (code == sizeof(theader)) {
418         /* read the header correctly */
419         if (theader.magic == AFS_FHMAGIC &&
420             theader.firstCSize == AFS_FIRSTCSIZE &&
421             theader.otherCSize == AFS_OTHERCSIZE &&
422             theader.version == AFS_CI_VERSION
423             )
424             goodFile = 1;
425     }
426     if (!goodFile) {
427         /* write out a good file label */
428         theader.magic = AFS_FHMAGIC;
429         theader.firstCSize = AFS_FIRSTCSIZE;
430         theader.otherCSize = AFS_OTHERCSIZE;
431         theader.version = AFS_CI_VERSION;
432         afs_osi_Write(tfile, 0, &theader, sizeof(theader));
433         /*
434          * Truncate the rest of the file, since it may be arbitrarily
435          * wrong
436          */
437         osi_UFSTruncate(tfile, sizeof(struct afs_fheader));
438     }
439     /* Leave the file open now, since reopening the file makes public pool
440      * vnode systems (like OSF/Alpha) much harder to handle, That's because
441      * they can do a vnode recycle operation any time we open a file, which
442      * we'd do on any afs_GetDSlot call, etc.
443      */
444     afs_cacheInodep = (struct osi_file *)tfile;
445     return 0;
446 }
447
448 int afs_resourceinit_flag = 0;
449 int afs_ResourceInit(int preallocs)
450 {
451     register afs_int32 i;
452     static struct rx_securityClass *secobj;
453
454     AFS_STATCNT(afs_ResourceInit);
455     RWLOCK_INIT(&afs_xuser, "afs_xuser");
456     RWLOCK_INIT(&afs_xvolume, "afs_xvolume");
457     RWLOCK_INIT(&afs_xserver, "afs_xserver");
458     RWLOCK_INIT(&afs_xsrvAddr, "afs_xsrvAddr");
459     RWLOCK_INIT(&afs_icl_lock, "afs_icl_lock");
460     RWLOCK_INIT(&afs_xinterface, "afs_xinterface");
461     LOCK_INIT(&afs_puttofileLock, "afs_puttofileLock");
462 #ifndef AFS_AIX32_ENV
463     LOCK_INIT(&osi_fsplock, "osi_fsplock");
464 #endif
465     LOCK_INIT(&osi_flplock, "osi_flplock");
466     RWLOCK_INIT(&afs_xconn, "afs_xconn");
467
468     afs_CellInit();
469     afs_InitCBQueue(1);  /* initialize callback queues */
470
471     if (afs_resourceinit_flag == 0) {
472         afs_resourceinit_flag = 1;
473         for (i=0;i<NFENTRIES;i++)
474             fvTable[i] = 0;
475         for(i=0;i<MAXNUMSYSNAMES;i++)
476           afs_sysnamelist[i] = afs_osi_Alloc(MAXSYSNAME);
477         afs_sysname = afs_sysnamelist[0];
478         strcpy(afs_sysname, SYS_NAME);
479         afs_sysnamecount = 1;
480 #if     defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
481     {  
482
483        if ((preallocs > 256) && (preallocs < 3600))
484            afs_preallocs = preallocs;
485        osi_AllocMoreSSpace(afs_preallocs);
486        osi_AllocMoreMSpace(100); 
487     }
488 #endif
489     }
490     
491     secobj = rxnull_NewServerSecurityObject();
492     afs_server =
493         rx_NewService(0, 1, "afs", &secobj, 1, RXAFSCB_ExecuteRequest);
494     afs_server =
495         rx_NewService(0, RX_STATS_SERVICE_ID, "rpcstats", &secobj, 1,
496                       RXSTATS_ExecuteRequest);
497     rx_StartServer(0);
498     afs_osi_Wakeup(&afs_server);        /* wakeup anyone waiting for it */
499     return 0;
500
501 } /*afs_ResourceInit*/
502
503 #if defined(AFS_AIX_ENV) && !defined(AFS_AIX51_ENV)
504
505 /*
506  * AIX dynamic sizeof(struct proc)
507  *
508  * AIX keeps its proc structures in an array.  The size of struct proc
509  * varies from release to release of the OS.  In order to maintain
510  * binary compatibility with releases later than what we build on, we
511  * need to determine the size of struct proc at run time.
512  *
513  * We need this in order to walk the proc[] array to do PAG garbage
514  * collection.
515  *
516  * We also need this in order to support 'klog -setpag', since the
517  * kernel code needs to locate the proc structure for the parent process
518  * of the current process.
519  *
520  * To compute sizeof(struct proc), we need the addresses of two proc
521  * structures and their corresponding pids.  Given the pids, we can use
522  * the PROCMASK() macro to compute their corresponding indices in the
523  * proc[] array.  By dividing the distance between the pointers by the
524  * number of proc structures, we can compute the size of a single proc
525  * structure.
526  *
527  * We know the base address of the proc table from v.vb_proc:
528  *
529  * <sys/sysconfig.h> declares sysconfig() and SYS_GETPARMS;
530  * (we don't use this, but I note it here for completeness)
531  *
532  * <sys/var.h> declares struct var and external variable v;
533  *
534  * v.v_proc             NPROC
535  * v.vb_proc            &proc[0]
536  * v.ve_proc            &proc[x] (current highwater mark for
537  *                                proc[] array usage)
538  *
539  * The first proc pointer is v.vb_proc, which is the proc structure for
540  * process 0.  Process 0's pointer to its first child is the other proc
541  * pointer.  If process 0 has no children, we simply give up and do not
542  * support features that require knowing the size of struct proc.
543  */
544
545 static void afs_procsize_init(void)
546 {
547     struct proc *p0;    /* pointer to process 0 */
548     struct proc *pN;    /* pointer to process 0's first child */
549 #ifdef AFS_AIX51_ENV
550     struct pvproc *pV;
551 #endif
552     int pN_index;
553     ptrdiff_t pN_offset;
554     int procsize;
555
556     p0 = (struct proc *)v.vb_proc;
557     if (!p0) {
558         afs_gcpags = AFS_GCPAGS_EPROC0;
559         return;
560     }
561
562 #ifdef AFS_AIX51_ENV
563     pN = (struct proc *)0;
564     pV = p0->p_pvprocp;
565     if (pV) {
566         pV = pV->pv_child;
567         if (pV)
568             pN = pV->pv_procp;
569     }
570 #else
571     pN = p0->p_child;
572 #endif
573     if (!pN) {
574         afs_gcpags = AFS_GCPAGS_EPROCN;
575         return;
576     }
577
578     if (pN->p_pid == p0->p_pid) {
579         afs_gcpags = AFS_GCPAGS_EEQPID;
580         return;
581     }
582
583     pN_index = PROCMASK(pN->p_pid);
584     pN_offset = ((char *)pN - (char *)p0);
585     procsize = pN_offset / pN_index;
586
587     /*
588      * check that the computation was exact
589      */
590
591     if (pN_index * procsize != pN_offset) {
592         afs_gcpags = AFS_GCPAGS_EINEXACT;
593         return;
594     }
595
596     /*
597      * check that the proc table size is a multiple of procsize.
598      */
599
600     if ((((char *)v.ve_proc - (char *)v.vb_proc) % procsize) != 0) {
601         afs_gcpags = AFS_GCPAGS_EPROCEND;
602         return;
603     }
604
605     /* okay, use it */
606
607     afs_gcpags_procsize = procsize;
608 }
609 #endif
610
611 /*
612  * shutdown_cache
613  *
614  * Description:
615  *      Clean up and shut down the AFS cache.
616  *
617  * Parameters:
618  *      None.
619  *
620  * Environment:
621  *      Nothing interesting.
622  */
623 void shutdown_cache(void)
624 {
625   AFS_STATCNT(shutdown_cache);
626   afs_WriteThroughDSlots();
627   if (afs_cold_shutdown) {
628     afs_cacheinit_flag = 0;
629     shutdown_dcache();
630     shutdown_vcache();
631
632     afs_cacheStats = 0;
633     afs_cacheFiles = afs_cacheBlocks = 0;
634     pag_epoch = maxIHint = nihints = usedihint = 0;
635     pagCounter = 0;
636     cacheInode = volumeInode = (ino_t)0;
637
638
639     cacheInfoModTime = 0;
640
641     afs_fsfragsize = 1023;
642     memset((char *)&afs_stats_cmperf, 0, sizeof(afs_stats_cmperf));
643     memset((char *)&cacheDev, 0, sizeof(struct osi_dev));
644     osi_dnlc_shutdown();
645   }
646 } /*shutdown_cache*/
647
648
649 void shutdown_vnodeops(void)
650 {
651 #if !defined(AFS_SGI_ENV) && !defined(AFS_SUN_ENV) && !defined(AFS_SUN5_ENV)
652     struct buf *afs_bread_freebp = 0;
653 #endif
654     
655
656     AFS_STATCNT(shutdown_vnodeops);
657     if (afs_cold_shutdown) {
658 #ifndef AFS_SUN5_ENV    /* XXX */
659       lastWarnTime = 0;
660 #endif
661 #ifndef AFS_LINUX20_ENV
662       afs_rd_stash_i = 0;      
663 #endif
664 #if !defined(AFS_SGI_ENV) && !defined(AFS_SUN_ENV) && !defined(AFS_SUN5_ENV)
665       afs_bread_freebp = 0;
666 #endif
667       shutdown_mariner();
668   }
669 }
670
671
672 void shutdown_AFS(void)
673 {
674     int i;
675     register struct srvAddr *sa;
676
677     AFS_STATCNT(shutdown_AFS);
678     if (afs_cold_shutdown) {
679       afs_resourceinit_flag = 0; 
680       /* 
681        * Free Volumes table allocations 
682        */
683       { 
684         struct volume *tv;
685         for (i = 0; i < NVOLS; i++) {
686             for (tv = afs_volumes[i]; tv; tv = tv->next) {
687                 if (tv->name) {
688                     afs_osi_Free(tv->name, strlen(tv->name)+1);
689                     tv->name = 0;
690                 }
691             }
692             afs_volumes[i] = 0;
693         }
694       }
695
696       /* 
697        * Free FreeVolList allocations 
698        */
699       afs_osi_Free(Initialafs_freeVolList, afs_memvolumes * sizeof(struct volume));
700       afs_freeVolList = Initialafs_freeVolList = 0;
701
702       /* XXX HACK fort MEM systems XXX 
703        *
704        * For -memcache cache managers when we run out of free in memory volumes
705        * we simply malloc more; we won't be able to free those additional volumes.
706        */
707
708       
709
710       /* 
711        * Free Users table allocation 
712        */
713       { 
714         struct unixuser *tu, *ntu;
715         for (i=0; i < NUSERS; i++) {
716             for (tu=afs_users[i]; tu; tu = ntu) {
717                 ntu = tu->next;
718                 if (tu->stp)
719                     afs_osi_Free(tu->stp, tu->stLen);
720                 if (tu->exporter)
721                     EXP_RELE(tu->exporter);
722                 afs_osi_Free(tu, sizeof(struct unixuser));
723             }
724             afs_users[i] = 0;
725         }
726       }
727
728       /* 
729        * Free Servers table allocation 
730        */
731       { 
732         struct server *ts, *nts;
733         struct conn *tc, *ntc;
734         register struct afs_cbr *tcbrp, *tbrp;
735
736         for (i=0; i < NSERVERS; i++) {
737             for (ts = afs_servers[i]; ts; ts = nts) {
738                 nts = ts->next;
739                 for (sa = ts->addr; sa; sa = sa->next_sa) {     
740                     if (sa->conns) {
741                         /*
742                          * Free all server's connection structs
743                          */
744                         tc = sa->conns;
745                         while (tc) {
746                             ntc = tc->next;
747                             AFS_GUNLOCK();
748                             rx_DestroyConnection(tc->id);
749                             AFS_GLOCK();
750                             afs_osi_Free(tc, sizeof(struct conn));
751                             tc = ntc;
752                         }
753                     }
754                 }
755                 for (tcbrp = ts->cbrs; tcbrp;  tcbrp = tbrp) {
756                     /*
757                      * Free all server's callback structs
758                      */
759                     tbrp = tcbrp->next;
760                     afs_FreeCBR(tcbrp);
761                 }
762                 afs_osi_Free(ts, sizeof(struct server));
763             }
764             afs_servers[i] = 0;
765         }
766       }
767       for (i=0; i<NFENTRIES; i++)
768         fvTable[i] = 0;
769       /* Reinitialize local globals to defaults */
770       for(i=0; i<MAXNUMSYSNAMES; i++)
771         afs_osi_Free(afs_sysnamelist[i], MAXSYSNAME);
772       afs_sysname = 0;
773       afs_sysnamecount = 0;
774       afs_marinerHost = 0;
775       afs_setTimeHost = NULL;
776       afs_volCounter = 1;
777       afs_waitForever = afs_waitForeverCount = 0;
778       afs_FVIndex = -1;
779       afs_server = (struct rx_service *)0;
780       RWLOCK_INIT(&afs_xconn, "afs_xconn");
781       memset((char *)&afs_rootFid, 0, sizeof(struct VenusFid));
782       RWLOCK_INIT(&afs_xuser, "afs_xuser");
783       RWLOCK_INIT(&afs_xvolume, "afs_xvolume");
784       RWLOCK_INIT(&afs_xserver, "afs_xserver");
785       LOCK_INIT(&afs_puttofileLock, "afs_puttofileLock");
786
787       shutdown_cell();
788     }
789 }