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
9 * Portions Copyright (c) 2006-2008 Sine Nomine Associates
15 Institution: The Information Technology Center, Carnegie-Mellon University
18 #ifndef AFS_PTHREAD_ENV
19 #define USUAL_PRIORITY (LWP_MAX_PRIORITY - 2)
22 * stack size increased from 8K because the HP machine seemed to have trouble
23 * with the smaller stack
25 #define USUAL_STACK_SIZE (24 * 1024)
26 #endif /* !AFS_PTHREAD_ENV */
30 File server synchronization with external volume utilities.
31 server-side implementation
34 /* This controls the size of an fd_set; it must be defined early before
35 * the system headers define that type and the macros that operate on it.
36 * Its value should be as large as the maximum file descriptor limit we
37 * are likely to run into on any platform. Right now, that is 65536
38 * which is the default hard fd limit on Solaris 9 */
40 #define FD_SETSIZE 65536
43 #include <afsconfig.h>
44 #include <afs/param.h>
49 #include <sys/types.h>
55 #include <sys/param.h>
56 #include <sys/socket.h>
57 #include <netinet/in.h>
62 #ifdef AFS_PTHREAD_ENV
64 #else /* AFS_PTHREAD_ENV */
65 #include <afs/assert.h>
66 #endif /* AFS_PTHREAD_ENV */
71 #include <afs/afsint.h>
73 #include <afs/errors.h>
74 #include "daemon_com.h"
78 #include <afs/afssyscalls.h>
82 #include "volume_inline.h"
83 #include "partition.h"
87 #endif /* HAVE_POLL */
89 #ifdef USE_UNIX_SOCKETS
91 #include <afs/afsutil.h>
92 #endif /* USE_UNIX_SOCKETS */
94 #ifdef FSSYNC_BUILD_SERVER
96 /*@printflike@*/ extern void Log(const char *format, ...);
98 int (*V_BreakVolumeCallbacks) (VolumeId volume);
100 #define MAXHANDLERS 4 /* Up to 4 clients; must be at least 2, so that
101 * move = dump+restore can run on single server */
102 #define MAXOFFLINEVOLUMES 128 /* This needs to be as big as the maximum
103 * number that would be offline for 1 operation.
104 * Current winner is salvage, which needs all
105 * cloned read-only copies offline when salvaging
106 * a single read-write volume */
110 static struct offlineInfo OfflineVolumes[MAXHANDLERS][MAXOFFLINEVOLUMES];
113 * fssync server socket handle.
115 static SYNC_server_state_t fssync_server_state =
116 { -1, /* file descriptor */
117 FSSYNC_ENDPOINT_DECL, /* server endpoint */
118 FSYNC_PROTO_VERSION, /* protocol version */
119 5, /* bind() retry limit */
120 100, /* listen() queue depth */
121 "FSSYNC", /* protocol name string */
125 /* Forward declarations */
126 static void * FSYNC_sync(void *);
127 static void FSYNC_newconnection(osi_socket afd);
128 static void FSYNC_com(osi_socket fd);
129 static void FSYNC_Drop(osi_socket fd);
130 static void AcceptOn(void);
131 static void AcceptOff(void);
132 static void InitHandler(void);
133 static int AddHandler(osi_socket fd, void (*aproc)(osi_socket));
134 static int FindHandler(osi_socket afd);
135 static int FindHandler_r(osi_socket afd);
136 static int RemoveHandler(osi_socket afd);
137 #if defined(HAVE_POLL) && defined (AFS_PTHREAD_ENV)
138 static void CallHandler(struct pollfd *fds, int nfds, int mask);
139 static void GetHandler(struct pollfd *fds, int maxfds, int events, int *nfds);
141 static void CallHandler(fd_set * fdsetp);
142 static void GetHandler(fd_set * fdsetp, int *maxfdp);
146 static afs_int32 FSYNC_com_VolOp(osi_socket fd, SYNC_command * com, SYNC_response * res);
148 #ifdef AFS_DEMAND_ATTACH_FS
149 static afs_int32 FSYNC_com_VolError(FSSYNC_VolOp_command * com, SYNC_response * res);
151 static afs_int32 FSYNC_com_VolOn(FSSYNC_VolOp_command * com, SYNC_response * res);
152 static afs_int32 FSYNC_com_VolOff(FSSYNC_VolOp_command * com, SYNC_response * res);
153 static afs_int32 FSYNC_com_VolMove(FSSYNC_VolOp_command * com, SYNC_response * res);
154 static afs_int32 FSYNC_com_VolBreakCBKs(FSSYNC_VolOp_command * com, SYNC_response * res);
155 static afs_int32 FSYNC_com_VolDone(FSSYNC_VolOp_command * com, SYNC_response * res);
156 static afs_int32 FSYNC_com_VolQuery(FSSYNC_VolOp_command * com, SYNC_response * res);
157 static afs_int32 FSYNC_com_VolHdrQuery(FSSYNC_VolOp_command * com, SYNC_response * res);
158 #ifdef AFS_DEMAND_ATTACH_FS
159 static afs_int32 FSYNC_com_VolOpQuery(FSSYNC_VolOp_command * com, SYNC_response * res);
160 #endif /* AFS_DEMAND_ATTACH_FS */
162 static afs_int32 FSYNC_com_VnQry(osi_socket fd, SYNC_command * com, SYNC_response * res);
164 static afs_int32 FSYNC_com_StatsOp(osi_socket fd, SYNC_command * com, SYNC_response * res);
166 static afs_int32 FSYNC_com_StatsOpGeneral(FSSYNC_StatsOp_command * scom, SYNC_response * res);
168 #ifdef AFS_DEMAND_ATTACH_FS
169 static afs_int32 FSYNC_com_StatsOpViceP(FSSYNC_StatsOp_command * scom, SYNC_response * res);
170 static afs_int32 FSYNC_com_StatsOpHash(FSSYNC_StatsOp_command * scom, SYNC_response * res);
171 static afs_int32 FSYNC_com_StatsOpHdr(FSSYNC_StatsOp_command * scom, SYNC_response * res);
172 static afs_int32 FSYNC_com_StatsOpVLRU(FSSYNC_StatsOp_command * scom, SYNC_response * res);
175 static void FSYNC_com_to_info(FSSYNC_VolOp_command * vcom, FSSYNC_VolOp_info * info);
177 static int FSYNC_partMatch(FSSYNC_VolOp_command * vcom, Volume * vp, int match_anon);
181 * This lock controls access to the handler array. The overhead
182 * is minimal in non-preemptive environments.
184 struct Lock FSYNC_handler_lock;
189 #ifdef AFS_PTHREAD_ENV
191 pthread_attr_t tattr;
192 #else /* AFS_PTHREAD_ENV */
194 #endif /* AFS_PTHREAD_ENV */
196 Lock_Init(&FSYNC_handler_lock);
198 #ifdef AFS_PTHREAD_ENV
199 assert(pthread_attr_init(&tattr) == 0);
200 assert(pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED) == 0);
201 assert(pthread_create(&tid, &tattr, FSYNC_sync, NULL) == 0);
202 #else /* AFS_PTHREAD_ENV */
203 assert(LWP_CreateProcess
204 (FSYNC_sync, USUAL_STACK_SIZE, USUAL_PRIORITY, (void *)0,
205 "FSYNC_sync", &pid) == LWP_SUCCESS);
206 #endif /* AFS_PTHREAD_ENV */
209 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
210 static struct pollfd FSYNC_readfds[MAXHANDLERS];
212 static fd_set FSYNC_readfds;
217 FSYNC_sync(void * args)
221 #ifdef AFS_PTHREAD_ENV
224 SYNC_server_state_t * state = &fssync_server_state;
225 #ifdef AFS_DEMAND_ATTACH_FS
226 VThreadOptions_t * thread_opts;
229 SYNC_getAddr(&state->endpoint, &state->addr);
230 SYNC_cleanupSock(state);
233 (void)signal(SIGPIPE, SIG_IGN);
236 #ifdef AFS_PTHREAD_ENV
237 /* set our 'thread-id' so that the host hold table works */
238 MUTEX_ENTER(&rx_stats_mutex); /* protects rxi_pthread_hinum */
239 tid = ++rxi_pthread_hinum;
240 MUTEX_EXIT(&rx_stats_mutex);
241 pthread_setspecific(rx_thread_id_key, (void *)tid);
242 Log("Set thread id %d for FSYNC_sync\n", tid);
243 #endif /* AFS_PTHREAD_ENV */
246 /* Let somebody else run until level > 0. That doesn't mean that
247 * all volumes have been attached. */
248 #ifdef AFS_PTHREAD_ENV
250 #else /* AFS_PTHREAD_ENV */
251 LWP_DispatchProcess();
252 #endif /* AFS_PTHREAD_ENV */
254 state->fd = SYNC_getSock(&state->endpoint);
255 code = SYNC_bindSock(state);
258 #ifdef AFS_DEMAND_ATTACH_FS
260 * make sure the volume package is incapable of recursively executing
261 * salvsync calls on this thread, since there is a possibility of
264 thread_opts = malloc(sizeof(VThreadOptions_t));
265 if (thread_opts == NULL) {
266 Log("failed to allocate memory for thread-specific volume package options structure\n");
269 memcpy(thread_opts, &VThread_defaults, sizeof(VThread_defaults));
270 thread_opts->disallow_salvsync = 1;
271 assert(pthread_setspecific(VThread_key, thread_opts) == 0);
278 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
280 GetHandler(FSYNC_readfds, MAXHANDLERS, POLLIN|POLLPRI, &nfds);
281 if (poll(FSYNC_readfds, nfds, -1) >=1)
282 CallHandler(FSYNC_readfds, nfds, POLLIN|POLLPRI);
285 GetHandler(&FSYNC_readfds, &maxfd);
286 /* Note: check for >= 1 below is essential since IOMGR_select
287 * doesn't have exactly same semantics as select.
289 #ifdef AFS_PTHREAD_ENV
290 if (select(maxfd + 1, &FSYNC_readfds, NULL, NULL, NULL) >= 1)
291 #else /* AFS_PTHREAD_ENV */
292 if (IOMGR_Select(maxfd + 1, &FSYNC_readfds, NULL, NULL, NULL) >= 1)
293 #endif /* AFS_PTHREAD_ENV */
294 CallHandler(&FSYNC_readfds);
297 return NULL; /* hush now, little gcc */
301 FSYNC_newconnection(osi_socket afd)
303 #ifdef USE_UNIX_SOCKETS
304 struct sockaddr_un other;
305 #else /* USE_UNIX_SOCKETS */
306 struct sockaddr_in other;
310 junk = sizeof(other);
311 fd = accept(afd, (struct sockaddr *)&other, &junk);
313 Log("FSYNC_newconnection: accept failed, errno==%d\n", errno);
315 } else if (!AddHandler(fd, FSYNC_com)) {
317 assert(AddHandler(fd, FSYNC_com));
321 /* this function processes commands from an fssync file descriptor (fd) */
322 afs_int32 FS_cnt = 0;
324 FSYNC_com(osi_socket fd)
328 SYNC_PROTO_BUF_DECL(com_buf);
329 SYNC_PROTO_BUF_DECL(res_buf);
331 memset(&res.hdr, 0, sizeof(res.hdr));
333 com.payload.buf = (void *)com_buf;
334 com.payload.len = SYNC_PROTO_MAX_LEN;
335 res.hdr.response_len = sizeof(res.hdr);
336 res.payload.len = SYNC_PROTO_MAX_LEN;
337 res.payload.buf = (void *)res_buf;
340 if (SYNC_getCom(&fssync_server_state, fd, &com)) {
341 Log("FSYNC_com: read failed; dropping connection (cnt=%d)\n", FS_cnt);
346 if (com.recv_len < sizeof(com.hdr)) {
347 Log("FSSYNC_com: invalid protocol message length (%u)\n", com.recv_len);
348 res.hdr.response = SYNC_COM_ERROR;
349 res.hdr.reason = SYNC_REASON_MALFORMED_PACKET;
350 res.hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
354 if (com.hdr.proto_version != FSYNC_PROTO_VERSION) {
355 Log("FSYNC_com: invalid protocol version (%u)\n", com.hdr.proto_version);
356 res.hdr.response = SYNC_COM_ERROR;
357 res.hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
361 if (com.hdr.command == SYNC_COM_CHANNEL_CLOSE) {
362 res.hdr.response = SYNC_OK;
363 res.hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
367 res.hdr.com_seq = com.hdr.com_seq;
370 switch (com.hdr.command) {
372 case FSYNC_VOL_ATTACH:
373 case FSYNC_VOL_LEAVE_OFF:
375 case FSYNC_VOL_FORCE_ERROR:
376 case FSYNC_VOL_LISTVOLUMES:
377 case FSYNC_VOL_NEEDVOLUME:
379 case FSYNC_VOL_BREAKCBKS:
381 case FSYNC_VOL_QUERY:
382 case FSYNC_VOL_QUERY_HDR:
383 case FSYNC_VOL_QUERY_VOP:
384 res.hdr.response = FSYNC_com_VolOp(fd, &com, &res);
386 case FSYNC_VOL_STATS_GENERAL:
387 case FSYNC_VOL_STATS_VICEP:
388 case FSYNC_VOL_STATS_HASH:
389 case FSYNC_VOL_STATS_HDR:
390 case FSYNC_VOL_STATS_VLRU:
391 res.hdr.response = FSYNC_com_StatsOp(fd, &com, &res);
393 case FSYNC_VOL_QUERY_VNODE:
394 res.hdr.response = FSYNC_com_VnQry(fd, &com, &res);
397 res.hdr.response = SYNC_BAD_COMMAND;
403 SYNC_putRes(&fssync_server_state, fd, &res);
404 if (res.hdr.flags & SYNC_FLAG_CHANNEL_SHUTDOWN) {
410 FSYNC_com_VolOp(osi_socket fd, SYNC_command * com, SYNC_response * res)
413 afs_int32 code = SYNC_OK;
414 FSSYNC_VolOp_command vcom;
416 if (com->recv_len != (sizeof(com->hdr) + sizeof(FSSYNC_VolOp_hdr))) {
417 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
418 res->hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
419 return SYNC_COM_ERROR;
422 vcom.hdr = &com->hdr;
423 vcom.vop = (FSSYNC_VolOp_hdr *) com->payload.buf;
426 vcom.volumes = OfflineVolumes[FindHandler(fd)];
427 for (vcom.v = NULL, i = 0; i < MAXOFFLINEVOLUMES; i++) {
428 if ((vcom.volumes[i].volumeID == vcom.vop->volume) &&
429 (strncmp(vcom.volumes[i].partName, vcom.vop->partName,
430 sizeof(vcom.volumes[i].partName)) == 0)) {
431 vcom.v = &vcom.volumes[i];
436 switch (com->hdr.command) {
438 case FSYNC_VOL_ATTACH:
439 case FSYNC_VOL_LEAVE_OFF:
440 code = FSYNC_com_VolOn(&vcom, res);
443 case FSYNC_VOL_NEEDVOLUME:
444 code = FSYNC_com_VolOff(&vcom, res);
446 case FSYNC_VOL_LISTVOLUMES:
450 code = FSYNC_com_VolMove(&vcom, res);
452 case FSYNC_VOL_BREAKCBKS:
453 code = FSYNC_com_VolBreakCBKs(&vcom, res);
456 code = FSYNC_com_VolDone(&vcom, res);
458 case FSYNC_VOL_QUERY:
459 code = FSYNC_com_VolQuery(&vcom, res);
461 case FSYNC_VOL_QUERY_HDR:
462 code = FSYNC_com_VolHdrQuery(&vcom, res);
464 #ifdef AFS_DEMAND_ATTACH_FS
465 case FSYNC_VOL_FORCE_ERROR:
466 code = FSYNC_com_VolError(&vcom, res);
468 case FSYNC_VOL_QUERY_VOP:
469 code = FSYNC_com_VolOpQuery(&vcom, res);
471 #endif /* AFS_DEMAND_ATTACH_FS */
473 code = SYNC_BAD_COMMAND;
480 * service an FSYNC request to bring a volume online.
482 * @param[in] vcom pointer command object
483 * @param[out] res object in which to store response packet
485 * @return operation status
486 * @retval SYNC_OK volume transitioned online
487 * @retval SYNC_FAILED invalid command protocol message
488 * @retval SYNC_DENIED operation could not be completed
490 * @note this is an FSYNC RPC server stub
492 * @note this procedure handles the following FSSYNC command codes:
495 * - FSYNC_VOL_LEAVE_OFF
497 * @note the supplementary reason code contains additional details.
498 * When SYNC_DENIED is returned, the specific reason is
499 * placed in the response packet reason field.
504 FSYNC_com_VolOn(FSSYNC_VolOp_command * vcom, SYNC_response * res)
506 afs_int32 code = SYNC_OK;
507 char tvolName[VMAXPATHLEN];
511 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
512 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
517 /* so, we need to attach the volume */
519 #ifdef AFS_DEMAND_ATTACH_FS
520 /* check DAFS permissions */
521 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
523 FSYNC_partMatch(vcom, vp, 1) &&
524 vp->pending_vol_op &&
525 (vcom->hdr->programType != vp->pending_vol_op->com.programType)) {
526 /* a different program has this volume checked out. deny. */
527 Log("FSYNC_VolOn: WARNING: program type %u has attempted to manipulate "
528 "state for volume %u using command code %u while the volume is "
529 "checked out by program type %u for command code %u.\n",
530 vcom->hdr->programType,
533 vp->pending_vol_op->com.programType,
534 vp->pending_vol_op->com.command);
536 res->hdr.reason = FSYNC_EXCLUSIVE;
542 vcom->v->volumeID = 0;
545 if (vcom->hdr->command == FSYNC_VOL_LEAVE_OFF) {
546 /* nothing much to do if we're leaving the volume offline */
547 #ifdef AFS_DEMAND_ATTACH_FS
549 if (FSYNC_partMatch(vcom, vp, 1)) {
550 if ((V_attachState(vp) == VOL_STATE_UNATTACHED) ||
551 (V_attachState(vp) == VOL_STATE_PREATTACHED)) {
552 VChangeState_r(vp, VOL_STATE_UNATTACHED);
553 VDeregisterVolOp_r(vp);
556 res->hdr.reason = FSYNC_BAD_STATE;
560 res->hdr.reason = FSYNC_WRONG_PART;
564 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
570 #ifdef AFS_DEMAND_ATTACH_FS
571 /* first, check to see whether we have such a volume defined */
572 vp = VPreAttachVolumeById_r(&error,
576 VDeregisterVolOp_r(vp);
578 #else /* !AFS_DEMAND_ATTACH_FS */
580 snprintf(&tvolName[1], sizeof(tvolName)-1, VFORMAT, afs_cast_uint32(vcom->vop->volume));
581 tvolName[sizeof(tvolName)-1] = '\0';
583 vp = VAttachVolumeByName_r(&error, vcom->vop->partName, tvolName,
589 res->hdr.reason = error;
591 #endif /* !AFS_DEMAND_ATTACH_FS */
598 * service an FSYNC request to take a volume offline.
600 * @param[in] vcom pointer command object
601 * @param[out] res object in which to store response packet
603 * @return operation status
604 * @retval SYNC_OK volume transitioned offline
605 * @retval SYNC_FAILED invalid command protocol message
606 * @retval SYNC_DENIED operation could not be completed
608 * @note this is an FSYNC RPC server stub
610 * @note this procedure handles the following FSSYNC command codes:
612 * - FSYNC_VOL_NEEDVOLUME
614 * @note the supplementary reason code contains additional details.
615 * When SYNC_DENIED is returned, the specific reason is
616 * placed in the response packet reason field.
621 FSYNC_com_VolOff(FSSYNC_VolOp_command * vcom, SYNC_response * res)
623 FSSYNC_VolOp_info info;
624 afs_int32 code = SYNC_OK;
628 #ifdef AFS_DEMAND_ATTACH_FS
633 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
634 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
639 /* not already offline, we need to find a slot for newly offline volume */
640 if (vcom->hdr->programType == debugUtility) {
641 /* debug utilities do not have their operations tracked */
645 for (i = 0; i < MAXOFFLINEVOLUMES; i++) {
646 if (vcom->volumes[i].volumeID == 0) {
647 vcom->v = &vcom->volumes[i];
657 FSYNC_com_to_info(vcom, &info);
659 #ifdef AFS_DEMAND_ATTACH_FS
660 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
662 vp = VGetVolume_r(&error, vcom->vop->volume);
666 if (!FSYNC_partMatch(vcom, vp, 1)) {
667 /* volume on desired partition is not online, so we
668 * should treat this as an offline volume.
670 #ifndef AFS_DEMAND_ATTACH_FS
678 #ifdef AFS_DEMAND_ATTACH_FS
680 ProgramType type = (ProgramType) vcom->hdr->programType;
682 /* do initial filtering of requests */
684 /* enforce mutual exclusion for volume ops */
685 if (vp->pending_vol_op) {
686 if (vp->pending_vol_op->com.programType != type) {
687 Log("volume %u already checked out\n", vp->hashid);
689 Log("vp->vop = { com = { ver=%u, prog=%d, com=%d, reason=%d, len=%u, flags=0x%x }, vop = { vol=%u, part='%s' } }\n",
690 vp->pending_vol_op->com.proto_version,
691 vp->pending_vol_op->com.programType,
692 vp->pending_vol_op->com.command,
693 vp->pending_vol_op->com.reason,
694 vp->pending_vol_op->com.command_len,
695 vp->pending_vol_op->com.flags,
696 vp->pending_vol_op->vop.volume,
697 vp->pending_vol_op->vop.partName );
698 Log("vcom = { com = { ver=%u, prog=%d, com=%d, reason=%d, len=%u, flags=0x%x } , vop = { vol=%u, part='%s' } }\n",
699 vcom->hdr->proto_version,
700 vcom->hdr->programType,
703 vcom->hdr->command_len,
706 vcom->vop->partName);
707 res->hdr.reason = FSYNC_EXCLUSIVE;
710 Log("warning: volume %u recursively checked out by programType id %d\n",
711 vp->hashid, vcom->hdr->programType);
715 /* filter based upon requestor
717 * volume utilities are not allowed to check out volumes
718 * which are in an error state
720 * unknown utility programs will be denied on principal
724 /* it is possible for the salvageserver to checkout a
725 * volume for salvage before its scheduling request
726 * has been sent to the salvageserver */
727 if (vp->salvage.requested && !vp->salvage.scheduled) {
728 vp->salvage.scheduled = 1;
734 if (VIsErrorState(V_attachState(vp))) {
737 if (vp->salvage.requested) {
743 Log("bad program type passed to FSSYNC\n");
747 /* short circuit for offline volume states
748 * so we can avoid I/O penalty of attachment */
749 switch (V_attachState(vp)) {
750 case VOL_STATE_UNATTACHED:
751 case VOL_STATE_PREATTACHED:
752 case VOL_STATE_SALVAGING:
753 case VOL_STATE_ERROR:
754 /* register the volume operation metadata with the volume
756 * if the volume is currently pre-attached, attach2()
757 * will evaluate the vol op metadata to determine whether
758 * attaching the volume would be safe */
759 VRegisterVolOp_r(vp, &info);
760 vp->pending_vol_op->vol_op_state = FSSYNC_VolOpRunningUnknown;
766 /* convert to heavyweight ref */
767 nvp = VGetVolumeByVp_r(&error, vp);
770 Log("FSYNC_com_VolOff: failed to get heavyweight reference to volume %u\n",
772 res->hdr.reason = FSYNC_VOL_PKG_ERROR;
774 } else if (nvp != vp) {
775 /* i don't think this should ever happen, but just in case... */
776 Log("FSYNC_com_VolOff: warning: potentially dangerous race detected\n");
780 /* register the volume operation metadata with the volume */
781 VRegisterVolOp_r(vp, &info);
784 #endif /* AFS_DEMAND_ATTACH_FS */
787 if (VVolOpLeaveOnline_r(vp, &info)) {
788 VUpdateVolume_r(&error, vp, VOL_UPDATE_WAIT); /* At least get volume stats right */
790 Log("FSYNC: Volume %u (%s) was left on line for an external %s request\n",
791 V_id(vp), V_name(vp),
792 vcom->hdr->reason == V_CLONE ? "clone" :
793 vcom->hdr->reason == V_READONLY ? "readonly" :
794 vcom->hdr->reason == V_DUMP ? "dump" :
797 #ifdef AFS_DEMAND_ATTACH_FS
798 vp->pending_vol_op->vol_op_state = FSSYNC_VolOpRunningOnline;
802 if (VVolOpSetVBusy_r(vp, &info)) {
803 vp->specialStatus = VBUSY;
806 /* remember what volume we got, so we can keep track of how
807 * many volumes the volserver or whatever is using. Note that
808 * vp is valid since leaveonline is only set when vp is valid.
811 vcom->v->volumeID = vcom->vop->volume;
812 strlcpy(vcom->v->partName, vp->partition->name, sizeof(vcom->v->partName));
815 #ifdef AFS_DEMAND_ATTACH_FS
816 VOfflineForVolOp_r(&error, vp, "A volume utility is running.");
818 assert(vp->nUsers==0);
819 vp->pending_vol_op->vol_op_state = FSSYNC_VolOpRunningOffline;
822 VDeregisterVolOp_r(vp);
826 VOffline_r(vp, "A volume utility is running.");
840 * service an FSYNC request to mark a volume as moved.
842 * @param[in] vcom pointer command object
843 * @param[out] res object in which to store response packet
845 * @return operation status
846 * @retval SYNC_OK volume marked as moved to a remote server
847 * @retval SYNC_FAILED invalid command protocol message
848 * @retval SYNC_DENIED current volume state does not permit this operation
850 * @note this is an FSYNC RPC server stub
852 * @note this operation also breaks all callbacks for the given volume
854 * @note this procedure handles the following FSSYNC command codes:
857 * @note the supplementary reason code contains additional details. For
858 * instance, SYNC_OK is still returned when the partition specified
859 * does not match the one registered in the volume object -- reason
860 * will be FSYNC_WRONG_PART in this case.
865 FSYNC_com_VolMove(FSSYNC_VolOp_command * vcom, SYNC_response * res)
867 afs_int32 code = SYNC_DENIED;
871 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
872 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
877 /* Yuch: the "reason" for the move is the site it got moved to... */
878 /* still set specialStatus so we stop sending back VBUSY.
879 * also should still break callbacks. Note that I don't know
880 * how to tell if we should break all or not, so we just do it
881 * since it doesn't matter much if we do an extra break
882 * volume callbacks on a volume move within the same server */
883 #ifdef AFS_DEMAND_ATTACH_FS
884 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
886 vp = VGetVolume_r(&error, vcom->vop->volume);
889 if (FSYNC_partMatch(vcom, vp, 1)) {
890 #ifdef AFS_DEMAND_ATTACH_FS
891 if ((V_attachState(vp) == VOL_STATE_UNATTACHED) ||
892 (V_attachState(vp) == VOL_STATE_PREATTACHED)) {
895 vp->specialStatus = VMOVED;
896 #ifdef AFS_DEMAND_ATTACH_FS
898 res->hdr.reason = FSYNC_BAD_STATE;
902 res->hdr.reason = FSYNC_WRONG_PART;
906 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
909 if ((code == SYNC_OK) && (V_BreakVolumeCallbacks != NULL)) {
910 Log("fssync: volume %u moved to %x; breaking all call backs\n",
911 vcom->vop->volume, vcom->hdr->reason);
913 (*V_BreakVolumeCallbacks) (vcom->vop->volume);
923 * service an FSYNC request to mark a volume as destroyed.
925 * @param[in] vcom pointer command object
926 * @param[out] res object in which to store response packet
928 * @return operation status
929 * @retval SYNC_OK volume marked as destroyed
930 * @retval SYNC_FAILED invalid command protocol message
931 * @retval SYNC_DENIED current volume state does not permit this operation
933 * @note this is an FSYNC RPC server stub
935 * @note this procedure handles the following FSSYNC command codes:
938 * @note the supplementary reason code contains additional details. For
939 * instance, SYNC_OK is still returned when the partition specified
940 * does not match the one registered in the volume object -- reason
941 * will be FSYNC_WRONG_PART in this case.
946 FSYNC_com_VolDone(FSSYNC_VolOp_command * vcom, SYNC_response * res)
948 afs_int32 code = SYNC_FAILED;
949 #ifdef AFS_DEMAND_ATTACH_FS
954 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
955 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
959 /* don't try to put online, this call is made only after deleting
960 * a volume, in which case we want to remove the vol # from the
961 * OfflineVolumes array only */
963 vcom->v->volumeID = 0;
965 #ifdef AFS_DEMAND_ATTACH_FS
966 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
968 if (FSYNC_partMatch(vcom, vp, 1)) {
969 if ((V_attachState(vp) == VOL_STATE_UNATTACHED) ||
970 (V_attachState(vp) == VOL_STATE_PREATTACHED)) {
971 VChangeState_r(vp, VOL_STATE_UNATTACHED);
972 VDeregisterVolOp_r(vp);
976 res->hdr.reason = FSYNC_BAD_STATE;
979 code = SYNC_OK; /* XXX is this really a good idea? */
980 res->hdr.reason = FSYNC_WRONG_PART;
983 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
991 #ifdef AFS_DEMAND_ATTACH_FS
993 * service an FSYNC request to transition a volume to the hard error state.
995 * @param[in] vcom pointer command object
996 * @param[out] res object in which to store response packet
998 * @return operation status
999 * @retval SYNC_OK volume transitioned to hard error state
1000 * @retval SYNC_FAILED invalid command protocol message
1001 * @retval SYNC_DENIED (see note)
1003 * @note this is an FSYNC RPC server stub
1005 * @note this procedure handles the following FSSYNC command codes:
1006 * - FSYNC_VOL_FORCE_ERROR
1008 * @note SYNC_DENIED is returned in the following cases:
1009 * - no partition name is specified (reason field set to
1010 * FSYNC_WRONG_PART).
1011 * - volume id not known to fileserver (reason field set
1012 * to FSYNC_UNKNOWN_VOLID).
1014 * @note demand attach fileserver only
1019 FSYNC_com_VolError(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1023 afs_int32 code = SYNC_FAILED;
1025 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1026 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1030 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
1032 if (FSYNC_partMatch(vcom, vp, 0)) {
1033 /* null out salvsync control state, as it's no longer relevant */
1034 memset(&vp->salvage, 0, sizeof(vp->salvage));
1035 VChangeState_r(vp, VOL_STATE_ERROR);
1038 res->hdr.reason = FSYNC_WRONG_PART;
1041 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1047 #endif /* AFS_DEMAND_ATTACH_FS */
1050 * service an FSYNC request to break all callbacks for this volume.
1052 * @param[in] vcom pointer command object
1053 * @param[out] res object in which to store response packet
1055 * @return operation status
1056 * @retval SYNC_OK callback breaks scheduled for volume
1058 * @note this is an FSYNC RPC server stub
1060 * @note this procedure handles the following FSSYNC command codes:
1061 * - FSYNC_VOL_BREAKCBKS
1063 * @note demand attach fileserver only
1065 * @todo should do partition matching
1070 FSYNC_com_VolBreakCBKs(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1072 /* if the volume is being restored, break all callbacks on it */
1073 if (V_BreakVolumeCallbacks) {
1074 Log("fssync: breaking all call backs for volume %u\n",
1077 (*V_BreakVolumeCallbacks) (vcom->vop->volume);
1084 * service an FSYNC request to return the Volume object.
1086 * @param[in] vcom pointer command object
1087 * @param[out] res object in which to store response packet
1089 * @return operation status
1090 * @retval SYNC_OK volume object returned to caller
1091 * @retval SYNC_FAILED bad command packet, or failed to locate volume object
1093 * @note this is an FSYNC RPC server stub
1095 * @note this procedure handles the following FSSYNC command codes:
1101 FSYNC_com_VolQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1103 afs_int32 code = SYNC_FAILED;
1107 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1108 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1112 #ifdef AFS_DEMAND_ATTACH_FS
1113 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
1114 #else /* !AFS_DEMAND_ATTACH_FS */
1115 vp = VGetVolume_r(&error, vcom->vop->volume);
1116 #endif /* !AFS_DEMAND_ATTACH_FS */
1119 if (FSYNC_partMatch(vcom, vp, 1)) {
1120 if (res->payload.len >= sizeof(Volume)) {
1121 memcpy(res->payload.buf, vp, sizeof(Volume));
1122 res->hdr.response_len += sizeof(Volume);
1125 res->hdr.reason = SYNC_REASON_PAYLOAD_TOO_BIG;
1128 res->hdr.reason = FSYNC_WRONG_PART;
1130 #ifndef AFS_DEMAND_ATTACH_FS
1134 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1142 * service an FSYNC request to return the Volume header.
1144 * @param[in] vcom pointer command object
1145 * @param[out] res object in which to store response packet
1147 * @return operation status
1148 * @retval SYNC_OK volume header returned to caller
1149 * @retval SYNC_FAILED bad command packet, or failed to locate volume header
1151 * @note this is an FSYNC RPC server stub
1153 * @note this procedure handles the following FSSYNC command codes:
1154 * - FSYNC_VOL_QUERY_HDR
1159 FSYNC_com_VolHdrQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1161 afs_int32 code = SYNC_FAILED;
1165 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1166 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1169 if (res->payload.len < sizeof(VolumeDiskData)) {
1170 res->hdr.reason = SYNC_REASON_PAYLOAD_TOO_BIG;
1174 #ifdef AFS_DEMAND_ATTACH_FS
1175 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
1176 #else /* !AFS_DEMAND_ATTACH_FS */
1177 vp = VGetVolume_r(&error, vcom->vop->volume);
1181 if (FSYNC_partMatch(vcom, vp, 1)) {
1182 #ifdef AFS_DEMAND_ATTACH_FS
1183 if ((vp->header == NULL) ||
1184 !(V_attachFlags(vp) & VOL_HDR_ATTACHED) ||
1185 !(V_attachFlags(vp) & VOL_HDR_LOADED)) {
1186 res->hdr.reason = FSYNC_HDR_NOT_ATTACHED;
1189 #else /* !AFS_DEMAND_ATTACH_FS */
1190 if (!vp || !vp->header) {
1191 res->hdr.reason = FSYNC_HDR_NOT_ATTACHED;
1194 #endif /* !AFS_DEMAND_ATTACH_FS */
1196 res->hdr.reason = FSYNC_WRONG_PART;
1200 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1204 memcpy(res->payload.buf, &V_disk(vp), sizeof(VolumeDiskData));
1205 res->hdr.response_len += sizeof(VolumeDiskData);
1206 #ifndef AFS_DEMAND_ATTACH_FS
1215 #ifdef AFS_DEMAND_ATTACH_FS
1217 FSYNC_com_VolOpQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1219 afs_int32 code = SYNC_OK;
1223 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
1225 if (vp && vp->pending_vol_op) {
1226 assert(sizeof(FSSYNC_VolOp_info) <= res->payload.len);
1227 memcpy(res->payload.buf, vp->pending_vol_op, sizeof(FSSYNC_VolOp_info));
1228 res->hdr.response_len += sizeof(FSSYNC_VolOp_info);
1231 res->hdr.reason = FSYNC_NO_PENDING_VOL_OP;
1233 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1239 #endif /* AFS_DEMAND_ATTACH_FS */
1242 FSYNC_com_VnQry(osi_socket fd, SYNC_command * com, SYNC_response * res)
1244 afs_int32 code = SYNC_OK;
1245 FSSYNC_VnQry_hdr * qry = com->payload.buf;
1250 if (com->recv_len != (sizeof(com->hdr) + sizeof(FSSYNC_VnQry_hdr))) {
1251 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1252 res->hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
1253 return SYNC_COM_ERROR;
1256 #ifdef AFS_DEMAND_ATTACH_FS
1257 vp = VLookupVolume_r(&error, qry->volume, NULL);
1258 #else /* !AFS_DEMAND_ATTACH_FS */
1259 vp = VGetVolume_r(&error, qry->volume);
1260 #endif /* !AFS_DEMAND_ATTACH_FS */
1263 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1268 vnp = VLookupVnode(vp, qry->vnode);
1270 res->hdr.reason = FSYNC_UNKNOWN_VNID;
1275 if (Vn_class(vnp)->residentSize > res->payload.len) {
1276 res->hdr.reason = SYNC_REASON_ENCODING_ERROR;
1281 memcpy(res->payload.buf, vnp, Vn_class(vnp)->residentSize);
1282 res->hdr.response_len += Vn_class(vnp)->residentSize;
1285 #ifndef AFS_DEMAND_ATTACH_FS
1294 FSYNC_com_StatsOp(osi_socket fd, SYNC_command * com, SYNC_response * res)
1296 afs_int32 code = SYNC_OK;
1297 FSSYNC_StatsOp_command scom;
1299 if (com->recv_len != (sizeof(com->hdr) + sizeof(FSSYNC_StatsOp_hdr))) {
1300 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1301 res->hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
1302 return SYNC_COM_ERROR;
1305 scom.hdr = &com->hdr;
1306 scom.sop = (FSSYNC_StatsOp_hdr *) com->payload.buf;
1309 switch (com->hdr.command) {
1310 case FSYNC_VOL_STATS_GENERAL:
1311 code = FSYNC_com_StatsOpGeneral(&scom, res);
1313 #ifdef AFS_DEMAND_ATTACH_FS
1314 /* statistics for the following subsystems are only tracked
1315 * for demand attach fileservers */
1316 case FSYNC_VOL_STATS_VICEP:
1317 code = FSYNC_com_StatsOpViceP(&scom, res);
1319 case FSYNC_VOL_STATS_HASH:
1320 code = FSYNC_com_StatsOpHash(&scom, res);
1322 case FSYNC_VOL_STATS_HDR:
1323 code = FSYNC_com_StatsOpHdr(&scom, res);
1325 case FSYNC_VOL_STATS_VLRU:
1326 code = FSYNC_com_StatsOpVLRU(&scom, res);
1328 #endif /* AFS_DEMAND_ATTACH_FS */
1330 code = SYNC_BAD_COMMAND;
1337 FSYNC_com_StatsOpGeneral(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1339 afs_int32 code = SYNC_OK;
1341 memcpy(res->payload.buf, &VStats, sizeof(VStats));
1342 res->hdr.response_len += sizeof(VStats);
1347 #ifdef AFS_DEMAND_ATTACH_FS
1349 FSYNC_com_StatsOpViceP(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1351 afs_int32 code = SYNC_OK;
1352 struct DiskPartition64 * dp;
1353 struct DiskPartitionStats64 * stats;
1355 if (SYNC_verifyProtocolString(scom->sop->args.partName, sizeof(scom->sop->args.partName))) {
1356 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1361 dp = VGetPartition_r(scom->sop->args.partName, 0);
1365 stats = (struct DiskPartitionStats64 *) res->payload.buf;
1366 stats->free = dp->free;
1367 stats->totalUsable = dp->totalUsable;
1368 stats->minFree = dp->minFree;
1369 stats->f_files = dp->f_files;
1370 stats->vol_list_len = dp->vol_list.len;
1372 res->hdr.response_len += sizeof(struct DiskPartitionStats64);
1380 FSYNC_com_StatsOpHash(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1382 afs_int32 code = SYNC_OK;
1383 struct VolumeHashChainStats * stats;
1384 struct VolumeHashChainHead * head;
1386 if (scom->sop->args.hash_bucket >= VolumeHashTable.Size) {
1390 head = &VolumeHashTable.Table[scom->sop->args.hash_bucket];
1391 stats = (struct VolumeHashChainStats *) res->payload.buf;
1392 stats->table_size = VolumeHashTable.Size;
1393 stats->chain_len = head->len;
1394 stats->chain_cacheCheck = head->cacheCheck;
1395 stats->chain_busy = head->busy;
1396 AssignInt64(head->looks, &stats->chain_looks);
1397 AssignInt64(head->gets, &stats->chain_gets);
1398 AssignInt64(head->reorders, &stats->chain_reorders);
1400 res->hdr.response_len += sizeof(struct VolumeHashChainStats);
1406 FSYNC_com_StatsOpHdr(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1408 afs_int32 code = SYNC_OK;
1410 memcpy(res->payload.buf, &volume_hdr_LRU.stats, sizeof(volume_hdr_LRU.stats));
1411 res->hdr.response_len += sizeof(volume_hdr_LRU.stats);
1417 FSYNC_com_StatsOpVLRU(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1419 afs_int32 code = SYNC_OK;
1421 code = SYNC_BAD_COMMAND;
1425 #endif /* AFS_DEMAND_ATTACH_FS */
1428 * populate an FSSYNC_VolOp_info object from a command packet object.
1430 * @param[in] vcom pointer to command packet
1431 * @param[out] info pointer to info object which will be populated
1433 * @note FSSYNC_VolOp_info objects are attached to Volume objects when
1434 * a volume operation is commenced.
1439 FSYNC_com_to_info(FSSYNC_VolOp_command * vcom, FSSYNC_VolOp_info * info)
1441 memcpy(&info->com, vcom->hdr, sizeof(SYNC_command_hdr));
1442 memcpy(&info->vop, vcom->vop, sizeof(FSSYNC_VolOp_hdr));
1443 info->vol_op_state = FSSYNC_VolOpPending;
1447 * check whether command packet partition name matches volume
1448 * object's partition name.
1450 * @param[in] vcom pointer to command packet
1451 * @param[in] vp pointer to volume object
1452 * @param[in] match_anon anon matching control flag (see note below)
1454 * @return whether partitions match
1455 * @retval 0 partitions do NOT match
1456 * @retval 1 partitions match
1458 * @note if match_anon is non-zero, then this function will return a
1459 * positive match for a zero-length partition string in the
1465 FSYNC_partMatch(FSSYNC_VolOp_command * vcom, Volume * vp, int match_anon)
1467 return ((match_anon && vcom->vop->partName[0] == 0) ||
1468 (strncmp(vcom->vop->partName, V_partition(vp)->name,
1469 sizeof(vcom->vop->partName)) == 0));
1474 FSYNC_Drop(osi_socket fd)
1476 struct offlineInfo *p;
1479 char tvolName[VMAXPATHLEN];
1482 p = OfflineVolumes[FindHandler(fd)];
1483 for (i = 0; i < MAXOFFLINEVOLUMES; i++) {
1484 if (p[i].volumeID) {
1489 sprintf(&tvolName[1], VFORMAT, afs_cast_uint32(p[i].volumeID));
1490 vp = VAttachVolumeByName_r(&error, p[i].partName, tvolName,
1507 static int AcceptHandler = -1; /* handler id for accept, if turned on */
1512 if (AcceptHandler == -1) {
1513 assert(AddHandler(fssync_server_state.fd, FSYNC_newconnection));
1514 AcceptHandler = FindHandler(fssync_server_state.fd);
1521 if (AcceptHandler != -1) {
1522 assert(RemoveHandler(fssync_server_state.fd));
1527 /* The multiple FD handling code. */
1529 static osi_socket HandlerFD[MAXHANDLERS];
1530 static void (*HandlerProc[MAXHANDLERS]) (osi_socket);
1536 ObtainWriteLock(&FSYNC_handler_lock);
1537 for (i = 0; i < MAXHANDLERS; i++) {
1541 ReleaseWriteLock(&FSYNC_handler_lock);
1544 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
1546 CallHandler(struct pollfd *fds, int nfds, int mask)
1550 ObtainReadLock(&FSYNC_handler_lock);
1551 for (i = 0; i < nfds; i++) {
1552 if (fds[i].revents & mask) {
1553 handler = FindHandler_r(fds[i].fd);
1554 ReleaseReadLock(&FSYNC_handler_lock);
1555 (*HandlerProc[handler]) (fds[i].fd);
1556 ObtainReadLock(&FSYNC_handler_lock);
1559 ReleaseReadLock(&FSYNC_handler_lock);
1563 CallHandler(fd_set * fdsetp)
1566 ObtainReadLock(&FSYNC_handler_lock);
1567 for (i = 0; i < MAXHANDLERS; i++) {
1568 if (HandlerFD[i] >= 0 && FD_ISSET(HandlerFD[i], fdsetp)) {
1569 ReleaseReadLock(&FSYNC_handler_lock);
1570 (*HandlerProc[i]) (HandlerFD[i]);
1571 ObtainReadLock(&FSYNC_handler_lock);
1574 ReleaseReadLock(&FSYNC_handler_lock);
1579 AddHandler(osi_socket afd, void (*aproc) (osi_socket))
1582 ObtainWriteLock(&FSYNC_handler_lock);
1583 for (i = 0; i < MAXHANDLERS; i++)
1584 if (HandlerFD[i] == -1)
1586 if (i >= MAXHANDLERS) {
1587 ReleaseWriteLock(&FSYNC_handler_lock);
1591 HandlerProc[i] = aproc;
1592 ReleaseWriteLock(&FSYNC_handler_lock);
1597 FindHandler(register osi_socket afd)
1600 ObtainReadLock(&FSYNC_handler_lock);
1601 for (i = 0; i < MAXHANDLERS; i++)
1602 if (HandlerFD[i] == afd) {
1603 ReleaseReadLock(&FSYNC_handler_lock);
1606 ReleaseReadLock(&FSYNC_handler_lock); /* just in case */
1608 return -1; /* satisfy compiler */
1612 FindHandler_r(register osi_socket afd)
1615 for (i = 0; i < MAXHANDLERS; i++)
1616 if (HandlerFD[i] == afd) {
1620 return -1; /* satisfy compiler */
1624 RemoveHandler(register osi_socket afd)
1626 ObtainWriteLock(&FSYNC_handler_lock);
1627 HandlerFD[FindHandler_r(afd)] = -1;
1628 ReleaseWriteLock(&FSYNC_handler_lock);
1632 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
1634 GetHandler(struct pollfd *fds, int maxfds, int events, int *nfds)
1638 ObtainReadLock(&FSYNC_handler_lock);
1639 for (i = 0; i < MAXHANDLERS; i++)
1640 if (HandlerFD[i] != -1) {
1642 fds[fdi].fd = HandlerFD[i];
1643 fds[fdi].events = events;
1644 fds[fdi].revents = 0;
1648 ReleaseReadLock(&FSYNC_handler_lock);
1652 GetHandler(fd_set * fdsetp, int *maxfdp)
1655 register int maxfd = -1;
1657 ObtainReadLock(&FSYNC_handler_lock); /* just in case */
1658 for (i = 0; i < MAXHANDLERS; i++)
1659 if (HandlerFD[i] != -1) {
1660 FD_SET(HandlerFD[i], fdsetp);
1661 #ifndef AFS_NT40_ENV
1662 /* On Windows the nfds parameter to select() is ignored */
1663 if (maxfd < HandlerFD[i] || maxfd == (int)-1)
1664 maxfd = HandlerFD[i];
1665 #endif /* AFS_NT40_ENV */
1668 ReleaseReadLock(&FSYNC_handler_lock); /* just in case */
1670 #endif /* HAVE_POLL && AFS_PTHREAD_ENV */
1672 #endif /* FSSYNC_BUILD_SERVER */