1 /* BLURB lgpl
2
3 Coda File System
4 Release 5
5
6 Copyright (c) 1987-1999 Carnegie Mellon University
7 Additional copyrights listed below
8
9 This code is distributed "AS IS" without warranty of any kind under
10 the terms of the GNU Library General Public Licence Version 2, as
11 shown in the file LICENSE. The technical and financial contributors to
12 Coda are listed in the file CREDITS.
13
14 Additional copyrights
15
16 #*/
17
18 /*
19 IBM COPYRIGHT NOTICE
20
21 Copyright (C) 1986
22 International Business Machines Corporation
23 All Rights Reserved
24
25 This file contains some code identical to or derived from the 1986
26 version of the Andrew File System ("AFS"), which is owned by the IBM
27 Corporation. This code is provided "AS IS" and IBM does not warrant
28 that it is free of infringement of any intellectual rights of any
29 third party. IBM disclaims liability of any kind for any damages
30 whatsoever resulting directly or indirectly from use of this software
31 or of any derivative work. Carnegie Mellon University has obtained
32 permission to modify, distribute and sublicense this code, which is
33 based on Version 2 of AFS and does not contain the features and
34 enhancements that are part of Version 3 of AFS. Version 3 of AFS is
35 commercially available and supported by Transarc Corporation,
36 Pittsburgh, PA.
37
38 */
39
40
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <unistd.h>
44 #include <string.h>
45 #include <sys/types.h>
46 #include <sys/socket.h>
47 #include <netinet/in.h>
48 #include <sys/time.h>
49 #include <assert.h>
50 #include "rpc2.private.h"
51
52
53 /* Routines to allocate and manipulate the doubly-linked circular lists
54 used elsewhere in rpc2 */
55
rpc2_Replenish(whichList,whichCount,elemSize,creationCount,magicNumber)56 void rpc2_Replenish(whichList, whichCount, elemSize, creationCount, magicNumber)
57 struct LinkEntry **whichList;
58 long *whichCount;
59 long elemSize; /* size of each element in the list */
60 long *creationCount;
61 long magicNumber;
62 /* Routine to avoid using malloc() too often.
63 Assumes *whichList is empty and grows it by 1 entry of size elemSize.
64 Sets *whichCount to 1.
65 Bumps creationCount by 1.
66 */
67 {
68
69 *whichList = (struct LinkEntry *)malloc(elemSize);
70 assert(*whichList != NULL);
71 memset(*whichList, 0, elemSize);
72 (*whichList)->NextEntry = (*whichList)->PrevEntry = *whichList; /* 1-element circular list */
73 (*whichList)->MagicNumber = magicNumber;
74 (*whichList)->Qname = whichList;
75 *whichCount = 1;
76 (*creationCount)++;
77 }
78
79
80 /* Generic routine to move elements between lists Assumes p points to
81 an entry in the list pointed to by fromPtr. Moves that entry to
82 the list pointed to by toPtr. If p is NULL, an arbitrary entry in
83 the from list is selected as a victim and moved. If toPtr is NULL,
84 the moved entry is made into a singleton list. In all cases a
85 pointer to the moved entry is returned as the value of the
86 function.
87
88 *fromCount is decremented by one.
89 *toCount is incremented by one.
90
91 Frequently used routine -- optimize the hell out of it. */
rpc2_MoveEntry(fromPtr,toPtr,p,fromCount,toCount)92 struct LinkEntry *rpc2_MoveEntry(fromPtr, toPtr, p, fromCount, toCount)
93 /* pointers to header pointers of from and to lists */
94 struct LinkEntry **fromPtr, **toPtr;
95 struct LinkEntry *p; /* pointer to entry to be moved */
96 long *fromCount; /* pointer to count of entries in from list */
97 long *toCount; /* pointer to count of entries in to list */
98
99 {
100 struct LinkEntry *victim;
101
102 if (p == NULL)
103 victim = *fromPtr;
104 else
105 victim = p;
106 assert(victim->Qname == fromPtr); /* sanity check for list corruption */
107
108 /* first remove element from the first list */
109 if (victim == *fromPtr)
110 *fromPtr = victim->NextEntry;
111
112 /* remque(victim); */
113 victim->PrevEntry->NextEntry = victim->NextEntry;
114 victim->NextEntry->PrevEntry = victim->PrevEntry;
115 victim->PrevEntry = victim->NextEntry = victim;
116
117 if (victim == *fromPtr)
118 *fromPtr = NULL;
119 (*fromCount)--;
120
121 /* make victim a singleton list */
122 victim->NextEntry = victim->PrevEntry = victim;
123
124 /* then insert into second list */
125 if (*toPtr == NULL)
126 *toPtr = victim;
127 else {
128 /* PrevEntry because semantics of insque() causes non-FIFO queue */
129 /* insque(victim, (*toPtr)->PrevEntry); */
130 victim->PrevEntry = (*toPtr)->PrevEntry;
131 victim->NextEntry = *toPtr;
132 (*toPtr)->PrevEntry->NextEntry = victim;
133 (*toPtr)->PrevEntry = victim;
134 }
135 victim->Qname = toPtr;
136 (*toCount)++;
137 return(victim);
138 }
139
140 /* Allocates an SL entry and binds it to slConn */
rpc2_AllocSle(enum SL_Type slType,struct CEntry * slConn)141 struct SL_Entry *rpc2_AllocSle(enum SL_Type slType, struct CEntry *slConn)
142 {
143 struct SL_Entry *sl, **tolist;
144 long *tocount;
145
146 if (rpc2_SLFreeCount == 0)
147 {
148 rpc2_Replenish(&rpc2_SLFreeList, &rpc2_SLFreeCount,
149 sizeof(struct SL_Entry), &rpc2_SLCreationCount, OBJ_SLENTRY);
150 }
151
152 if (slType == REQ)
153 {
154 tolist = &rpc2_SLReqList;
155 tocount = &rpc2_SLReqCount;
156 }
157 else
158 {
159 tolist = &rpc2_SLList;
160 tocount = &rpc2_SLCount;
161 }
162
163 sl = (struct SL_Entry *)rpc2_MoveEntry(&rpc2_SLFreeList,
164 tolist, NULL, &rpc2_SLFreeCount, tocount);
165
166 assert(sl->MagicNumber == OBJ_SLENTRY);
167 sl->Type = slType;
168 if (slType != REQ && slConn != NULL) {
169 slConn->MySl = sl;
170 sl->Conn = slConn->UniqueCID;
171 } else
172 sl->Conn = 0;
173
174 return(sl);
175 }
176
rpc2_FreeSle(INOUT struct SL_Entry ** sl)177 void rpc2_FreeSle(INOUT struct SL_Entry **sl)
178 /* Releases the SL_Entry pointed to by sl. Sets sl to NULL.
179 Removes binding between sl and its connection */
180 {
181 struct SL_Entry *tsl, **fromlist;
182 long *fromcount;
183 struct CEntry *ce;
184
185 tsl = *sl;
186 assert(tsl->MagicNumber == OBJ_SLENTRY);
187
188 if (tsl->Conn != 0) {
189 ce = __rpc2_GetConn(tsl->Conn);
190 if (ce) ce->MySl = NULL;
191 }
192
193 if (tsl->Type == REQ) {
194 fromlist = &rpc2_SLReqList;
195 fromcount = &rpc2_SLReqCount;
196 } else {
197 fromlist = &rpc2_SLList;
198 fromcount = &rpc2_SLCount;
199 }
200
201 rpc2_MoveEntry(fromlist, &rpc2_SLFreeList, tsl, fromcount, &rpc2_SLFreeCount);
202 *sl = NULL;
203 }
204
rpc2_ActivateSle(selem,exptime)205 void rpc2_ActivateSle (selem, exptime)
206 struct SL_Entry *selem;
207 struct timeval *exptime;
208 {
209 struct TM_Elem *t, *oldt;
210
211 assert(selem->MagicNumber == OBJ_SLENTRY);
212 selem->TElem.BackPointer = (char *)selem;
213 selem->ReturnCode = WAITING;
214
215 t = &selem->TElem;
216
217 if (exptime == NULL)
218 {/* infinite timeout, don't add to timer chain */
219 t->TotalTime.tv_sec = -1;
220 t->TotalTime.tv_usec = -1;
221 return;
222 }
223
224 t->TotalTime = *exptime; /* structure assignment */
225
226 oldt = TM_GetEarliest(rpc2_TimerQueue);
227 /* if the new entry expires before any previous timeout, signal the socket
228 * listener to recheck the timerqueue (being able to rely on the
229 * availability of timercmp would be nice) */
230 if (!oldt || oldt->TimeLeft.tv_sec > t->TotalTime.tv_sec ||
231 (oldt->TimeLeft.tv_sec == t->TotalTime.tv_sec &&
232 oldt->TimeLeft.tv_usec > t->TotalTime.tv_usec))
233 IOMGR_Cancel(rpc2_SocketListenerPID);
234
235 TM_Insert(rpc2_TimerQueue, t);
236 }
237
rpc2_DeactivateSle(sl,rc)238 void rpc2_DeactivateSle(sl, rc)
239 struct SL_Entry *sl;
240 enum RetVal rc;
241 {
242 struct timeval *t;
243
244 assert(sl->MagicNumber == OBJ_SLENTRY);
245
246 sl->ReturnCode = rc;
247 t = &sl->TElem.TotalTime;
248 if (t->tv_sec == -1 && t->tv_usec == -1) return; /* not timed */
249 else {
250 TM_Remove(rpc2_TimerQueue, &sl->TElem);
251 t->tv_sec = t->tv_usec = -1; /* keep routine idempotent */
252 }
253 }
254
255
rpc2_AllocSubsys()256 struct SubsysEntry *rpc2_AllocSubsys()
257 /* Allocates a new subsystem entry and returns a pointer to it.
258 Returns NULL if unable to allocate such an entry.
259 */
260 {
261 struct SubsysEntry *ss;
262 if (rpc2_SSFreeCount == 0)
263 rpc2_Replenish(&rpc2_SSFreeList,
264 &rpc2_SSFreeCount, sizeof(struct SubsysEntry),
265 &rpc2_SSCreationCount, OBJ_SSENTRY);
266 ss = (struct SubsysEntry *)rpc2_MoveEntry(&rpc2_SSFreeList,
267 &rpc2_SSList, NULL, &rpc2_SSFreeCount, &rpc2_SSCount);
268 assert(ss->MagicNumber == OBJ_SSENTRY);
269 return(ss);
270 }
271
rpc2_FreeSubsys(whichSubsys)272 void rpc2_FreeSubsys(whichSubsys)
273 struct SubsysEntry **whichSubsys;
274 /* Releases the subsystem entry pointed to by whichSubsys.
275 Sets whichSubsys to NULL; */
276 {
277 assert((*whichSubsys)->MagicNumber == OBJ_SSENTRY);
278 rpc2_MoveEntry(&rpc2_SSList, &rpc2_SSFreeList, whichSubsys,
279 &rpc2_SSCount, &rpc2_SSFreeCount);
280 *whichSubsys = NULL;
281 }
282
283
284
285 /* Moves packet whichPB to hold list from inuse list */
rpc2_HoldPacket(RPC2_PacketBuffer * whichPB)286 void rpc2_HoldPacket(RPC2_PacketBuffer *whichPB)
287 {
288 assert(whichPB->Prefix.MagicNumber == OBJ_PACKETBUFFER);
289 rpc2_MoveEntry(&rpc2_PBList, &rpc2_PBHoldList, whichPB,
290 &rpc2_PBCount, &rpc2_PBHoldCount);
291 if (rpc2_HoldHWMark < rpc2_PBHoldCount)
292 rpc2_HoldHWMark = rpc2_PBHoldCount;
293 }
294
295 /* Moves packet whichPB to inuse list from hold list */
rpc2_UnholdPacket(RPC2_PacketBuffer * whichPB)296 void rpc2_UnholdPacket(RPC2_PacketBuffer *whichPB)
297 {
298 assert(whichPB->Prefix.MagicNumber == OBJ_PACKETBUFFER);
299 rpc2_MoveEntry(&rpc2_PBHoldList, &rpc2_PBList, whichPB,
300 &rpc2_PBHoldCount, &rpc2_PBCount);
301 }
302
303
304