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-2010 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>
56 #include <sys/param.h>
57 #include <sys/socket.h>
58 #include <netinet/in.h>
64 #ifdef AFS_PTHREAD_ENV
66 #else /* AFS_PTHREAD_ENV */
67 #include <afs/assert.h>
68 #endif /* AFS_PTHREAD_ENV */
73 #include <afs/afsint.h>
75 #include <afs/errors.h>
76 #include "daemon_com.h"
77 #include "daemon_com_inline.h"
79 #include "fssync_inline.h"
83 #include <afs/afssyscalls.h>
87 #include "volume_inline.h"
88 #include "partition.h"
94 #endif /* HAVE_POLL */
96 #ifdef USE_UNIX_SOCKETS
98 #include <afs/afsutil.h>
99 #endif /* USE_UNIX_SOCKETS */
101 #ifdef FSSYNC_BUILD_SERVER
103 int (*V_BreakVolumeCallbacks) (VolumeId volume);
105 #define MAXHANDLERS 4 /* Up to 4 clients; must be at least 2, so that
106 * move = dump+restore can run on single server */
107 #define MAXOFFLINEVOLUMES 128 /* This needs to be as big as the maximum
108 * number that would be offline for 1 operation.
109 * Current winner is salvage, which needs all
110 * cloned read-only copies offline when salvaging
111 * a single read-write volume */
115 static struct offlineInfo OfflineVolumes[MAXHANDLERS][MAXOFFLINEVOLUMES];
118 * fssync server socket handle.
120 static SYNC_server_state_t fssync_server_state =
121 { -1, /* file descriptor */
122 FSSYNC_ENDPOINT_DECL, /* server endpoint */
123 FSYNC_PROTO_VERSION, /* protocol version */
124 5, /* bind() retry limit */
125 100, /* listen() queue depth */
126 "FSSYNC", /* protocol name string */
129 #ifdef AFS_DEMAND_ATTACH_FS
131 * a queue of volume pointers to salvage in the background.
133 struct fsync_salv_node {
135 Volume *vp; /**< volume to salvage */
136 unsigned char update_salv_prio; /**< whether we should update the salvage priority or not */
139 struct rx_queue head;
143 static void * FSYNC_salvageThread(void *);
144 static void FSYNC_backgroundSalvage(Volume *vp);
145 #endif /* AFS_DEMAND_ATTACH_FS */
147 /* Forward declarations */
148 static void * FSYNC_sync(void *);
149 static void FSYNC_newconnection(osi_socket afd);
150 static void FSYNC_com(osi_socket fd);
151 static void FSYNC_Drop(osi_socket fd);
152 static void AcceptOn(void);
153 static void AcceptOff(void);
154 static void InitHandler(void);
155 static int AddHandler(osi_socket fd, void (*aproc)(osi_socket));
156 static int FindHandler(osi_socket afd);
157 static int FindHandler_r(osi_socket afd);
158 static int RemoveHandler(osi_socket afd);
159 #if defined(HAVE_POLL) && defined (AFS_PTHREAD_ENV)
160 static void CallHandler(struct pollfd *fds, int nfds, int mask);
161 static void GetHandler(struct pollfd *fds, int maxfds, int events, int *nfds);
163 static void CallHandler(fd_set * fdsetp);
164 static void GetHandler(fd_set * fdsetp, int *maxfdp);
168 static afs_int32 FSYNC_com_VolOp(osi_socket fd, SYNC_command * com, SYNC_response * res);
170 #ifdef AFS_DEMAND_ATTACH_FS
171 static afs_int32 FSYNC_com_VolError(FSSYNC_VolOp_command * com, SYNC_response * res);
173 static afs_int32 FSYNC_com_VolOn(FSSYNC_VolOp_command * com, SYNC_response * res);
174 static afs_int32 FSYNC_com_VolOff(FSSYNC_VolOp_command * com, SYNC_response * res);
175 static afs_int32 FSYNC_com_VolMove(FSSYNC_VolOp_command * com, SYNC_response * res);
176 static afs_int32 FSYNC_com_VolBreakCBKs(FSSYNC_VolOp_command * com, SYNC_response * res);
177 static afs_int32 FSYNC_com_VolDone(FSSYNC_VolOp_command * com, SYNC_response * res);
178 static afs_int32 FSYNC_com_VolQuery(FSSYNC_VolOp_command * com, SYNC_response * res);
179 static afs_int32 FSYNC_com_VolHdrQuery(FSSYNC_VolOp_command * com, SYNC_response * res);
180 #ifdef AFS_DEMAND_ATTACH_FS
181 static afs_int32 FSYNC_com_VGUpdate(osi_socket fd, SYNC_command * com, SYNC_response * res);
182 static afs_int32 FSYNC_com_VolOpQuery(FSSYNC_VolOp_command * com, SYNC_response * res);
183 static afs_int32 FSYNC_com_VGQuery(FSSYNC_VolOp_command * com, SYNC_response * res);
184 static afs_int32 FSYNC_com_VGScan(FSSYNC_VolOp_command * com, SYNC_response * res);
185 static afs_int32 FSYNC_com_VGScanAll(FSSYNC_VolOp_command * com, SYNC_response * res);
186 #endif /* AFS_DEMAND_ATTACH_FS */
188 static afs_int32 FSYNC_com_VnQry(osi_socket fd, SYNC_command * com, SYNC_response * res);
190 static afs_int32 FSYNC_com_StatsOp(osi_socket fd, SYNC_command * com, SYNC_response * res);
192 static afs_int32 FSYNC_com_StatsOpGeneral(FSSYNC_StatsOp_command * scom, SYNC_response * res);
194 #ifdef AFS_DEMAND_ATTACH_FS
195 static afs_int32 FSYNC_com_StatsOpViceP(FSSYNC_StatsOp_command * scom, SYNC_response * res);
196 static afs_int32 FSYNC_com_StatsOpHash(FSSYNC_StatsOp_command * scom, SYNC_response * res);
197 static afs_int32 FSYNC_com_StatsOpHdr(FSSYNC_StatsOp_command * scom, SYNC_response * res);
198 static afs_int32 FSYNC_com_StatsOpVLRU(FSSYNC_StatsOp_command * scom, SYNC_response * res);
201 static void FSYNC_com_to_info(FSSYNC_VolOp_command * vcom, FSSYNC_VolOp_info * info);
203 static int FSYNC_partMatch(FSSYNC_VolOp_command * vcom, Volume * vp, int match_anon);
207 * This lock controls access to the handler array. The overhead
208 * is minimal in non-preemptive environments.
210 struct Lock FSYNC_handler_lock;
215 #ifdef AFS_PTHREAD_ENV
217 pthread_attr_t tattr;
218 #else /* AFS_PTHREAD_ENV */
220 #endif /* AFS_PTHREAD_ENV */
222 Lock_Init(&FSYNC_handler_lock);
224 #ifdef AFS_PTHREAD_ENV
225 assert(pthread_attr_init(&tattr) == 0);
226 assert(pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED) == 0);
227 assert(pthread_create(&tid, &tattr, FSYNC_sync, NULL) == 0);
228 #else /* AFS_PTHREAD_ENV */
229 assert(LWP_CreateProcess
230 (FSYNC_sync, USUAL_STACK_SIZE, USUAL_PRIORITY, (void *)0,
231 "FSYNC_sync", &pid) == LWP_SUCCESS);
232 #endif /* AFS_PTHREAD_ENV */
234 #ifdef AFS_DEMAND_ATTACH_FS
235 queue_Init(&fsync_salv.head);
236 assert(pthread_cond_init(&fsync_salv.cv, NULL) == 0);
237 assert(pthread_create(&tid, &tattr, FSYNC_salvageThread, NULL) == 0);
238 #endif /* AFS_DEMAND_ATTACH_FS */
241 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
242 static struct pollfd FSYNC_readfds[MAXHANDLERS];
244 static fd_set FSYNC_readfds;
249 FSYNC_sync(void * args)
253 #ifdef AFS_PTHREAD_ENV
256 SYNC_server_state_t * state = &fssync_server_state;
257 #ifdef AFS_DEMAND_ATTACH_FS
258 VThreadOptions_t * thread_opts;
262 * For non-DAFS, only wait until we begin attaching volumes (instead
263 * of waiting until all volumes are attached), since it can take
264 * awhile until VInit == 2.
267 #endif /* AFS_DEMAND_ATTACH_FS */
269 /* we must not be called before vol package initialization, since we use
270 * vol package mutexes and conds etc */
273 SYNC_getAddr(&state->endpoint, &state->addr);
274 SYNC_cleanupSock(state);
277 (void)signal(SIGPIPE, SIG_IGN);
280 #ifdef AFS_PTHREAD_ENV
281 /* set our 'thread-id' so that the host hold table works */
282 MUTEX_ENTER(&rx_stats_mutex); /* protects rxi_pthread_hinum */
283 tid = ++rxi_pthread_hinum;
284 MUTEX_EXIT(&rx_stats_mutex);
285 pthread_setspecific(rx_thread_id_key, (void *)(intptr_t)tid);
286 Log("Set thread id %d for FSYNC_sync\n", tid);
287 #endif /* AFS_PTHREAD_ENV */
291 while (VInit < min_vinit) {
292 /* Let somebody else run until all volumes have been preattached
293 * (DAFS), or we have started attaching volumes (non-DAFS). This
294 * doesn't mean that all volumes have been attached.
296 #ifdef AFS_PTHREAD_ENV
297 VOL_CV_WAIT(&vol_vinit_cond);
298 #else /* AFS_PTHREAD_ENV */
299 LWP_DispatchProcess();
300 #endif /* AFS_PTHREAD_ENV */
305 state->fd = SYNC_getSock(&state->endpoint);
306 code = SYNC_bindSock(state);
309 #ifdef AFS_DEMAND_ATTACH_FS
311 * make sure the volume package is incapable of recursively executing
312 * salvsync calls on this thread, since there is a possibility of
315 thread_opts = malloc(sizeof(VThreadOptions_t));
316 if (thread_opts == NULL) {
317 Log("failed to allocate memory for thread-specific volume package options structure\n");
320 memcpy(thread_opts, &VThread_defaults, sizeof(VThread_defaults));
321 thread_opts->disallow_salvsync = 1;
322 assert(pthread_setspecific(VThread_key, thread_opts) == 0);
324 code = VVGCache_PkgInit();
332 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
334 GetHandler(FSYNC_readfds, MAXHANDLERS, POLLIN|POLLPRI, &nfds);
335 if (poll(FSYNC_readfds, nfds, -1) >=1)
336 CallHandler(FSYNC_readfds, nfds, POLLIN|POLLPRI);
339 GetHandler(&FSYNC_readfds, &maxfd);
340 /* Note: check for >= 1 below is essential since IOMGR_select
341 * doesn't have exactly same semantics as select.
343 #ifdef AFS_PTHREAD_ENV
344 if (select(maxfd + 1, &FSYNC_readfds, NULL, NULL, NULL) >= 1)
345 #else /* AFS_PTHREAD_ENV */
346 if (IOMGR_Select(maxfd + 1, &FSYNC_readfds, NULL, NULL, NULL) >= 1)
347 #endif /* AFS_PTHREAD_ENV */
348 CallHandler(&FSYNC_readfds);
351 return NULL; /* hush now, little gcc */
354 #ifdef AFS_DEMAND_ATTACH_FS
356 * thread for salvaging volumes in the background.
358 * Since FSSYNC handlers cannot issue SALVSYNC requests in order to avoid
359 * deadlock issues, this thread exists so code in the FSSYNC handler thread
360 * can hand off volumes to be salvaged in the background.
362 * @param[in] args unused
364 * @note DEMAND_ATTACH_FS only
367 FSYNC_salvageThread(void * args)
370 struct fsync_salv_node *node;
375 while (queue_IsEmpty(&fsync_salv.head)) {
376 VOL_CV_WAIT(&fsync_salv.cv);
379 node = queue_First(&fsync_salv.head, fsync_salv_node);
383 if (node->update_salv_prio) {
384 if (VUpdateSalvagePriority_r(vp)) {
385 ViceLog(0, ("FSYNC_salvageThread: unable to raise salvage priority "
386 "for volume %lu\n", afs_printable_uint32_lu(vp->hashid)));
393 VCancelReservation_r(vp);
402 * salvage a volume in the background.
404 * Salvages cannot be scheduled directly from the main FSYNC thread, so
405 * instead call this function to schedule a salvage asynchronously in the
406 * FSYNC_salvageThread thread.
408 * @param[in] vp volume to pointer to salvage
412 * @note DEMAND_ATTACH_FS only
415 FSYNC_backgroundSalvage(Volume *vp)
417 struct fsync_salv_node *node;
420 VCreateReservation_r(vp);
422 node = malloc(sizeof(struct fsync_salv_node));
425 /* Save this value, to know if we should VUpdateSalvagePriority_r.
426 * We need to save it here, snce VRequestSalvage_r will change it. */
427 node->update_salv_prio = vp->salvage.requested;
429 if (VRequestSalvage_r(&ec, vp, SALVSYNC_ERROR, 0)) {
430 ViceLog(0, ("FSYNC_backgroundSalvage: unable to request salvage for volume %lu\n",
431 afs_printable_uint32_lu(vp->hashid)));
434 queue_Append(&fsync_salv.head, node);
435 assert(pthread_cond_broadcast(&fsync_salv.cv) == 0);
437 #endif /* AFS_DEMAND_ATTACH_FS */
440 FSYNC_newconnection(osi_socket afd)
442 #ifdef USE_UNIX_SOCKETS
443 struct sockaddr_un other;
444 #else /* USE_UNIX_SOCKETS */
445 struct sockaddr_in other;
449 junk = sizeof(other);
450 fd = accept(afd, (struct sockaddr *)&other, &junk);
452 Log("FSYNC_newconnection: accept failed, errno==%d\n", errno);
454 } else if (!AddHandler(fd, FSYNC_com)) {
456 assert(AddHandler(fd, FSYNC_com));
460 /* this function processes commands from an fssync file descriptor (fd) */
461 afs_int32 FS_cnt = 0;
463 FSYNC_com(osi_socket fd)
467 SYNC_PROTO_BUF_DECL(com_buf);
468 SYNC_PROTO_BUF_DECL(res_buf);
470 memset(&res.hdr, 0, sizeof(res.hdr));
472 com.payload.buf = (void *)com_buf;
473 com.payload.len = SYNC_PROTO_MAX_LEN;
474 res.hdr.response_len = sizeof(res.hdr);
475 res.payload.len = SYNC_PROTO_MAX_LEN;
476 res.payload.buf = (void *)res_buf;
479 if (SYNC_getCom(&fssync_server_state, fd, &com)) {
480 Log("FSYNC_com: read failed; dropping connection (cnt=%d)\n", FS_cnt);
485 if (com.recv_len < sizeof(com.hdr)) {
486 Log("FSSYNC_com: invalid protocol message length (%u)\n", com.recv_len);
487 res.hdr.response = SYNC_COM_ERROR;
488 res.hdr.reason = SYNC_REASON_MALFORMED_PACKET;
489 res.hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
493 if (com.hdr.proto_version != FSYNC_PROTO_VERSION) {
494 Log("FSYNC_com: invalid protocol version (%u)\n", com.hdr.proto_version);
495 res.hdr.response = SYNC_COM_ERROR;
496 res.hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
500 if (com.hdr.command == SYNC_COM_CHANNEL_CLOSE) {
501 res.hdr.response = SYNC_OK;
502 res.hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
504 /* don't respond, just drop; senders of SYNC_COM_CHANNEL_CLOSE
505 * never wait for a response. */
509 ViceLog(125, ("FSYNC_com: from fd %d got command %ld (%s) reason %ld (%s) "
510 "pt %ld (%s) pid %ld\n", (int)fd,
511 afs_printable_int32_ld(com.hdr.command),
512 FSYNC_com2string(com.hdr.command),
513 afs_printable_int32_ld(com.hdr.reason),
514 FSYNC_reason2string(com.hdr.reason),
515 afs_printable_int32_ld(com.hdr.programType),
516 VPTypeToString(com.hdr.programType),
517 afs_printable_int32_ld(com.hdr.pid)));
519 res.hdr.com_seq = com.hdr.com_seq;
522 switch (com.hdr.command) {
524 case FSYNC_VOL_ATTACH:
525 case FSYNC_VOL_LEAVE_OFF:
527 case FSYNC_VOL_FORCE_ERROR:
528 case FSYNC_VOL_LISTVOLUMES:
529 case FSYNC_VOL_NEEDVOLUME:
531 case FSYNC_VOL_BREAKCBKS:
533 case FSYNC_VOL_QUERY:
534 case FSYNC_VOL_QUERY_HDR:
535 case FSYNC_VOL_QUERY_VOP:
536 #ifdef AFS_DEMAND_ATTACH_FS
539 case FSYNC_VG_SCAN_ALL:
541 res.hdr.response = FSYNC_com_VolOp(fd, &com, &res);
543 case FSYNC_VOL_STATS_GENERAL:
544 case FSYNC_VOL_STATS_VICEP:
545 case FSYNC_VOL_STATS_HASH:
546 case FSYNC_VOL_STATS_HDR:
547 case FSYNC_VOL_STATS_VLRU:
548 res.hdr.response = FSYNC_com_StatsOp(fd, &com, &res);
550 case FSYNC_VOL_QUERY_VNODE:
551 res.hdr.response = FSYNC_com_VnQry(fd, &com, &res);
553 #ifdef AFS_DEMAND_ATTACH_FS
556 res.hdr.response = FSYNC_com_VGUpdate(fd, &com, &res);
560 res.hdr.response = SYNC_BAD_COMMAND;
565 ViceLog(125, ("FSYNC_com: fd %d responding with code %ld (%s) reason %ld "
567 afs_printable_int32_ld(res.hdr.response),
568 SYNC_res2string(res.hdr.response),
569 afs_printable_int32_ld(res.hdr.reason),
570 FSYNC_reason2string(res.hdr.reason)));
573 SYNC_putRes(&fssync_server_state, fd, &res);
576 if (res.hdr.flags & SYNC_FLAG_CHANNEL_SHUTDOWN) {
582 FSYNC_com_VolOp(osi_socket fd, SYNC_command * com, SYNC_response * res)
585 afs_int32 code = SYNC_OK;
586 FSSYNC_VolOp_command vcom;
588 if (com->recv_len != (sizeof(com->hdr) + sizeof(FSSYNC_VolOp_hdr))) {
589 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
590 res->hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
591 return SYNC_COM_ERROR;
594 vcom.hdr = &com->hdr;
595 vcom.vop = (FSSYNC_VolOp_hdr *) com->payload.buf;
598 vcom.volumes = OfflineVolumes[FindHandler(fd)];
599 for (vcom.v = NULL, i = 0; i < MAXOFFLINEVOLUMES; i++) {
600 if ((vcom.volumes[i].volumeID == vcom.vop->volume) &&
601 (strncmp(vcom.volumes[i].partName, vcom.vop->partName,
602 sizeof(vcom.volumes[i].partName)) == 0)) {
603 vcom.v = &vcom.volumes[i];
608 ViceLog(125, ("FSYNC_com_VolOp: fd %d got command for vol %lu part %.16s\n",
609 (int)fd, afs_printable_uint32_lu(vcom.vop->volume),
610 vcom.vop->partName));
612 switch (com->hdr.command) {
614 case FSYNC_VOL_ATTACH:
615 case FSYNC_VOL_LEAVE_OFF:
616 code = FSYNC_com_VolOn(&vcom, res);
619 case FSYNC_VOL_NEEDVOLUME:
620 code = FSYNC_com_VolOff(&vcom, res);
622 case FSYNC_VOL_LISTVOLUMES:
626 code = FSYNC_com_VolMove(&vcom, res);
628 case FSYNC_VOL_BREAKCBKS:
629 code = FSYNC_com_VolBreakCBKs(&vcom, res);
632 code = FSYNC_com_VolDone(&vcom, res);
634 case FSYNC_VOL_QUERY:
635 code = FSYNC_com_VolQuery(&vcom, res);
637 case FSYNC_VOL_QUERY_HDR:
638 code = FSYNC_com_VolHdrQuery(&vcom, res);
640 #ifdef AFS_DEMAND_ATTACH_FS
641 case FSYNC_VOL_FORCE_ERROR:
642 code = FSYNC_com_VolError(&vcom, res);
644 case FSYNC_VOL_QUERY_VOP:
645 code = FSYNC_com_VolOpQuery(&vcom, res);
648 code = FSYNC_com_VGQuery(&vcom, res);
651 code = FSYNC_com_VGScan(&vcom, res);
653 case FSYNC_VG_SCAN_ALL:
654 code = FSYNC_com_VGScanAll(&vcom, res);
656 #endif /* AFS_DEMAND_ATTACH_FS */
658 code = SYNC_BAD_COMMAND;
665 * service an FSYNC request to bring a volume online.
667 * @param[in] vcom pointer command object
668 * @param[out] res object in which to store response packet
670 * @return operation status
671 * @retval SYNC_OK volume transitioned online
672 * @retval SYNC_FAILED invalid command protocol message
673 * @retval SYNC_DENIED operation could not be completed
675 * @note this is an FSYNC RPC server stub
677 * @note this procedure handles the following FSSYNC command codes:
680 * - FSYNC_VOL_LEAVE_OFF
682 * @note the supplementary reason code contains additional details.
683 * When SYNC_DENIED is returned, the specific reason is
684 * placed in the response packet reason field.
689 FSYNC_com_VolOn(FSSYNC_VolOp_command * vcom, SYNC_response * res)
691 afs_int32 code = SYNC_OK;
692 #ifndef AFS_DEMAND_ATTACH_FS
693 char tvolName[VMAXPATHLEN];
698 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
699 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
704 /* so, we need to attach the volume */
706 #ifdef AFS_DEMAND_ATTACH_FS
707 /* check DAFS permissions */
708 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
710 FSYNC_partMatch(vcom, vp, 1) &&
711 vp->pending_vol_op &&
712 (vcom->hdr->programType != vp->pending_vol_op->com.programType)) {
713 /* a different program has this volume checked out. deny. */
714 Log("FSYNC_VolOn: WARNING: program type %u has attempted to manipulate "
715 "state for volume %u using command code %u while the volume is "
716 "checked out by program type %u for command code %u.\n",
717 vcom->hdr->programType,
720 vp->pending_vol_op->com.programType,
721 vp->pending_vol_op->com.command);
723 res->hdr.reason = FSYNC_EXCLUSIVE;
729 vcom->v->volumeID = 0;
732 if (vcom->hdr->command == FSYNC_VOL_LEAVE_OFF) {
733 /* nothing much to do if we're leaving the volume offline */
734 #ifdef AFS_DEMAND_ATTACH_FS
736 if (FSYNC_partMatch(vcom, vp, 1)) {
737 if ((V_attachState(vp) == VOL_STATE_UNATTACHED) ||
738 (V_attachState(vp) == VOL_STATE_PREATTACHED)) {
739 VChangeState_r(vp, VOL_STATE_UNATTACHED);
740 VDeregisterVolOp_r(vp);
743 res->hdr.reason = FSYNC_BAD_STATE;
747 res->hdr.reason = FSYNC_WRONG_PART;
751 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
757 #ifdef AFS_DEMAND_ATTACH_FS
758 /* first, check to see whether we have such a volume defined */
759 vp = VPreAttachVolumeById_r(&error,
763 VDeregisterVolOp_r(vp);
765 #else /* !AFS_DEMAND_ATTACH_FS */
767 snprintf(&tvolName[1], sizeof(tvolName)-1, VFORMAT, afs_printable_uint32_lu(vcom->vop->volume));
768 tvolName[sizeof(tvolName)-1] = '\0';
770 vp = VAttachVolumeByName_r(&error, vcom->vop->partName, tvolName,
776 res->hdr.reason = error;
778 #endif /* !AFS_DEMAND_ATTACH_FS */
785 * service an FSYNC request to take a volume offline.
787 * @param[in] vcom pointer command object
788 * @param[out] res object in which to store response packet
790 * @return operation status
791 * @retval SYNC_OK volume transitioned offline
792 * @retval SYNC_FAILED invalid command protocol message
793 * @retval SYNC_DENIED operation could not be completed
795 * @note this is an FSYNC RPC server stub
797 * @note this procedure handles the following FSSYNC command codes:
799 * - FSYNC_VOL_NEEDVOLUME
801 * @note the supplementary reason code contains additional details.
802 * When SYNC_DENIED is returned, the specific reason is
803 * placed in the response packet reason field.
808 FSYNC_com_VolOff(FSSYNC_VolOp_command * vcom, SYNC_response * res)
810 FSSYNC_VolOp_info info;
811 afs_int32 code = SYNC_OK;
815 #ifdef AFS_DEMAND_ATTACH_FS
816 Volume *nvp, *rvp = NULL;
819 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
820 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
825 /* not already offline, we need to find a slot for newly offline volume */
826 if (vcom->hdr->programType == debugUtility) {
827 /* debug utilities do not have their operations tracked */
831 for (i = 0; i < MAXOFFLINEVOLUMES; i++) {
832 if (vcom->volumes[i].volumeID == 0) {
833 vcom->v = &vcom->volumes[i];
843 FSYNC_com_to_info(vcom, &info);
845 #ifdef AFS_DEMAND_ATTACH_FS
846 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
848 vp = VGetVolume_r(&error, vcom->vop->volume);
852 if (!FSYNC_partMatch(vcom, vp, 1)) {
853 /* volume on desired partition is not online, so we
854 * should treat this as an offline volume.
856 #ifndef AFS_DEMAND_ATTACH_FS
864 #ifdef AFS_DEMAND_ATTACH_FS
866 ProgramType type = (ProgramType) vcom->hdr->programType;
868 /* do initial filtering of requests */
870 /* enforce mutual exclusion for volume ops */
871 if (vp->pending_vol_op) {
872 if (vp->pending_vol_op->com.programType != type) {
873 if (vp->pending_vol_op->com.command == FSYNC_VOL_OFF &&
874 vp->pending_vol_op->com.reason == FSYNC_SALVAGE) {
876 Log("denying offline request for volume %lu; volume is salvaging\n",
877 afs_printable_uint32_lu(vp->hashid));
879 res->hdr.reason = FSYNC_SALVAGE;
882 Log("volume %u already checked out\n", vp->hashid);
884 Log("vp->vop = { com = { ver=%u, prog=%d, com=%d, reason=%d, len=%u, flags=0x%x }, vop = { vol=%u, part='%s' } }\n",
885 vp->pending_vol_op->com.proto_version,
886 vp->pending_vol_op->com.programType,
887 vp->pending_vol_op->com.command,
888 vp->pending_vol_op->com.reason,
889 vp->pending_vol_op->com.command_len,
890 vp->pending_vol_op->com.flags,
891 vp->pending_vol_op->vop.volume,
892 vp->pending_vol_op->vop.partName );
893 Log("vcom = { com = { ver=%u, prog=%d, com=%d, reason=%d, len=%u, flags=0x%x } , vop = { vol=%u, part='%s' } }\n",
894 vcom->hdr->proto_version,
895 vcom->hdr->programType,
898 vcom->hdr->command_len,
901 vcom->vop->partName);
902 res->hdr.reason = FSYNC_EXCLUSIVE;
905 Log("warning: volume %u recursively checked out by programType id %d\n",
906 vp->hashid, vcom->hdr->programType);
910 /* wait for exclusive ops, so we have an accurate picture of the
911 * vol attach state */
912 VCreateReservation_r(vp);
913 VWaitExclusiveState_r(vp);
916 /* filter based upon requestor
918 * volume utilities / volserver are not allowed to check out
919 * volumes which are in an error state
921 * unknown utility programs will be denied on principal
925 /* it is possible for the salvageserver to checkout a
926 * volume for salvage before its scheduling request
927 * has been sent to the salvageserver */
928 if (vp->salvage.requested && !vp->salvage.scheduled) {
929 vp->salvage.scheduled = 1;
936 if (V_attachState(vp) == VOL_STATE_SALVAGING ||
937 vp->salvage.requested) {
939 Log("denying offline request for volume %lu; volume is in salvaging state\n",
940 afs_printable_uint32_lu(vp->hashid));
941 res->hdr.reason = FSYNC_SALVAGE;
943 /* the volume hasn't been checked out yet by the salvager,
944 * but we think the volume is salvaging; schedule a
945 * a salvage to update the salvage priority */
946 FSYNC_backgroundSalvage(vp);
950 if (VIsErrorState(V_attachState(vp))) {
956 Log("bad program type passed to FSSYNC\n");
960 /* short circuit for offline volume states
961 * so we can avoid I/O penalty of attachment */
962 switch (V_attachState(vp)) {
963 case VOL_STATE_UNATTACHED:
964 case VOL_STATE_PREATTACHED:
965 case VOL_STATE_SALVAGING:
966 case VOL_STATE_ERROR:
967 /* register the volume operation metadata with the volume
969 * if the volume is currently pre-attached, attach2()
970 * will evaluate the vol op metadata to determine whether
971 * attaching the volume would be safe */
972 VRegisterVolOp_r(vp, &info);
973 vp->pending_vol_op->vol_op_state = FSSYNC_VolOpRunningUnknown;
979 /* convert to heavyweight ref */
980 nvp = VGetVolumeByVp_r(&error, vp);
981 VCancelReservation_r(rvp);
986 * It's possible for VGetVolumeByVp_r to have dropped and
987 * re-acquired VOL_LOCK, so volume state may have changed
988 * back to one of the states we tested for above. Since
989 * GetVolume can return NULL in some of those states, just
990 * test for the states again here.
992 switch (V_attachState(vp)) {
993 case VOL_STATE_UNATTACHED:
994 case VOL_STATE_PREATTACHED:
995 case VOL_STATE_SALVAGING:
996 case VOL_STATE_ERROR:
997 /* register the volume operation metadata with the volume
999 * if the volume is currently pre-attached, attach2()
1000 * will evaluate the vol op metadata to determine whether
1001 * attaching the volume would be safe */
1002 VRegisterVolOp_r(vp, &info);
1003 vp->pending_vol_op->vol_op_state = FSSYNC_VolOpRunningUnknown;
1009 Log("FSYNC_com_VolOff: failed to get heavyweight reference to volume %u\n",
1011 res->hdr.reason = FSYNC_VOL_PKG_ERROR;
1013 } else if (nvp != vp) {
1014 /* i don't think this should ever happen, but just in case... */
1015 Log("FSYNC_com_VolOff: warning: potentially dangerous race detected\n");
1019 /* register the volume operation metadata with the volume */
1020 VRegisterVolOp_r(vp, &info);
1023 #endif /* AFS_DEMAND_ATTACH_FS */
1026 if (VVolOpLeaveOnline_r(vp, &info)) {
1027 VUpdateVolume_r(&error, vp, VOL_UPDATE_WAIT); /* At least get volume stats right */
1029 Log("FSYNC: Volume %u (%s) was left on line for an external %s request\n",
1030 V_id(vp), V_name(vp),
1031 vcom->hdr->reason == V_CLONE ? "clone" :
1032 vcom->hdr->reason == V_READONLY ? "readonly" :
1033 vcom->hdr->reason == V_DUMP ? "dump" :
1034 vcom->hdr->reason == FSYNC_SALVAGE ? "salvage" :
1037 #ifdef AFS_DEMAND_ATTACH_FS
1038 vp->pending_vol_op->vol_op_state = FSSYNC_VolOpRunningOnline;
1042 if (VVolOpSetVBusy_r(vp, &info)) {
1043 vp->specialStatus = VBUSY;
1046 /* remember what volume we got, so we can keep track of how
1047 * many volumes the volserver or whatever is using. Note that
1048 * vp is valid since leaveonline is only set when vp is valid.
1051 vcom->v->volumeID = vcom->vop->volume;
1052 strlcpy(vcom->v->partName, vp->partition->name, sizeof(vcom->v->partName));
1055 #ifdef AFS_DEMAND_ATTACH_FS
1056 VOfflineForVolOp_r(&error, vp, "A volume utility is running.");
1058 assert(vp->nUsers==0);
1059 vp->pending_vol_op->vol_op_state = FSSYNC_VolOpRunningOffline;
1062 VDeregisterVolOp_r(vp);
1066 VOffline_r(vp, "A volume utility is running.");
1077 #ifdef AFS_DEMAND_ATTACH_FS
1079 VCancelReservation_r(rvp);
1086 * service an FSYNC request to mark a volume as moved.
1088 * @param[in] vcom pointer command object
1089 * @param[out] res object in which to store response packet
1091 * @return operation status
1092 * @retval SYNC_OK volume marked as moved to a remote server
1093 * @retval SYNC_FAILED invalid command protocol message
1094 * @retval SYNC_DENIED current volume state does not permit this operation
1096 * @note this is an FSYNC RPC server stub
1098 * @note this operation also breaks all callbacks for the given volume
1100 * @note this procedure handles the following FSSYNC command codes:
1103 * @note the supplementary reason code contains additional details. For
1104 * instance, SYNC_OK is still returned when the partition specified
1105 * does not match the one registered in the volume object -- reason
1106 * will be FSYNC_WRONG_PART in this case.
1111 FSYNC_com_VolMove(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1113 afs_int32 code = SYNC_DENIED;
1117 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1118 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1123 /* Yuch: the "reason" for the move is the site it got moved to... */
1124 /* still set specialStatus so we stop sending back VBUSY.
1125 * also should still break callbacks. Note that I don't know
1126 * how to tell if we should break all or not, so we just do it
1127 * since it doesn't matter much if we do an extra break
1128 * volume callbacks on a volume move within the same server */
1129 #ifdef AFS_DEMAND_ATTACH_FS
1130 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
1132 vp = VGetVolume_r(&error, vcom->vop->volume);
1135 if (FSYNC_partMatch(vcom, vp, 1)) {
1136 #ifdef AFS_DEMAND_ATTACH_FS
1137 if ((V_attachState(vp) == VOL_STATE_UNATTACHED) ||
1138 (V_attachState(vp) == VOL_STATE_PREATTACHED)) {
1141 vp->specialStatus = VMOVED;
1142 #ifdef AFS_DEMAND_ATTACH_FS
1144 res->hdr.reason = FSYNC_BAD_STATE;
1148 res->hdr.reason = FSYNC_WRONG_PART;
1150 #ifndef AFS_DEMAND_ATTACH_FS
1152 #endif /* !AFS_DEMAND_ATTACH_FS */
1154 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1157 if ((code == SYNC_OK) && (V_BreakVolumeCallbacks != NULL)) {
1158 Log("fssync: volume %u moved to %x; breaking all call backs\n",
1159 vcom->vop->volume, vcom->hdr->reason);
1161 (*V_BreakVolumeCallbacks) (vcom->vop->volume);
1171 * service an FSYNC request to mark a volume as destroyed.
1173 * @param[in] vcom pointer command object
1174 * @param[out] res object in which to store response packet
1176 * @return operation status
1177 * @retval SYNC_OK volume marked as destroyed
1178 * @retval SYNC_FAILED invalid command protocol message
1179 * @retval SYNC_DENIED current volume state does not permit this operation
1181 * @note this is an FSYNC RPC server stub
1183 * @note this procedure handles the following FSSYNC command codes:
1186 * @note the supplementary reason code contains additional details. For
1187 * instance, SYNC_OK is still returned when the partition specified
1188 * does not match the one registered in the volume object -- reason
1189 * will be FSYNC_WRONG_PART in this case.
1194 FSYNC_com_VolDone(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1196 afs_int32 code = SYNC_FAILED;
1200 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1201 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1205 /* don't try to put online, this call is made only after deleting
1206 * a volume, in which case we want to remove the vol # from the
1207 * OfflineVolumes array only */
1209 vcom->v->volumeID = 0;
1211 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
1213 if (FSYNC_partMatch(vcom, vp, 1)) {
1214 #ifdef AFS_DEMAND_ATTACH_FS
1215 if ((V_attachState(vp) == VOL_STATE_UNATTACHED) ||
1216 (V_attachState(vp) == VOL_STATE_PREATTACHED)) {
1218 /* Change state to DELETED, not UNATTACHED, so clients get
1219 * a VNOVOL error when they try to access from now on. */
1221 VChangeState_r(vp, VOL_STATE_DELETED);
1222 VDeregisterVolOp_r(vp);
1224 /* Someday we should free the vp, too, after about 2 hours,
1225 * possibly by putting the vp back on the VLRU. */
1230 res->hdr.reason = FSYNC_BAD_STATE;
1232 #else /* AFS_DEMAND_ATTACH_FS */
1233 if (!vp->specialStatus) {
1234 vp->specialStatus = VNOVOL;
1237 #endif /* !AFS_DEMAND_ATTACH_FS */
1239 code = SYNC_OK; /* XXX is this really a good idea? */
1240 res->hdr.reason = FSYNC_WRONG_PART;
1243 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1250 #ifdef AFS_DEMAND_ATTACH_FS
1252 * service an FSYNC request to transition a volume to the hard error state.
1254 * @param[in] vcom pointer command object
1255 * @param[out] res object in which to store response packet
1257 * @return operation status
1258 * @retval SYNC_OK volume transitioned to hard error state
1259 * @retval SYNC_FAILED invalid command protocol message
1260 * @retval SYNC_DENIED (see note)
1262 * @note this is an FSYNC RPC server stub
1264 * @note this procedure handles the following FSSYNC command codes:
1265 * - FSYNC_VOL_FORCE_ERROR
1267 * @note SYNC_DENIED is returned in the following cases:
1268 * - no partition name is specified (reason field set to
1269 * FSYNC_WRONG_PART).
1270 * - volume id not known to fileserver (reason field set
1271 * to FSYNC_UNKNOWN_VOLID).
1273 * @note demand attach fileserver only
1278 FSYNC_com_VolError(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1282 afs_int32 code = SYNC_FAILED;
1284 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1285 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1289 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
1291 if (!vp && vcom->hdr->reason == FSYNC_SALVAGE) {
1292 /* The requested volume doesn't seem to exist. However, it is possible
1293 * that this is triggered by trying to create or clone a volume that
1294 * was prevented from succeeding by a half-created volume in the way.
1295 * (e.g. we tried to create volume X, but volume X exists except that
1296 * its .vol header was deleted for some reason) So, still try to
1297 * a salvage for that volume ID. */
1299 Log("FSYNC_com_VolError: attempting to schedule salvage for unknown "
1300 "volume %lu part %s\n", afs_printable_uint32_lu(vcom->vop->volume),
1301 vcom->vop->partName);
1302 vp = VPreAttachVolumeById_r(&error, vcom->vop->partName,
1307 if (FSYNC_partMatch(vcom, vp, 0)) {
1308 /* null out salvsync control state, as it's no longer relevant */
1309 memset(&vp->salvage, 0, sizeof(vp->salvage));
1310 VDeregisterVolOp_r(vp);
1312 if (vcom->hdr->reason == FSYNC_SALVAGE) {
1313 FSYNC_backgroundSalvage(vp);
1315 VChangeState_r(vp, VOL_STATE_ERROR);
1320 res->hdr.reason = FSYNC_WRONG_PART;
1323 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1329 #endif /* AFS_DEMAND_ATTACH_FS */
1332 * service an FSYNC request to break all callbacks for this volume.
1334 * @param[in] vcom pointer command object
1335 * @param[out] res object in which to store response packet
1337 * @return operation status
1338 * @retval SYNC_OK callback breaks scheduled for volume
1340 * @note this is an FSYNC RPC server stub
1342 * @note this procedure handles the following FSSYNC command codes:
1343 * - FSYNC_VOL_BREAKCBKS
1345 * @note demand attach fileserver only
1347 * @todo should do partition matching
1352 FSYNC_com_VolBreakCBKs(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1354 /* if the volume is being restored, break all callbacks on it */
1355 if (V_BreakVolumeCallbacks) {
1356 Log("fssync: breaking all call backs for volume %u\n",
1359 (*V_BreakVolumeCallbacks) (vcom->vop->volume);
1366 * service an FSYNC request to return the Volume object.
1368 * @param[in] vcom pointer command object
1369 * @param[out] res object in which to store response packet
1371 * @return operation status
1372 * @retval SYNC_OK volume object returned to caller
1373 * @retval SYNC_FAILED bad command packet, or failed to locate volume object
1375 * @note this is an FSYNC RPC server stub
1377 * @note this procedure handles the following FSSYNC command codes:
1383 FSYNC_com_VolQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1385 afs_int32 code = SYNC_FAILED;
1389 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1390 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1394 #ifdef AFS_DEMAND_ATTACH_FS
1395 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
1396 #else /* !AFS_DEMAND_ATTACH_FS */
1397 vp = VGetVolume_r(&error, vcom->vop->volume);
1398 #endif /* !AFS_DEMAND_ATTACH_FS */
1401 if (FSYNC_partMatch(vcom, vp, 1)) {
1402 if (res->payload.len >= sizeof(Volume)) {
1403 memcpy(res->payload.buf, vp, sizeof(Volume));
1404 res->hdr.response_len += sizeof(Volume);
1407 res->hdr.reason = SYNC_REASON_PAYLOAD_TOO_BIG;
1410 res->hdr.reason = FSYNC_WRONG_PART;
1412 #ifndef AFS_DEMAND_ATTACH_FS
1416 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1424 * service an FSYNC request to return the Volume header.
1426 * @param[in] vcom pointer command object
1427 * @param[out] res object in which to store response packet
1429 * @return operation status
1430 * @retval SYNC_OK volume header returned to caller
1431 * @retval SYNC_FAILED bad command packet, or failed to locate volume header
1433 * @note this is an FSYNC RPC server stub
1435 * @note this procedure handles the following FSSYNC command codes:
1436 * - FSYNC_VOL_QUERY_HDR
1441 FSYNC_com_VolHdrQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1443 afs_int32 code = SYNC_FAILED;
1447 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1448 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1451 if (res->payload.len < sizeof(VolumeDiskData)) {
1452 res->hdr.reason = SYNC_REASON_PAYLOAD_TOO_BIG;
1456 #ifdef AFS_DEMAND_ATTACH_FS
1457 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
1458 #else /* !AFS_DEMAND_ATTACH_FS */
1459 vp = VGetVolume_r(&error, vcom->vop->volume);
1463 if (FSYNC_partMatch(vcom, vp, 1)) {
1464 #ifdef AFS_DEMAND_ATTACH_FS
1465 if ((vp->header == NULL) ||
1466 !(V_attachFlags(vp) & VOL_HDR_ATTACHED) ||
1467 !(V_attachFlags(vp) & VOL_HDR_LOADED)) {
1468 res->hdr.reason = FSYNC_HDR_NOT_ATTACHED;
1471 #else /* !AFS_DEMAND_ATTACH_FS */
1472 if (!vp || !vp->header) {
1473 res->hdr.reason = FSYNC_HDR_NOT_ATTACHED;
1476 #endif /* !AFS_DEMAND_ATTACH_FS */
1478 res->hdr.reason = FSYNC_WRONG_PART;
1482 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1486 memcpy(res->payload.buf, &V_disk(vp), sizeof(VolumeDiskData));
1487 res->hdr.response_len += sizeof(VolumeDiskData);
1491 #ifndef AFS_DEMAND_ATTACH_FS
1499 #ifdef AFS_DEMAND_ATTACH_FS
1501 FSYNC_com_VolOpQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1503 afs_int32 code = SYNC_OK;
1507 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
1509 if (vp && vp->pending_vol_op) {
1510 assert(sizeof(FSSYNC_VolOp_info) <= res->payload.len);
1511 memcpy(res->payload.buf, vp->pending_vol_op, sizeof(FSSYNC_VolOp_info));
1512 res->hdr.response_len += sizeof(FSSYNC_VolOp_info);
1515 res->hdr.reason = FSYNC_NO_PENDING_VOL_OP;
1517 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1525 FSYNC_com_VGQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1527 afs_int32 code = SYNC_FAILED;
1529 struct DiskPartition64 * dp;
1531 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1532 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1536 dp = VGetPartition_r(vcom->vop->partName, 0);
1538 res->hdr.reason = FSYNC_BAD_PART;
1542 assert(sizeof(FSSYNC_VGQry_response_t) <= res->payload.len);
1544 rc = VVGCache_query_r(dp, vcom->vop->volume, res->payload.buf);
1547 res->hdr.response_len += sizeof(FSSYNC_VGQry_response_t);
1551 res->hdr.reason = FSYNC_PART_SCANNING;
1554 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1565 FSYNC_com_VGUpdate(osi_socket fd, SYNC_command * com, SYNC_response * res)
1567 afs_int32 code = SYNC_FAILED;
1568 struct DiskPartition64 * dp;
1569 FSSYNC_VGUpdate_command_t * vgucom;
1572 if (com->recv_len != (sizeof(com->hdr) + sizeof(*vgucom))) {
1573 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1574 res->hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
1575 code = SYNC_COM_ERROR;
1579 vgucom = com->payload.buf;
1581 ViceLog(125, ("FSYNC_com_VGUpdate: fd %d got command for parent %lu child "
1582 "%lu partName %.16s\n", (int)fd,
1583 afs_printable_uint32_lu(vgucom->parent),
1584 afs_printable_uint32_lu(vgucom->child),
1587 if (SYNC_verifyProtocolString(vgucom->partName, sizeof(vgucom->partName))) {
1588 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1592 dp = VGetPartition_r(vgucom->partName, 0);
1594 res->hdr.reason = FSYNC_BAD_PART;
1598 switch(com->hdr.command) {
1600 rc = VVGCache_entry_add_r(dp, vgucom->parent, vgucom->child, NULL);
1604 rc = VVGCache_entry_del_r(dp, vgucom->parent, vgucom->child);
1608 Log("FSYNC_com_VGUpdate called improperly\n");
1613 /* EINVAL means the partition VGC doesn't exist at all; not really
1615 if (rc == 0 || rc == EINVAL) {
1620 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1622 res->hdr.reason = FSYNC_WHATEVER;
1630 FSYNC_com_VGScan(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1632 afs_int32 code = SYNC_FAILED;
1633 struct DiskPartition64 * dp;
1635 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1636 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1640 dp = VGetPartition_r(vcom->vop->partName, 0);
1642 res->hdr.reason = FSYNC_BAD_PART;
1646 if (VVGCache_scanStart_r(dp) == 0) {
1655 FSYNC_com_VGScanAll(FSSYNC_VolOp_command * com, SYNC_response * res)
1657 afs_int32 code = SYNC_FAILED;
1659 if (VVGCache_scanStart_r(NULL) == 0) {
1665 #endif /* AFS_DEMAND_ATTACH_FS */
1668 FSYNC_com_VnQry(osi_socket fd, SYNC_command * com, SYNC_response * res)
1670 afs_int32 code = SYNC_OK;
1671 FSSYNC_VnQry_hdr * qry = com->payload.buf;
1676 if (com->recv_len != (sizeof(com->hdr) + sizeof(FSSYNC_VnQry_hdr))) {
1677 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1678 res->hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
1679 return SYNC_COM_ERROR;
1682 ViceLog(125, ("FSYNC_com_VnQry: fd %d got command for vol %lu vnode %lu "
1683 "uniq %lu spare %lu partName %.16s\n", (int)fd,
1684 afs_printable_uint32_lu(qry->volume),
1685 afs_printable_uint32_lu(qry->vnode),
1686 afs_printable_uint32_lu(qry->unique),
1687 afs_printable_uint32_lu(qry->spare),
1690 #ifdef AFS_DEMAND_ATTACH_FS
1691 vp = VLookupVolume_r(&error, qry->volume, NULL);
1692 #else /* !AFS_DEMAND_ATTACH_FS */
1693 vp = VGetVolume_r(&error, qry->volume);
1694 #endif /* !AFS_DEMAND_ATTACH_FS */
1697 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1702 vnp = VLookupVnode(vp, qry->vnode);
1704 res->hdr.reason = FSYNC_UNKNOWN_VNID;
1709 if (Vn_class(vnp)->residentSize > res->payload.len) {
1710 res->hdr.reason = SYNC_REASON_ENCODING_ERROR;
1715 memcpy(res->payload.buf, vnp, Vn_class(vnp)->residentSize);
1716 res->hdr.response_len += Vn_class(vnp)->residentSize;
1719 #ifndef AFS_DEMAND_ATTACH_FS
1728 FSYNC_com_StatsOp(osi_socket fd, SYNC_command * com, SYNC_response * res)
1730 afs_int32 code = SYNC_OK;
1731 FSSYNC_StatsOp_command scom;
1733 if (com->recv_len != (sizeof(com->hdr) + sizeof(FSSYNC_StatsOp_hdr))) {
1734 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1735 res->hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
1736 return SYNC_COM_ERROR;
1739 scom.hdr = &com->hdr;
1740 scom.sop = (FSSYNC_StatsOp_hdr *) com->payload.buf;
1743 ViceLog(125, ("FSYNC_com_StatsOp: fd %d got command for stats: "
1744 "{vlru_generation = %lu, hash_bucket = %lu, partName = "
1745 "%.16s}\n", (int)fd,
1746 afs_printable_uint32_lu(scom.sop->args.vlru_generation),
1747 afs_printable_uint32_lu(scom.sop->args.hash_bucket),
1748 scom.sop->args.partName));
1750 switch (com->hdr.command) {
1751 case FSYNC_VOL_STATS_GENERAL:
1752 code = FSYNC_com_StatsOpGeneral(&scom, res);
1754 #ifdef AFS_DEMAND_ATTACH_FS
1755 /* statistics for the following subsystems are only tracked
1756 * for demand attach fileservers */
1757 case FSYNC_VOL_STATS_VICEP:
1758 code = FSYNC_com_StatsOpViceP(&scom, res);
1760 case FSYNC_VOL_STATS_HASH:
1761 code = FSYNC_com_StatsOpHash(&scom, res);
1763 case FSYNC_VOL_STATS_HDR:
1764 code = FSYNC_com_StatsOpHdr(&scom, res);
1766 case FSYNC_VOL_STATS_VLRU:
1767 code = FSYNC_com_StatsOpVLRU(&scom, res);
1769 #endif /* AFS_DEMAND_ATTACH_FS */
1771 code = SYNC_BAD_COMMAND;
1778 FSYNC_com_StatsOpGeneral(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1780 afs_int32 code = SYNC_OK;
1782 memcpy(res->payload.buf, &VStats, sizeof(VStats));
1783 res->hdr.response_len += sizeof(VStats);
1788 #ifdef AFS_DEMAND_ATTACH_FS
1790 FSYNC_com_StatsOpViceP(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1792 afs_int32 code = SYNC_OK;
1793 struct DiskPartition64 * dp;
1794 struct DiskPartitionStats64 * stats;
1796 if (SYNC_verifyProtocolString(scom->sop->args.partName, sizeof(scom->sop->args.partName))) {
1797 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1802 dp = VGetPartition_r(scom->sop->args.partName, 0);
1806 stats = (struct DiskPartitionStats64 *) res->payload.buf;
1807 stats->free = dp->free;
1808 stats->totalUsable = dp->totalUsable;
1809 stats->minFree = dp->minFree;
1810 stats->f_files = dp->f_files;
1811 stats->vol_list_len = dp->vol_list.len;
1813 res->hdr.response_len += sizeof(struct DiskPartitionStats64);
1821 FSYNC_com_StatsOpHash(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1823 afs_int32 code = SYNC_OK;
1824 struct VolumeHashChainStats * stats;
1825 struct VolumeHashChainHead * head;
1827 if (scom->sop->args.hash_bucket >= VolumeHashTable.Size) {
1831 head = &VolumeHashTable.Table[scom->sop->args.hash_bucket];
1832 stats = (struct VolumeHashChainStats *) res->payload.buf;
1833 stats->table_size = VolumeHashTable.Size;
1834 stats->chain_len = head->len;
1835 stats->chain_cacheCheck = head->cacheCheck;
1836 stats->chain_busy = head->busy;
1837 AssignInt64(head->looks, &stats->chain_looks);
1838 AssignInt64(head->gets, &stats->chain_gets);
1839 AssignInt64(head->reorders, &stats->chain_reorders);
1841 res->hdr.response_len += sizeof(struct VolumeHashChainStats);
1847 FSYNC_com_StatsOpHdr(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1849 afs_int32 code = SYNC_OK;
1851 memcpy(res->payload.buf, &volume_hdr_LRU.stats, sizeof(volume_hdr_LRU.stats));
1852 res->hdr.response_len += sizeof(volume_hdr_LRU.stats);
1858 FSYNC_com_StatsOpVLRU(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1860 afs_int32 code = SYNC_OK;
1862 code = SYNC_BAD_COMMAND;
1866 #endif /* AFS_DEMAND_ATTACH_FS */
1869 * populate an FSSYNC_VolOp_info object from a command packet object.
1871 * @param[in] vcom pointer to command packet
1872 * @param[out] info pointer to info object which will be populated
1874 * @note FSSYNC_VolOp_info objects are attached to Volume objects when
1875 * a volume operation is commenced.
1880 FSYNC_com_to_info(FSSYNC_VolOp_command * vcom, FSSYNC_VolOp_info * info)
1882 memcpy(&info->com, vcom->hdr, sizeof(SYNC_command_hdr));
1883 memcpy(&info->vop, vcom->vop, sizeof(FSSYNC_VolOp_hdr));
1884 info->vol_op_state = FSSYNC_VolOpPending;
1888 * check whether command packet partition name matches volume
1889 * object's partition name.
1891 * @param[in] vcom pointer to command packet
1892 * @param[in] vp pointer to volume object
1893 * @param[in] match_anon anon matching control flag (see note below)
1895 * @return whether partitions match
1896 * @retval 0 partitions do NOT match
1897 * @retval 1 partitions match
1899 * @note if match_anon is non-zero, then this function will return a
1900 * positive match for a zero-length partition string in the
1906 FSYNC_partMatch(FSSYNC_VolOp_command * vcom, Volume * vp, int match_anon)
1908 return ((match_anon && vcom->vop->partName[0] == 0) ||
1909 (strncmp(vcom->vop->partName, V_partition(vp)->name,
1910 sizeof(vcom->vop->partName)) == 0));
1915 FSYNC_Drop(osi_socket fd)
1917 struct offlineInfo *p;
1920 char tvolName[VMAXPATHLEN];
1923 p = OfflineVolumes[FindHandler(fd)];
1924 for (i = 0; i < MAXOFFLINEVOLUMES; i++) {
1925 if (p[i].volumeID) {
1930 sprintf(&tvolName[1], VFORMAT, afs_printable_uint32_lu(p[i].volumeID));
1931 vp = VAttachVolumeByName_r(&error, p[i].partName, tvolName,
1948 static int AcceptHandler = -1; /* handler id for accept, if turned on */
1953 if (AcceptHandler == -1) {
1954 assert(AddHandler(fssync_server_state.fd, FSYNC_newconnection));
1955 AcceptHandler = FindHandler(fssync_server_state.fd);
1962 if (AcceptHandler != -1) {
1963 assert(RemoveHandler(fssync_server_state.fd));
1968 /* The multiple FD handling code. */
1970 static osi_socket HandlerFD[MAXHANDLERS];
1971 static void (*HandlerProc[MAXHANDLERS]) (osi_socket);
1977 ObtainWriteLock(&FSYNC_handler_lock);
1978 for (i = 0; i < MAXHANDLERS; i++) {
1982 ReleaseWriteLock(&FSYNC_handler_lock);
1985 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
1987 CallHandler(struct pollfd *fds, int nfds, int mask)
1991 ObtainReadLock(&FSYNC_handler_lock);
1992 for (i = 0; i < nfds; i++) {
1993 if (fds[i].revents & mask) {
1994 handler = FindHandler_r(fds[i].fd);
1995 ReleaseReadLock(&FSYNC_handler_lock);
1996 (*HandlerProc[handler]) (fds[i].fd);
1997 ObtainReadLock(&FSYNC_handler_lock);
2000 ReleaseReadLock(&FSYNC_handler_lock);
2004 CallHandler(fd_set * fdsetp)
2007 ObtainReadLock(&FSYNC_handler_lock);
2008 for (i = 0; i < MAXHANDLERS; i++) {
2009 if (HandlerFD[i] >= 0 && FD_ISSET(HandlerFD[i], fdsetp)) {
2010 ReleaseReadLock(&FSYNC_handler_lock);
2011 (*HandlerProc[i]) (HandlerFD[i]);
2012 ObtainReadLock(&FSYNC_handler_lock);
2015 ReleaseReadLock(&FSYNC_handler_lock);
2020 AddHandler(osi_socket afd, void (*aproc) (osi_socket))
2023 ObtainWriteLock(&FSYNC_handler_lock);
2024 for (i = 0; i < MAXHANDLERS; i++)
2025 if (HandlerFD[i] == -1)
2027 if (i >= MAXHANDLERS) {
2028 ReleaseWriteLock(&FSYNC_handler_lock);
2032 HandlerProc[i] = aproc;
2033 ReleaseWriteLock(&FSYNC_handler_lock);
2038 FindHandler(osi_socket afd)
2041 ObtainReadLock(&FSYNC_handler_lock);
2042 for (i = 0; i < MAXHANDLERS; i++)
2043 if (HandlerFD[i] == afd) {
2044 ReleaseReadLock(&FSYNC_handler_lock);
2047 ReleaseReadLock(&FSYNC_handler_lock); /* just in case */
2049 return -1; /* satisfy compiler */
2053 FindHandler_r(osi_socket afd)
2056 for (i = 0; i < MAXHANDLERS; i++)
2057 if (HandlerFD[i] == afd) {
2061 return -1; /* satisfy compiler */
2065 RemoveHandler(osi_socket afd)
2067 ObtainWriteLock(&FSYNC_handler_lock);
2068 HandlerFD[FindHandler_r(afd)] = -1;
2069 ReleaseWriteLock(&FSYNC_handler_lock);
2073 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
2075 GetHandler(struct pollfd *fds, int maxfds, int events, int *nfds)
2079 ObtainReadLock(&FSYNC_handler_lock);
2080 for (i = 0; i < MAXHANDLERS; i++)
2081 if (HandlerFD[i] != -1) {
2083 fds[fdi].fd = HandlerFD[i];
2084 fds[fdi].events = events;
2085 fds[fdi].revents = 0;
2089 ReleaseReadLock(&FSYNC_handler_lock);
2093 GetHandler(fd_set * fdsetp, int *maxfdp)
2098 ObtainReadLock(&FSYNC_handler_lock); /* just in case */
2099 for (i = 0; i < MAXHANDLERS; i++)
2100 if (HandlerFD[i] != -1) {
2101 FD_SET(HandlerFD[i], fdsetp);
2102 #ifndef AFS_NT40_ENV
2103 /* On Windows the nfds parameter to select() is ignored */
2104 if (maxfd < HandlerFD[i] || maxfd == (int)-1)
2105 maxfd = HandlerFD[i];
2106 #endif /* AFS_NT40_ENV */
2109 ReleaseReadLock(&FSYNC_handler_lock); /* just in case */
2111 #endif /* HAVE_POLL && AFS_PTHREAD_ENV */
2113 #endif /* FSSYNC_BUILD_SERVER */