windows-scache-release-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_DARWIN_ENV)
385         if (!VFS_STATFS(filevp->v_mount, &st, current_proc()))
386 #elif defined(AFS_FBSD50_ENV)
387         if (!VFS_STATFS(filevp->v_mount, &st, curthread))
388 #elif defined(AFS_XBSD_ENV)
389         if (!VFS_STATFS(filevp->v_mount, &st, curproc))
390 #else
391         if (!VFS_STATFS(filevp->v_vfsp, &st))
392 #endif /* SGI... */
393 #if     defined(AFS_SUN5_ENV) || defined(AFS_HPUX100_ENV)
394             afs_fsfragsize = st.f_frsize - 1;
395 #else
396             afs_fsfragsize = st.f_bsize - 1;
397 #endif
398     }
399 #if defined(AFS_LINUX20_ENV)
400     cacheInode = filevp->i_ino;
401     afs_cacheSBp = filevp->i_sb;
402 #elif defined(AFS_XBSD_ENV)
403     cacheInode = VTOI(filevp)->i_number;
404     cacheDev.mp = filevp->v_mount;
405     cacheDev.held_vnode = filevp;
406     vref(filevp);               /* Make sure mount point stays busy. XXX */
407 #if !defined(AFS_OBSD_ENV)
408     afs_cacheVfsp = filevp->v_vfsp;
409 #endif
410 #else
411 #if defined(AFS_SGI62_ENV) || defined(AFS_HAVE_VXFS) || defined(AFS_DARWIN_ENV)
412     afs_InitDualFSCacheOps(filevp);
413 #endif
414     cacheInode = afs_vnodeToInumber(filevp);
415     cacheDev.dev = afs_vnodeToDev(filevp);
416     afs_cacheVfsp = filevp->v_vfsp;
417 #endif /* AFS_LINUX20_ENV */
418     AFS_RELE(filevp);
419 #endif /* AFS_LINUX22_ENV */
420     tfile = osi_UFSOpen(cacheInode);
421     afs_osi_Stat(tfile, &tstat);
422     cacheInfoModTime = tstat.mtime;
423     code = afs_osi_Read(tfile, -1, &theader, sizeof(theader));
424     goodFile = 0;
425     if (code == sizeof(theader)) {
426         /* read the header correctly */
427         if (theader.magic == AFS_FHMAGIC
428             && theader.firstCSize == AFS_FIRSTCSIZE
429             && theader.otherCSize == AFS_OTHERCSIZE
430             && theader.version == AFS_CI_VERSION)
431             goodFile = 1;
432     }
433     if (!goodFile) {
434         /* write out a good file label */
435         theader.magic = AFS_FHMAGIC;
436         theader.firstCSize = AFS_FIRSTCSIZE;
437         theader.otherCSize = AFS_OTHERCSIZE;
438         theader.version = AFS_CI_VERSION;
439         afs_osi_Write(tfile, 0, &theader, sizeof(theader));
440         /*
441          * Truncate the rest of the file, since it may be arbitrarily
442          * wrong
443          */
444         osi_UFSTruncate(tfile, sizeof(struct afs_fheader));
445     }
446     /* Leave the file open now, since reopening the file makes public pool
447      * vnode systems (like OSF/Alpha) much harder to handle, That's because
448      * they can do a vnode recycle operation any time we open a file, which
449      * we'd do on any afs_GetDSlot call, etc.
450      */
451     afs_cacheInodep = (struct osi_file *)tfile;
452     return 0;
453 }
454
455 int afs_resourceinit_flag = 0;
456 int
457 afs_ResourceInit(int preallocs)
458 {
459     register afs_int32 i;
460     static struct rx_securityClass *secobj;
461
462     AFS_STATCNT(afs_ResourceInit);
463     RWLOCK_INIT(&afs_xuser, "afs_xuser");
464     RWLOCK_INIT(&afs_xvolume, "afs_xvolume");
465     RWLOCK_INIT(&afs_xserver, "afs_xserver");
466     RWLOCK_INIT(&afs_xsrvAddr, "afs_xsrvAddr");
467     RWLOCK_INIT(&afs_icl_lock, "afs_icl_lock");
468     RWLOCK_INIT(&afs_xinterface, "afs_xinterface");
469     LOCK_INIT(&afs_puttofileLock, "afs_puttofileLock");
470 #ifndef AFS_FBSD_ENV
471     LOCK_INIT(&osi_fsplock, "osi_fsplock");
472     LOCK_INIT(&osi_flplock, "osi_flplock");
473 #endif
474     RWLOCK_INIT(&afs_xconn, "afs_xconn");
475
476     afs_CellInit();
477     afs_InitCBQueue(1);         /* initialize callback queues */
478
479     if (afs_resourceinit_flag == 0) {
480         afs_resourceinit_flag = 1;
481         for (i = 0; i < NFENTRIES; i++)
482             fvTable[i] = 0;
483         for (i = 0; i < MAXNUMSYSNAMES; i++)
484             afs_sysnamelist[i] = afs_osi_Alloc(MAXSYSNAME);
485         afs_sysname = afs_sysnamelist[0];
486         strcpy(afs_sysname, SYS_NAME);
487         afs_sysnamecount = 1;
488     }
489
490     secobj = rxnull_NewServerSecurityObject();
491     afs_server =
492         rx_NewService(0, 1, "afs", &secobj, 1, RXAFSCB_ExecuteRequest);
493     afs_server =
494         rx_NewService(0, RX_STATS_SERVICE_ID, "rpcstats", &secobj, 1,
495                       RXSTATS_ExecuteRequest);
496     rx_StartServer(0);
497     afs_osi_Wakeup(&afs_server);        /* wakeup anyone waiting for it */
498     return 0;
499
500 }                               /*afs_ResourceInit */
501
502 #if defined(AFS_AIX_ENV) && !defined(AFS_AIX51_ENV)
503
504 /*
505  * AIX dynamic sizeof(struct proc)
506  *
507  * AIX keeps its proc structures in an array.  The size of struct proc
508  * varies from release to release of the OS.  In order to maintain
509  * binary compatibility with releases later than what we build on, we
510  * need to determine the size of struct proc at run time.
511  *
512  * We need this in order to walk the proc[] array to do PAG garbage
513  * collection.
514  *
515  * We also need this in order to support 'klog -setpag', since the
516  * kernel code needs to locate the proc structure for the parent process
517  * of the current process.
518  *
519  * To compute sizeof(struct proc), we need the addresses of two proc
520  * structures and their corresponding pids.  Given the pids, we can use
521  * the PROCMASK() macro to compute their corresponding indices in the
522  * proc[] array.  By dividing the distance between the pointers by the
523  * number of proc structures, we can compute the size of a single proc
524  * structure.
525  *
526  * We know the base address of the proc table from v.vb_proc:
527  *
528  * <sys/sysconfig.h> declares sysconfig() and SYS_GETPARMS;
529  * (we don't use this, but I note it here for completeness)
530  *
531  * <sys/var.h> declares struct var and external variable v;
532  *
533  * v.v_proc             NPROC
534  * v.vb_proc            &proc[0]
535  * v.ve_proc            &proc[x] (current highwater mark for
536  *                                proc[] array usage)
537  *
538  * The first proc pointer is v.vb_proc, which is the proc structure for
539  * process 0.  Process 0's pointer to its first child is the other proc
540  * pointer.  If process 0 has no children, we simply give up and do not
541  * support features that require knowing the size of struct proc.
542  */
543
544 static void
545 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 #ifdef AFS_AIX51_ENV
562     pN = (struct proc *)0;
563     pV = p0->p_pvprocp;
564     if (pV) {
565         pV = pV->pv_child;
566         if (pV)
567             pN = pV->pv_procp;
568     }
569 #else
570     pN = p0->p_child;
571 #endif
572     if (!pN) {
573         afs_gcpags = AFS_GCPAGS_EPROCN;
574         return;
575     }
576
577     if (pN->p_pid == p0->p_pid) {
578         afs_gcpags = AFS_GCPAGS_EEQPID;
579         return;
580     }
581
582     pN_index = PROCMASK(pN->p_pid);
583     pN_offset = ((char *)pN - (char *)p0);
584     procsize = pN_offset / pN_index;
585
586     /*
587      * check that the computation was exact
588      */
589
590     if (pN_index * procsize != pN_offset) {
591         afs_gcpags = AFS_GCPAGS_EINEXACT;
592         return;
593     }
594
595     /*
596      * check that the proc table size is a multiple of procsize.
597      */
598
599     if ((((char *)v.ve_proc - (char *)v.vb_proc) % procsize) != 0) {
600         afs_gcpags = AFS_GCPAGS_EPROCEND;
601         return;
602     }
603
604     /* okay, use it */
605
606     afs_gcpags_procsize = procsize;
607 }
608 #endif
609
610 /*
611  * shutdown_cache
612  *
613  * Description:
614  *      Clean up and shut down the AFS cache.
615  *
616  * Parameters:
617  *      None.
618  *
619  * Environment:
620  *      Nothing interesting.
621  */
622 void
623 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 #if defined(AFS_XBSD_ENV)
637         vrele(volumeVnode);     /* let it go, finally. */
638         volumeVnode = NULL;
639         if (cacheDev.held_vnode) {
640             vrele(cacheDev.held_vnode);
641             cacheDev.held_vnode = NULL;
642         }
643 #endif
644         cacheInode = volumeInode = (ino_t) 0;
645
646         cacheInfoModTime = 0;
647
648         afs_fsfragsize = 1023;
649         memset((char *)&afs_stats_cmperf, 0, sizeof(afs_stats_cmperf));
650         memset((char *)&cacheDev, 0, sizeof(struct osi_dev));
651         osi_dnlc_shutdown();
652     }
653 }                               /*shutdown_cache */
654
655
656 void
657 shutdown_vnodeops(void)
658 {
659 #if !defined(AFS_SGI_ENV) && !defined(AFS_SUN5_ENV)
660     struct buf *afs_bread_freebp = 0;
661 #endif
662
663
664     AFS_STATCNT(shutdown_vnodeops);
665     if (afs_cold_shutdown) {
666 #ifndef AFS_SUN5_ENV            /* XXX */
667         lastWarnTime = 0;
668 #endif
669 #ifndef AFS_LINUX20_ENV
670         afs_rd_stash_i = 0;
671 #endif
672 #if !defined(AFS_SGI_ENV) && !defined(AFS_SUN5_ENV)
673         afs_bread_freebp = 0;
674 #endif
675         shutdown_mariner();
676     }
677 }
678
679
680 void
681 shutdown_AFS(void)
682 {
683     int i;
684     register struct srvAddr *sa;
685
686     AFS_STATCNT(shutdown_AFS);
687     if (afs_cold_shutdown) {
688         afs_resourceinit_flag = 0;
689         /* 
690          * Free Volumes table allocations 
691          */
692         {
693             struct volume *tv;
694             for (i = 0; i < NVOLS; i++) {
695                 for (tv = afs_volumes[i]; tv; tv = tv->next) {
696                     if (tv->name) {
697                         afs_osi_Free(tv->name, strlen(tv->name) + 1);
698                         tv->name = 0;
699                     }
700                 }
701                 afs_volumes[i] = 0;
702             }
703         }
704
705         /* 
706          * Free FreeVolList allocations 
707          */
708         afs_osi_Free(Initialafs_freeVolList,
709                      afs_memvolumes * sizeof(struct volume));
710         afs_freeVolList = Initialafs_freeVolList = 0;
711
712         /* XXX HACK fort MEM systems XXX 
713          *
714          * For -memcache cache managers when we run out of free in memory volumes
715          * we simply malloc more; we won't be able to free those additional volumes.
716          */
717
718
719
720         /* 
721          * Free Users table allocation 
722          */
723         {
724             struct unixuser *tu, *ntu;
725             for (i = 0; i < NUSERS; i++) {
726                 for (tu = afs_users[i]; tu; tu = ntu) {
727                     ntu = tu->next;
728                     if (tu->stp)
729                         afs_osi_Free(tu->stp, tu->stLen);
730                     if (tu->exporter)
731                         EXP_RELE(tu->exporter);
732                     afs_osi_Free(tu, sizeof(struct unixuser));
733                 }
734                 afs_users[i] = 0;
735             }
736         }
737
738         /* 
739          * Free Servers table allocation 
740          */
741         {
742             struct server *ts, *nts;
743             struct conn *tc, *ntc;
744             register struct afs_cbr *tcbrp, *tbrp;
745
746             for (i = 0; i < NSERVERS; i++) {
747                 for (ts = afs_servers[i]; ts; ts = nts) {
748                     nts = ts->next;
749                     for (sa = ts->addr; sa; sa = sa->next_sa) {
750                         if (sa->conns) {
751                             /*
752                              * Free all server's connection structs
753                              */
754                             tc = sa->conns;
755                             while (tc) {
756                                 ntc = tc->next;
757                                 AFS_GUNLOCK();
758                                 rx_DestroyConnection(tc->id);
759                                 AFS_GLOCK();
760                                 afs_osi_Free(tc, sizeof(struct conn));
761                                 tc = ntc;
762                             }
763                         }
764                     }
765                     for (tcbrp = ts->cbrs; tcbrp; tcbrp = tbrp) {
766                         /*
767                          * Free all server's callback structs
768                          */
769                         tbrp = tcbrp->next;
770                         afs_FreeCBR(tcbrp);
771                     }
772                     afs_osi_Free(ts, sizeof(struct server));
773                 }
774                 afs_servers[i] = 0;
775             }
776         }
777         for (i = 0; i < NFENTRIES; i++)
778             fvTable[i] = 0;
779         /* Reinitialize local globals to defaults */
780         for (i = 0; i < MAXNUMSYSNAMES; i++)
781             afs_osi_Free(afs_sysnamelist[i], MAXSYSNAME);
782         afs_sysname = 0;
783         afs_sysnamecount = 0;
784         afs_marinerHost = 0;
785         afs_setTimeHost = NULL;
786         afs_volCounter = 1;
787         afs_waitForever = afs_waitForeverCount = 0;
788         afs_FVIndex = -1;
789         afs_server = (struct rx_service *)0;
790         RWLOCK_INIT(&afs_xconn, "afs_xconn");
791         memset((char *)&afs_rootFid, 0, sizeof(struct VenusFid));
792         RWLOCK_INIT(&afs_xuser, "afs_xuser");
793         RWLOCK_INIT(&afs_xvolume, "afs_xvolume");
794         RWLOCK_INIT(&afs_xserver, "afs_xserver");
795         LOCK_INIT(&afs_puttofileLock, "afs_puttofileLock");
796
797         shutdown_cell();
798         shutdown_server();
799     }
800 }