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