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