Standardize License information
[openafs.git] / src / afs / afs_cell.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  */
13 #include "../afs/param.h"       /* Should be always first */
14 #include "../afs/stds.h"
15 #include "../afs/sysincludes.h" /* Standard vendor system headers */
16
17 #if !defined(UKERNEL)
18 #include <net/if.h>
19 #include <netinet/in.h>
20
21 #ifdef AFS_SGI62_ENV
22 #include "../h/hashing.h"
23 #endif
24 #if !defined(AFS_HPUX110_ENV) && !defined(AFS_LINUX20_ENV)
25 #include <netinet/in_var.h>
26 #endif /* ! ASF_HPUX110_ENV */
27 #endif /* !defined(UKERNEL) */
28
29 #include "../afs/afsincludes.h" /* Afs-based standard headers */
30 #include "../afs/afs_stats.h"   /* afs statistics */
31
32 #if     defined(AFS_SUN56_ENV)
33 #include <inet/led.h>
34 #include <inet/common.h>
35 #include <inet/ip.h>
36 #endif
37
38 /* Exported variables */
39 afs_rwlock_t afs_xcell;                 /* allocation lock for cells */
40 struct afs_q CellLRU;
41 afs_int32 afs_cellindex=0;
42
43
44 /* Local variables. */
45 struct cell *afs_rootcell = 0;
46
47 struct cell *afs_GetCellByName(acellName, locktype)
48     register char *acellName;
49     afs_int32 locktype;
50 {
51     register struct cell *tc;
52     register struct afs_q *cq, *tq;
53
54     AFS_STATCNT(afs_GetCellByName);
55     ObtainWriteLock(&afs_xcell,100);
56     for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
57         tc = QTOC(cq); tq = QNext(cq);
58         if (!strcmp(tc->cellName, acellName)) {
59             QRemove(&tc->lruq);
60             QAdd(&CellLRU, &tc->lruq);
61             ReleaseWriteLock(&afs_xcell);
62             return tc;
63         }
64     }
65     ReleaseWriteLock(&afs_xcell);
66     return (struct cell *) 0;
67
68 } /*afs_GetCellByName*/
69
70
71 struct cell *afs_GetCell(acell, locktype)
72     register afs_int32 acell;
73     afs_int32 locktype;
74 {
75     register struct cell *tc;
76     register struct afs_q *cq, *tq;
77
78     AFS_STATCNT(afs_GetCell);
79     if (acell == 1 && afs_rootcell) return afs_rootcell;
80     ObtainWriteLock(&afs_xcell,101);
81     for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
82         tc = QTOC(cq); tq = QNext(cq);
83         if (tc->cell == acell) {
84             QRemove(&tc->lruq);
85             QAdd(&CellLRU, &tc->lruq);
86             ReleaseWriteLock(&afs_xcell);
87             return tc;
88         }
89     }
90     ReleaseWriteLock(&afs_xcell);
91     return (struct cell *) 0;
92
93 } /*afs_GetCell*/
94
95
96 struct cell *afs_GetCellByIndex(cellindex, locktype)
97     register afs_int32 cellindex;
98     afs_int32 locktype;
99 {
100     register struct cell *tc;
101     register struct afs_q *cq, *tq;
102
103     AFS_STATCNT(afs_GetCellByIndex);
104     ObtainWriteLock(&afs_xcell,102);
105     for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
106         tc = QTOC(cq); tq = QNext(cq);
107         if (tc->cellIndex == cellindex) {
108             QRemove(&tc->lruq);
109             QAdd(&CellLRU, &tc->lruq);
110             ReleaseWriteLock(&afs_xcell);
111             return tc;
112         }
113     }
114     ReleaseWriteLock(&afs_xcell);
115     return (struct cell *) 0;
116
117 } /*afs_GetCellByIndex*/
118
119
120 afs_int32 afs_NewCell(acellName, acellHosts, aflags, linkedcname, fsport, vlport)
121     int aflags;
122     char *acellName;
123     register afs_int32 *acellHosts;
124     char *linkedcname;
125     u_short fsport, vlport;
126 {
127     register struct cell *tc, *tcl=0;
128     register afs_int32 i, newc=0, code=0;
129     register struct afs_q *cq, *tq;
130
131     AFS_STATCNT(afs_NewCell);
132     if (*acellHosts == 0)
133         /* need >= one host to gen cell # */
134         return EINVAL;
135
136     ObtainWriteLock(&afs_xcell,103);
137
138     /* Find the cell and mark its servers as not down but gone */
139     for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
140         tc = QTOC(cq); tq = QNext(cq);
141         if (strcmp(tc->cellName, acellName) == 0) {
142             /* we don't want to keep pinging old vlservers which were down,
143              * since they don't matter any more.  It's easier to do this than
144              * to remove the server from its various hash tables. */
145             for (i=0; i<MAXCELLHOSTS; i++) {
146                 if (!tc->cellHosts[i]) break;
147                 tc->cellHosts[i]->flags &= ~SRVR_ISDOWN;
148                 tc->cellHosts[i]->flags |= SRVR_ISGONE;
149             }
150             break;
151         }
152     }
153
154     if (cq != &CellLRU) {
155         aflags &= ~CNoSUID;
156     }
157     else {
158         tc = (struct cell *) afs_osi_Alloc(sizeof(struct cell));
159         QAdd(&CellLRU, &tc->lruq);                      /* put in lruq */
160         tc->cellName = (char *) afs_osi_Alloc(strlen(acellName)+1);
161         strcpy(tc->cellName, acellName);
162         tc->cellIndex = afs_cellindex++;
163         if (aflags & CPrimary) {
164             extern int afs_rootCellIndex;
165             tc->cell = 1;       /* primary cell is always 1 */
166             afs_rootcell = tc;
167             afs_rootCellIndex = tc->cellIndex;
168         } else {
169             tc->cell = *acellHosts; /* won't be reused by another cell */
170         }
171         tc->states = 0;
172         tc->lcellp = (struct cell *)0;
173         tc->fsport = (fsport ? fsport : AFS_FSPORT);
174         tc->vlport = (vlport ? vlport : AFS_VLPORT);
175         afs_stats_cmperf.numCellsVisible++;
176         newc++;
177     }
178
179     if (aflags & CLinkedCell) {
180         if (!linkedcname) {
181             code = EINVAL;
182             goto bad;
183         }
184         for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
185             tcl = QTOC(cq); tq = QNext(cq);
186             if (!strcmp(tcl->cellName, linkedcname)) {
187                 break;
188             }
189             tcl = 0;
190         }
191         if (!tcl) {
192             code = ENOENT;
193             goto bad;
194         }
195         if (tcl->lcellp) {      /* XXX Overwriting if one existed before! XXX */
196             tcl->lcellp->lcellp = (struct cell *)0;
197             tcl->lcellp->states &= ~CLinkedCell;
198         }
199         tc->lcellp = tcl;
200         tcl->lcellp = tc;
201     }
202     tc->states |= aflags;
203  
204     bzero((char *)tc->cellHosts, sizeof(tc->cellHosts));
205     for (i=0; i<MAXCELLHOSTS; i++) {
206         struct server *ts;
207         afs_uint32 temp = acellHosts[i];
208         if (!temp) break;
209         ts = afs_GetServer(&temp, 1, 0, tc->vlport, WRITE_LOCK, (afsUUID *)0, 0);
210         ts->cell = tc;
211         ts->flags &= ~SRVR_ISGONE;
212         tc->cellHosts[i] = ts;
213         afs_PutServer(ts, WRITE_LOCK);
214     }
215     afs_SortServers(tc->cellHosts, MAXCELLHOSTS);       /* randomize servers */
216     ReleaseWriteLock(&afs_xcell);
217     return 0;
218 bad:
219     if (newc) {
220         QRemove(&tc->lruq);
221         afs_osi_Free(tc->cellName, strlen(tc->cellName)+1);
222         afs_osi_Free((char *)tc, sizeof(struct cell));
223     }
224     ReleaseWriteLock(&afs_xcell);
225     return code;
226
227 } /*afs_NewCell*/
228
229 afs_RemoveCellEntry(struct server *srvp)
230 {
231   struct cell *tc;
232   afs_int32 j, k;
233
234   tc = srvp->cell;
235   if (!tc) return;
236
237   /* Remove the server structure from the cell list - if there */
238   ObtainWriteLock(&afs_xcell,200);
239   for (j=k=0; j<MAXCELLHOSTS; j++) {
240      if (!tc->cellHosts[j]) break;
241      if (tc->cellHosts[j] != srvp) {
242         tc->cellHosts[k++] = tc->cellHosts[j];
243      }
244   }
245   if (k == 0) {
246      /* What do we do if we remove the last one? */
247   }
248   for (; k<MAXCELLHOSTS; k++) {
249      tc->cellHosts[k] = 0;
250   }
251   ReleaseWriteLock(&afs_xcell);
252 }
253