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>
47 #include <sys/types.h>
53 #include <sys/param.h>
54 #include <sys/socket.h>
55 #include <netinet/in.h>
61 #ifdef AFS_PTHREAD_ENV
63 #else /* AFS_PTHREAD_ENV */
64 #include <afs/assert.h>
65 #endif /* AFS_PTHREAD_ENV */
70 #include <afs/afsint.h>
72 #include <afs/errors.h>
73 #include "daemon_com.h"
77 #include <afs/afssyscalls.h>
81 #include "volume_inline.h"
82 #include "partition.h"
86 #endif /* HAVE_POLL */
88 #ifdef USE_UNIX_SOCKETS
90 #include <afs/afsutil.h>
91 #endif /* USE_UNIX_SOCKETS */
93 #ifdef FSSYNC_BUILD_SERVER
95 /*@printflike@*/ extern void Log(const char *format, ...);
97 int (*V_BreakVolumeCallbacks) (VolumeId volume);
99 #define MAXHANDLERS 4 /* Up to 4 clients; must be at least 2, so that
100 * move = dump+restore can run on single server */
101 #define MAXOFFLINEVOLUMES 128 /* This needs to be as big as the maximum
102 * number that would be offline for 1 operation.
103 * Current winner is salvage, which needs all
104 * cloned read-only copies offline when salvaging
105 * a single read-write volume */
109 static struct offlineInfo OfflineVolumes[MAXHANDLERS][MAXOFFLINEVOLUMES];
112 * fssync server socket handle.
114 static SYNC_server_state_t fssync_server_state =
115 { -1, /* file descriptor */
116 FSSYNC_ENDPOINT_DECL, /* server endpoint */
117 FSYNC_PROTO_VERSION, /* protocol version */
118 5, /* bind() retry limit */
119 100, /* listen() queue depth */
120 "FSSYNC", /* protocol name string */
124 /* Forward declarations */
125 static void * FSYNC_sync(void *);
126 static void FSYNC_newconnection(osi_socket afd);
127 static void FSYNC_com(osi_socket fd);
128 static void FSYNC_Drop(osi_socket fd);
129 static void AcceptOn(void);
130 static void AcceptOff(void);
131 static void InitHandler(void);
132 static int AddHandler(osi_socket fd, void (*aproc)(osi_socket));
133 static int FindHandler(osi_socket afd);
134 static int FindHandler_r(osi_socket afd);
135 static int RemoveHandler(osi_socket afd);
136 #if defined(HAVE_POLL) && defined (AFS_PTHREAD_ENV)
137 static void CallHandler(struct pollfd *fds, int nfds, int mask);
138 static void GetHandler(struct pollfd *fds, int maxfds, int events, int *nfds);
140 static void CallHandler(fd_set * fdsetp);
141 static void GetHandler(fd_set * fdsetp, int *maxfdp);
145 static afs_int32 FSYNC_com_VolOp(osi_socket fd, SYNC_command * com, SYNC_response * res);
147 #ifdef AFS_DEMAND_ATTACH_FS
148 static afs_int32 FSYNC_com_VolError(FSSYNC_VolOp_command * com, SYNC_response * res);
150 static afs_int32 FSYNC_com_VolOn(FSSYNC_VolOp_command * com, SYNC_response * res);
151 static afs_int32 FSYNC_com_VolOff(FSSYNC_VolOp_command * com, SYNC_response * res);
152 static afs_int32 FSYNC_com_VolMove(FSSYNC_VolOp_command * com, SYNC_response * res);
153 static afs_int32 FSYNC_com_VolBreakCBKs(FSSYNC_VolOp_command * com, SYNC_response * res);
154 static afs_int32 FSYNC_com_VolDone(FSSYNC_VolOp_command * com, SYNC_response * res);
155 static afs_int32 FSYNC_com_VolQuery(FSSYNC_VolOp_command * com, SYNC_response * res);
156 static afs_int32 FSYNC_com_VolHdrQuery(FSSYNC_VolOp_command * com, SYNC_response * res);
157 #ifdef AFS_DEMAND_ATTACH_FS
158 static afs_int32 FSYNC_com_VolOpQuery(FSSYNC_VolOp_command * com, SYNC_response * res);
159 #endif /* AFS_DEMAND_ATTACH_FS */
161 static afs_int32 FSYNC_com_VnQry(osi_socket fd, SYNC_command * com, SYNC_response * res);
163 static afs_int32 FSYNC_com_StatsOp(osi_socket fd, SYNC_command * com, SYNC_response * res);
165 static afs_int32 FSYNC_com_StatsOpGeneral(FSSYNC_StatsOp_command * scom, SYNC_response * res);
167 #ifdef AFS_DEMAND_ATTACH_FS
168 static afs_int32 FSYNC_com_StatsOpViceP(FSSYNC_StatsOp_command * scom, SYNC_response * res);
169 static afs_int32 FSYNC_com_StatsOpHash(FSSYNC_StatsOp_command * scom, SYNC_response * res);
170 static afs_int32 FSYNC_com_StatsOpHdr(FSSYNC_StatsOp_command * scom, SYNC_response * res);
171 static afs_int32 FSYNC_com_StatsOpVLRU(FSSYNC_StatsOp_command * scom, SYNC_response * res);
174 static void FSYNC_com_to_info(FSSYNC_VolOp_command * vcom, FSSYNC_VolOp_info * info);
176 static int FSYNC_partMatch(FSSYNC_VolOp_command * vcom, Volume * vp, int match_anon);
180 * This lock controls access to the handler array. The overhead
181 * is minimal in non-preemptive environments.
183 struct Lock FSYNC_handler_lock;
188 #ifdef AFS_PTHREAD_ENV
190 pthread_attr_t tattr;
191 #else /* AFS_PTHREAD_ENV */
193 #endif /* AFS_PTHREAD_ENV */
195 Lock_Init(&FSYNC_handler_lock);
197 #ifdef AFS_PTHREAD_ENV
198 assert(pthread_attr_init(&tattr) == 0);
199 assert(pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED) == 0);
200 assert(pthread_create(&tid, &tattr, FSYNC_sync, NULL) == 0);
201 #else /* AFS_PTHREAD_ENV */
202 assert(LWP_CreateProcess
203 (FSYNC_sync, USUAL_STACK_SIZE, USUAL_PRIORITY, (void *)0,
204 "FSYNC_sync", &pid) == LWP_SUCCESS);
205 #endif /* AFS_PTHREAD_ENV */
208 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
209 static struct pollfd FSYNC_readfds[MAXHANDLERS];
211 static fd_set FSYNC_readfds;
216 FSYNC_sync(void * args)
220 #ifdef AFS_PTHREAD_ENV
223 SYNC_server_state_t * state = &fssync_server_state;
224 #ifdef AFS_DEMAND_ATTACH_FS
225 VThreadOptions_t * thread_opts;
229 * For non-DAFS, only wait until we begin attaching volumes (instead
230 * of waiting until all volumes are attached), since it can take
231 * awhile until VInit == 2.
234 #endif /* AFS_DEMAND_ATTACH_FS */
236 SYNC_getAddr(&state->endpoint, &state->addr);
237 SYNC_cleanupSock(state);
240 (void)signal(SIGPIPE, SIG_IGN);
243 #ifdef AFS_PTHREAD_ENV
244 /* set our 'thread-id' so that the host hold table works */
245 MUTEX_ENTER(&rx_stats_mutex); /* protects rxi_pthread_hinum */
246 tid = ++rxi_pthread_hinum;
247 MUTEX_EXIT(&rx_stats_mutex);
248 pthread_setspecific(rx_thread_id_key, (void *)(intptr_t)tid);
249 Log("Set thread id %d for FSYNC_sync\n", tid);
250 #endif /* AFS_PTHREAD_ENV */
252 while (VInit < min_vinit) {
253 /* Let somebody else run until all volumes have been preattached
254 * (DAFS), or we have started attaching volumes (non-DAFS). This
255 * doesn't mean that all volumes have been attached.
257 #ifdef AFS_PTHREAD_ENV
259 #else /* AFS_PTHREAD_ENV */
260 LWP_DispatchProcess();
261 #endif /* AFS_PTHREAD_ENV */
263 state->fd = SYNC_getSock(&state->endpoint);
264 code = SYNC_bindSock(state);
267 #ifdef AFS_DEMAND_ATTACH_FS
269 * make sure the volume package is incapable of recursively executing
270 * salvsync calls on this thread, since there is a possibility of
273 thread_opts = malloc(sizeof(VThreadOptions_t));
274 if (thread_opts == NULL) {
275 Log("failed to allocate memory for thread-specific volume package options structure\n");
278 memcpy(thread_opts, &VThread_defaults, sizeof(VThread_defaults));
279 thread_opts->disallow_salvsync = 1;
280 assert(pthread_setspecific(VThread_key, thread_opts) == 0);
287 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
289 GetHandler(FSYNC_readfds, MAXHANDLERS, POLLIN|POLLPRI, &nfds);
290 if (poll(FSYNC_readfds, nfds, -1) >=1)
291 CallHandler(FSYNC_readfds, nfds, POLLIN|POLLPRI);
294 GetHandler(&FSYNC_readfds, &maxfd);
295 /* Note: check for >= 1 below is essential since IOMGR_select
296 * doesn't have exactly same semantics as select.
298 #ifdef AFS_PTHREAD_ENV
299 if (select(maxfd + 1, &FSYNC_readfds, NULL, NULL, NULL) >= 1)
300 #else /* AFS_PTHREAD_ENV */
301 if (IOMGR_Select(maxfd + 1, &FSYNC_readfds, NULL, NULL, NULL) >= 1)
302 #endif /* AFS_PTHREAD_ENV */
303 CallHandler(&FSYNC_readfds);
306 return NULL; /* hush now, little gcc */
310 FSYNC_newconnection(osi_socket afd)
312 #ifdef USE_UNIX_SOCKETS
313 struct sockaddr_un other;
314 #else /* USE_UNIX_SOCKETS */
315 struct sockaddr_in other;
319 junk = sizeof(other);
320 fd = accept(afd, (struct sockaddr *)&other, &junk);
322 Log("FSYNC_newconnection: accept failed, errno==%d\n", errno);
324 } else if (!AddHandler(fd, FSYNC_com)) {
326 assert(AddHandler(fd, FSYNC_com));
330 /* this function processes commands from an fssync file descriptor (fd) */
331 afs_int32 FS_cnt = 0;
333 FSYNC_com(osi_socket fd)
337 SYNC_PROTO_BUF_DECL(com_buf);
338 SYNC_PROTO_BUF_DECL(res_buf);
340 memset(&res.hdr, 0, sizeof(res.hdr));
342 com.payload.buf = (void *)com_buf;
343 com.payload.len = SYNC_PROTO_MAX_LEN;
344 res.hdr.response_len = sizeof(res.hdr);
345 res.payload.len = SYNC_PROTO_MAX_LEN;
346 res.payload.buf = (void *)res_buf;
349 if (SYNC_getCom(&fssync_server_state, fd, &com)) {
350 Log("FSYNC_com: read failed; dropping connection (cnt=%d)\n", FS_cnt);
355 if (com.recv_len < sizeof(com.hdr)) {
356 Log("FSSYNC_com: invalid protocol message length (%u)\n", com.recv_len);
357 res.hdr.response = SYNC_COM_ERROR;
358 res.hdr.reason = SYNC_REASON_MALFORMED_PACKET;
359 res.hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
363 if (com.hdr.proto_version != FSYNC_PROTO_VERSION) {
364 Log("FSYNC_com: invalid protocol version (%u)\n", com.hdr.proto_version);
365 res.hdr.response = SYNC_COM_ERROR;
366 res.hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
370 if (com.hdr.command == SYNC_COM_CHANNEL_CLOSE) {
371 res.hdr.response = SYNC_OK;
372 res.hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
374 /* don't respond, just drop; senders of SYNC_COM_CHANNEL_CLOSE
375 * never wait for a response. */
379 res.hdr.com_seq = com.hdr.com_seq;
382 switch (com.hdr.command) {
384 case FSYNC_VOL_ATTACH:
385 case FSYNC_VOL_LEAVE_OFF:
387 case FSYNC_VOL_FORCE_ERROR:
388 case FSYNC_VOL_LISTVOLUMES:
389 case FSYNC_VOL_NEEDVOLUME:
391 case FSYNC_VOL_BREAKCBKS:
393 case FSYNC_VOL_QUERY:
394 case FSYNC_VOL_QUERY_HDR:
395 case FSYNC_VOL_QUERY_VOP:
396 res.hdr.response = FSYNC_com_VolOp(fd, &com, &res);
398 case FSYNC_VOL_STATS_GENERAL:
399 case FSYNC_VOL_STATS_VICEP:
400 case FSYNC_VOL_STATS_HASH:
401 case FSYNC_VOL_STATS_HDR:
402 case FSYNC_VOL_STATS_VLRU:
403 res.hdr.response = FSYNC_com_StatsOp(fd, &com, &res);
405 case FSYNC_VOL_QUERY_VNODE:
406 res.hdr.response = FSYNC_com_VnQry(fd, &com, &res);
409 res.hdr.response = SYNC_BAD_COMMAND;
415 SYNC_putRes(&fssync_server_state, fd, &res);
418 if (res.hdr.flags & SYNC_FLAG_CHANNEL_SHUTDOWN) {
424 FSYNC_com_VolOp(osi_socket fd, SYNC_command * com, SYNC_response * res)
427 afs_int32 code = SYNC_OK;
428 FSSYNC_VolOp_command vcom;
430 if (com->recv_len != (sizeof(com->hdr) + sizeof(FSSYNC_VolOp_hdr))) {
431 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
432 res->hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
433 return SYNC_COM_ERROR;
436 vcom.hdr = &com->hdr;
437 vcom.vop = (FSSYNC_VolOp_hdr *) com->payload.buf;
440 vcom.volumes = OfflineVolumes[FindHandler(fd)];
441 for (vcom.v = NULL, i = 0; i < MAXOFFLINEVOLUMES; i++) {
442 if ((vcom.volumes[i].volumeID == vcom.vop->volume) &&
443 (strncmp(vcom.volumes[i].partName, vcom.vop->partName,
444 sizeof(vcom.volumes[i].partName)) == 0)) {
445 vcom.v = &vcom.volumes[i];
450 switch (com->hdr.command) {
452 case FSYNC_VOL_ATTACH:
453 case FSYNC_VOL_LEAVE_OFF:
454 code = FSYNC_com_VolOn(&vcom, res);
457 case FSYNC_VOL_NEEDVOLUME:
458 code = FSYNC_com_VolOff(&vcom, res);
460 case FSYNC_VOL_LISTVOLUMES:
464 code = FSYNC_com_VolMove(&vcom, res);
466 case FSYNC_VOL_BREAKCBKS:
467 code = FSYNC_com_VolBreakCBKs(&vcom, res);
470 code = FSYNC_com_VolDone(&vcom, res);
472 case FSYNC_VOL_QUERY:
473 code = FSYNC_com_VolQuery(&vcom, res);
475 case FSYNC_VOL_QUERY_HDR:
476 code = FSYNC_com_VolHdrQuery(&vcom, res);
478 #ifdef AFS_DEMAND_ATTACH_FS
479 case FSYNC_VOL_FORCE_ERROR:
480 code = FSYNC_com_VolError(&vcom, res);
482 case FSYNC_VOL_QUERY_VOP:
483 code = FSYNC_com_VolOpQuery(&vcom, res);
485 #endif /* AFS_DEMAND_ATTACH_FS */
487 code = SYNC_BAD_COMMAND;
494 * service an FSYNC request to bring a volume online.
496 * @param[in] vcom pointer command object
497 * @param[out] res object in which to store response packet
499 * @return operation status
500 * @retval SYNC_OK volume transitioned online
501 * @retval SYNC_FAILED invalid command protocol message
502 * @retval SYNC_DENIED operation could not be completed
504 * @note this is an FSYNC RPC server stub
506 * @note this procedure handles the following FSSYNC command codes:
509 * - FSYNC_VOL_LEAVE_OFF
511 * @note the supplementary reason code contains additional details.
512 * When SYNC_DENIED is returned, the specific reason is
513 * placed in the response packet reason field.
518 FSYNC_com_VolOn(FSSYNC_VolOp_command * vcom, SYNC_response * res)
520 afs_int32 code = SYNC_OK;
521 #ifndef AFS_DEMAND_ATTACH_FS
522 char tvolName[VMAXPATHLEN];
527 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
528 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
533 /* so, we need to attach the volume */
535 #ifdef AFS_DEMAND_ATTACH_FS
536 /* check DAFS permissions */
537 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
539 FSYNC_partMatch(vcom, vp, 1) &&
540 vp->pending_vol_op &&
541 (vcom->hdr->programType != vp->pending_vol_op->com.programType)) {
542 /* a different program has this volume checked out. deny. */
543 Log("FSYNC_VolOn: WARNING: program type %u has attempted to manipulate "
544 "state for volume %u using command code %u while the volume is "
545 "checked out by program type %u for command code %u.\n",
546 vcom->hdr->programType,
549 vp->pending_vol_op->com.programType,
550 vp->pending_vol_op->com.command);
552 res->hdr.reason = FSYNC_EXCLUSIVE;
558 vcom->v->volumeID = 0;
561 if (vcom->hdr->command == FSYNC_VOL_LEAVE_OFF) {
562 /* nothing much to do if we're leaving the volume offline */
563 #ifdef AFS_DEMAND_ATTACH_FS
565 if (FSYNC_partMatch(vcom, vp, 1)) {
566 if ((V_attachState(vp) == VOL_STATE_UNATTACHED) ||
567 (V_attachState(vp) == VOL_STATE_PREATTACHED)) {
568 VChangeState_r(vp, VOL_STATE_UNATTACHED);
569 VDeregisterVolOp_r(vp);
572 res->hdr.reason = FSYNC_BAD_STATE;
576 res->hdr.reason = FSYNC_WRONG_PART;
580 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
586 #ifdef AFS_DEMAND_ATTACH_FS
587 /* first, check to see whether we have such a volume defined */
588 vp = VPreAttachVolumeById_r(&error,
592 VDeregisterVolOp_r(vp);
594 #else /* !AFS_DEMAND_ATTACH_FS */
596 snprintf(&tvolName[1], sizeof(tvolName)-1, VFORMAT, afs_printable_uint32_lu(vcom->vop->volume));
597 tvolName[sizeof(tvolName)-1] = '\0';
599 vp = VAttachVolumeByName_r(&error, vcom->vop->partName, tvolName,
605 res->hdr.reason = error;
607 #endif /* !AFS_DEMAND_ATTACH_FS */
614 * service an FSYNC request to take a volume offline.
616 * @param[in] vcom pointer command object
617 * @param[out] res object in which to store response packet
619 * @return operation status
620 * @retval SYNC_OK volume transitioned offline
621 * @retval SYNC_FAILED invalid command protocol message
622 * @retval SYNC_DENIED operation could not be completed
624 * @note this is an FSYNC RPC server stub
626 * @note this procedure handles the following FSSYNC command codes:
628 * - FSYNC_VOL_NEEDVOLUME
630 * @note the supplementary reason code contains additional details.
631 * When SYNC_DENIED is returned, the specific reason is
632 * placed in the response packet reason field.
637 FSYNC_com_VolOff(FSSYNC_VolOp_command * vcom, SYNC_response * res)
639 FSSYNC_VolOp_info info;
640 afs_int32 code = SYNC_OK;
644 #ifdef AFS_DEMAND_ATTACH_FS
645 Volume *nvp, *rvp = NULL;
648 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
649 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
654 /* not already offline, we need to find a slot for newly offline volume */
655 if (vcom->hdr->programType == debugUtility) {
656 /* debug utilities do not have their operations tracked */
660 for (i = 0; i < MAXOFFLINEVOLUMES; i++) {
661 if (vcom->volumes[i].volumeID == 0) {
662 vcom->v = &vcom->volumes[i];
672 FSYNC_com_to_info(vcom, &info);
674 #ifdef AFS_DEMAND_ATTACH_FS
675 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
677 vp = VGetVolume_r(&error, vcom->vop->volume);
681 if (!FSYNC_partMatch(vcom, vp, 1)) {
682 /* volume on desired partition is not online, so we
683 * should treat this as an offline volume.
685 #ifndef AFS_DEMAND_ATTACH_FS
693 #ifdef AFS_DEMAND_ATTACH_FS
695 ProgramType type = (ProgramType) vcom->hdr->programType;
697 /* do initial filtering of requests */
699 /* enforce mutual exclusion for volume ops */
700 if (vp->pending_vol_op) {
701 if (vp->pending_vol_op->com.programType != type) {
702 Log("volume %u already checked out\n", vp->hashid);
704 Log("vp->vop = { com = { ver=%u, prog=%d, com=%d, reason=%d, len=%u, flags=0x%x }, vop = { vol=%u, part='%s' } }\n",
705 vp->pending_vol_op->com.proto_version,
706 vp->pending_vol_op->com.programType,
707 vp->pending_vol_op->com.command,
708 vp->pending_vol_op->com.reason,
709 vp->pending_vol_op->com.command_len,
710 vp->pending_vol_op->com.flags,
711 vp->pending_vol_op->vop.volume,
712 vp->pending_vol_op->vop.partName );
713 Log("vcom = { com = { ver=%u, prog=%d, com=%d, reason=%d, len=%u, flags=0x%x } , vop = { vol=%u, part='%s' } }\n",
714 vcom->hdr->proto_version,
715 vcom->hdr->programType,
718 vcom->hdr->command_len,
721 vcom->vop->partName);
722 res->hdr.reason = FSYNC_EXCLUSIVE;
725 Log("warning: volume %u recursively checked out by programType id %d\n",
726 vp->hashid, vcom->hdr->programType);
730 /* wait for exclusive ops, so we have an accurate picture of the
731 * vol attach state */
732 VCreateReservation_r(vp);
733 VWaitExclusiveState_r(vp);
736 /* filter based upon requestor
738 * volume utilities are not allowed to check out volumes
739 * which are in an error state
741 * unknown utility programs will be denied on principal
745 /* it is possible for the salvageserver to checkout a
746 * volume for salvage before its scheduling request
747 * has been sent to the salvageserver */
748 if (vp->salvage.requested && !vp->salvage.scheduled) {
749 vp->salvage.scheduled = 1;
755 if (VIsErrorState(V_attachState(vp))) {
758 if (vp->salvage.requested) {
764 Log("bad program type passed to FSSYNC\n");
768 /* short circuit for offline volume states
769 * so we can avoid I/O penalty of attachment */
770 switch (V_attachState(vp)) {
771 case VOL_STATE_UNATTACHED:
772 case VOL_STATE_PREATTACHED:
773 case VOL_STATE_SALVAGING:
774 case VOL_STATE_ERROR:
775 /* register the volume operation metadata with the volume
777 * if the volume is currently pre-attached, attach2()
778 * will evaluate the vol op metadata to determine whether
779 * attaching the volume would be safe */
780 VRegisterVolOp_r(vp, &info);
781 vp->pending_vol_op->vol_op_state = FSSYNC_VolOpRunningUnknown;
787 /* convert to heavyweight ref */
788 nvp = VGetVolumeByVp_r(&error, vp);
789 VCancelReservation_r(rvp);
794 * It's possible for VGetVolumeByVp_r to have dropped and
795 * re-acquired VOL_LOCK, so volume state may have changed
796 * back to one of the states we tested for above. Since
797 * GetVolume can return NULL in some of those states, just
798 * test for the states again here.
800 switch (V_attachState(vp)) {
801 case VOL_STATE_UNATTACHED:
802 case VOL_STATE_PREATTACHED:
803 case VOL_STATE_SALVAGING:
804 case VOL_STATE_ERROR:
805 /* register the volume operation metadata with the volume
807 * if the volume is currently pre-attached, attach2()
808 * will evaluate the vol op metadata to determine whether
809 * attaching the volume would be safe */
810 VRegisterVolOp_r(vp, &info);
811 vp->pending_vol_op->vol_op_state = FSSYNC_VolOpRunningUnknown;
817 Log("FSYNC_com_VolOff: failed to get heavyweight reference to volume %u\n",
819 res->hdr.reason = FSYNC_VOL_PKG_ERROR;
821 } else if (nvp != vp) {
822 /* i don't think this should ever happen, but just in case... */
823 Log("FSYNC_com_VolOff: warning: potentially dangerous race detected\n");
827 /* register the volume operation metadata with the volume */
828 VRegisterVolOp_r(vp, &info);
831 #endif /* AFS_DEMAND_ATTACH_FS */
834 if (VVolOpLeaveOnline_r(vp, &info)) {
835 VUpdateVolume_r(&error, vp, VOL_UPDATE_WAIT); /* At least get volume stats right */
837 Log("FSYNC: Volume %u (%s) was left on line for an external %s request\n",
838 V_id(vp), V_name(vp),
839 vcom->hdr->reason == V_CLONE ? "clone" :
840 vcom->hdr->reason == V_READONLY ? "readonly" :
841 vcom->hdr->reason == V_DUMP ? "dump" :
844 #ifdef AFS_DEMAND_ATTACH_FS
845 vp->pending_vol_op->vol_op_state = FSSYNC_VolOpRunningOnline;
849 if (VVolOpSetVBusy_r(vp, &info)) {
850 vp->specialStatus = VBUSY;
853 /* remember what volume we got, so we can keep track of how
854 * many volumes the volserver or whatever is using. Note that
855 * vp is valid since leaveonline is only set when vp is valid.
858 vcom->v->volumeID = vcom->vop->volume;
859 strlcpy(vcom->v->partName, vp->partition->name, sizeof(vcom->v->partName));
862 #ifdef AFS_DEMAND_ATTACH_FS
863 VOfflineForVolOp_r(&error, vp, "A volume utility is running.");
865 assert(vp->nUsers==0);
866 vp->pending_vol_op->vol_op_state = FSSYNC_VolOpRunningOffline;
869 VDeregisterVolOp_r(vp);
873 VOffline_r(vp, "A volume utility is running.");
884 #ifdef AFS_DEMAND_ATTACH_FS
886 VCancelReservation_r(rvp);
893 * service an FSYNC request to mark a volume as moved.
895 * @param[in] vcom pointer command object
896 * @param[out] res object in which to store response packet
898 * @return operation status
899 * @retval SYNC_OK volume marked as moved to a remote server
900 * @retval SYNC_FAILED invalid command protocol message
901 * @retval SYNC_DENIED current volume state does not permit this operation
903 * @note this is an FSYNC RPC server stub
905 * @note this operation also breaks all callbacks for the given volume
907 * @note this procedure handles the following FSSYNC command codes:
910 * @note the supplementary reason code contains additional details. For
911 * instance, SYNC_OK is still returned when the partition specified
912 * does not match the one registered in the volume object -- reason
913 * will be FSYNC_WRONG_PART in this case.
918 FSYNC_com_VolMove(FSSYNC_VolOp_command * vcom, SYNC_response * res)
920 afs_int32 code = SYNC_DENIED;
924 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
925 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
930 /* Yuch: the "reason" for the move is the site it got moved to... */
931 /* still set specialStatus so we stop sending back VBUSY.
932 * also should still break callbacks. Note that I don't know
933 * how to tell if we should break all or not, so we just do it
934 * since it doesn't matter much if we do an extra break
935 * volume callbacks on a volume move within the same server */
936 #ifdef AFS_DEMAND_ATTACH_FS
937 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
939 vp = VGetVolume_r(&error, vcom->vop->volume);
942 if (FSYNC_partMatch(vcom, vp, 1)) {
943 #ifdef AFS_DEMAND_ATTACH_FS
944 if ((V_attachState(vp) == VOL_STATE_UNATTACHED) ||
945 (V_attachState(vp) == VOL_STATE_PREATTACHED)) {
948 vp->specialStatus = VMOVED;
949 #ifdef AFS_DEMAND_ATTACH_FS
951 res->hdr.reason = FSYNC_BAD_STATE;
955 res->hdr.reason = FSYNC_WRONG_PART;
957 #ifndef AFS_DEMAND_ATTACH_FS
959 #endif /* !AFS_DEMAND_ATTACH_FS */
961 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
964 if ((code == SYNC_OK) && (V_BreakVolumeCallbacks != NULL)) {
965 Log("fssync: volume %u moved to %x; breaking all call backs\n",
966 vcom->vop->volume, vcom->hdr->reason);
968 (*V_BreakVolumeCallbacks) (vcom->vop->volume);
978 * service an FSYNC request to mark a volume as destroyed.
980 * @param[in] vcom pointer command object
981 * @param[out] res object in which to store response packet
983 * @return operation status
984 * @retval SYNC_OK volume marked as destroyed
985 * @retval SYNC_FAILED invalid command protocol message
986 * @retval SYNC_DENIED current volume state does not permit this operation
988 * @note this is an FSYNC RPC server stub
990 * @note this procedure handles the following FSSYNC command codes:
993 * @note the supplementary reason code contains additional details. For
994 * instance, SYNC_OK is still returned when the partition specified
995 * does not match the one registered in the volume object -- reason
996 * will be FSYNC_WRONG_PART in this case.
1001 FSYNC_com_VolDone(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1003 afs_int32 code = SYNC_FAILED;
1004 #ifdef AFS_DEMAND_ATTACH_FS
1009 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1010 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1014 /* don't try to put online, this call is made only after deleting
1015 * a volume, in which case we want to remove the vol # from the
1016 * OfflineVolumes array only */
1018 vcom->v->volumeID = 0;
1020 #ifdef AFS_DEMAND_ATTACH_FS
1021 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
1023 if (FSYNC_partMatch(vcom, vp, 1)) {
1024 if ((V_attachState(vp) == VOL_STATE_UNATTACHED) ||
1025 (V_attachState(vp) == VOL_STATE_PREATTACHED)) {
1026 VChangeState_r(vp, VOL_STATE_UNATTACHED);
1027 VDeregisterVolOp_r(vp);
1031 res->hdr.reason = FSYNC_BAD_STATE;
1034 code = SYNC_OK; /* XXX is this really a good idea? */
1035 res->hdr.reason = FSYNC_WRONG_PART;
1038 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1046 #ifdef AFS_DEMAND_ATTACH_FS
1048 * service an FSYNC request to transition a volume to the hard error state.
1050 * @param[in] vcom pointer command object
1051 * @param[out] res object in which to store response packet
1053 * @return operation status
1054 * @retval SYNC_OK volume transitioned to hard error state
1055 * @retval SYNC_FAILED invalid command protocol message
1056 * @retval SYNC_DENIED (see note)
1058 * @note this is an FSYNC RPC server stub
1060 * @note this procedure handles the following FSSYNC command codes:
1061 * - FSYNC_VOL_FORCE_ERROR
1063 * @note SYNC_DENIED is returned in the following cases:
1064 * - no partition name is specified (reason field set to
1065 * FSYNC_WRONG_PART).
1066 * - volume id not known to fileserver (reason field set
1067 * to FSYNC_UNKNOWN_VOLID).
1069 * @note demand attach fileserver only
1074 FSYNC_com_VolError(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1078 afs_int32 code = SYNC_FAILED;
1080 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1081 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1085 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
1087 if (FSYNC_partMatch(vcom, vp, 0)) {
1088 /* null out salvsync control state, as it's no longer relevant */
1089 memset(&vp->salvage, 0, sizeof(vp->salvage));
1090 VChangeState_r(vp, VOL_STATE_ERROR);
1093 res->hdr.reason = FSYNC_WRONG_PART;
1096 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1102 #endif /* AFS_DEMAND_ATTACH_FS */
1105 * service an FSYNC request to break all callbacks for this volume.
1107 * @param[in] vcom pointer command object
1108 * @param[out] res object in which to store response packet
1110 * @return operation status
1111 * @retval SYNC_OK callback breaks scheduled for volume
1113 * @note this is an FSYNC RPC server stub
1115 * @note this procedure handles the following FSSYNC command codes:
1116 * - FSYNC_VOL_BREAKCBKS
1118 * @note demand attach fileserver only
1120 * @todo should do partition matching
1125 FSYNC_com_VolBreakCBKs(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1127 /* if the volume is being restored, break all callbacks on it */
1128 if (V_BreakVolumeCallbacks) {
1129 Log("fssync: breaking all call backs for volume %u\n",
1132 (*V_BreakVolumeCallbacks) (vcom->vop->volume);
1139 * service an FSYNC request to return the Volume object.
1141 * @param[in] vcom pointer command object
1142 * @param[out] res object in which to store response packet
1144 * @return operation status
1145 * @retval SYNC_OK volume object returned to caller
1146 * @retval SYNC_FAILED bad command packet, or failed to locate volume object
1148 * @note this is an FSYNC RPC server stub
1150 * @note this procedure handles the following FSSYNC command codes:
1156 FSYNC_com_VolQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1158 afs_int32 code = SYNC_FAILED;
1162 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1163 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1167 #ifdef AFS_DEMAND_ATTACH_FS
1168 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
1169 #else /* !AFS_DEMAND_ATTACH_FS */
1170 vp = VGetVolume_r(&error, vcom->vop->volume);
1171 #endif /* !AFS_DEMAND_ATTACH_FS */
1174 if (FSYNC_partMatch(vcom, vp, 1)) {
1175 if (res->payload.len >= sizeof(Volume)) {
1176 memcpy(res->payload.buf, vp, sizeof(Volume));
1177 res->hdr.response_len += sizeof(Volume);
1180 res->hdr.reason = SYNC_REASON_PAYLOAD_TOO_BIG;
1183 res->hdr.reason = FSYNC_WRONG_PART;
1185 #ifndef AFS_DEMAND_ATTACH_FS
1189 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1197 * service an FSYNC request to return the Volume header.
1199 * @param[in] vcom pointer command object
1200 * @param[out] res object in which to store response packet
1202 * @return operation status
1203 * @retval SYNC_OK volume header returned to caller
1204 * @retval SYNC_FAILED bad command packet, or failed to locate volume header
1206 * @note this is an FSYNC RPC server stub
1208 * @note this procedure handles the following FSSYNC command codes:
1209 * - FSYNC_VOL_QUERY_HDR
1214 FSYNC_com_VolHdrQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1216 afs_int32 code = SYNC_FAILED;
1220 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1221 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1224 if (res->payload.len < sizeof(VolumeDiskData)) {
1225 res->hdr.reason = SYNC_REASON_PAYLOAD_TOO_BIG;
1229 #ifdef AFS_DEMAND_ATTACH_FS
1230 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
1231 #else /* !AFS_DEMAND_ATTACH_FS */
1232 vp = VGetVolume_r(&error, vcom->vop->volume);
1236 if (FSYNC_partMatch(vcom, vp, 1)) {
1237 #ifdef AFS_DEMAND_ATTACH_FS
1238 if ((vp->header == NULL) ||
1239 !(V_attachFlags(vp) & VOL_HDR_ATTACHED) ||
1240 !(V_attachFlags(vp) & VOL_HDR_LOADED)) {
1241 res->hdr.reason = FSYNC_HDR_NOT_ATTACHED;
1244 #else /* !AFS_DEMAND_ATTACH_FS */
1245 if (!vp || !vp->header) {
1246 res->hdr.reason = FSYNC_HDR_NOT_ATTACHED;
1249 #endif /* !AFS_DEMAND_ATTACH_FS */
1251 res->hdr.reason = FSYNC_WRONG_PART;
1255 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1259 memcpy(res->payload.buf, &V_disk(vp), sizeof(VolumeDiskData));
1260 res->hdr.response_len += sizeof(VolumeDiskData);
1264 #ifndef AFS_DEMAND_ATTACH_FS
1272 #ifdef AFS_DEMAND_ATTACH_FS
1274 FSYNC_com_VolOpQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1276 afs_int32 code = SYNC_OK;
1280 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
1282 if (vp && vp->pending_vol_op) {
1283 assert(sizeof(FSSYNC_VolOp_info) <= res->payload.len);
1284 memcpy(res->payload.buf, vp->pending_vol_op, sizeof(FSSYNC_VolOp_info));
1285 res->hdr.response_len += sizeof(FSSYNC_VolOp_info);
1288 res->hdr.reason = FSYNC_NO_PENDING_VOL_OP;
1290 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1296 #endif /* AFS_DEMAND_ATTACH_FS */
1299 FSYNC_com_VnQry(osi_socket fd, SYNC_command * com, SYNC_response * res)
1301 afs_int32 code = SYNC_OK;
1302 FSSYNC_VnQry_hdr * qry = com->payload.buf;
1307 if (com->recv_len != (sizeof(com->hdr) + sizeof(FSSYNC_VnQry_hdr))) {
1308 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1309 res->hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
1310 return SYNC_COM_ERROR;
1313 #ifdef AFS_DEMAND_ATTACH_FS
1314 vp = VLookupVolume_r(&error, qry->volume, NULL);
1315 #else /* !AFS_DEMAND_ATTACH_FS */
1316 vp = VGetVolume_r(&error, qry->volume);
1317 #endif /* !AFS_DEMAND_ATTACH_FS */
1320 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1325 vnp = VLookupVnode(vp, qry->vnode);
1327 res->hdr.reason = FSYNC_UNKNOWN_VNID;
1332 if (Vn_class(vnp)->residentSize > res->payload.len) {
1333 res->hdr.reason = SYNC_REASON_ENCODING_ERROR;
1338 memcpy(res->payload.buf, vnp, Vn_class(vnp)->residentSize);
1339 res->hdr.response_len += Vn_class(vnp)->residentSize;
1342 #ifndef AFS_DEMAND_ATTACH_FS
1351 FSYNC_com_StatsOp(osi_socket fd, SYNC_command * com, SYNC_response * res)
1353 afs_int32 code = SYNC_OK;
1354 FSSYNC_StatsOp_command scom;
1356 if (com->recv_len != (sizeof(com->hdr) + sizeof(FSSYNC_StatsOp_hdr))) {
1357 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1358 res->hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
1359 return SYNC_COM_ERROR;
1362 scom.hdr = &com->hdr;
1363 scom.sop = (FSSYNC_StatsOp_hdr *) com->payload.buf;
1366 switch (com->hdr.command) {
1367 case FSYNC_VOL_STATS_GENERAL:
1368 code = FSYNC_com_StatsOpGeneral(&scom, res);
1370 #ifdef AFS_DEMAND_ATTACH_FS
1371 /* statistics for the following subsystems are only tracked
1372 * for demand attach fileservers */
1373 case FSYNC_VOL_STATS_VICEP:
1374 code = FSYNC_com_StatsOpViceP(&scom, res);
1376 case FSYNC_VOL_STATS_HASH:
1377 code = FSYNC_com_StatsOpHash(&scom, res);
1379 case FSYNC_VOL_STATS_HDR:
1380 code = FSYNC_com_StatsOpHdr(&scom, res);
1382 case FSYNC_VOL_STATS_VLRU:
1383 code = FSYNC_com_StatsOpVLRU(&scom, res);
1385 #endif /* AFS_DEMAND_ATTACH_FS */
1387 code = SYNC_BAD_COMMAND;
1394 FSYNC_com_StatsOpGeneral(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1396 afs_int32 code = SYNC_OK;
1398 memcpy(res->payload.buf, &VStats, sizeof(VStats));
1399 res->hdr.response_len += sizeof(VStats);
1404 #ifdef AFS_DEMAND_ATTACH_FS
1406 FSYNC_com_StatsOpViceP(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1408 afs_int32 code = SYNC_OK;
1409 struct DiskPartition64 * dp;
1410 struct DiskPartitionStats64 * stats;
1412 if (SYNC_verifyProtocolString(scom->sop->args.partName, sizeof(scom->sop->args.partName))) {
1413 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1418 dp = VGetPartition_r(scom->sop->args.partName, 0);
1422 stats = (struct DiskPartitionStats64 *) res->payload.buf;
1423 stats->free = dp->free;
1424 stats->totalUsable = dp->totalUsable;
1425 stats->minFree = dp->minFree;
1426 stats->f_files = dp->f_files;
1427 stats->vol_list_len = dp->vol_list.len;
1429 res->hdr.response_len += sizeof(struct DiskPartitionStats64);
1437 FSYNC_com_StatsOpHash(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1439 afs_int32 code = SYNC_OK;
1440 struct VolumeHashChainStats * stats;
1441 struct VolumeHashChainHead * head;
1443 if (scom->sop->args.hash_bucket >= VolumeHashTable.Size) {
1447 head = &VolumeHashTable.Table[scom->sop->args.hash_bucket];
1448 stats = (struct VolumeHashChainStats *) res->payload.buf;
1449 stats->table_size = VolumeHashTable.Size;
1450 stats->chain_len = head->len;
1451 stats->chain_cacheCheck = head->cacheCheck;
1452 stats->chain_busy = head->busy;
1453 AssignInt64(head->looks, &stats->chain_looks);
1454 AssignInt64(head->gets, &stats->chain_gets);
1455 AssignInt64(head->reorders, &stats->chain_reorders);
1457 res->hdr.response_len += sizeof(struct VolumeHashChainStats);
1463 FSYNC_com_StatsOpHdr(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1465 afs_int32 code = SYNC_OK;
1467 memcpy(res->payload.buf, &volume_hdr_LRU.stats, sizeof(volume_hdr_LRU.stats));
1468 res->hdr.response_len += sizeof(volume_hdr_LRU.stats);
1474 FSYNC_com_StatsOpVLRU(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1476 afs_int32 code = SYNC_OK;
1478 code = SYNC_BAD_COMMAND;
1482 #endif /* AFS_DEMAND_ATTACH_FS */
1485 * populate an FSSYNC_VolOp_info object from a command packet object.
1487 * @param[in] vcom pointer to command packet
1488 * @param[out] info pointer to info object which will be populated
1490 * @note FSSYNC_VolOp_info objects are attached to Volume objects when
1491 * a volume operation is commenced.
1496 FSYNC_com_to_info(FSSYNC_VolOp_command * vcom, FSSYNC_VolOp_info * info)
1498 memcpy(&info->com, vcom->hdr, sizeof(SYNC_command_hdr));
1499 memcpy(&info->vop, vcom->vop, sizeof(FSSYNC_VolOp_hdr));
1500 info->vol_op_state = FSSYNC_VolOpPending;
1504 * check whether command packet partition name matches volume
1505 * object's partition name.
1507 * @param[in] vcom pointer to command packet
1508 * @param[in] vp pointer to volume object
1509 * @param[in] match_anon anon matching control flag (see note below)
1511 * @return whether partitions match
1512 * @retval 0 partitions do NOT match
1513 * @retval 1 partitions match
1515 * @note if match_anon is non-zero, then this function will return a
1516 * positive match for a zero-length partition string in the
1522 FSYNC_partMatch(FSSYNC_VolOp_command * vcom, Volume * vp, int match_anon)
1524 return ((match_anon && vcom->vop->partName[0] == 0) ||
1525 (strncmp(vcom->vop->partName, V_partition(vp)->name,
1526 sizeof(vcom->vop->partName)) == 0));
1531 FSYNC_Drop(osi_socket fd)
1533 struct offlineInfo *p;
1536 char tvolName[VMAXPATHLEN];
1539 p = OfflineVolumes[FindHandler(fd)];
1540 for (i = 0; i < MAXOFFLINEVOLUMES; i++) {
1541 if (p[i].volumeID) {
1546 sprintf(&tvolName[1], VFORMAT, afs_printable_uint32_lu(p[i].volumeID));
1547 vp = VAttachVolumeByName_r(&error, p[i].partName, tvolName,
1564 static int AcceptHandler = -1; /* handler id for accept, if turned on */
1569 if (AcceptHandler == -1) {
1570 assert(AddHandler(fssync_server_state.fd, FSYNC_newconnection));
1571 AcceptHandler = FindHandler(fssync_server_state.fd);
1578 if (AcceptHandler != -1) {
1579 assert(RemoveHandler(fssync_server_state.fd));
1584 /* The multiple FD handling code. */
1586 static osi_socket HandlerFD[MAXHANDLERS];
1587 static void (*HandlerProc[MAXHANDLERS]) (osi_socket);
1593 ObtainWriteLock(&FSYNC_handler_lock);
1594 for (i = 0; i < MAXHANDLERS; i++) {
1598 ReleaseWriteLock(&FSYNC_handler_lock);
1601 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
1603 CallHandler(struct pollfd *fds, int nfds, int mask)
1607 ObtainReadLock(&FSYNC_handler_lock);
1608 for (i = 0; i < nfds; i++) {
1609 if (fds[i].revents & mask) {
1610 handler = FindHandler_r(fds[i].fd);
1611 ReleaseReadLock(&FSYNC_handler_lock);
1612 (*HandlerProc[handler]) (fds[i].fd);
1613 ObtainReadLock(&FSYNC_handler_lock);
1616 ReleaseReadLock(&FSYNC_handler_lock);
1620 CallHandler(fd_set * fdsetp)
1623 ObtainReadLock(&FSYNC_handler_lock);
1624 for (i = 0; i < MAXHANDLERS; i++) {
1625 if (HandlerFD[i] >= 0 && FD_ISSET(HandlerFD[i], fdsetp)) {
1626 ReleaseReadLock(&FSYNC_handler_lock);
1627 (*HandlerProc[i]) (HandlerFD[i]);
1628 ObtainReadLock(&FSYNC_handler_lock);
1631 ReleaseReadLock(&FSYNC_handler_lock);
1636 AddHandler(osi_socket afd, void (*aproc) (osi_socket))
1639 ObtainWriteLock(&FSYNC_handler_lock);
1640 for (i = 0; i < MAXHANDLERS; i++)
1641 if (HandlerFD[i] == -1)
1643 if (i >= MAXHANDLERS) {
1644 ReleaseWriteLock(&FSYNC_handler_lock);
1648 HandlerProc[i] = aproc;
1649 ReleaseWriteLock(&FSYNC_handler_lock);
1654 FindHandler(register osi_socket afd)
1657 ObtainReadLock(&FSYNC_handler_lock);
1658 for (i = 0; i < MAXHANDLERS; i++)
1659 if (HandlerFD[i] == afd) {
1660 ReleaseReadLock(&FSYNC_handler_lock);
1663 ReleaseReadLock(&FSYNC_handler_lock); /* just in case */
1665 return -1; /* satisfy compiler */
1669 FindHandler_r(register osi_socket afd)
1672 for (i = 0; i < MAXHANDLERS; i++)
1673 if (HandlerFD[i] == afd) {
1677 return -1; /* satisfy compiler */
1681 RemoveHandler(register osi_socket afd)
1683 ObtainWriteLock(&FSYNC_handler_lock);
1684 HandlerFD[FindHandler_r(afd)] = -1;
1685 ReleaseWriteLock(&FSYNC_handler_lock);
1689 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
1691 GetHandler(struct pollfd *fds, int maxfds, int events, int *nfds)
1695 ObtainReadLock(&FSYNC_handler_lock);
1696 for (i = 0; i < MAXHANDLERS; i++)
1697 if (HandlerFD[i] != -1) {
1699 fds[fdi].fd = HandlerFD[i];
1700 fds[fdi].events = events;
1701 fds[fdi].revents = 0;
1705 ReleaseReadLock(&FSYNC_handler_lock);
1709 GetHandler(fd_set * fdsetp, int *maxfdp)
1712 register int maxfd = -1;
1714 ObtainReadLock(&FSYNC_handler_lock); /* just in case */
1715 for (i = 0; i < MAXHANDLERS; i++)
1716 if (HandlerFD[i] != -1) {
1717 FD_SET(HandlerFD[i], fdsetp);
1718 #ifndef AFS_NT40_ENV
1719 /* On Windows the nfds parameter to select() is ignored */
1720 if (maxfd < HandlerFD[i] || maxfd == (int)-1)
1721 maxfd = HandlerFD[i];
1722 #endif /* AFS_NT40_ENV */
1725 ReleaseReadLock(&FSYNC_handler_lock); /* just in case */
1727 #endif /* HAVE_POLL && AFS_PTHREAD_ENV */
1729 #endif /* FSSYNC_BUILD_SERVER */