rx-glock-order-headers-correctly-so-its-defined-or-not-consistently-20020322
[openafs.git] / src / afs / afs_volume.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  * Implements:
12  * afs_vtoi (local)
13  * afs_UFSGetVolSlot
14  * afs_MemGetVolSlot
15  * afs_CheckVolumeNames
16  * afs_FindVolume
17  */
18 #include <afsconfig.h>
19 #include "../afs/param.h"
20
21 RCSID("$Header$");
22
23 #include "../afs/stds.h"
24 #include "../afs/sysincludes.h" /* Standard vendor system headers */
25
26 #if !defined(UKERNEL)
27 #include <net/if.h>
28 #include <netinet/in.h>
29
30 #ifdef AFS_SGI62_ENV
31 #include "../h/hashing.h"
32 #endif
33 #if !defined(AFS_HPUX110_ENV) && !defined(AFS_LINUX20_ENV)
34 #include <netinet/in_var.h>
35 #endif /* ! AFS_HPUX110_ENV */
36 #endif /* !defined(UKERNEL) */
37
38 #include "../afs/afsincludes.h" /* Afs-based standard headers */
39 #include "../afs/afs_stats.h"   /* afs statistics */
40
41 #if     defined(AFS_SUN56_ENV)
42 #include <inet/led.h>
43 #include <inet/common.h>
44 #if     defined(AFS_SUN58_ENV)
45 #include <netinet/ip6.h>
46 #endif
47 #include <inet/ip.h>
48 #endif
49
50 /* Imported variables */
51 extern afs_rwlock_t afs_xserver;
52 extern afs_rwlock_t afs_xsrvAddr; 
53 extern afs_rwlock_t afs_xvcache;
54 extern afs_rwlock_t afs_xcbhash;
55 extern struct srvAddr *afs_srvAddrs[NSERVERS];  /* Hashed by server's ip */
56 extern int afs_totalSrvAddrs;
57
58 /* In case we don't have the vl error table yet. */
59 #ifndef ERROR_TABLE_BASE_VL
60 #define ERROR_TABLE_BASE_VL     (363520L)
61 #define VL_NOENT                (363524L)
62 #endif /* vlserver error base define */
63
64 /* Exported variables */
65 ino_t volumeInode;                      /*Inode for VolumeItems file*/
66 afs_rwlock_t afs_xvolume;               /* allocation lock for volumes */
67 struct volume *afs_freeVolList;
68 struct volume *afs_volumes[NVOLS];
69 afs_int32 afs_volCounter = 1; /* for allocating volume indices */
70 afs_int32 fvTable[NFENTRIES];
71
72 /* Forward declarations */
73 static struct volume *afs_NewVolumeByName(char *aname, afs_int32 acell, int agood,
74                                    struct vrequest *areq, afs_int32 locktype);
75 static struct volume *afs_NewDynrootVolume(struct VenusFid *fid);
76 static inVolList();
77
78
79 /* Convert a volume name to a #; return 0 if can't parse as a number */
80 static int afs_vtoi(aname)
81     register char *aname;
82
83 {
84     register afs_int32 temp;
85     register int tc;
86     temp = 0;
87     AFS_STATCNT(afs_vtoi);
88     while(tc = *aname++) {
89         if (tc > '9' || tc < '0')
90             return 0; /* invalid name */
91         temp *= 10;
92         temp += tc - '0';
93     }
94     return temp;
95
96 } /*afs_vtoi*/
97
98
99 /*
100  * All of the vol cache routines must be called with the afs_xvolume
101  * lock held in exclusive mode, since they use static variables.
102  * In addition, we don't want two people adding the same volume
103  * at the same time.
104  */
105
106 static struct fvolume staticFVolume;
107 afs_int32 afs_FVIndex = -1;
108
109 /* UFS specific version of afs_GetVolSlot */
110
111 struct volume *afs_UFSGetVolSlot()
112
113 {
114     register struct volume *tv, **lv;
115     register char *tfile;
116     register afs_int32 i, code;
117     afs_int32 bestTime;
118     struct volume *bestVp, **bestLp;
119
120     AFS_STATCNT(afs_UFSGetVolSlot);
121     if (!afs_freeVolList) {
122         /* get free slot */
123         bestTime = 0x7fffffff;
124         bestVp = 0;
125         bestLp = 0;
126         for (i=0;i<NVOLS;i++) {
127             lv = &afs_volumes[i];
128             for (tv = *lv; tv; lv = &tv->next, tv = *lv) {
129                 if (tv->refCount == 0) {    /* is this one available? */
130                     if (tv->accessTime < bestTime) { /* best one available? */
131                         bestTime = tv->accessTime;
132                         bestLp = lv;
133                         bestVp = tv;
134                     }
135                 }
136             }
137         }
138         if (!bestVp)
139             osi_Panic("getvolslot none");
140         tv = bestVp;
141         *bestLp = tv->next;
142         if (tv->name)
143             afs_osi_Free(tv->name, strlen(tv->name)+1);
144         tv->name = (char *) 0;
145         /* now write out volume structure to file */
146         if (tv->vtix < 0) {
147             tv->vtix = afs_volCounter++;
148             /* now put on hash chain */
149             i = FVHash(tv->cell, tv->volume);
150             staticFVolume.next = fvTable[i];
151             fvTable[i]=tv->vtix;
152         }
153         else {
154             /*
155              * Haul the guy in from disk so we don't overwrite hash table
156              * next chain
157              */
158             if (afs_FVIndex != tv->vtix) {
159                 tfile = osi_UFSOpen(volumeInode);
160                 code = afs_osi_Read(tfile, sizeof(struct fvolume) * tv->vtix,
161                                 &staticFVolume, sizeof(struct fvolume));
162                 if (code != sizeof(struct fvolume))
163                     osi_Panic("read volumeinfo");
164                 osi_UFSClose(tfile);
165                 afs_FVIndex = tv->vtix;
166             }
167         }
168         afs_FVIndex = tv->vtix;
169         staticFVolume.volume = tv->volume;
170         staticFVolume.cell = tv->cell;
171         staticFVolume.mtpoint = tv->mtpoint;
172         staticFVolume.dotdot = tv->dotdot;
173         staticFVolume.rootVnode = tv->rootVnode;
174         staticFVolume.rootUnique = tv->rootUnique;
175         tfile = osi_UFSOpen(volumeInode);
176         code = afs_osi_Write(tfile, sizeof(struct fvolume) * afs_FVIndex, 
177                          &staticFVolume, sizeof(struct fvolume));
178         if (code != sizeof(struct fvolume))
179             osi_Panic("write volumeinfo");
180         osi_UFSClose(tfile);    
181     }
182     else {
183         tv = afs_freeVolList;
184         afs_freeVolList = tv->next;
185     }
186     return tv;
187
188 } /*afs_UFSGetVolSlot*/
189
190
191 struct volume *afs_MemGetVolSlot()
192
193 {
194     register struct volume *tv, **lv;
195     register afs_int32 i;
196     afs_int32 bestTime;
197     struct volume *bestVp, **bestLp;
198
199     AFS_STATCNT(afs_MemGetVolSlot);
200     if (!afs_freeVolList) {
201         struct volume *newVp;
202
203         newVp = (struct volume *) afs_osi_Alloc(sizeof(struct volume));
204
205         newVp->next = (struct volume *)0;
206         afs_freeVolList = newVp;
207     }
208     tv = afs_freeVolList;
209     afs_freeVolList = tv->next;
210     return tv;
211
212 } /*afs_MemGetVolSlot*/
213
214 /* afs_ResetVolumes()
215  * Reset volume inforamation for all volume structs that
216  * point to a speicific server.
217  */
218 void afs_ResetVolumes(struct server *srvp)
219 {
220   int j, k;
221   struct volume *vp;
222
223   /* Find any volumes residing on this server and flush their state */
224   for (j=0; j<NVOLS; j++) {
225      for (vp=afs_volumes[j]; vp; vp=vp->next) {
226         for (k=0; k<MAXHOSTS; k++) {
227            if (!srvp || (vp->serverHost[k] == srvp)) {
228               vp->serverHost[k] = 0;
229               afs_ResetVolumeInfo(vp);
230               break;
231            }
232         }
233      }
234   }
235 }
236
237
238 /* reset volume name to volume id mapping  cache */
239 void afs_CheckVolumeNames(flags) 
240     int flags;
241 {
242     afs_int32 i,j;
243     extern int osi_dnlc_purge();
244     struct volume *tv;
245     unsigned int now;
246     struct vcache *tvc;
247     afs_int32 *volumeID, *cellID, vsize, nvols;
248     AFS_STATCNT(afs_CheckVolumeNames);
249
250     nvols = 0;
251     volumeID = cellID = NULL;
252     vsize=0;
253     ObtainReadLock(&afs_xvolume);
254     if (flags & AFS_VOLCHECK_EXPIRED) {
255         /*
256          * allocate space to hold the volumeIDs and cellIDs, only if
257          * we will be invalidating the mountpoints later on
258          */
259         for (i=0; i< NVOLS; i++)
260             for (tv = afs_volumes[i]; tv; tv=tv->next)
261                 ++vsize;
262
263         volumeID = (afs_int32 *) afs_osi_Alloc(2 * vsize * sizeof(*volumeID));
264         cellID   = (volumeID) ? volumeID + vsize : 0;
265     }
266
267     now = osi_Time();
268     for (i=0;i<NVOLS;i++) {
269         for (tv = afs_volumes[i]; tv; tv=tv->next) {
270             if (flags & AFS_VOLCHECK_EXPIRED) {
271                     if ( ((tv->expireTime<(now+10)) && (tv->states & VRO)) ||
272                                 (flags & AFS_VOLCHECK_FORCE)){
273                     afs_ResetVolumeInfo(tv);  /* also resets status */
274                     if (volumeID) {
275                         volumeID[nvols] = tv->volume;
276                         cellID[nvols]   = tv->cell;
277                     }
278                     ++nvols;
279                     continue;
280                 }
281             }
282             if (flags & (AFS_VOLCHECK_BUSY | AFS_VOLCHECK_FORCE)) {
283                 for (j=0; j<MAXHOSTS; j++) 
284                     tv->status[j] = not_busy;
285             }
286
287         }
288     }
289     ReleaseReadLock(&afs_xvolume);
290
291
292     /* next ensure all mt points are re-evaluated */
293     if (nvols || (flags & (AFS_VOLCHECK_FORCE | AFS_VOLCHECK_MTPTS))) {
294         ObtainReadLock(&afs_xvcache);
295         for(i=0;i<VCSIZE;i++) {
296             for(tvc = afs_vhashT[i]; tvc; tvc=tvc->hnext) {
297
298                 /* if the volume of "mvid" of the vcache entry is among the
299                  * ones we found earlier, then we re-evaluate it.  Also, if the
300                  * force bit is set or we explicitly asked to reevaluate the
301                  * mt-pts, we clean the cmvalid bit */
302
303                 if ((flags & (AFS_VOLCHECK_FORCE | AFS_VOLCHECK_MTPTS)) ||
304                     (tvc->mvid &&
305                      inVolList(tvc->mvid, nvols, volumeID, cellID)))
306                     tvc->states &= ~CMValid;
307
308                 /* If the volume that this file belongs to was reset earlier,
309                  * then we should remove its callback.
310                  * Again, if forced, always do it.
311                  */
312                 if ((tvc->states & CRO) &&
313                     (inVolList(&tvc->fid, nvols, volumeID, cellID) ||
314                      (flags & AFS_VOLCHECK_FORCE))) {
315
316                     AFS_FAST_HOLD(tvc);
317                     ReleaseReadLock(&afs_xvcache);
318
319                     ObtainWriteLock(&afs_xcbhash, 485);
320                     /* LOCKXXX: We aren't holding tvc write lock? */
321                     afs_DequeueCallback(tvc);
322                     tvc->states &= ~CStatd;
323                     ReleaseWriteLock(&afs_xcbhash);
324                     if (tvc->fid.Fid.Vnode & 1 || (vType(tvc) == VDIR))
325                         osi_dnlc_purgedp(tvc);
326
327                     ObtainReadLock(&afs_xvcache);
328
329                     /* our tvc ptr is still good until now */
330                     AFS_FAST_RELE(tvc);
331                 }
332             }
333         }
334         osi_dnlc_purge ();   /* definitely overkill, but it's safer this way. */
335         ReleaseReadLock(&afs_xvcache);
336     }
337
338     if (volumeID)
339         afs_osi_Free(volumeID, 2 * vsize * sizeof(*volumeID));
340
341 } /*afs_CheckVolumeNames*/
342
343
344 static inVolList(fid, nvols, vID, cID)
345     struct VenusFid *fid;
346     afs_int32  nvols, *vID, *cID;
347 {
348     afs_int32 i;
349
350     /* if no arrays present, be conservative and return true */
351     if ( nvols && (!vID || !cID))
352         return 1;
353
354     for (i=0; i< nvols; ++i) {
355         if (fid->Fid.Volume == vID[i] && fid->Cell == cID[i])
356             return 1;
357     }
358     return 0;
359 }
360
361
362 /* afs_PutVolume is now a macro in afs.h */
363
364
365 /* afs_FindVolume()
366  *  return volume struct if we have it cached and it's up-to-date
367  *
368  *  Environment:  Must be called with afs_xvolume unlocked.
369  */
370 struct volume *afs_FindVolume(struct VenusFid *afid, afs_int32 locktype)
371 {
372     struct volume *tv;
373     afs_int32 i;
374
375     if (afid == NULL)
376         return NULL;
377
378     i = VHash(afid->Fid.Volume);
379     ObtainWriteLock(&afs_xvolume,106);
380     for (tv = afs_volumes[i]; tv; tv=tv->next) {
381         if (tv->volume == afid->Fid.Volume && tv->cell == afid->Cell
382             && (tv->states & VRecheck) == 0) {
383             tv->refCount++;
384             break;
385           }
386     }
387     ReleaseWriteLock(&afs_xvolume);
388     return tv;      /* NULL if we didn't find it */
389 } /*afs_FindVolume*/
390
391
392
393 /*
394  * Note that areq may be null, in which case we don't bother to set any
395  * request status information.
396  */
397 struct volume *afs_GetVolume(afid, areq, locktype)
398     struct vrequest *areq;
399     struct VenusFid *afid;
400     afs_int32 locktype;
401 {
402     struct volume *tv;
403     char *bp, tbuf[CVBS];
404     AFS_STATCNT(afs_GetVolume);
405
406     tv = afs_FindVolume(afid, locktype);
407     if (!tv) {
408        if (afs_IsDynrootFid(afid)) {
409           tv = afs_NewDynrootVolume(afid);
410        } else {
411           bp = afs_cv2string(&tbuf[CVBS], afid->Fid.Volume);
412           tv = afs_NewVolumeByName(bp, afid->Cell, 0, areq, locktype);
413        }
414     }
415     return tv;
416 } /*afs_GetVolume*/
417
418
419
420 static struct volume *afs_SetupVolume(volid, aname, ve, tcell, agood, type, areq)
421     char *aname;
422     char *ve;
423     afs_int32 volid, agood, type;
424     struct cell *tcell;
425     struct vrequest *areq;
426 {
427     struct volume *tv;
428     struct vldbentry *ove = (struct vldbentry *)ve;
429     struct nvldbentry *nve = (struct nvldbentry *)ve;
430     struct uvldbentry *uve = (struct uvldbentry *)ve;
431
432     int whichType;  /* which type of volume to look for */
433     int i, j, err=0;
434
435     if (!volid) {
436         int len;
437         /* special hint from file server to use vlserver */
438         len = strlen(aname);
439         if (len >= 8 && strcmp(aname+len-7, ".backup") == 0)
440             whichType = BACKVOL;
441         else if (len >= 10 && strcmp(aname+len-9, ".readonly")==0)
442             whichType = ROVOL;
443         else 
444             whichType = RWVOL;
445
446         /* figure out which one we're really interested in (a set is returned) */
447         volid = afs_vtoi(aname);
448         if (volid == 0) {
449             if (type == 2) {
450                 volid = uve->volumeId[whichType];
451             }
452             else if (type == 1) {
453                 volid = nve->volumeId[whichType];
454             }
455             else {
456                 volid = ove->volumeId[whichType];
457             }
458         }
459     }
460
461     
462     ObtainWriteLock(&afs_xvolume,108);
463     i = VHash(volid);
464     for (tv = afs_volumes[i]; tv; tv=tv->next) {
465         if (tv->volume == volid && tv->cell == tcell->cell) {
466             break;
467         }
468     }
469     if (!tv) {
470         struct fvolume *tf=0;
471
472         tv = afs_GetVolSlot();
473         memset((char *)tv, 0, sizeof(struct volume));
474         tv->cell = tcell->cell;
475         RWLOCK_INIT(&tv->lock, "volume lock");
476         tv->next = afs_volumes[i];      /* thread into list */
477         afs_volumes[i] = tv;
478         tv->volume = volid;
479         for (j=fvTable[FVHash(tv->cell,volid)]; j!=0; j=tf->next) {
480             if (afs_FVIndex != j) {
481                 char *tfile;
482                 tfile = osi_UFSOpen(volumeInode);
483                 err = afs_osi_Read(tfile, sizeof(struct fvolume) * j, &staticFVolume, sizeof(struct fvolume));
484                 if (err != sizeof(struct fvolume))
485                     osi_Panic("read volumeinfo2");
486                 osi_UFSClose(tfile);
487                 afs_FVIndex = j;
488             }
489             tf = &staticFVolume;
490             if (tf->cell == tv->cell && tf->volume == volid)
491                 break;
492         }
493         if (tf && (j != 0)) {
494             tv->vtix = afs_FVIndex;
495             tv->mtpoint = tf->mtpoint;
496             tv->dotdot = tf->dotdot;
497             tv->rootVnode = tf->rootVnode;          
498             tv->rootUnique = tf->rootUnique;        
499         } else {
500             tv->vtix = -1;
501             tv->rootVnode = tv->rootUnique = 0;
502         }
503     }
504     tv->refCount++;
505     tv->states &= ~VRecheck;        /* just checked it */
506     tv->accessTime = osi_Time();
507     ReleaseWriteLock(&afs_xvolume);
508     ObtainWriteLock(&tv->lock,111);
509     if (type == 2) {
510         InstallUVolumeEntry(tv, uve, tcell->cell, tcell, areq);
511     }
512     else if (type == 1)
513         InstallNVolumeEntry(tv, nve, tcell->cell);
514     else
515         InstallVolumeEntry(tv, ove, tcell->cell);
516     if (agood) {
517         if (!tv->name) {
518             tv->name = afs_osi_Alloc(strlen(aname) + 1);
519             strcpy(tv->name, aname);
520         }
521     }
522     for (i=0; i<NMAXNSERVERS; i++) {
523        tv->status[i] = not_busy;
524     }
525     ReleaseWriteLock(&tv->lock);
526     return tv;
527 }
528
529
530 struct volume *afs_GetVolumeByName(aname, acell, agood, areq, locktype)
531     struct vrequest *areq;
532     afs_int32 acell;
533     int agood;
534     register char *aname;
535     afs_int32 locktype;
536 {
537   afs_int32 i;
538   struct volume *tv;
539
540     AFS_STATCNT(afs_GetVolumeByName);
541     ObtainWriteLock(&afs_xvolume,112);
542   for (i=0;i<NVOLS;i++) {
543         for (tv = afs_volumes[i]; tv; tv=tv->next) {
544             if (tv->name && !strcmp(aname,tv->name) && tv->cell == acell
545                 && (tv->states&VRecheck) == 0) {
546                 tv->refCount++;
547                 ReleaseWriteLock(&afs_xvolume);
548                 return tv;
549             }
550         }
551     }
552
553     ReleaseWriteLock(&afs_xvolume);
554
555   tv = afs_NewVolumeByName(aname, acell, agood, areq, locktype);
556   return(tv);
557 }
558
559 static struct volume *afs_NewDynrootVolume(struct VenusFid *fid) {
560     struct cell *tcell;
561     struct volume *tv;
562     struct vldbentry tve;
563     char *bp, tbuf[CVBS];
564
565     tcell = afs_GetCell(fid->Cell, READ_LOCK);
566     if (!tcell)
567         return (struct volume *) 0;
568     if (!(tcell->states & CHasVolRef))
569         tcell->states |= CHasVolRef;
570
571     bp = afs_cv2string(&tbuf[CVBS], fid->Fid.Volume);
572     memset(&tve, 0, sizeof(tve));
573     strcpy(tve.name, "local-dynroot");
574     tve.volumeId[ROVOL] = fid->Fid.Volume;
575     tve.flags = VLF_ROEXISTS;
576
577     tv = afs_SetupVolume(0, bp, &tve, tcell, 0, 0, 0);
578     afs_PutCell(tcell, READ_LOCK);
579     return tv;
580 }
581
582 int lastnvcode;
583 static struct volume *afs_NewVolumeByName(char *aname, afs_int32 acell, int agood,
584                                    struct vrequest *areq, afs_int32 locktype)
585 {
586     afs_int32 code, i, type=0;
587     struct volume *tv, *tv1;
588     struct vldbentry *tve;
589     struct nvldbentry *ntve;
590     struct uvldbentry *utve;
591     struct cell *tcell;
592     char *tbuffer, *ve;
593     struct conn *tconn;
594     struct vrequest treq;
595     XSTATS_DECLS;
596
597     if (strlen(aname) > VL_MAXNAMELEN)  /* Invalid volume name */
598         return (struct volume *) 0;
599
600     tcell = afs_GetCell(acell, READ_LOCK);
601     if (!tcell) {
602         return (struct volume *) 0;
603     }
604
605     /* allow null request if we don't care about ENODEV/ETIMEDOUT distinction */
606     if (!areq)  areq = &treq;
607
608
609     afs_Trace2(afs_iclSetp, CM_TRACE_GETVOL, ICL_TYPE_STRING, aname,
610                            ICL_TYPE_POINTER, aname);
611     tbuffer = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
612     tve = (struct vldbentry *) (tbuffer+1024);
613     ntve = (struct nvldbentry *)tve;
614     utve = (struct uvldbentry *)tve;
615     afs_InitReq(&treq, &afs_osi_cred);  /* *must* be unauth for vldb */
616     do {
617         tconn = afs_ConnByMHosts(tcell->cellHosts, tcell->vlport,
618                                  tcell->cell, &treq, SHARED_LOCK);
619         if (tconn) {
620             if (tconn->srvr->server->flags & SNO_LHOSTS) {
621                 type = 0;
622                 RX_AFS_GUNLOCK();
623                 code = VL_GetEntryByNameO(tconn->id, aname, tve);
624                 RX_AFS_GLOCK();
625             } else if (tconn->srvr->server->flags & SYES_LHOSTS) {
626                 type = 1;
627                 RX_AFS_GUNLOCK();
628                 code = VL_GetEntryByNameN(tconn->id, aname, ntve);
629                 RX_AFS_GLOCK();
630             } else {
631                 type = 2;
632                 RX_AFS_GUNLOCK();
633                 code = VL_GetEntryByNameU(tconn->id, aname, utve);
634                 RX_AFS_GLOCK();
635                 if (!(tconn->srvr->server->flags & SVLSRV_UUID)) {
636                     if (code == RXGEN_OPCODE) {
637                         type = 1;
638                         RX_AFS_GUNLOCK();
639                         code = VL_GetEntryByNameN(tconn->id, aname, ntve);
640                         RX_AFS_GLOCK();
641                         if (code == RXGEN_OPCODE) {
642                             type = 0;
643                             tconn->srvr->server->flags |= SNO_LHOSTS;
644                             RX_AFS_GUNLOCK();
645                             code = VL_GetEntryByNameO(tconn->id, aname, tve);
646                             RX_AFS_GLOCK();
647                         } else if (!code)
648                             tconn->srvr->server->flags |= SYES_LHOSTS;
649                     } else if (!code)
650                             tconn->srvr->server->flags |= SVLSRV_UUID;
651                 }
652                 lastnvcode = code;
653             }
654         } else
655             code = -1;
656     } while
657       (afs_Analyze(tconn, code, (struct VenusFid *) 0, &treq,
658                    -1, /* no op code for this */
659                    SHARED_LOCK, tcell));
660
661     if (code) {
662         /* If the client has yet to contact this cell and contact failed due
663          * to network errors, mark the VLDB servers as back up.
664          * That the client tried and failed can be determined from the
665          * fact that there was a downtime incident, but CHasVolRef is not set.
666          */
667         if (areq->networkError && !(tcell->states & CHasVolRef)) {
668             int i;
669             struct server *sp;
670             struct srvAddr *sap;
671             for (i=0; i<MAXCELLHOSTS; i++) {
672                 if ((sp = tcell->cellHosts[i]) == (struct server *) 0) break;
673                 for (sap = sp->addr; sap; sap = sap->next_sa)
674                     afs_MarkServerUpOrDown(sap, 0);
675             }
676         }
677         afs_CopyError(&treq, areq);
678         osi_FreeLargeSpace(tbuffer);
679         afs_PutCell(tcell, READ_LOCK);
680         return (struct volume *) 0;
681     }
682     /*
683      * Check to see if this cell has not yet referenced a volume.  If
684      * it hasn't, it's just about to change its status, and we need to mark
685      * this fact down. Note that it is remotely possible that afs_SetupVolume
686      * could fail and we would still not have a volume reference.
687      */
688     if (!(tcell->states & CHasVolRef)) {
689         tcell->states |= CHasVolRef;
690         afs_stats_cmperf.numCellsContacted++;
691     } /*First time a volume in this cell has been referenced*/
692
693     if (type == 2)
694         ve = (char *)utve;
695     else if (type == 1)
696         ve = (char *)ntve;
697     else
698         ve = (char *)tve;
699     tv = afs_SetupVolume(0, aname, ve, tcell, agood, type, areq);
700     if ((agood == 2) && tv->roVol) {
701         /*
702          * This means that very soon we'll ask for the RO volume so
703          * we'll prefetch it (well we did already.)
704          */
705         tv1 = afs_SetupVolume(tv->roVol, (char *)0, ve, tcell, 0, type, areq);
706         tv1->refCount--;
707     }
708     osi_FreeLargeSpace(tbuffer);
709     afs_PutCell(tcell, READ_LOCK);
710     return tv;
711
712 } /*afs_NewVolumeByName*/
713
714
715
716 /* call this with the volume structure locked; used for new-style vldb requests */
717 void InstallVolumeEntry(struct volume *av, struct vldbentry *ve, int acell)
718 {
719     register struct server *ts;
720     struct cell *cellp;
721     register int i, j;
722     afs_int32 mask;
723     afs_uint32 temp;
724
725     AFS_STATCNT(InstallVolumeEntry);
726
727     /* Determine the type of volume we want */
728     if ((ve->flags & VLF_RWEXISTS) && (av->volume == ve->volumeId[RWVOL])) {
729        mask = VLSF_RWVOL;
730     }
731     else if ((ve->flags & VLF_ROEXISTS) && (av->volume == ve->volumeId[ROVOL])) {
732        mask = VLSF_ROVOL;
733        av->states |= VRO;
734     }
735     else if ((ve->flags & VLF_BACKEXISTS) && (av->volume == ve->volumeId[BACKVOL])) {
736        /* backup always is on the same volume as parent */
737        mask = VLSF_RWVOL;
738        av->states |= (VRO|VBackup);
739     }
740     else {
741        mask = 0;  /* Can't find volume in vldb entry */
742     }
743
744     /* fill in volume types */
745     av->rwVol   = ((ve->flags & VLF_RWEXISTS)   ? ve->volumeId[RWVOL]   : 0);
746     av->roVol   = ((ve->flags & VLF_ROEXISTS)   ? ve->volumeId[ROVOL]   : 0);
747     av->backVol = ((ve->flags & VLF_BACKEXISTS) ? ve->volumeId[BACKVOL] : 0);
748
749     if (ve->flags & VLF_DFSFILESET)
750         av->states |= VForeign;
751
752     cellp = afs_GetCell(acell, 0);
753
754     /* This volume, av, is locked. Zero out the serverHosts[] array 
755      * so that if afs_GetServer() decides to replace the server 
756      * struct, we don't deadlock trying to afs_ResetVolumeInfo()
757      * this volume.
758      */
759     for (j=0; j<MAXHOSTS; j++) {
760        av->serverHost[j] = 0;
761     }
762
763     /* Step through the VLDB entry making sure each server listed is there */
764     for (i=0,j=0; i<ve->nServers; i++) {
765         if ( ((ve->serverFlags[i] & mask) == 0) || (ve->serverFlags[i] & VLSF_DONTUSE) ) {
766            continue;      /* wrong volume or  don't use this volume */
767         }
768
769         temp = htonl(ve->serverNumber[i]);
770         ts = afs_GetServer(&temp, 1, acell, cellp->fsport, WRITE_LOCK, (afsUUID *)0, 0);
771         av->serverHost[j] = ts;
772
773         /*
774          * The cell field could be 0 if the server entry was created
775          * first with the 'fs setserverprefs' call which doesn't set
776          * the cell field. Thus if the afs_GetServer call above
777          * follows later on it will find the server entry thus it will
778          * simply return without setting any fields, so we set the
779          * field ourselves below.
780          */
781         if (!ts->cell)
782             ts->cell = cellp;
783         afs_PutServer(ts, WRITE_LOCK);
784         j++;
785     }
786     if (j < MAXHOSTS) {
787         av->serverHost[j++] = 0;
788     }
789     afs_SortServers(av->serverHost, MAXHOSTS);
790 } /*InstallVolumeEntry*/
791
792
793 void InstallNVolumeEntry(struct volume *av, struct nvldbentry *ve, int acell)
794 {
795     register struct server *ts;
796     struct cell *cellp;
797     register int i, j;
798     afs_int32 mask;
799     afs_uint32 temp;
800
801     AFS_STATCNT(InstallVolumeEntry);
802
803     /* Determine type of volume we want */
804     if ((ve->flags & VLF_RWEXISTS) && (av->volume == ve->volumeId[RWVOL])) {
805        mask = VLSF_RWVOL;
806     }
807     else if ((ve->flags & VLF_ROEXISTS) && (av->volume == ve->volumeId[ROVOL])) {
808        mask = VLSF_ROVOL;
809        av->states |= VRO;
810     }
811     else if ((ve->flags&VLF_BACKEXISTS) && (av->volume == ve->volumeId[BACKVOL])) {
812        /* backup always is on the same volume as parent */
813        mask = VLSF_RWVOL;
814        av->states |= (VRO|VBackup);
815     }
816     else {
817        mask = 0;     /* Can't find volume in vldb entry */
818     }
819
820     /* fill in volume types */
821     av->rwVol   = ((ve->flags & VLF_RWEXISTS)   ? ve->volumeId[RWVOL]   : 0);
822     av->roVol   = ((ve->flags & VLF_ROEXISTS)   ? ve->volumeId[ROVOL]   : 0);
823     av->backVol = ((ve->flags & VLF_BACKEXISTS) ? ve->volumeId[BACKVOL] : 0);
824
825     if (ve->flags & VLF_DFSFILESET)
826         av->states |= VForeign;
827
828     cellp = afs_GetCell(acell, 0);
829
830     /* This volume, av, is locked. Zero out the serverHosts[] array 
831      * so that if afs_GetServer() decides to replace the server 
832      * struct, we don't deadlock trying to afs_ResetVolumeInfo()
833      * this volume.
834      */
835     for (j=0; j<MAXHOSTS; j++) {
836        av->serverHost[j] = 0;
837     }
838
839     /* Step through the VLDB entry making sure each server listed is there */
840     for (i=0,j=0; i<ve->nServers; i++) {
841         if ( ((ve->serverFlags[i] & mask) == 0) || (ve->serverFlags[i] & VLSF_DONTUSE) ) {
842            continue;      /* wrong volume or don't use this volume */
843         }
844
845         temp = htonl(ve->serverNumber[i]);
846         ts = afs_GetServer(&temp, 1, acell, cellp->fsport, WRITE_LOCK, (afsUUID *)0,0);
847         av->serverHost[j] = ts;
848         /*
849          * The cell field could be 0 if the server entry was created
850          * first with the 'fs setserverprefs' call which doesn't set
851          * the cell field. Thus if the afs_GetServer call above
852          * follows later on it will find the server entry thus it will
853          * simply return without setting any fields, so we set the
854          * field ourselves below.
855          */
856         if (!ts->cell)
857             ts->cell = cellp;
858         afs_PutServer(ts, WRITE_LOCK);
859         j++;
860     }
861     if (j < MAXHOSTS) {
862         av->serverHost[j++] = 0;
863     }
864     afs_SortServers(av->serverHost, MAXHOSTS);
865 } /*InstallNVolumeEntry*/
866
867
868 void InstallUVolumeEntry(struct volume *av, struct uvldbentry *ve,
869                          int acell, struct cell *tcell, struct vrequest *areq)
870 {
871     register struct srvAddr *sa;
872     register struct server *ts;
873     struct conn *tconn;
874     struct cell *cellp;
875     register int i, j;
876     afs_uint32 serverid;
877     afs_int32 mask;
878     int hash, k;
879
880     AFS_STATCNT(InstallVolumeEntry);
881
882     /* Determine type of volume we want */
883     if ((ve->flags & VLF_RWEXISTS) && (av->volume == ve->volumeId[RWVOL])) {
884        mask = VLSF_RWVOL;
885     }
886     else if ((ve->flags & VLF_ROEXISTS) && av->volume == ve->volumeId[ROVOL]) {
887        mask = VLSF_ROVOL;
888        av->states |= VRO;
889     }
890     else if ((ve->flags & VLF_BACKEXISTS) && (av->volume == ve->volumeId[BACKVOL])) {
891        /* backup always is on the same volume as parent */
892        mask = VLSF_RWVOL;
893        av->states |= (VRO|VBackup);
894     }
895     else {
896        mask = 0;      /* Can't find volume in vldb entry */
897     }
898
899     /* fill in volume types */
900     av->rwVol   = ((ve->flags & VLF_RWEXISTS)   ? ve->volumeId[RWVOL]   : 0);
901     av->roVol   = ((ve->flags & VLF_ROEXISTS)   ? ve->volumeId[ROVOL]   : 0);
902     av->backVol = ((ve->flags & VLF_BACKEXISTS) ? ve->volumeId[BACKVOL] : 0);
903
904     if (ve->flags & VLF_DFSFILESET)
905         av->states |= VForeign;
906
907     cellp = afs_GetCell(acell, 0);
908
909     /* This volume, av, is locked. Zero out the serverHosts[] array 
910      * so that if afs_GetServer() decides to replace the server 
911      * struct, we don't deadlock trying to afs_ResetVolumeInfo()
912      * this volume.
913      */
914     for (j=0; j<MAXHOSTS; j++) {
915        av->serverHost[j] = 0;
916     }
917
918     /* Gather the list of servers the VLDB says the volume is on
919      * and initialize the ve->serverHost[] array. If a server struct
920      * is not found, then get the list of addresses for the
921      * server, VL_GetAddrsU(), and create a server struct, afs_GetServer().
922      */
923     for (i=0,j=0; i<ve->nServers; i++) {
924         if ( ((ve->serverFlags[i] & mask) == 0) || (ve->serverFlags[i] & VLSF_DONTUSE) ) {
925            continue;       /* wrong volume don't use this volume */
926         }
927
928         if (!(ve->serverFlags[i] & VLSERVER_FLAG_UUID)) {
929             /* The server has no uuid */
930             serverid = htonl(ve->serverNumber[i].time_low);
931             ts = afs_GetServer(&serverid, 1, acell, cellp->fsport, WRITE_LOCK, (afsUUID *)0,0);
932         } else {
933             ts = afs_FindServer(0, cellp->fsport, &ve->serverNumber[i], 0);
934             if (ts && (ts->sr_addr_uniquifier == ve->serverUnique[i]) && ts->addr) {
935                /* uuid, uniquifier, and portal are the same */
936             } else {
937                 afs_uint32 *addrp, nentries, code, unique;
938                 bulkaddrs addrs;
939                 ListAddrByAttributes attrs;
940                 afsUUID uuid;
941
942                 memset((char *)&attrs, 0, sizeof(attrs));
943                 attrs.Mask = VLADDR_UUID;
944                 attrs.uuid = ve->serverNumber[i];
945                 memset((char *)&uuid, 0, sizeof(uuid));
946                 memset((char *)&addrs, 0, sizeof(addrs));
947                 do {
948                     tconn = afs_ConnByMHosts(tcell->cellHosts, tcell->vlport,
949                                              tcell->cell, areq, SHARED_LOCK);
950                     if (tconn) {
951                         RX_AFS_GUNLOCK();
952                         code = VL_GetAddrsU(tconn->id, &attrs, &uuid, &unique, &nentries, &addrs);
953                         RX_AFS_GLOCK();
954                     } else {
955                         code = -1;
956                     }
957
958                     /* Handle corrupt VLDB (defect 7393) */
959                     if (code == 0 && nentries == 0)
960                         code = VL_NOENT;
961
962                 } while (afs_Analyze(tconn, code, (struct VenusFid *) 0, areq,
963                                      -1, SHARED_LOCK, tcell));
964                 if (code) {
965                     /* Better handing of such failures; for now we'll simply retry this call */
966                     areq->volumeError = 1;
967                     return;
968                 }
969
970                 addrp = addrs.bulkaddrs_val;
971                 for (k = 0; k < nentries; k++) {
972                    addrp[k] = htonl(addrp[k]);
973                 }
974                 ts = afs_GetServer(addrp, nentries, acell, cellp->fsport,
975                                    WRITE_LOCK, &ve->serverNumber[i],
976                                    ve->serverUnique[i]);
977                 afs_osi_Free(addrs.bulkaddrs_val, addrs.bulkaddrs_len*sizeof(*addrp));
978             }
979         }
980         av->serverHost[j] = ts;
981
982         /* The cell field could be 0 if the server entry was created
983          * first with the 'fs setserverprefs' call which doesn't set
984          * the cell field. Thus if the afs_GetServer call above
985          * follows later on it will find the server entry thus it will
986          * simply return without setting any fields, so we set the
987          * field ourselves below.
988          */
989         if (!ts->cell)
990             ts->cell = cellp;
991         afs_PutServer(ts, WRITE_LOCK);
992         j++;
993     }
994
995     afs_SortServers(av->serverHost, MAXHOSTS);
996 } /*InstallVolumeEntry*/
997
998
999 void afs_ResetVolumeInfo(struct volume *tv)
1000 {
1001     int i;
1002
1003     AFS_STATCNT(afs_ResetVolumeInfo);
1004     ObtainWriteLock(&tv->lock,117);
1005     tv->states |= VRecheck;
1006     for (i=0; i<MAXHOSTS; i++)
1007       tv->status[i] = not_busy;
1008     if (tv->name) {
1009         afs_osi_Free(tv->name, strlen(tv->name)+1);
1010         tv->name = (char *) 0;
1011       }
1012     ReleaseWriteLock(&tv->lock);
1013 } /*afs_ResetVolumeInfo*/