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