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
10 #include <afs/param.h>
23 osi_rwlock_t cm_volumeLock;
24 cm_volume_t *cm_allVolumesp;
26 void cm_InitVolume(void)
28 static osi_once_t once;
29 if (osi_Once(&once)) {
30 lock_InitializeRWLock(&cm_volumeLock, "cm global volume lock");
31 cm_allVolumesp = NULL;
37 * Update a volume. Caller holds volume's lock (volp->mx).
39 long cm_UpdateVolume(struct cm_cell *cellp, cm_user_t *userp, cm_req_t *reqp,
46 struct sockaddr_in tsockAddr;
49 struct vldbentry vldbEntry; /* don't use NVLDB yet; they're not common */
53 /* clear out old bindings */
54 while (tsrp = volp->rwServersp) {
55 volp->rwServersp = tsrp->next;
56 cm_PutServer(tsrp->server);
59 while (tsrp = volp->roServersp) {
60 volp->roServersp = tsrp->next;
61 cm_PutServer(tsrp->server);
64 while (tsrp = volp->bkServersp) {
65 volp->bkServersp = tsrp->next;
66 cm_PutServer(tsrp->server);
70 /* now we have volume structure locked and held; make RPC to fill it */
72 code = cm_ConnByMServers(cellp->vlServersp, userp, reqp,
75 osi_Log1(afsd_logp, "CALL VL_GetEntryByNameO name %s",
77 code = VL_GetEntryByNameO(connp->callp, volp->namep, &vldbEntry);
78 } while (cm_Analyze(connp, userp, reqp, NULL, NULL, NULL, code));
79 code = cm_MapVLRPCError(code, reqp);
82 /* decode the response */
83 lock_ObtainWrite(&cm_volumeLock);
84 if (vldbEntry.flags & VLF_RWEXISTS)
85 volp->rwID = vldbEntry.volumeId[0];
88 if (vldbEntry.flags & VLF_ROEXISTS)
89 volp->roID = vldbEntry.volumeId[1];
92 if (vldbEntry.flags & VLF_BACKEXISTS)
93 volp->bkID = vldbEntry.volumeId[2];
96 lock_ReleaseWrite(&cm_volumeLock);
97 for(i=0; i<vldbEntry.nServers; i++) {
98 /* create a server entry */
99 tflags = vldbEntry.serverFlags[i];
100 if (tflags & VLSF_DONTUSE) continue;
101 tsockAddr.sin_family = AF_INET;
102 tempAddr = htonl(vldbEntry.serverNumber[i]);
103 tsockAddr.sin_addr.s_addr = tempAddr;
104 tsp = cm_FindServer(&tsockAddr, CM_SERVER_FILE);
106 tsp = cm_NewServer(&tsockAddr, CM_SERVER_FILE,
109 /* if this server was created by fs setserverprefs */
113 osi_assert(tsp != NULL);
115 /* and add it to the list(s). */
117 * Each call to cm_NewServerRef() increments the
118 * ref count of tsp. These reference will be dropped,
119 * if and when the volume is reset; see reset code
120 * earlier in this function.
122 if ((tflags & VLSF_RWVOL)
123 && (vldbEntry.flags & VLF_RWEXISTS)) {
124 tsrp = cm_NewServerRef(tsp);
125 tsrp->next = volp->rwServersp;
126 volp->rwServersp = tsrp;
128 if ((tflags & VLSF_ROVOL)
129 && (vldbEntry.flags & VLF_ROEXISTS)) {
130 tsrp = cm_NewServerRef(tsp);
131 cm_InsertServerList(&volp->roServersp, tsrp);
134 /* We don't use VLSF_BACKVOL !?! */
135 if ((tflags & VLSF_RWVOL)
136 && (vldbEntry.flags & VLF_BACKEXISTS)) {
137 tsrp = cm_NewServerRef(tsp);
138 tsrp->next = volp->bkServersp;
139 volp->bkServersp = tsrp;
141 /* Drop the reference obtained by cm_FindServer() */
148 * If the first n servers have the same ipRank, then we
149 * randomly pick one among them and move it to the beginning.
150 * We don't bother to re-order the whole list because
151 * the rest of the list is used only if the first server is
152 * down. We only do this for the RO list; we assume the other
153 * lists are length 1.
156 cm_RandomizeServer(&volp->roServersp);
162 long cm_GetVolumeByID(cm_cell_t *cellp, long volumeID, cm_user_t *userp,
163 cm_req_t *reqp, cm_volume_t **outVolpp)
166 char volNameString[100];
169 lock_ObtainWrite(&cm_volumeLock);
170 for(volp = cm_allVolumesp; volp; volp=volp->nextp) {
171 if (cellp == volp->cellp &&
172 ((unsigned) volumeID == volp->rwID ||
173 (unsigned) volumeID == volp->roID ||
174 (unsigned) volumeID == volp->bkID))
178 /* hold the volume if we found it */
179 if (volp) volp->refCount++;
180 lock_ReleaseWrite(&cm_volumeLock);
184 lock_ObtainMutex(&volp->mx);
186 if (volp->flags & CM_VOLUMEFLAG_RESET) {
187 code = cm_UpdateVolume(cellp, userp, reqp, volp);
189 volp->flags &= ~CM_VOLUMEFLAG_RESET;
194 lock_ReleaseMutex(&volp->mx);
200 /* otherwise, we didn't find it so consult the VLDB */
201 sprintf(volNameString, "%u", volumeID);
202 code = cm_GetVolumeByName(cellp, volNameString, userp, reqp,
207 long cm_GetVolumeByName(struct cm_cell *cellp, char *volumeNamep,
208 struct cm_user *userp, struct cm_req *reqp,
209 long flags, cm_volume_t **outVolpp)
214 /* initialize this */
217 lock_ObtainWrite(&cm_volumeLock);
218 for(volp = cm_allVolumesp; volp; volp=volp->nextp) {
219 if (cellp == volp->cellp && strcmp(volumeNamep, volp->namep) == 0) {
224 /* otherwise, get from VLDB */
226 volp = malloc(sizeof(*volp));
227 memset(volp, 0, sizeof(*volp));
229 volp->nextp = cm_allVolumesp;
230 cm_allVolumesp = volp;
231 volp->namep = malloc(strlen(volumeNamep)+1);
232 strcpy(volp->namep, volumeNamep);
233 lock_InitializeMutex(&volp->mx, "cm_volume_t mutex");
234 volp->refCount = 1; /* starts off held */
235 volp->flags |= CM_VOLUMEFLAG_RESET;
241 /* next should work since no one could have gotten ptr to this structure yet */
242 lock_ReleaseWrite(&cm_volumeLock);
243 lock_ObtainMutex(&volp->mx);
245 if (volp->flags & CM_VOLUMEFLAG_RESET) {
246 code = cm_UpdateVolume(cellp, userp, reqp, volp);
248 volp->flags &= ~CM_VOLUMEFLAG_RESET;
253 lock_ReleaseMutex(&volp->mx);
257 void cm_ForceUpdateVolume(cm_fid_t *fidp, cm_user_t *userp, cm_req_t *reqp)
263 cellp = cm_FindCellByID(fidp->cell);
266 /* search for the volume */
267 lock_ObtainWrite(&cm_volumeLock);
268 for(volp = cm_allVolumesp; volp; volp=volp->nextp) {
269 if (cellp == volp->cellp &&
270 (fidp->volume == volp->rwID ||
271 fidp->volume == volp->roID ||
272 fidp->volume == volp->bkID))
276 /* hold the volume if we found it */
277 if (volp) volp->refCount++;
278 lock_ReleaseWrite(&cm_volumeLock);
282 lock_ObtainMutex(&volp->mx);
283 volp->flags |= CM_VOLUMEFLAG_RESET;
284 code = cm_UpdateVolume(cellp, userp, reqp, volp);
286 volp->flags &= ~CM_VOLUMEFLAG_RESET;
287 lock_ReleaseMutex(&volp->mx);
292 /* find the appropriate servers from a volume */
293 cm_serverRef_t *cm_GetVolServers(cm_volume_t *volp, unsigned long volume)
295 cm_serverRef_t *serversp;
297 if (volume == volp->rwID)
298 serversp = volp->rwServersp;
299 else if (volume == volp->roID)
300 serversp = volp->roServersp;
301 else if (volume == volp->bkID)
302 serversp = volp->bkServersp;
303 else osi_panic("bad volume ID in cm_GetVolServers", __FILE__, __LINE__);
308 void cm_PutVolume(cm_volume_t *volp)
310 lock_ObtainWrite(&cm_volumeLock);
311 osi_assert(volp->refCount-- > 0);
312 lock_ReleaseWrite(&cm_volumeLock);
315 /* return the read-only volume, if there is one, or the read-write volume if
318 long cm_GetROVolumeID(cm_volume_t *volp)
322 lock_ObtainMutex(&volp->mx);
323 if (volp->roID && volp->roServersp)
327 lock_ReleaseMutex(&volp->mx);
332 void cm_CheckVolumes(void)
337 lock_ObtainWrite(&cm_volumeLock);
338 for(volp = cm_allVolumesp; volp; volp=volp->nextp) {
340 lock_ReleaseWrite(&cm_volumeLock);
341 lock_ObtainMutex(&volp->mx);
343 volp->flags |= CM_VOLUMEFLAG_RESET;
345 lock_ReleaseMutex(&volp->mx);
346 lock_ObtainWrite(&cm_volumeLock);
347 osi_assert(volp->refCount-- > 0);
349 lock_ReleaseWrite(&cm_volumeLock);
351 /* We should also refresh cached mount points */
356 ** Finds all volumes that reside on this server and reorders their
357 ** RO list according to the changed rank of server.
359 void cm_ChangeRankVolume(cm_server_t *tsp)
364 /* find volumes which might have RO copy on server*/
365 lock_ObtainWrite(&cm_volumeLock);
366 for(volp = cm_allVolumesp; volp; volp=volp->nextp)
368 code = 1 ; /* assume that list is unchanged */
370 lock_ReleaseWrite(&cm_volumeLock);
371 lock_ObtainMutex(&volp->mx);
373 if ((tsp->cellp==volp->cellp) && (volp->roServersp))
374 code =cm_ChangeRankServer(&volp->roServersp, tsp);
376 /* this volume list was changed */
378 cm_RandomizeServer(&volp->roServersp);
380 lock_ReleaseMutex(&volp->mx);
381 lock_ObtainWrite(&cm_volumeLock);
382 osi_assert(volp->refCount-- > 0);
384 lock_ReleaseWrite(&cm_volumeLock);