2 * Copyright 2000, International Business Machines Corporation and others.
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
15 * afs_CheckVolumeNames
18 #include <afsconfig.h>
19 #include "afs/param.h"
23 #include "afs/sysincludes.h" /* Standard vendor system headers */
26 #if !defined(AFS_LINUX20_ENV)
29 #include <netinet/in.h>
32 #include "h/hashing.h"
34 #if !defined(AFS_HPUX110_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_DARWIN_ENV)
35 #include <netinet/in_var.h>
36 #endif /* ! AFS_HPUX110_ENV */
37 #endif /* !defined(UKERNEL) */
39 #include "afsincludes.h" /* Afs-based standard headers */
40 #include "afs/afs_stats.h" /* afs statistics */
41 #include "afs/afs_dynroot.h"
43 #if defined(AFS_SUN5_ENV)
45 #include <inet/common.h>
46 #include <netinet/ip6.h>
50 /* In case we don't have the vl error table yet. */
51 #ifndef ERROR_TABLE_BASE_VL
52 #define ERROR_TABLE_BASE_VL (363520L)
53 #define VL_NOENT (363524L)
54 #endif /* vlserver error base define */
56 /* Exported variables */
57 afs_int32 afs_volume_ttl
= 0;
58 afs_dcache_id_t volumeInode
; /* Inode for VolumeItems file */
59 afs_rwlock_t afs_xvolume
; /** allocation lock for volumes */
60 struct volume
*afs_freeVolList
;
61 struct volume
*afs_volumes
[NVOLS
];
62 afs_int32 afs_volCounter
= 1; /** for allocating volume indices */
63 afs_int32 fvTable
[NFENTRIES
];
65 /* Forward declarations */
66 static struct volume
*afs_NewVolumeByName(char *aname
, afs_int32 acell
,
67 int agood
, struct vrequest
*areq
,
69 static struct volume
*afs_NewDynrootVolume(struct VenusFid
*fid
);
70 static int inVolList(struct VenusFid
*fid
, afs_int32 nvols
, afs_int32
* vID
,
76 * Convert a volume name to a number;
77 * @param aname Volume name.
78 * @return return 0 if can't parse as a number.
86 AFS_STATCNT(afs_vtoi
);
87 while ((tc
= *aname
++)) {
88 if (tc
> '9' || tc
< '0')
89 return 0; /* invalid name */
99 * All of the vol cache routines must be called with the afs_xvolume
100 * lock held in exclusive mode, since they use static variables.
101 * In addition, we don't want two people adding the same volume
105 static struct fvolume staticFVolume
;
106 afs_int32 afs_FVIndex
= -1;
109 * Initialize a newly gotten volume slot.
111 * \param tv volume slot to be initialized
112 * \param tf volume item data; null if none
113 * \param volid volume id for this volume slot
114 * \param cell cell for this volume slot
118 afs_InitVolSlot(struct volume
*tv
, struct fvolume
*tf
, afs_int32 volid
,
121 AFS_STATCNT(afs_InitVolSlot
);
122 memset(tv
, 0, sizeof(struct volume
));
123 tv
->cell
= tcell
->cellNum
;
124 AFS_RWLOCK_INIT(&tv
->lock
, "volume lock");
127 tv
->vtix
= afs_FVIndex
;
128 tv
->mtpoint
= tf
->mtpoint
;
129 tv
->dotdot
= tf
->dotdot
;
130 tv
->rootVnode
= tf
->rootVnode
;
131 tv
->rootUnique
= tf
->rootUnique
;
134 tv
->rootVnode
= tv
->rootUnique
= 0;
135 afs_GetDynrootMountFid(&tv
->dotdot
);
136 afs_GetDynrootMountFid(&tv
->mtpoint
);
137 tv
->mtpoint
.Fid
.Vnode
=
138 VNUM_FROM_TYPEID(VN_TYPE_MOUNT
, tcell
->cellIndex
<< 2);
139 tv
->mtpoint
.Fid
.Unique
= volid
;
144 * UFS specific version of afs_GetVolSlot
148 afs_UFSGetVolSlot(afs_int32 volid
, struct cell
*tcell
)
150 struct volume
*tv
= NULL
, **lv
;
151 struct osi_file
*tfile
;
152 afs_int32 i
= -1, code
;
154 struct volume
*bestVp
, *oldLp
= NULL
, **bestLp
= NULL
;
155 char *oldname
= NULL
;
156 afs_int32 oldvtix
= -2; /* Initialize to a value that doesn't occur */
157 struct fvolume
*tf
= NULL
;
160 AFS_STATCNT(afs_UFSGetVolSlot
);
161 if (!afs_freeVolList
) {
163 bestTime
= 0x7fffffff;
166 for (i
= 0; i
< NVOLS
; i
++) {
167 lv
= &afs_volumes
[i
];
168 for (tv
= *lv
; tv
; lv
= &tv
->next
, tv
= *lv
) {
169 if (tv
->refCount
== 0) { /* is this one available? */
170 if (tv
->setupTime
< bestTime
) { /* best one available? */
171 bestTime
= tv
->setupTime
;
179 afs_warn("afs_UFSGetVolSlot: no vol slots available\n");
191 /* now write out volume structure to file */
193 tv
->vtix
= afs_volCounter
++;
194 /* now put on hash chain */
195 i
= FVHash(tv
->cell
, tv
->volume
);
196 staticFVolume
.next
= fvTable
[i
];
197 fvTable
[i
] = tv
->vtix
;
200 * Haul the guy in from disk so we don't overwrite hash table
203 if (afs_FVIndex
!= tv
->vtix
) {
204 tfile
= osi_UFSOpen(&volumeInode
);
206 afs_warn("afs_UFSGetVolSlot: unable to open volumeinfo\n");
210 afs_osi_Read(tfile
, sizeof(struct fvolume
) * tv
->vtix
,
211 &staticFVolume
, sizeof(struct fvolume
));
213 if (code
!= sizeof(struct fvolume
)) {
214 afs_warn("afs_UFSGetVolSlot: error %d reading volumeinfo\n",
220 afs_FVIndex
= tv
->vtix
;
221 staticFVolume
.volume
= tv
->volume
;
222 staticFVolume
.cell
= tv
->cell
;
223 staticFVolume
.mtpoint
= tv
->mtpoint
;
224 staticFVolume
.dotdot
= tv
->dotdot
;
225 staticFVolume
.rootVnode
= tv
->rootVnode
;
226 staticFVolume
.rootUnique
= tv
->rootUnique
;
227 tfile
= osi_UFSOpen(&volumeInode
);
229 afs_warn("afs_UFSGetVolSlot: unable to open volumeinfo\n");
233 afs_osi_Write(tfile
, sizeof(struct fvolume
) * afs_FVIndex
,
234 &staticFVolume
, sizeof(struct fvolume
));
236 if (code
!= sizeof(struct fvolume
)) {
237 afs_warn("afs_UFSGetVolSlot: error %d writing volumeinfo\n",
242 afs_osi_Free(oldname
, strlen(oldname
) + 1);
246 tv
= afs_freeVolList
;
247 afs_freeVolList
= tv
->next
;
250 /* read volume item data from disk for the gotten slot */
251 for (j
= fvTable
[FVHash(tcell
->cellNum
, volid
)]; j
!= 0; j
= tf
->next
) {
252 if (afs_FVIndex
!= j
) {
253 tfile
= osi_UFSOpen(&volumeInode
);
255 afs_warn("afs_UFSGetVolSlot: unable to open volumeinfo\n");
256 code
= -1; /* indicate error */
259 afs_osi_Read(tfile
, sizeof(struct fvolume
) * j
,
260 &staticFVolume
, sizeof(struct fvolume
));
262 if (code
!= sizeof(struct fvolume
)) {
263 afs_warn("afs_UFSGetVolSlot: error %d reading volumeinfo\n",
267 if (code
!= sizeof(struct fvolume
)) {
268 /* put tv back on the free list; the data in it is not valid */
269 tv
->next
= afs_freeVolList
;
270 afs_freeVolList
= tv
;
271 /* staticFVolume contents are not valid */
277 if (j
!= 0) { /* volume items record 0 is not used */
279 if (tf
->cell
== tcell
->cellNum
&& tf
->volume
== volid
) {
285 afs_InitVolSlot(tv
, tf
, volid
, tcell
);
291 afs_warn("afs_UFSGetVolSlot: oldvtix is uninitialized\n");
300 fvTable
[i
] = staticFVolume
.next
;
306 /* we messed with staticFVolume, so make sure someone else
307 * doesn't think it's fine to use */
311 } /*afs_UFSGetVolSlot */
315 * Get an available volume list slot. If the list does not exist,
316 * create one containing a single element.
320 afs_MemGetVolSlot(afs_int32 volid
, struct cell
*tcell
)
324 AFS_STATCNT(afs_MemGetVolSlot
);
325 if (!afs_freeVolList
) {
326 struct volume
*newVp
;
328 newVp
= afs_osi_Alloc(sizeof(struct volume
));
329 osi_Assert(newVp
!= NULL
);
332 afs_freeVolList
= newVp
;
334 tv
= afs_freeVolList
;
335 afs_freeVolList
= tv
->next
;
337 afs_InitVolSlot(tv
, NULL
, volid
, tcell
);
340 } /*afs_MemGetVolSlot */
343 * Setup a volume slot for cell:volume.
345 * Find the volume slot for the cell:volume, otherwise get
346 * and initialize a new slot.
348 * \param volid volume id
352 static struct volume
*
353 afs_SetupVolSlot(afs_int32 volid
, struct cell
*tcell
)
358 AFS_STATCNT(afs_SetupVolSlot
);
359 ObtainWriteLock(&afs_xvolume
, 108);
361 for (tv
= afs_volumes
[i
]; tv
; tv
= tv
->next
) {
362 if (tv
->volume
== volid
&& tv
->cell
== tcell
->cellNum
) {
367 tv
= afs_GetVolSlot(volid
, tcell
);
369 ReleaseWriteLock(&afs_xvolume
);
372 tv
->next
= afs_volumes
[i
]; /* thread into list */
376 tv
->states
&= ~VRecheck
; /* just checked it */
377 tv
->setupTime
= osi_Time();
378 ReleaseWriteLock(&afs_xvolume
);
383 * Reset volume information for all volume structs that
384 * point to a speicific server, skipping a given volume if provided.
387 * The server to reset volume info about
389 * The volume to skip resetting info about
392 afs_ResetVolumes(struct server
*srvp
, struct volume
*tv
)
397 /* Find any volumes residing on this server and flush their state */
398 for (j
= 0; j
< NVOLS
; j
++) {
399 for (vp
= afs_volumes
[j
]; vp
; vp
= vp
->next
) {
400 for (k
= 0; k
< AFS_MAXHOSTS
; k
++) {
401 if (!srvp
|| (vp
->serverHost
[k
] == srvp
)) {
402 if (tv
&& tv
!= vp
) {
403 vp
->serverHost
[k
] = 0;
404 afs_ResetVolumeInfo(vp
);
414 * Returns non-zero if the volume information is expired.
416 * Dynroot volumes are not setup from vldb queries, so never expire.
417 * Read-only volume expiry is tied to the volume callback.
419 * Optionally, invalidate volume information after a fixed timeout.
420 * The vlservers will be periodically probed for volume information.
421 * This avoids a situation where the vldb information is cached
422 * indefinitely as long as files in the volume are accessed (and are
423 * not in the vcache) before the callback expires.
425 * \param tv volume to check
426 * \param now current time
428 * \return non-zero if the volume should be reset
431 IsExpired(struct volume
*tv
, afs_int32 now
)
433 if (afs_IsDynrootVolume(tv
)) {
436 if ((tv
->states
& VRO
) && (tv
->expireTime
< (now
+ 10))) {
439 if ((afs_volume_ttl
!= 0) && ((tv
->setupTime
+ afs_volume_ttl
) < now
)) {
446 * Reset volume name to volume id mapping cache.
450 afs_CheckVolumeNames(int flags
)
456 afs_int32
*volumeID
, *cellID
, vsize
, nvols
;
457 #ifdef AFS_DARWIN80_ENV
460 AFS_STATCNT(afs_CheckVolumeNames
);
463 volumeID
= cellID
= NULL
;
465 ObtainReadLock(&afs_xvolume
);
466 if (flags
& AFS_VOLCHECK_EXPIRED
) {
468 * allocate space to hold the volumeIDs and cellIDs, only if
469 * we will be invalidating the mountpoints later on
471 for (i
= 0; i
< NVOLS
; i
++)
472 for (tv
= afs_volumes
[i
]; tv
; tv
= tv
->next
)
475 volumeID
= afs_osi_Alloc(2 * vsize
* sizeof(*volumeID
));
476 cellID
= (volumeID
) ? volumeID
+ vsize
: 0;
480 for (i
= 0; i
< NVOLS
; i
++) {
481 for (tv
= afs_volumes
[i
]; tv
; tv
= tv
->next
) {
482 if (flags
& AFS_VOLCHECK_EXPIRED
) {
483 if (IsExpired(tv
, now
) || (flags
& AFS_VOLCHECK_FORCE
)) {
484 afs_ResetVolumeInfo(tv
); /* also resets status */
486 volumeID
[nvols
] = tv
->volume
;
487 cellID
[nvols
] = tv
->cell
;
494 if (flags
& (AFS_VOLCHECK_BUSY
| AFS_VOLCHECK_FORCE
)) {
495 for (j
= 0; j
< AFS_MAXHOSTS
; j
++)
496 tv
->status
[j
] = not_busy
;
501 ReleaseReadLock(&afs_xvolume
);
504 /* next ensure all mt points are re-evaluated */
505 if (nvols
|| (flags
& (AFS_VOLCHECK_FORCE
| AFS_VOLCHECK_MTPTS
))) {
507 ObtainReadLock(&afs_xvcache
);
508 for (i
= 0; i
< VCSIZE
; i
++) {
509 for (tvc
= afs_vhashT
[i
]; tvc
; tvc
= tvc
->hnext
) {
511 /* if the volume of "mvid.target_root" of the vcache entry is
512 * among the ones we found earlier, then we re-evaluate it.
513 * Also, if the force bit is set or we explicitly asked to
514 * reevaluate the mt-pts, we clean the cmvalid bit */
516 if ((flags
& (AFS_VOLCHECK_FORCE
| AFS_VOLCHECK_MTPTS
))
517 || (tvc
->mvid
.target_root
518 && inVolList(tvc
->mvid
.target_root
, nvols
, volumeID
, cellID
)))
519 tvc
->f
.states
&= ~CMValid
;
521 /* If the volume that this file belongs to was reset earlier,
522 * then we should remove its callback.
523 * Again, if forced, always do it.
525 if ((tvc
->f
.states
& CRO
)
526 && (inVolList(&tvc
->f
.fid
, nvols
, volumeID
, cellID
)
527 || (flags
& AFS_VOLCHECK_FORCE
))) {
529 if (tvc
->f
.states
& CVInit
) {
530 ReleaseReadLock(&afs_xvcache
);
531 afs_osi_Sleep(&tvc
->f
.states
);
534 #ifdef AFS_DARWIN80_ENV
535 if (tvc
->f
.states
& CDeadVnode
) {
536 ReleaseReadLock(&afs_xvcache
);
537 afs_osi_Sleep(&tvc
->f
.states
);
543 if (vnode_ref(tvp
)) {
545 /* AFSTOV(tvc) may be NULL */
553 ReleaseReadLock(&afs_xvcache
);
555 /* LOCKXXX: We aren't holding tvc write lock? */
556 afs_StaleVCache(tvc
);
558 #ifdef AFS_DARWIN80_ENV
559 vnode_put(AFSTOV(tvc
));
560 /* our tvc ptr is still good until now */
562 ObtainReadLock(&afs_xvcache
);
564 ObtainReadLock(&afs_xvcache
);
566 /* our tvc ptr is still good until now */
572 osi_dnlc_purge(); /* definitely overkill, but it's safer this way. */
573 ReleaseReadLock(&afs_xvcache
);
577 afs_osi_Free(volumeID
, 2 * vsize
* sizeof(*volumeID
));
579 } /*afs_CheckVolumeNames */
583 * Check if volume is in the specified list.
584 * @param fid File FID.
585 * @param nvols Nomber of volumes???
586 * @param vID Array of volume IDs.
587 * @param cID Array of cache IDs.
588 * @return 1 - true, 0 - false.
591 inVolList(struct VenusFid
*fid
, afs_int32 nvols
, afs_int32
* vID
,
596 /* if no arrays present, be conservative and return true */
597 if (nvols
&& (!vID
|| !cID
))
600 for (i
= 0; i
< nvols
; ++i
) {
601 if (fid
->Fid
.Volume
== vID
[i
] && fid
->Cell
== cID
[i
])
608 /* afs_PutVolume is now a macro in afs.h */
612 * Return volume struct if we have it cached and it's up-to-date.
613 * Environment: Must be called with afs_xvolume unlocked.
614 * @param afid Volume FID.
616 * @return Volume or NULL if no result.
619 afs_FindVolume(struct VenusFid
*afid
, afs_int32 locktype
)
627 i
= VHash(afid
->Fid
.Volume
);
628 ObtainWriteLock(&afs_xvolume
, 106);
629 for (tv
= afs_volumes
[i
]; tv
; tv
= tv
->next
) {
630 if (tv
->volume
== afid
->Fid
.Volume
&& tv
->cell
== afid
->Cell
631 && (tv
->states
& VRecheck
) == 0) {
636 ReleaseWriteLock(&afs_xvolume
);
637 return tv
; /* NULL if we didn't find it */
638 } /*afs_FindVolume */
643 * Note that areq may be null, in which case we don't bother to set any
644 * request status information.
645 * @param afid Volume FID.
646 * @param areq Request type.
647 * @param locktype Lock to be used.
648 * @return Volume or NULL if no result.
651 afs_GetVolume(struct VenusFid
*afid
, struct vrequest
*areq
,
655 char *bp
, tbuf
[CVBS
];
656 AFS_STATCNT(afs_GetVolume
);
658 tv
= afs_FindVolume(afid
, locktype
);
660 /* Do a dynroot check and add dynroot volume if found. */
661 if (afs_IsDynrootAnyFid(afid
)) {
662 tv
= afs_NewDynrootVolume(afid
);
664 bp
= afs_cv2string(&tbuf
[CVBS
], afid
->Fid
.Volume
);
665 tv
= afs_NewVolumeByName(bp
, afid
->Cell
, 0, areq
, locktype
);
675 * @param volid Volume ID. If it's 0, get it from the name.
676 * @param aname Volume name.
677 * @param ve Volume entry.
678 * @param tcell The cell containing this volume.
680 * @param type Type of volume.
681 * @param areq Request.
682 * @return Volume or NULL if failure.
684 static struct volume
*
685 afs_SetupVolume(afs_int32 volid
, char *aname
, void *ve
, struct cell
*tcell
,
686 afs_int32 agood
, afs_int32 type
, struct vrequest
*areq
)
689 struct vldbentry
*ove
= (struct vldbentry
*)ve
;
690 struct nvldbentry
*nve
= (struct nvldbentry
*)ve
;
691 struct uvldbentry
*uve
= (struct uvldbentry
*)ve
;
693 int whichType
; /* which type of volume to look for */
698 /* special hint from file server to use vlserver */
700 if (len
>= 8 && strcmp(aname
+ len
- 7, ".backup") == 0)
702 else if (len
>= 10 && strcmp(aname
+ len
- 9, ".readonly") == 0)
707 /* figure out which one we're really interested in (a set is returned) */
708 volid
= afs_vtoi(aname
);
711 volid
= uve
->volumeId
[whichType
];
712 } else if (type
== 1) {
713 volid
= nve
->volumeId
[whichType
];
715 volid
= ove
->volumeId
[whichType
];
717 } /* end of if (volid == 0) */
718 } /* end of if (!volid) */
720 tv
= afs_SetupVolSlot(volid
, tcell
);
726 LockAndInstallUVolumeEntry(tv
, uve
, tcell
->cellNum
, tcell
, areq
);
727 } else if (type
== 1)
728 LockAndInstallNVolumeEntry(tv
, nve
, tcell
->cellNum
);
730 LockAndInstallVolumeEntry(tv
, ove
, tcell
->cellNum
);
733 tv
->name
= afs_osi_Alloc(strlen(aname
) + 1);
734 osi_Assert(tv
->name
!= NULL
);
735 strcpy(tv
->name
, aname
);
738 for (i
= 0; i
< NMAXNSERVERS
; i
++) {
739 tv
->status
[i
] = not_busy
;
741 ReleaseWriteLock(&tv
->lock
);
747 * Seek volume by it's name and attributes.
748 * If volume not found, try to add one.
749 * @param aname Volume name.
753 * @param locktype Type of lock to be used.
757 afs_GetVolumeByName(char *aname
, afs_int32 acell
, int agood
,
758 struct vrequest
*areq
, afs_int32 locktype
)
763 AFS_STATCNT(afs_GetVolumeByName
);
764 ObtainWriteLock(&afs_xvolume
, 112);
765 for (i
= 0; i
< NVOLS
; i
++) {
766 for (tv
= afs_volumes
[i
]; tv
; tv
= tv
->next
) {
767 if (tv
->name
&& !strcmp(aname
, tv
->name
) && tv
->cell
== acell
768 && (tv
->states
& VRecheck
) == 0) {
770 ReleaseWriteLock(&afs_xvolume
);
776 ReleaseWriteLock(&afs_xvolume
);
778 if (AFS_IS_DISCONNECTED
)
781 tv
= afs_NewVolumeByName(aname
, acell
, agood
, areq
, locktype
);
786 * Init a new dynroot volume.
788 * @return Volume or NULL if not found.
790 static struct volume
*
791 afs_NewDynrootVolume(struct VenusFid
*fid
)
795 struct vldbentry
*tve
;
796 char *bp
, tbuf
[CVBS
];
798 tcell
= afs_GetCell(fid
->Cell
, READ_LOCK
);
801 tve
= afs_osi_Alloc(sizeof(*tve
));
802 osi_Assert(tve
!= NULL
);
803 if (!(tcell
->states
& CHasVolRef
))
804 tcell
->states
|= CHasVolRef
;
806 bp
= afs_cv2string(&tbuf
[CVBS
], fid
->Fid
.Volume
);
807 memset(tve
, 0, sizeof(*tve
));
808 strcpy(tve
->name
, "local-dynroot");
809 tve
->volumeId
[ROVOL
] = fid
->Fid
.Volume
;
810 tve
->flags
= VLF_ROEXISTS
;
812 tv
= afs_SetupVolume(0, bp
, tve
, tcell
, 0, 0, 0);
813 afs_PutCell(tcell
, READ_LOCK
);
814 afs_osi_Free(tve
, sizeof(*tve
));
821 * @param aname Volume name.
822 * @param acell Cell id.
824 * @param areq Request type.
825 * @param locktype Type of lock to be used.
826 * @return Volume or NULL if failure.
828 static struct volume
*
829 afs_NewVolumeByName(char *aname
, afs_int32 acell
, int agood
,
830 struct vrequest
*areq
, afs_int32 locktype
)
832 afs_int32 code
, type
= 0;
833 struct volume
*tv
, *tv1
;
834 struct vldbentry
*tve
;
835 struct nvldbentry
*ntve
;
836 struct uvldbentry
*utve
;
839 struct afs_conn
*tconn
;
840 struct vrequest
*treq
= NULL
;
841 struct rx_connection
*rxconn
;
843 if (strlen(aname
) > VL_MAXNAMELEN
) /* Invalid volume name */
846 tcell
= afs_GetCell(acell
, READ_LOCK
);
851 code
= afs_CreateReq(&treq
, afs_osi_credp
); /* *must* be unauth for vldb */
856 /* allow null request if we don't care about ENODEV/ETIMEDOUT distinction */
861 afs_Trace2(afs_iclSetp
, CM_TRACE_GETVOL
, ICL_TYPE_STRING
, aname
,
862 ICL_TYPE_POINTER
, aname
);
863 tbuffer
= osi_AllocLargeSpace(AFS_LRALLOCSIZ
);
864 tve
= (struct vldbentry
*)(tbuffer
+ 1024);
865 ntve
= (struct nvldbentry
*)tve
;
866 utve
= (struct uvldbentry
*)tve
;
870 afs_ConnByMHosts(tcell
->cellHosts
, tcell
->vlport
, tcell
->cellNum
,
871 treq
, SHARED_LOCK
, 0, &rxconn
);
873 if (tconn
->parent
->srvr
->server
->flags
& SNO_LHOSTS
) {
876 code
= VL_GetEntryByNameO(rxconn
, aname
, tve
);
878 } else if (tconn
->parent
->srvr
->server
->flags
& SYES_LHOSTS
) {
881 code
= VL_GetEntryByNameN(rxconn
, aname
, ntve
);
886 code
= VL_GetEntryByNameU(rxconn
, aname
, utve
);
888 if (!(tconn
->parent
->srvr
->server
->flags
& SVLSRV_UUID
)) {
889 if (code
== RXGEN_OPCODE
) {
892 code
= VL_GetEntryByNameN(rxconn
, aname
, ntve
);
894 if (code
== RXGEN_OPCODE
) {
896 tconn
->parent
->srvr
->server
->flags
|= SNO_LHOSTS
;
898 code
= VL_GetEntryByNameO(rxconn
, aname
, tve
);
901 tconn
->parent
->srvr
->server
->flags
|= SYES_LHOSTS
;
903 tconn
->parent
->srvr
->server
->flags
|= SVLSRV_UUID
;
909 } while (afs_Analyze(tconn
, rxconn
, code
, NULL
, treq
, -1, /* no op code for this */
910 SHARED_LOCK
, tcell
));
913 /* If the client has yet to contact this cell and contact failed due
914 * to network errors, mark the VLDB servers as back up.
915 * That the client tried and failed can be determined from the
916 * fact that there was a downtime incident, but CHasVolRef is not set.
918 /* RT 48959 - unclear if this should really go */
920 if (areq
->networkError
&& !(tcell
->states
& CHasVolRef
)) {
924 for (i
= 0; i
< AFS_MAXCELLHOSTS
; i
++) {
925 if ((sp
= tcell
->cellHosts
[i
]) == NULL
)
927 for (sap
= sp
->addr
; sap
; sap
= sap
->next_sa
)
928 afs_MarkServerUpOrDown(sap
, 0);
932 afs_CopyError(treq
, areq
);
933 osi_FreeLargeSpace(tbuffer
);
934 afs_PutCell(tcell
, READ_LOCK
);
935 afs_DestroyReq(treq
);
939 * Check to see if this cell has not yet referenced a volume. If
940 * it hasn't, it's just about to change its status, and we need to mark
941 * this fact down. Note that it is remotely possible that afs_SetupVolume
942 * could fail and we would still not have a volume reference.
944 if (!(tcell
->states
& CHasVolRef
)) {
945 tcell
->states
|= CHasVolRef
;
946 afs_stats_cmperf
.numCellsContacted
++;
948 /*First time a volume in this cell has been referenced */
955 tv
= afs_SetupVolume(0, aname
, ve
, tcell
, agood
, type
, treq
);
956 if ((agood
== 3) && tv
&& tv
->backVol
) {
958 * This means that very soon we'll ask for the BK volume so
959 * we'll prefetch it (well we did already.)
962 afs_SetupVolume(tv
->backVol
, (char *)0, ve
, tcell
, 0, type
, treq
);
967 if ((agood
>= 2) && tv
&& tv
->roVol
) {
969 * This means that very soon we'll ask for the RO volume so
970 * we'll prefetch it (well we did already.)
972 tv1
= afs_SetupVolume(tv
->roVol
, NULL
, ve
, tcell
, 0, type
, treq
);
977 osi_FreeLargeSpace(tbuffer
);
978 afs_PutCell(tcell
, READ_LOCK
);
979 afs_DestroyReq(treq
);
982 } /*afs_NewVolumeByName */
987 * Call this with the volume structure locked; used for new-style vldb requests.
993 LockAndInstallVolumeEntry(struct volume
*av
, struct vldbentry
*ve
, int acell
)
1001 struct server
*serverHost
[AFS_MAXHOSTS
];
1003 AFS_STATCNT(InstallVolumeEntry
);
1005 memset(serverHost
, 0, sizeof(serverHost
));
1007 /* Determine the type of volume we want */
1008 if ((ve
->flags
& VLF_RWEXISTS
) && (av
->volume
== ve
->volumeId
[RWVOL
])) {
1010 } else if ((ve
->flags
& VLF_ROEXISTS
)
1011 && (av
->volume
== ve
->volumeId
[ROVOL
])) {
1014 } else if ((ve
->flags
& VLF_BACKEXISTS
)
1015 && (av
->volume
== ve
->volumeId
[BACKVOL
])) {
1016 /* backup always is on the same volume as parent */
1018 types
|= (VRO
| VBackup
);
1020 mask
= 0; /* Can't find volume in vldb entry */
1023 cellp
= afs_GetCell(acell
, 0);
1025 /* Step through the VLDB entry making sure each server listed is there */
1026 for (i
= 0, j
= 0; i
< ve
->nServers
; i
++) {
1027 if (((ve
->serverFlags
[i
] & mask
) == 0)
1028 || (ve
->serverFlags
[i
] & VLSF_DONTUSE
)) {
1029 continue; /* wrong volume or don't use this volume */
1032 temp
= htonl(ve
->serverNumber
[i
]);
1033 ts
= afs_GetServer(&temp
, 1, acell
, cellp
->fsport
, WRITE_LOCK
,
1034 (afsUUID
*) 0, 0, av
);
1038 * The cell field could be 0 if the server entry was created
1039 * first with the 'fs setserverprefs' call which doesn't set
1040 * the cell field. Thus if the afs_GetServer call above
1041 * follows later on it will find the server entry thus it will
1042 * simply return without setting any fields, so we set the
1043 * field ourselves below.
1047 afs_PutServer(ts
, WRITE_LOCK
);
1051 ObtainWriteLock(&av
->lock
, 109);
1053 memcpy(av
->serverHost
, serverHost
, sizeof(serverHost
));
1056 av
->states
|= types
;
1058 /* fill in volume types */
1059 av
->rwVol
= ((ve
->flags
& VLF_RWEXISTS
) ? ve
->volumeId
[RWVOL
] : 0);
1060 av
->roVol
= ((ve
->flags
& VLF_ROEXISTS
) ? ve
->volumeId
[ROVOL
] : 0);
1061 av
->backVol
= ((ve
->flags
& VLF_BACKEXISTS
) ? ve
->volumeId
[BACKVOL
] : 0);
1063 if (ve
->flags
& VLF_DFSFILESET
)
1064 av
->states
|= VForeign
;
1066 afs_SortServers(av
->serverHost
, AFS_MAXHOSTS
);
1067 } /*InstallVolumeEntry */
1071 LockAndInstallNVolumeEntry(struct volume
*av
, struct nvldbentry
*ve
, int acell
)
1079 struct server
*serverHost
[AFS_MAXHOSTS
];
1081 AFS_STATCNT(InstallVolumeEntry
);
1083 memset(serverHost
, 0, sizeof(serverHost
));
1085 /* Determine type of volume we want */
1086 if ((ve
->flags
& VLF_RWEXISTS
) && (av
->volume
== ve
->volumeId
[RWVOL
])) {
1088 } else if ((ve
->flags
& VLF_ROEXISTS
)
1089 && (av
->volume
== ve
->volumeId
[ROVOL
])) {
1092 } else if ((ve
->flags
& VLF_BACKEXISTS
)
1093 && (av
->volume
== ve
->volumeId
[BACKVOL
])) {
1094 /* backup always is on the same volume as parent */
1096 types
|= (VRO
| VBackup
);
1098 mask
= 0; /* Can't find volume in vldb entry */
1101 cellp
= afs_GetCell(acell
, 0);
1103 /* Step through the VLDB entry making sure each server listed is there */
1104 for (i
= 0, j
= 0; i
< ve
->nServers
; i
++) {
1105 if (((ve
->serverFlags
[i
] & mask
) == 0)
1106 || (ve
->serverFlags
[i
] & VLSF_DONTUSE
)) {
1107 continue; /* wrong volume or don't use this volume */
1110 temp
= htonl(ve
->serverNumber
[i
]);
1111 ts
= afs_GetServer(&temp
, 1, acell
, cellp
->fsport
, WRITE_LOCK
,
1112 (afsUUID
*) 0, 0, av
);
1115 * The cell field could be 0 if the server entry was created
1116 * first with the 'fs setserverprefs' call which doesn't set
1117 * the cell field. Thus if the afs_GetServer call above
1118 * follows later on it will find the server entry thus it will
1119 * simply return without setting any fields, so we set the
1120 * field ourselves below.
1124 afs_PutServer(ts
, WRITE_LOCK
);
1128 ObtainWriteLock(&av
->lock
, 110);
1130 memcpy(av
->serverHost
, serverHost
, sizeof(serverHost
));
1133 av
->states
|= types
;
1135 /* fill in volume types */
1136 av
->rwVol
= ((ve
->flags
& VLF_RWEXISTS
) ? ve
->volumeId
[RWVOL
] : 0);
1137 av
->roVol
= ((ve
->flags
& VLF_ROEXISTS
) ? ve
->volumeId
[ROVOL
] : 0);
1138 av
->backVol
= ((ve
->flags
& VLF_BACKEXISTS
) ? ve
->volumeId
[BACKVOL
] : 0);
1140 if (ve
->flags
& VLF_DFSFILESET
)
1141 av
->states
|= VForeign
;
1143 afs_SortServers(av
->serverHost
, AFS_MAXHOSTS
);
1144 } /*InstallNVolumeEntry */
1148 LockAndInstallUVolumeEntry(struct volume
*av
, struct uvldbentry
*ve
, int acell
,
1149 struct cell
*tcell
, struct vrequest
*areq
)
1152 struct afs_conn
*tconn
;
1155 afs_uint32 serverid
;
1159 struct server
*serverHost
[AFS_MAXHOSTS
];
1161 AFS_STATCNT(InstallVolumeEntry
);
1163 memset(serverHost
, 0, sizeof(serverHost
));
1165 /* Determine type of volume we want */
1166 if ((ve
->flags
& VLF_RWEXISTS
) && (av
->volume
== ve
->volumeId
[RWVOL
])) {
1168 } else if ((ve
->flags
& VLF_ROEXISTS
)
1169 && av
->volume
== ve
->volumeId
[ROVOL
]) {
1172 } else if ((ve
->flags
& VLF_BACKEXISTS
)
1173 && (av
->volume
== ve
->volumeId
[BACKVOL
])) {
1174 /* backup always is on the same volume as parent */
1176 type
|= (VRO
| VBackup
);
1178 mask
= 0; /* Can't find volume in vldb entry */
1181 cellp
= afs_GetCell(acell
, 0);
1183 /* Gather the list of servers the VLDB says the volume is on
1184 * and initialize the ve->serverHost[] array. If a server struct
1185 * is not found, then get the list of addresses for the
1186 * server, VL_GetAddrsU(), and create a server struct, afs_GetServer().
1188 for (i
= 0, j
= 0; i
< ve
->nServers
; i
++) {
1189 if (((ve
->serverFlags
[i
] & mask
) == 0)
1190 || (ve
->serverFlags
[i
] & VLSF_DONTUSE
)) {
1191 continue; /* wrong volume don't use this volume */
1194 if (!(ve
->serverFlags
[i
] & VLSF_UUID
)) {
1195 /* The server has no uuid */
1196 serverid
= htonl(ve
->serverNumber
[i
].time_low
);
1197 ts
= afs_GetServer(&serverid
, 1, acell
, cellp
->fsport
,
1198 WRITE_LOCK
, (afsUUID
*) 0, 0, av
);
1200 ts
= afs_FindServer(0, cellp
->fsport
, &ve
->serverNumber
[i
], 0);
1201 if (ts
&& (ts
->sr_addr_uniquifier
== ve
->serverUnique
[i
])
1203 /* uuid, uniquifier, and portal are the same */
1205 afs_uint32
*addrp
, code
;
1206 afs_int32 nentries
, unique
;
1208 ListAddrByAttributes attrs
;
1210 struct rx_connection
*rxconn
;
1212 memset(&attrs
, 0, sizeof(attrs
));
1213 attrs
.Mask
= VLADDR_UUID
;
1214 attrs
.uuid
= ve
->serverNumber
[i
];
1215 memset(&uuid
, 0, sizeof(uuid
));
1216 memset(&addrs
, 0, sizeof(addrs
));
1219 afs_ConnByMHosts(tcell
->cellHosts
, tcell
->vlport
,
1220 tcell
->cellNum
, areq
, SHARED_LOCK
,
1225 VL_GetAddrsU(rxconn
, &attrs
, &uuid
, &unique
,
1232 /* Handle corrupt VLDB (defect 7393) */
1233 if (code
== 0 && nentries
== 0)
1236 } while (afs_Analyze
1237 (tconn
, rxconn
, code
, NULL
, areq
, -1, SHARED_LOCK
, tcell
));
1239 /* Better handing of such failures; for now we'll simply retry this call */
1240 areq
->volumeError
= 1;
1244 addrp
= addrs
.bulkaddrs_val
;
1245 for (k
= 0; k
< nentries
; k
++) {
1246 addrp
[k
] = htonl(addrp
[k
]);
1248 ts
= afs_GetServer(addrp
, nentries
, acell
,
1249 cellp
->fsport
, WRITE_LOCK
,
1250 &ve
->serverNumber
[i
],
1251 ve
->serverUnique
[i
], av
);
1252 xdr_free((xdrproc_t
) xdr_bulkaddrs
, &addrs
);
1257 /* The cell field could be 0 if the server entry was created
1258 * first with the 'fs setserverprefs' call which doesn't set
1259 * the cell field. Thus if the afs_GetServer call above
1260 * follows later on it will find the server entry thus it will
1261 * simply return without setting any fields, so we set the
1262 * field ourselves below.
1266 afs_PutServer(ts
, WRITE_LOCK
);
1270 ObtainWriteLock(&av
->lock
, 111);
1272 memcpy(av
->serverHost
, serverHost
, sizeof(serverHost
));
1277 /* fill in volume types */
1278 av
->rwVol
= ((ve
->flags
& VLF_RWEXISTS
) ? ve
->volumeId
[RWVOL
] : 0);
1279 av
->roVol
= ((ve
->flags
& VLF_ROEXISTS
) ? ve
->volumeId
[ROVOL
] : 0);
1280 av
->backVol
= ((ve
->flags
& VLF_BACKEXISTS
) ? ve
->volumeId
[BACKVOL
] : 0);
1282 if (ve
->flags
& VLF_DFSFILESET
)
1283 av
->states
|= VForeign
;
1285 afs_SortServers(av
->serverHost
, AFS_MAXHOSTS
);
1286 } /*InstallVolumeEntry */
1290 * Reset volume info for the specified volume strecture. Mark volume
1291 * to be rechecked next time.
1295 afs_ResetVolumeInfo(struct volume
*tv
)
1299 AFS_STATCNT(afs_ResetVolumeInfo
);
1300 ObtainWriteLock(&tv
->lock
, 117);
1301 tv
->states
|= VRecheck
;
1303 /* the hard-mount code in afs_Analyze may not be able to reset this flag
1304 * when VRecheck is set, so clear it here to ensure it gets cleared. */
1305 tv
->states
&= ~VHardMount
;
1307 for (i
= 0; i
< AFS_MAXHOSTS
; i
++)
1308 tv
->status
[i
] = not_busy
;
1310 afs_osi_Free(tv
->name
, strlen(tv
->name
) + 1);
1313 ReleaseWriteLock(&tv
->lock
);