Commit | Line | Data |
---|---|---|
805e021f CE |
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 | #include <afsconfig.h> | |
11 | #include <afs/param.h> | |
12 | ||
13 | #include <roken.h> | |
14 | ||
15 | #include <afs/com_err.h> | |
16 | #include <lock.h> | |
17 | #include <afs/bubasics.h> | |
18 | #include <afs/tcdata.h> | |
19 | #include <afs/butc.h> | |
20 | #include <afs/budb_client.h> | |
21 | #include <afs/bucoord_prototypes.h> | |
22 | ||
23 | #include "butc_internal.h" | |
24 | #include "error_macros.h" | |
25 | #include "butc_xbsa.h" | |
26 | #include "afs/audit.h" | |
27 | ||
28 | /* tape coordinator - task status management */ | |
29 | extern afs_int32 xbsaType; | |
30 | ||
31 | dlqlinkT statusHead; | |
32 | struct Lock statusQueueLock; | |
33 | struct Lock cmdLineLock; | |
34 | ||
35 | static afs_int32 SGetStatus(struct rx_call *call, afs_uint32 taskId, | |
36 | struct tciStatusS *statusPtr); | |
37 | static afs_int32 SEndStatus(struct rx_call *call, afs_uint32 taskId); | |
38 | static afs_int32 SRequestAbort(struct rx_call *call, afs_uint32 taskId); | |
39 | static afs_int32 SScanStatus(struct rx_call *call, afs_uint32 *taskId, | |
40 | struct tciStatusS *statusPtr, afs_uint32 *flags); | |
41 | ||
42 | /* STC_GetStatus | |
43 | * get the status of a task | |
44 | * entry: | |
45 | * taskId - task for which status required | |
46 | * exit: | |
47 | * statusPtr - filled in with task status | |
48 | */ | |
49 | ||
50 | afs_int32 | |
51 | STC_GetStatus(struct rx_call *call, afs_uint32 taskId, | |
52 | struct tciStatusS *status) | |
53 | { | |
54 | afs_int32 code; | |
55 | ||
56 | code = SGetStatus(call, taskId, status); | |
57 | osi_auditU(call, TC_GetStatusEvent, code, | |
58 | AUD_INT, taskId, AUD_TSTT, status, AUD_END); | |
59 | return code; | |
60 | } | |
61 | ||
62 | static afs_int32 | |
63 | SGetStatus(struct rx_call *call, afs_uint32 taskId, | |
64 | struct tciStatusS *statusPtr) | |
65 | { | |
66 | statusP ptr; | |
67 | int retval = 0; | |
68 | ||
69 | memset(statusPtr, 0, sizeof(*statusPtr)); | |
70 | if (callPermitted(call) == 0) | |
71 | return (TC_NOTPERMITTED); | |
72 | ||
73 | lock_Status(); | |
74 | ptr = findStatus(taskId); | |
75 | if (ptr) { | |
76 | strcpy(statusPtr->taskName, ptr->taskName); | |
77 | strcpy(statusPtr->volumeName, ptr->volumeName); | |
78 | statusPtr->taskId = ptr->taskId; | |
79 | statusPtr->flags = ptr->flags; | |
80 | statusPtr->nKBytes = ptr->nKBytes; | |
81 | statusPtr->dbDumpId = ptr->dbDumpId; | |
82 | statusPtr->lastPolled = ptr->lastPolled; | |
83 | statusPtr->volsFailed = ptr->volsFailed; | |
84 | ptr->lastPolled = time(0); | |
85 | } else | |
86 | retval = TC_NODENOTFOUND; | |
87 | unlock_Status(); | |
88 | ||
89 | return (retval); | |
90 | } | |
91 | ||
92 | afs_int32 | |
93 | STC_EndStatus(struct rx_call *call, afs_uint32 taskId) | |
94 | { | |
95 | afs_int32 code; | |
96 | ||
97 | code = SEndStatus(call, taskId); | |
98 | osi_auditU(call, TC_EndStatusEvent, code, AUD_INT, taskId, AUD_END); | |
99 | return code; | |
100 | } | |
101 | ||
102 | static afs_int32 | |
103 | SEndStatus(struct rx_call *call, afs_uint32 taskId) | |
104 | { | |
105 | statusP ptr; | |
106 | int retval = 0; | |
107 | ||
108 | if (callPermitted(call) == 0) | |
109 | return (TC_NOTPERMITTED); | |
110 | ||
111 | lock_Status(); | |
112 | ptr = findStatus(taskId); | |
113 | unlock_Status(); | |
114 | ||
115 | if (ptr) | |
116 | deleteStatusNode(ptr); | |
117 | else | |
118 | retval = TC_NODENOTFOUND; | |
119 | ||
120 | return (retval); | |
121 | } | |
122 | ||
123 | afs_int32 | |
124 | STC_RequestAbort(struct rx_call *call, afs_uint32 taskId) | |
125 | { | |
126 | afs_int32 code; | |
127 | ||
128 | code = SRequestAbort(call, taskId); | |
129 | osi_auditU(call, TC_RequestAbortEvent, code, AUD_INT, taskId, AUD_END); | |
130 | return code; | |
131 | } | |
132 | ||
133 | static afs_int32 | |
134 | SRequestAbort(struct rx_call *call, afs_uint32 taskId) | |
135 | { | |
136 | statusP ptr; | |
137 | int retval = 0; | |
138 | ||
139 | if (callPermitted(call) == 0) | |
140 | return (TC_NOTPERMITTED); | |
141 | ||
142 | lock_Status(); | |
143 | ptr = findStatus(taskId); | |
144 | if (ptr) | |
145 | ptr->flags |= ABORT_REQUEST; | |
146 | else | |
147 | retval = TC_NODENOTFOUND; | |
148 | unlock_Status(); | |
149 | return (retval); | |
150 | } | |
151 | ||
152 | /* STC_ScanStatus | |
153 | * Get status of all tasks on the butc, successively. Initial call | |
154 | * should come in with TSK_STAT_FIRST flag set to initialize the | |
155 | * scan. | |
156 | * entry: | |
157 | * taskId - specifies the task whose status is to be returned | |
158 | * (unless TSK_STAT_FIRST set in which case it is ignored) | |
159 | * exit: | |
160 | * taskId - id of next task in the list | |
161 | * flags - TSK_STAT_END will be set when one reaches the end of | |
162 | * the task list. taskId is not updated in this case. | |
163 | * return values: | |
164 | * 0 - normal | |
165 | * TC_NOTASKS - no tasks active | |
166 | */ | |
167 | ||
168 | afs_int32 | |
169 | STC_ScanStatus(struct rx_call *call, afs_uint32 *taskId, | |
170 | struct tciStatusS *status, afs_uint32 *flags) | |
171 | { | |
172 | afs_int32 code; | |
173 | ||
174 | code = SScanStatus(call, taskId, status, flags); | |
175 | osi_auditU(call, TC_ScanStatusEvent, code, | |
176 | AUD_INT, *taskId, AUD_TSTT, status, AUD_INT, *flags, AUD_END); | |
177 | return code; | |
178 | } | |
179 | ||
180 | static afs_int32 | |
181 | SScanStatus(struct rx_call *call, afs_uint32 *taskId, | |
182 | struct tciStatusS *statusPtr, afs_uint32 *flags) | |
183 | { | |
184 | statusP ptr = 0; | |
185 | dlqlinkP dlqPtr; | |
186 | ||
187 | memset(statusPtr, 0, sizeof(*statusPtr)); | |
188 | if (callPermitted(call) == 0) | |
189 | return (TC_NOTPERMITTED); | |
190 | ||
191 | lock_Status(); | |
192 | ||
193 | if (CONF_XBSA) | |
194 | *flags |= TSK_STAT_XBSA; | |
195 | if (xbsaType == XBSA_SERVER_TYPE_ADSM) | |
196 | *flags |= TSK_STAT_ADSM; | |
197 | ||
198 | if (*flags & TSK_STAT_FIRST) { | |
199 | /* find first status node */ | |
200 | dlqPtr = statusHead.dlq_next; | |
201 | if (dlqPtr == &statusHead) { | |
202 | /* no status nodes */ | |
203 | *flags |= (TSK_STAT_NOTFOUND | TSK_STAT_END); | |
204 | unlock_Status(); | |
205 | return (0); | |
206 | } | |
207 | ptr = (statusP) dlqPtr; | |
208 | } else { | |
209 | ptr = findStatus(*taskId); | |
210 | if (ptr == 0) { | |
211 | /* in the event that the set of tasks has changed, just | |
212 | * finish, letting the caller retry | |
213 | */ | |
214 | ||
215 | *flags |= (TSK_STAT_NOTFOUND | TSK_STAT_END); | |
216 | unlock_Status(); | |
217 | return (0); | |
218 | } | |
219 | } | |
220 | ||
221 | /* ptr is now set to the status node we wish to return. Determine | |
222 | * what the next node will be | |
223 | */ | |
224 | ||
225 | if (ptr->link.dlq_next == &statusHead) | |
226 | *flags |= TSK_STAT_END; | |
227 | else | |
228 | *taskId = ((statusP) ptr->link.dlq_next)->taskId; | |
229 | ||
230 | strcpy(statusPtr->taskName, ptr->taskName); | |
231 | strcpy(statusPtr->volumeName, ptr->volumeName); | |
232 | statusPtr->taskId = ptr->taskId; | |
233 | statusPtr->flags = ptr->flags; | |
234 | statusPtr->nKBytes = ptr->nKBytes; | |
235 | statusPtr->lastPolled = ptr->lastPolled; | |
236 | ||
237 | unlock_Status(); | |
238 | return (0); | |
239 | } | |
240 | ||
241 | ||
242 | /* --------------------------------- | |
243 | * misc. status management routines | |
244 | * --------------------------------- | |
245 | */ | |
246 | ||
247 | /* checkAbortByTaskId | |
248 | * exit: | |
249 | * 0 - continue | |
250 | * n - abort requested | |
251 | */ | |
252 | ||
253 | int | |
254 | checkAbortByTaskId(afs_uint32 taskId) | |
255 | { | |
256 | statusP statusPtr; | |
257 | int retval = 0; | |
258 | ||
259 | lock_Status(); | |
260 | statusPtr = findStatus(taskId); | |
261 | if (statusPtr) { | |
262 | retval = statusPtr->flags & ABORT_REQUEST; | |
263 | } | |
264 | unlock_Status(); | |
265 | return (retval); | |
266 | } | |
267 | ||
268 | /* getStatusFlag | |
269 | * For backwards compatibility. Queries flag status | |
270 | * exit: | |
271 | * 0 - flag clear | |
272 | * n - flag set | |
273 | */ | |
274 | ||
275 | afs_uint32 | |
276 | getStatusFlag(afs_uint32 taskId, afs_uint32 flag) | |
277 | { | |
278 | statusP statusPtr; | |
279 | int retval = 0; | |
280 | ||
281 | lock_Status(); | |
282 | statusPtr = findStatus(taskId); | |
283 | if (statusPtr) { | |
284 | retval = statusPtr->flags & flag; | |
285 | } | |
286 | unlock_Status(); | |
287 | return (retval); | |
288 | } |