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>
48 #include <sys/types.h>
57 #include <sys/param.h>
58 #include <sys/socket.h>
59 #include <netinet/in.h>
65 #include <afs/afs_assert.h>
70 #include <afs/afsint.h>
72 #include <afs/errors.h>
73 #include "daemon_com.h"
74 #include "daemon_com_inline.h"
76 #include "fssync_inline.h"
80 #include <afs/afssyscalls.h>
84 #include "volume_inline.h"
85 #include "partition.h"
91 #endif /* HAVE_POLL */
93 #ifdef USE_UNIX_SOCKETS
95 #include <afs/afsutil.h>
96 #endif /* USE_UNIX_SOCKETS */
98 #ifdef FSSYNC_BUILD_SERVER
100 int (*V_BreakVolumeCallbacks) (VolumeId volume);
102 #define MAXHANDLERS 4 /* Up to 4 clients; must be at least 2, so that
103 * move = dump+restore can run on single server */
104 #define MAXOFFLINEVOLUMES 128 /* This needs to be as big as the maximum
105 * number that would be offline for 1 operation.
106 * Current winner is salvage, which needs all
107 * cloned read-only copies offline when salvaging
108 * a single read-write volume */
112 static struct offlineInfo OfflineVolumes[MAXHANDLERS][MAXOFFLINEVOLUMES];
115 * fssync server socket handle.
117 static SYNC_server_state_t fssync_server_state =
118 { OSI_NULLSOCKET, /* file descriptor */
119 FSSYNC_ENDPOINT_DECL, /* server endpoint */
120 FSYNC_PROTO_VERSION, /* protocol version */
121 5, /* bind() retry limit */
122 100, /* listen() queue depth */
123 "FSSYNC", /* protocol name string */
126 #ifdef AFS_DEMAND_ATTACH_FS
128 * a queue of volume pointers to salvage in the background.
130 struct fsync_salv_node {
132 Volume *vp; /**< volume to salvage */
133 unsigned char update_salv_prio; /**< whether we should update the salvage priority or not */
136 struct rx_queue head;
140 static void * FSYNC_salvageThread(void *);
141 static void FSYNC_backgroundSalvage(Volume *vp);
142 #endif /* AFS_DEMAND_ATTACH_FS */
144 /* Forward declarations */
145 static void * FSYNC_sync(void *);
146 static void FSYNC_newconnection(osi_socket afd);
147 static void FSYNC_com(osi_socket fd);
148 static void FSYNC_Drop(osi_socket fd);
149 static void AcceptOn(void);
150 static void AcceptOff(void);
151 static void InitHandler(void);
152 static int AddHandler(osi_socket fd, void (*aproc)(osi_socket));
153 static int FindHandler(osi_socket afd);
154 static int FindHandler_r(osi_socket afd);
155 static int RemoveHandler(osi_socket afd);
156 #if defined(HAVE_POLL) && defined (AFS_PTHREAD_ENV)
157 static void CallHandler(struct pollfd *fds, int nfds, int mask);
158 static void GetHandler(struct pollfd *fds, int maxfds, int events, int *nfds);
160 static void CallHandler(fd_set * fdsetp);
161 static void GetHandler(fd_set * fdsetp, int *maxfdp);
165 static afs_int32 FSYNC_com_VolOp(osi_socket fd, SYNC_command * com, SYNC_response * res);
167 #ifdef AFS_DEMAND_ATTACH_FS
168 static afs_int32 FSYNC_com_VolError(FSSYNC_VolOp_command * com, SYNC_response * res);
170 static afs_int32 FSYNC_com_VolOn(FSSYNC_VolOp_command * com, SYNC_response * res);
171 static afs_int32 FSYNC_com_VolOff(FSSYNC_VolOp_command * com, SYNC_response * res);
172 static afs_int32 FSYNC_com_VolMove(FSSYNC_VolOp_command * com, SYNC_response * res);
173 static afs_int32 FSYNC_com_VolBreakCBKs(FSSYNC_VolOp_command * com, SYNC_response * res);
174 static afs_int32 FSYNC_com_VolDone(FSSYNC_VolOp_command * com, SYNC_response * res);
175 static afs_int32 FSYNC_com_VolQuery(FSSYNC_VolOp_command * com, SYNC_response * res);
176 static afs_int32 FSYNC_com_VolHdrQuery(FSSYNC_VolOp_command * com, SYNC_response * res);
177 #ifdef AFS_DEMAND_ATTACH_FS
178 static afs_int32 FSYNC_com_VGUpdate(osi_socket fd, SYNC_command * com, SYNC_response * res);
179 static afs_int32 FSYNC_com_VolOpQuery(FSSYNC_VolOp_command * com, SYNC_response * res);
180 static afs_int32 FSYNC_com_VGQuery(FSSYNC_VolOp_command * com, SYNC_response * res);
181 static afs_int32 FSYNC_com_VGScan(FSSYNC_VolOp_command * com, SYNC_response * res);
182 static afs_int32 FSYNC_com_VGScanAll(FSSYNC_VolOp_command * com, SYNC_response * res);
183 #endif /* AFS_DEMAND_ATTACH_FS */
185 static afs_int32 FSYNC_com_VnQry(osi_socket fd, SYNC_command * com, SYNC_response * res);
187 static afs_int32 FSYNC_com_StatsOp(osi_socket fd, SYNC_command * com, SYNC_response * res);
189 static afs_int32 FSYNC_com_StatsOpGeneral(FSSYNC_StatsOp_command * scom, SYNC_response * res);
191 #ifdef AFS_DEMAND_ATTACH_FS
192 static afs_int32 FSYNC_com_StatsOpViceP(FSSYNC_StatsOp_command * scom, SYNC_response * res);
193 static afs_int32 FSYNC_com_StatsOpHash(FSSYNC_StatsOp_command * scom, SYNC_response * res);
194 static afs_int32 FSYNC_com_StatsOpHdr(FSSYNC_StatsOp_command * scom, SYNC_response * res);
195 static afs_int32 FSYNC_com_StatsOpVLRU(FSSYNC_StatsOp_command * scom, SYNC_response * res);
198 static void FSYNC_com_to_info(FSSYNC_VolOp_command * vcom, FSSYNC_VolOp_info * info);
200 static int FSYNC_partMatch(FSSYNC_VolOp_command * vcom, Volume * vp, int match_anon);
204 * This lock controls access to the handler array. The overhead
205 * is minimal in non-preemptive environments.
207 struct Lock FSYNC_handler_lock;
212 #ifdef AFS_PTHREAD_ENV
214 pthread_attr_t tattr;
215 #else /* AFS_PTHREAD_ENV */
217 #endif /* AFS_PTHREAD_ENV */
219 Lock_Init(&FSYNC_handler_lock);
221 #ifdef AFS_PTHREAD_ENV
222 osi_Assert(pthread_attr_init(&tattr) == 0);
223 osi_Assert(pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED) == 0);
224 osi_Assert(pthread_create(&tid, &tattr, FSYNC_sync, NULL) == 0);
225 #else /* AFS_PTHREAD_ENV */
226 osi_Assert(LWP_CreateProcess
227 (FSYNC_sync, USUAL_STACK_SIZE, USUAL_PRIORITY, (void *)0,
228 "FSYNC_sync", &pid) == LWP_SUCCESS);
229 #endif /* AFS_PTHREAD_ENV */
231 #ifdef AFS_DEMAND_ATTACH_FS
232 queue_Init(&fsync_salv.head);
233 CV_INIT(&fsync_salv.cv, "fsync salv", CV_DEFAULT, 0);
234 osi_Assert(pthread_create(&tid, &tattr, FSYNC_salvageThread, NULL) == 0);
235 #endif /* AFS_DEMAND_ATTACH_FS */
238 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
239 static struct pollfd FSYNC_readfds[MAXHANDLERS];
241 static fd_set FSYNC_readfds;
246 FSYNC_sync(void * args)
250 #ifdef AFS_PTHREAD_ENV
253 SYNC_server_state_t * state = &fssync_server_state;
254 #ifdef AFS_DEMAND_ATTACH_FS
255 VThreadOptions_t * thread_opts;
259 * For non-DAFS, only wait until we begin attaching volumes (instead
260 * of waiting until all volumes are attached), since it can take
261 * awhile until VInit == 2.
264 #endif /* AFS_DEMAND_ATTACH_FS */
266 /* we must not be called before vol package initialization, since we use
267 * vol package mutexes and conds etc */
270 SYNC_getAddr(&state->endpoint, &state->addr);
271 SYNC_cleanupSock(state);
274 (void)signal(SIGPIPE, SIG_IGN);
277 #ifdef AFS_PTHREAD_ENV
278 /* set our 'thread-id' so that the host hold table works */
279 tid = rx_NewThreadId();
280 pthread_setspecific(rx_thread_id_key, (void *)(intptr_t)tid);
281 Log("Set thread id %d for FSYNC_sync\n", tid);
282 #endif /* AFS_PTHREAD_ENV */
286 while (VInit < min_vinit) {
287 /* Let somebody else run until all volumes have been preattached
288 * (DAFS), or we have started attaching volumes (non-DAFS). This
289 * doesn't mean that all volumes have been attached.
291 #ifdef AFS_PTHREAD_ENV
292 VOL_CV_WAIT(&vol_vinit_cond);
293 #else /* AFS_PTHREAD_ENV */
294 LWP_DispatchProcess();
295 #endif /* AFS_PTHREAD_ENV */
300 state->fd = SYNC_getSock(&state->endpoint);
301 code = SYNC_bindSock(state);
304 #ifdef AFS_DEMAND_ATTACH_FS
306 * make sure the volume package is incapable of recursively executing
307 * salvsync calls on this thread, since there is a possibility of
310 thread_opts = malloc(sizeof(VThreadOptions_t));
311 if (thread_opts == NULL) {
312 Log("failed to allocate memory for thread-specific volume package options structure\n");
315 memcpy(thread_opts, &VThread_defaults, sizeof(VThread_defaults));
316 thread_opts->disallow_salvsync = 1;
317 osi_Assert(pthread_setspecific(VThread_key, thread_opts) == 0);
319 code = VVGCache_PkgInit();
320 osi_Assert(code == 0);
327 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
329 GetHandler(FSYNC_readfds, MAXHANDLERS, POLLIN|POLLPRI, &nfds);
330 if (poll(FSYNC_readfds, nfds, -1) >=1)
331 CallHandler(FSYNC_readfds, nfds, POLLIN|POLLPRI);
334 GetHandler(&FSYNC_readfds, &maxfd);
335 /* Note: check for >= 1 below is essential since IOMGR_select
336 * doesn't have exactly same semantics as select.
338 #ifdef AFS_PTHREAD_ENV
339 if (select(maxfd + 1, &FSYNC_readfds, NULL, NULL, NULL) >= 1)
340 #else /* AFS_PTHREAD_ENV */
341 if (IOMGR_Select(maxfd + 1, &FSYNC_readfds, NULL, NULL, NULL) >= 1)
342 #endif /* AFS_PTHREAD_ENV */
343 CallHandler(&FSYNC_readfds);
346 return NULL; /* hush now, little gcc */
349 #ifdef AFS_DEMAND_ATTACH_FS
351 * thread for salvaging volumes in the background.
353 * Since FSSYNC handlers cannot issue SALVSYNC requests in order to avoid
354 * deadlock issues, this thread exists so code in the FSSYNC handler thread
355 * can hand off volumes to be salvaged in the background.
357 * @param[in] args unused
359 * @note DEMAND_ATTACH_FS only
362 FSYNC_salvageThread(void * args)
365 struct fsync_salv_node *node;
370 while (queue_IsEmpty(&fsync_salv.head)) {
371 VOL_CV_WAIT(&fsync_salv.cv);
374 node = queue_First(&fsync_salv.head, fsync_salv_node);
378 if (node->update_salv_prio) {
379 if (VUpdateSalvagePriority_r(vp)) {
380 ViceLog(0, ("FSYNC_salvageThread: unable to raise salvage priority "
381 "for volume %lu\n", afs_printable_uint32_lu(vp->hashid)));
388 VCancelReservation_r(vp);
397 * salvage a volume in the background.
399 * Salvages cannot be scheduled directly from the main FSYNC thread, so
400 * instead call this function to schedule a salvage asynchronously in the
401 * FSYNC_salvageThread thread.
403 * @param[in] vp volume to pointer to salvage
407 * @note DEMAND_ATTACH_FS only
410 FSYNC_backgroundSalvage(Volume *vp)
412 struct fsync_salv_node *node;
415 VCreateReservation_r(vp);
417 node = malloc(sizeof(struct fsync_salv_node));
420 /* Save this value, to know if we should VUpdateSalvagePriority_r.
421 * We need to save it here, snce VRequestSalvage_r will change it. */
422 node->update_salv_prio = vp->salvage.requested;
424 if (VRequestSalvage_r(&ec, vp, SALVSYNC_ERROR, 0)) {
425 ViceLog(0, ("FSYNC_backgroundSalvage: unable to request salvage for volume %lu\n",
426 afs_printable_uint32_lu(vp->hashid)));
429 queue_Append(&fsync_salv.head, node);
430 CV_BROADCAST(&fsync_salv.cv);
432 #endif /* AFS_DEMAND_ATTACH_FS */
435 FSYNC_newconnection(osi_socket afd)
437 #ifdef USE_UNIX_SOCKETS
438 struct sockaddr_un other;
439 #else /* USE_UNIX_SOCKETS */
440 struct sockaddr_in other;
444 junk = sizeof(other);
445 fd = accept(afd, (struct sockaddr *)&other, &junk);
446 if (fd == OSI_NULLSOCKET) {
447 Log("FSYNC_newconnection: accept failed, errno==%d\n", errno);
449 } else if (!AddHandler(fd, FSYNC_com)) {
451 osi_Assert(AddHandler(fd, FSYNC_com));
455 /* this function processes commands from an fssync file descriptor (fd) */
456 afs_int32 FS_cnt = 0;
458 FSYNC_com(osi_socket fd)
462 SYNC_PROTO_BUF_DECL(com_buf);
463 SYNC_PROTO_BUF_DECL(res_buf);
465 memset(&res.hdr, 0, sizeof(res.hdr));
467 com.payload.buf = (void *)com_buf;
468 com.payload.len = SYNC_PROTO_MAX_LEN;
469 res.hdr.response_len = sizeof(res.hdr);
470 res.payload.len = SYNC_PROTO_MAX_LEN;
471 res.payload.buf = (void *)res_buf;
474 if (SYNC_getCom(&fssync_server_state, fd, &com)) {
475 Log("FSYNC_com: read failed; dropping connection (cnt=%d)\n", FS_cnt);
480 if (com.recv_len < sizeof(com.hdr)) {
481 Log("FSSYNC_com: invalid protocol message length (%u)\n", com.recv_len);
482 res.hdr.response = SYNC_COM_ERROR;
483 res.hdr.reason = SYNC_REASON_MALFORMED_PACKET;
484 res.hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
488 if (com.hdr.proto_version != FSYNC_PROTO_VERSION) {
489 Log("FSYNC_com: invalid protocol version (%u)\n", com.hdr.proto_version);
490 res.hdr.response = SYNC_COM_ERROR;
491 res.hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
495 if (com.hdr.command == SYNC_COM_CHANNEL_CLOSE) {
496 res.hdr.response = SYNC_OK;
497 res.hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
499 /* don't respond, just drop; senders of SYNC_COM_CHANNEL_CLOSE
500 * never wait for a response. */
504 ViceLog(125, ("FSYNC_com: from fd %d got command %ld (%s) reason %ld (%s) "
505 "pt %ld (%s) pid %ld\n", (int)fd,
506 afs_printable_int32_ld(com.hdr.command),
507 FSYNC_com2string(com.hdr.command),
508 afs_printable_int32_ld(com.hdr.reason),
509 FSYNC_reason2string(com.hdr.reason),
510 afs_printable_int32_ld(com.hdr.programType),
511 VPTypeToString(com.hdr.programType),
512 afs_printable_int32_ld(com.hdr.pid)));
514 res.hdr.com_seq = com.hdr.com_seq;
517 switch (com.hdr.command) {
519 case FSYNC_VOL_ATTACH:
520 case FSYNC_VOL_LEAVE_OFF:
522 case FSYNC_VOL_FORCE_ERROR:
523 case FSYNC_VOL_LISTVOLUMES:
524 case FSYNC_VOL_NEEDVOLUME:
526 case FSYNC_VOL_BREAKCBKS:
528 case FSYNC_VOL_QUERY:
529 case FSYNC_VOL_QUERY_HDR:
530 #ifdef AFS_DEMAND_ATTACH_FS
531 case FSYNC_VOL_QUERY_VOP:
534 case FSYNC_VG_SCAN_ALL:
536 res.hdr.response = FSYNC_com_VolOp(fd, &com, &res);
538 case FSYNC_VOL_STATS_GENERAL:
539 case FSYNC_VOL_STATS_VICEP:
540 case FSYNC_VOL_STATS_HASH:
541 case FSYNC_VOL_STATS_HDR:
542 case FSYNC_VOL_STATS_VLRU:
543 res.hdr.response = FSYNC_com_StatsOp(fd, &com, &res);
545 case FSYNC_VOL_QUERY_VNODE:
546 res.hdr.response = FSYNC_com_VnQry(fd, &com, &res);
548 #ifdef AFS_DEMAND_ATTACH_FS
551 res.hdr.response = FSYNC_com_VGUpdate(fd, &com, &res);
555 res.hdr.response = SYNC_BAD_COMMAND;
560 ViceLog(125, ("FSYNC_com: fd %d responding with code %ld (%s) reason %ld "
562 afs_printable_int32_ld(res.hdr.response),
563 SYNC_res2string(res.hdr.response),
564 afs_printable_int32_ld(res.hdr.reason),
565 FSYNC_reason2string(res.hdr.reason)));
568 SYNC_putRes(&fssync_server_state, fd, &res);
571 if (res.hdr.flags & SYNC_FLAG_CHANNEL_SHUTDOWN) {
577 FSYNC_com_VolOp(osi_socket fd, SYNC_command * com, SYNC_response * res)
580 afs_int32 code = SYNC_OK;
581 FSSYNC_VolOp_command vcom;
583 if (com->recv_len != (sizeof(com->hdr) + sizeof(FSSYNC_VolOp_hdr))) {
584 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
585 res->hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
586 return SYNC_COM_ERROR;
589 vcom.hdr = &com->hdr;
590 vcom.vop = (FSSYNC_VolOp_hdr *) com->payload.buf;
593 vcom.volumes = OfflineVolumes[FindHandler(fd)];
594 for (vcom.v = NULL, i = 0; i < MAXOFFLINEVOLUMES; i++) {
595 if ((vcom.volumes[i].volumeID == vcom.vop->volume) &&
596 (strncmp(vcom.volumes[i].partName, vcom.vop->partName,
597 sizeof(vcom.volumes[i].partName)) == 0)) {
598 vcom.v = &vcom.volumes[i];
603 ViceLog(125, ("FSYNC_com_VolOp: fd %d got command for vol %lu part %.16s\n",
604 (int)fd, afs_printable_uint32_lu(vcom.vop->volume),
605 vcom.vop->partName));
607 switch (com->hdr.command) {
609 case FSYNC_VOL_ATTACH:
610 case FSYNC_VOL_LEAVE_OFF:
611 code = FSYNC_com_VolOn(&vcom, res);
614 case FSYNC_VOL_NEEDVOLUME:
615 code = FSYNC_com_VolOff(&vcom, res);
617 case FSYNC_VOL_LISTVOLUMES:
621 code = FSYNC_com_VolMove(&vcom, res);
623 case FSYNC_VOL_BREAKCBKS:
624 code = FSYNC_com_VolBreakCBKs(&vcom, res);
627 code = FSYNC_com_VolDone(&vcom, res);
629 case FSYNC_VOL_QUERY:
630 code = FSYNC_com_VolQuery(&vcom, res);
632 case FSYNC_VOL_QUERY_HDR:
633 code = FSYNC_com_VolHdrQuery(&vcom, res);
635 #ifdef AFS_DEMAND_ATTACH_FS
636 case FSYNC_VOL_FORCE_ERROR:
637 code = FSYNC_com_VolError(&vcom, res);
639 case FSYNC_VOL_QUERY_VOP:
640 code = FSYNC_com_VolOpQuery(&vcom, res);
643 code = FSYNC_com_VGQuery(&vcom, res);
646 code = FSYNC_com_VGScan(&vcom, res);
648 case FSYNC_VG_SCAN_ALL:
649 code = FSYNC_com_VGScanAll(&vcom, res);
651 #endif /* AFS_DEMAND_ATTACH_FS */
653 code = SYNC_BAD_COMMAND;
660 * service an FSYNC request to bring a volume online.
662 * @param[in] vcom pointer command object
663 * @param[out] res object in which to store response packet
665 * @return operation status
666 * @retval SYNC_OK volume transitioned online
667 * @retval SYNC_FAILED invalid command protocol message
668 * @retval SYNC_DENIED operation could not be completed
670 * @note this is an FSYNC RPC server stub
672 * @note this procedure handles the following FSSYNC command codes:
675 * - FSYNC_VOL_LEAVE_OFF
677 * @note the supplementary reason code contains additional details.
678 * When SYNC_DENIED is returned, the specific reason is
679 * placed in the response packet reason field.
684 FSYNC_com_VolOn(FSSYNC_VolOp_command * vcom, SYNC_response * res)
686 afs_int32 code = SYNC_OK;
687 #ifndef AFS_DEMAND_ATTACH_FS
688 char tvolName[VMAXPATHLEN];
693 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
694 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
699 /* so, we need to attach the volume */
701 #ifdef AFS_DEMAND_ATTACH_FS
702 /* check DAFS permissions */
703 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
705 FSYNC_partMatch(vcom, vp, 1) &&
706 vp->pending_vol_op &&
707 (vcom->hdr->programType != vp->pending_vol_op->com.programType)) {
708 /* a different program has this volume checked out. deny. */
709 Log("FSYNC_VolOn: WARNING: program type %u has attempted to manipulate "
710 "state for volume %u using command code %u while the volume is "
711 "checked out by program type %u for command code %u.\n",
712 vcom->hdr->programType,
715 vp->pending_vol_op->com.programType,
716 vp->pending_vol_op->com.command);
718 res->hdr.reason = FSYNC_EXCLUSIVE;
724 vcom->v->volumeID = 0;
727 if (vcom->hdr->command == FSYNC_VOL_LEAVE_OFF) {
728 /* nothing much to do if we're leaving the volume offline */
729 #ifdef AFS_DEMAND_ATTACH_FS
731 VCreateReservation_r(vp);
732 VWaitExclusiveState_r(vp);
734 if (vp && V_attachState(vp) != VOL_STATE_DELETED) {
735 if (FSYNC_partMatch(vcom, vp, 1)) {
736 if ((V_attachState(vp) == VOL_STATE_UNATTACHED) ||
737 (V_attachState(vp) == VOL_STATE_PREATTACHED)) {
738 VChangeState_r(vp, VOL_STATE_UNATTACHED);
739 VDeregisterVolOp_r(vp);
742 res->hdr.reason = FSYNC_BAD_STATE;
746 res->hdr.reason = FSYNC_WRONG_PART;
750 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
754 VCancelReservation_r(vp);
761 #ifdef AFS_DEMAND_ATTACH_FS
762 /* first, check to see whether we have such a volume defined */
763 vp = VPreAttachVolumeById_r(&error,
767 VCreateReservation_r(vp);
768 VWaitExclusiveState_r(vp);
769 VDeregisterVolOp_r(vp);
770 VCancelReservation_r(vp);
773 #else /* !AFS_DEMAND_ATTACH_FS */
774 tvolName[0] = OS_DIRSEPC;
775 snprintf(&tvolName[1], sizeof(tvolName)-1, VFORMAT, afs_printable_uint32_lu(vcom->vop->volume));
776 tvolName[sizeof(tvolName)-1] = '\0';
778 vp = VAttachVolumeByName_r(&error, vcom->vop->partName, tvolName,
784 res->hdr.reason = error;
786 #endif /* !AFS_DEMAND_ATTACH_FS */
793 * service an FSYNC request to take a volume offline.
795 * @param[in] vcom pointer command object
796 * @param[out] res object in which to store response packet
798 * @return operation status
799 * @retval SYNC_OK volume transitioned offline
800 * @retval SYNC_FAILED invalid command protocol message
801 * @retval SYNC_DENIED operation could not be completed
803 * @note this is an FSYNC RPC server stub
805 * @note this procedure handles the following FSSYNC command codes:
807 * - FSYNC_VOL_NEEDVOLUME
809 * @note the supplementary reason code contains additional details.
810 * When SYNC_DENIED is returned, the specific reason is
811 * placed in the response packet reason field.
816 FSYNC_com_VolOff(FSSYNC_VolOp_command * vcom, SYNC_response * res)
818 FSSYNC_VolOp_info info;
819 afs_int32 code = SYNC_OK;
823 #ifdef AFS_DEMAND_ATTACH_FS
824 Volume *nvp, *rvp = NULL;
827 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
828 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
833 /* not already offline, we need to find a slot for newly offline volume */
834 if (vcom->hdr->programType == debugUtility) {
835 /* debug utilities do not have their operations tracked */
839 for (i = 0; i < MAXOFFLINEVOLUMES; i++) {
840 if (vcom->volumes[i].volumeID == 0) {
841 vcom->v = &vcom->volumes[i];
851 FSYNC_com_to_info(vcom, &info);
853 #ifdef AFS_DEMAND_ATTACH_FS
854 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
856 vp = VGetVolume_r(&error, vcom->vop->volume);
860 if (!FSYNC_partMatch(vcom, vp, 1)) {
861 /* volume on desired partition is not online, so we
862 * should treat this as an offline volume.
864 #ifndef AFS_DEMAND_ATTACH_FS
872 #ifdef AFS_DEMAND_ATTACH_FS
874 ProgramType type = (ProgramType) vcom->hdr->programType;
876 /* do initial filtering of requests */
878 /* enforce mutual exclusion for volume ops */
879 if (vp->pending_vol_op) {
880 if (vp->pending_vol_op->com.programType != type) {
881 if (vp->pending_vol_op->com.command == FSYNC_VOL_OFF &&
882 vp->pending_vol_op->com.reason == FSYNC_SALVAGE) {
884 Log("denying offline request for volume %lu; volume is salvaging\n",
885 afs_printable_uint32_lu(vp->hashid));
887 res->hdr.reason = FSYNC_SALVAGE;
890 Log("volume %u already checked out\n", vp->hashid);
892 Log("vp->vop = { com = { ver=%u, prog=%d, com=%d, reason=%d, len=%u, flags=0x%x }, vop = { vol=%u, part='%s' } }\n",
893 vp->pending_vol_op->com.proto_version,
894 vp->pending_vol_op->com.programType,
895 vp->pending_vol_op->com.command,
896 vp->pending_vol_op->com.reason,
897 vp->pending_vol_op->com.command_len,
898 vp->pending_vol_op->com.flags,
899 vp->pending_vol_op->vop.volume,
900 vp->pending_vol_op->vop.partName );
901 Log("vcom = { com = { ver=%u, prog=%d, com=%d, reason=%d, len=%u, flags=0x%x } , vop = { vol=%u, part='%s' } }\n",
902 vcom->hdr->proto_version,
903 vcom->hdr->programType,
906 vcom->hdr->command_len,
909 vcom->vop->partName);
910 res->hdr.reason = FSYNC_EXCLUSIVE;
913 Log("warning: volume %u recursively checked out by programType id %d\n",
914 vp->hashid, vcom->hdr->programType);
918 /* wait for exclusive ops, so we have an accurate picture of the
919 * vol attach state */
920 VCreateReservation_r(vp);
921 VWaitExclusiveState_r(vp);
924 /* filter based upon requestor
926 * volume utilities / volserver are not allowed to check out
927 * volumes which are in an error state
929 * unknown utility programs will be denied on principal
934 /* it is possible for the salvageserver to checkout a
935 * volume for salvage before its scheduling request
936 * has been sent to the salvageserver */
937 if (vp->salvage.requested && !vp->salvage.scheduled) {
938 vp->salvage.scheduled = 1;
941 /* If the volume is in VOL_STATE_SALVAGE_REQ, we need to wait
942 * for the vol to go offline before we can give it away. Also
943 * make sure we don't come out with vp in an excl state. */
944 while (V_attachState(vp) == VOL_STATE_SALVAGE_REQ ||
945 VIsExclusiveState(V_attachState(vp))) {
947 VOL_CV_WAIT(&V_attachCV(vp));
955 if (VIsSalvaging(vp)) {
956 Log("denying offline request for volume %lu; volume is in salvaging state\n",
957 afs_printable_uint32_lu(vp->hashid));
958 res->hdr.reason = FSYNC_SALVAGE;
960 /* the volume hasn't been checked out yet by the salvager,
961 * but we think the volume is salvaging; schedule a
962 * a salvage to update the salvage priority */
963 FSYNC_backgroundSalvage(vp);
967 if (VIsErrorState(V_attachState(vp))) {
973 Log("bad program type passed to FSSYNC\n");
977 /* short circuit for offline volume states
978 * so we can avoid I/O penalty of attachment */
979 switch (V_attachState(vp)) {
980 case VOL_STATE_UNATTACHED:
981 case VOL_STATE_PREATTACHED:
982 case VOL_STATE_SALVAGING:
983 case VOL_STATE_ERROR:
984 /* register the volume operation metadata with the volume
986 * if the volume is currently pre-attached, attach2()
987 * will evaluate the vol op metadata to determine whether
988 * attaching the volume would be safe */
989 VRegisterVolOp_r(vp, &info);
990 vp->pending_vol_op->vol_op_state = FSSYNC_VolOpRunningUnknown;
993 case VOL_STATE_DELETED:
999 /* convert to heavyweight ref */
1000 nvp = VGetVolumeByVp_r(&error, vp);
1003 * It's possible for VGetVolumeByVp_r to have dropped and
1004 * re-acquired VOL_LOCK, so volume state may have changed
1005 * back to one of the states we tested for above. Since
1006 * GetVolume can return NULL in some of those states, just
1007 * test for the states again here.
1009 switch (V_attachState(vp)) {
1010 case VOL_STATE_UNATTACHED:
1011 case VOL_STATE_PREATTACHED:
1012 case VOL_STATE_SALVAGING:
1013 case VOL_STATE_ERROR:
1014 /* register the volume operation metadata with the volume
1016 * if the volume is currently pre-attached, attach2()
1017 * will evaluate the vol op metadata to determine whether
1018 * attaching the volume would be safe */
1019 VRegisterVolOp_r(vp, &info);
1020 vp->pending_vol_op->vol_op_state = FSSYNC_VolOpRunningUnknown;
1023 case VOL_STATE_DELETED:
1029 Log("FSYNC_com_VolOff: failed to get heavyweight reference to volume %u (state=%u, flags=0x%x)\n",
1030 vcom->vop->volume, V_attachState(vp), V_attachFlags(vp));
1031 res->hdr.reason = FSYNC_VOL_PKG_ERROR;
1033 } else if (nvp != vp) {
1034 /* i don't think this should ever happen, but just in case... */
1035 Log("FSYNC_com_VolOff: warning: potentially dangerous race detected\n");
1039 /* kill off lightweight ref to ensure we can't deadlock against ourselves later... */
1040 VCancelReservation_r(rvp);
1043 /* register the volume operation metadata with the volume */
1044 VRegisterVolOp_r(vp, &info);
1047 #endif /* AFS_DEMAND_ATTACH_FS */
1050 if (VVolOpLeaveOnline_r(vp, &info)) {
1051 VUpdateVolume_r(&error, vp, VOL_UPDATE_WAIT); /* At least get volume stats right */
1053 Log("FSYNC: Volume %u (%s) was left on line for an external %s request\n",
1054 V_id(vp), V_name(vp),
1055 vcom->hdr->reason == V_CLONE ? "clone" :
1056 vcom->hdr->reason == V_READONLY ? "readonly" :
1057 vcom->hdr->reason == V_DUMP ? "dump" :
1058 vcom->hdr->reason == FSYNC_SALVAGE ? "salvage" :
1061 #ifdef AFS_DEMAND_ATTACH_FS
1062 vp->pending_vol_op->vol_op_state = FSSYNC_VolOpRunningOnline;
1066 if (VVolOpSetVBusy_r(vp, &info)) {
1067 vp->specialStatus = VBUSY;
1070 /* remember what volume we got, so we can keep track of how
1071 * many volumes the volserver or whatever is using. Note that
1072 * vp is valid since leaveonline is only set when vp is valid.
1075 vcom->v->volumeID = vcom->vop->volume;
1076 strlcpy(vcom->v->partName, vp->partition->name, sizeof(vcom->v->partName));
1079 #ifdef AFS_DEMAND_ATTACH_FS
1080 VCreateReservation_r(vp);
1081 VOfflineForVolOp_r(&error, vp, "A volume utility is running.");
1083 osi_Assert(vp->nUsers==0);
1084 vp->pending_vol_op->vol_op_state = FSSYNC_VolOpRunningOffline;
1087 VWaitExclusiveState_r(vp);
1088 VDeregisterVolOp_r(vp);
1091 VCancelReservation_r(vp);
1093 VOffline_r(vp, "A volume utility is running.");
1104 #ifdef AFS_DEMAND_ATTACH_FS
1106 VCancelReservation_r(rvp);
1113 * service an FSYNC request to mark a volume as moved.
1115 * @param[in] vcom pointer command object
1116 * @param[out] res object in which to store response packet
1118 * @return operation status
1119 * @retval SYNC_OK volume marked as moved to a remote server
1120 * @retval SYNC_FAILED invalid command protocol message
1121 * @retval SYNC_DENIED current volume state does not permit this operation
1123 * @note this is an FSYNC RPC server stub
1125 * @note this operation also breaks all callbacks for the given volume
1127 * @note this procedure handles the following FSSYNC command codes:
1130 * @note the supplementary reason code contains additional details. For
1131 * instance, SYNC_OK is still returned when the partition specified
1132 * does not match the one registered in the volume object -- reason
1133 * will be FSYNC_WRONG_PART in this case.
1138 FSYNC_com_VolMove(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1140 afs_int32 code = SYNC_DENIED;
1144 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1145 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1150 /* Yuch: the "reason" for the move is the site it got moved to... */
1151 /* still set specialStatus so we stop sending back VBUSY.
1152 * also should still break callbacks. Note that I don't know
1153 * how to tell if we should break all or not, so we just do it
1154 * since it doesn't matter much if we do an extra break
1155 * volume callbacks on a volume move within the same server */
1156 #ifdef AFS_DEMAND_ATTACH_FS
1157 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
1159 vp = VGetVolume_r(&error, vcom->vop->volume);
1162 if (FSYNC_partMatch(vcom, vp, 1)) {
1163 #ifdef AFS_DEMAND_ATTACH_FS
1164 if ((V_attachState(vp) == VOL_STATE_UNATTACHED) ||
1165 (V_attachState(vp) == VOL_STATE_PREATTACHED)) {
1168 vp->specialStatus = VMOVED;
1169 #ifdef AFS_DEMAND_ATTACH_FS
1171 res->hdr.reason = FSYNC_BAD_STATE;
1175 res->hdr.reason = FSYNC_WRONG_PART;
1177 #ifndef AFS_DEMAND_ATTACH_FS
1179 #endif /* !AFS_DEMAND_ATTACH_FS */
1181 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1184 if ((code == SYNC_OK) && (V_BreakVolumeCallbacks != NULL)) {
1185 Log("fssync: volume %u moved to %x; breaking all call backs\n",
1186 vcom->vop->volume, vcom->hdr->reason);
1188 (*V_BreakVolumeCallbacks) (vcom->vop->volume);
1198 * service an FSYNC request to mark a volume as destroyed.
1200 * @param[in] vcom pointer command object
1201 * @param[out] res object in which to store response packet
1203 * @return operation status
1204 * @retval SYNC_OK volume marked as destroyed
1205 * @retval SYNC_FAILED invalid command protocol message
1206 * @retval SYNC_DENIED current volume state does not permit this operation
1208 * @note this is an FSYNC RPC server stub
1210 * @note this procedure handles the following FSSYNC command codes:
1213 * @note the supplementary reason code contains additional details. For
1214 * instance, SYNC_OK is still returned when the partition specified
1215 * does not match the one registered in the volume object -- reason
1216 * will be FSYNC_WRONG_PART in this case.
1221 FSYNC_com_VolDone(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1223 afs_int32 code = SYNC_FAILED;
1227 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1228 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1232 /* don't try to put online, this call is made only after deleting
1233 * a volume, in which case we want to remove the vol # from the
1234 * OfflineVolumes array only */
1236 vcom->v->volumeID = 0;
1238 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
1240 if (FSYNC_partMatch(vcom, vp, 1)) {
1241 #ifdef AFS_DEMAND_ATTACH_FS
1242 VCreateReservation_r(vp);
1243 VWaitExclusiveState_r(vp);
1245 if ((V_attachState(vp) == VOL_STATE_UNATTACHED) ||
1246 (V_attachState(vp) == VOL_STATE_PREATTACHED) ||
1247 VIsErrorState(V_attachState(vp))) {
1249 /* Change state to DELETED, not UNATTACHED, so clients get
1250 * a VNOVOL error when they try to access from now on. */
1252 VChangeState_r(vp, VOL_STATE_DELETED);
1253 VDeregisterVolOp_r(vp);
1255 /* Volume is gone; clear out old salvage stats */
1256 memset(&vp->salvage, 0, sizeof(vp->salvage));
1258 /* Someday we should free the vp, too, after about 2 hours,
1259 * possibly by putting the vp back on the VLRU. */
1262 } else if (V_attachState(vp) == VOL_STATE_DELETED) {
1263 VDeregisterVolOp_r(vp);
1264 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1268 res->hdr.reason = FSYNC_BAD_STATE;
1271 VCancelReservation_r(vp);
1273 #else /* AFS_DEMAND_ATTACH_FS */
1274 if (!vp->specialStatus) {
1275 vp->specialStatus = VNOVOL;
1278 #endif /* !AFS_DEMAND_ATTACH_FS */
1280 code = SYNC_OK; /* XXX is this really a good idea? */
1281 res->hdr.reason = FSYNC_WRONG_PART;
1284 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1291 #ifdef AFS_DEMAND_ATTACH_FS
1293 * service an FSYNC request to transition a volume to the hard error state.
1295 * @param[in] vcom pointer command object
1296 * @param[out] res object in which to store response packet
1298 * @return operation status
1299 * @retval SYNC_OK volume transitioned to hard error state
1300 * @retval SYNC_FAILED invalid command protocol message
1301 * @retval SYNC_DENIED (see note)
1303 * @note this is an FSYNC RPC server stub
1305 * @note this procedure handles the following FSSYNC command codes:
1306 * - FSYNC_VOL_FORCE_ERROR
1308 * @note SYNC_DENIED is returned in the following cases:
1309 * - no partition name is specified (reason field set to
1310 * FSYNC_WRONG_PART).
1311 * - volume id not known to fileserver (reason field set
1312 * to FSYNC_UNKNOWN_VOLID).
1314 * @note demand attach fileserver only
1319 FSYNC_com_VolError(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1323 afs_int32 code = SYNC_FAILED;
1325 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1326 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1330 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
1332 if (!vp && vcom->hdr->reason == FSYNC_SALVAGE) {
1333 /* The requested volume doesn't seem to exist. However, it is possible
1334 * that this is triggered by trying to create or clone a volume that
1335 * was prevented from succeeding by a half-created volume in the way.
1336 * (e.g. we tried to create volume X, but volume X exists except that
1337 * its .vol header was deleted for some reason) So, still try to
1338 * a salvage for that volume ID. */
1340 Log("FSYNC_com_VolError: attempting to schedule salvage for unknown "
1341 "volume %lu part %s\n", afs_printable_uint32_lu(vcom->vop->volume),
1342 vcom->vop->partName);
1343 vp = VPreAttachVolumeById_r(&error, vcom->vop->partName,
1348 if (FSYNC_partMatch(vcom, vp, 0)) {
1349 /* null out salvsync control state, as it's no longer relevant */
1350 memset(&vp->salvage, 0, sizeof(vp->salvage));
1352 VCreateReservation_r(vp);
1353 VWaitExclusiveState_r(vp);
1354 VDeregisterVolOp_r(vp);
1356 if (vcom->hdr->reason == FSYNC_SALVAGE) {
1357 FSYNC_backgroundSalvage(vp);
1359 VChangeState_r(vp, VOL_STATE_ERROR);
1362 VCancelReservation_r(vp);
1367 res->hdr.reason = FSYNC_WRONG_PART;
1370 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1376 #endif /* AFS_DEMAND_ATTACH_FS */
1379 * service an FSYNC request to break all callbacks for this volume.
1381 * @param[in] vcom pointer command object
1382 * @param[out] res object in which to store response packet
1384 * @return operation status
1385 * @retval SYNC_OK callback breaks scheduled for volume
1387 * @note this is an FSYNC RPC server stub
1389 * @note this procedure handles the following FSSYNC command codes:
1390 * - FSYNC_VOL_BREAKCBKS
1392 * @note demand attach fileserver only
1394 * @todo should do partition matching
1399 FSYNC_com_VolBreakCBKs(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1401 /* if the volume is being restored, break all callbacks on it */
1402 if (V_BreakVolumeCallbacks) {
1403 Log("fssync: breaking all call backs for volume %u\n",
1406 (*V_BreakVolumeCallbacks) (vcom->vop->volume);
1413 * service an FSYNC request to return the Volume object.
1415 * @param[in] vcom pointer command object
1416 * @param[out] res object in which to store response packet
1418 * @return operation status
1419 * @retval SYNC_OK volume object returned to caller
1420 * @retval SYNC_FAILED bad command packet, or failed to locate volume object
1422 * @note this is an FSYNC RPC server stub
1424 * @note this procedure handles the following FSSYNC command codes:
1430 FSYNC_com_VolQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1432 afs_int32 code = SYNC_FAILED;
1436 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1437 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1441 #ifdef AFS_DEMAND_ATTACH_FS
1442 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
1443 #else /* !AFS_DEMAND_ATTACH_FS */
1444 vp = VGetVolume_r(&error, vcom->vop->volume);
1445 #endif /* !AFS_DEMAND_ATTACH_FS */
1448 if (FSYNC_partMatch(vcom, vp, 1)) {
1449 if (res->payload.len >= sizeof(Volume)) {
1450 memcpy(res->payload.buf, vp, sizeof(Volume));
1451 res->hdr.response_len += sizeof(Volume);
1454 res->hdr.reason = SYNC_REASON_PAYLOAD_TOO_BIG;
1457 res->hdr.reason = FSYNC_WRONG_PART;
1459 #ifndef AFS_DEMAND_ATTACH_FS
1463 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1471 * service an FSYNC request to return the Volume header.
1473 * @param[in] vcom pointer command object
1474 * @param[out] res object in which to store response packet
1476 * @return operation status
1477 * @retval SYNC_OK volume header returned to caller
1478 * @retval SYNC_FAILED bad command packet, or failed to locate volume header
1480 * @note this is an FSYNC RPC server stub
1482 * @note this procedure handles the following FSSYNC command codes:
1483 * - FSYNC_VOL_QUERY_HDR
1488 FSYNC_com_VolHdrQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1490 afs_int32 code = SYNC_FAILED;
1494 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1495 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1498 if (res->payload.len < sizeof(VolumeDiskData)) {
1499 res->hdr.reason = SYNC_REASON_PAYLOAD_TOO_BIG;
1503 #ifdef AFS_DEMAND_ATTACH_FS
1504 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
1505 #else /* !AFS_DEMAND_ATTACH_FS */
1506 vp = VGetVolume_r(&error, vcom->vop->volume);
1510 if (FSYNC_partMatch(vcom, vp, 1)) {
1511 #ifdef AFS_DEMAND_ATTACH_FS
1512 if ((vp->header == NULL) ||
1513 !(V_attachFlags(vp) & VOL_HDR_ATTACHED) ||
1514 !(V_attachFlags(vp) & VOL_HDR_LOADED)) {
1515 res->hdr.reason = FSYNC_HDR_NOT_ATTACHED;
1518 #else /* !AFS_DEMAND_ATTACH_FS */
1519 if (!vp || !vp->header) {
1520 res->hdr.reason = FSYNC_HDR_NOT_ATTACHED;
1523 #endif /* !AFS_DEMAND_ATTACH_FS */
1525 res->hdr.reason = FSYNC_WRONG_PART;
1529 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1533 memcpy(res->payload.buf, &V_disk(vp), sizeof(VolumeDiskData));
1534 res->hdr.response_len += sizeof(VolumeDiskData);
1538 #ifndef AFS_DEMAND_ATTACH_FS
1546 #ifdef AFS_DEMAND_ATTACH_FS
1548 FSYNC_com_VolOpQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1550 afs_int32 code = SYNC_OK;
1554 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
1557 VCreateReservation_r(vp);
1558 VWaitExclusiveState_r(vp);
1561 if (vp && vp->pending_vol_op) {
1562 if (!FSYNC_partMatch(vcom, vp, 1)) {
1563 res->hdr.reason = FSYNC_WRONG_PART;
1566 osi_Assert(sizeof(FSSYNC_VolOp_info) <= res->payload.len);
1567 memcpy(res->payload.buf, vp->pending_vol_op, sizeof(FSSYNC_VolOp_info));
1568 res->hdr.response_len += sizeof(FSSYNC_VolOp_info);
1571 if (!vp || V_attachState(vp) == VOL_STATE_DELETED) {
1572 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1573 } else if (!FSYNC_partMatch(vcom, vp, 1)) {
1574 res->hdr.reason = FSYNC_WRONG_PART;
1576 res->hdr.reason = FSYNC_NO_PENDING_VOL_OP;
1582 VCancelReservation_r(vp);
1588 FSYNC_com_VGQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1590 afs_int32 code = SYNC_FAILED;
1592 struct DiskPartition64 * dp;
1594 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1595 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1599 dp = VGetPartition_r(vcom->vop->partName, 0);
1601 res->hdr.reason = FSYNC_BAD_PART;
1605 osi_Assert(sizeof(FSSYNC_VGQry_response_t) <= res->payload.len);
1607 rc = VVGCache_query_r(dp, vcom->vop->volume, res->payload.buf);
1610 res->hdr.response_len += sizeof(FSSYNC_VGQry_response_t);
1614 res->hdr.reason = FSYNC_PART_SCANNING;
1617 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1628 FSYNC_com_VGUpdate(osi_socket fd, SYNC_command * com, SYNC_response * res)
1630 afs_int32 code = SYNC_FAILED;
1631 struct DiskPartition64 * dp;
1632 FSSYNC_VGUpdate_command_t * vgucom;
1635 if (com->recv_len != (sizeof(com->hdr) + sizeof(*vgucom))) {
1636 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1637 res->hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
1638 code = SYNC_COM_ERROR;
1642 vgucom = com->payload.buf;
1644 ViceLog(125, ("FSYNC_com_VGUpdate: fd %d got command for parent %lu child "
1645 "%lu partName %.16s\n", (int)fd,
1646 afs_printable_uint32_lu(vgucom->parent),
1647 afs_printable_uint32_lu(vgucom->child),
1650 if (SYNC_verifyProtocolString(vgucom->partName, sizeof(vgucom->partName))) {
1651 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1655 dp = VGetPartition_r(vgucom->partName, 0);
1657 res->hdr.reason = FSYNC_BAD_PART;
1661 switch(com->hdr.command) {
1663 rc = VVGCache_entry_add_r(dp, vgucom->parent, vgucom->child, NULL);
1667 rc = VVGCache_entry_del_r(dp, vgucom->parent, vgucom->child);
1671 Log("FSYNC_com_VGUpdate called improperly\n");
1676 /* EINVAL means the partition VGC doesn't exist at all; not really
1678 if (rc == 0 || rc == EINVAL) {
1683 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1685 res->hdr.reason = FSYNC_WHATEVER;
1693 FSYNC_com_VGScan(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1695 afs_int32 code = SYNC_FAILED;
1696 struct DiskPartition64 * dp;
1698 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1699 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1703 dp = VGetPartition_r(vcom->vop->partName, 0);
1705 res->hdr.reason = FSYNC_BAD_PART;
1709 if (VVGCache_scanStart_r(dp) == 0) {
1718 FSYNC_com_VGScanAll(FSSYNC_VolOp_command * com, SYNC_response * res)
1720 afs_int32 code = SYNC_FAILED;
1722 if (VVGCache_scanStart_r(NULL) == 0) {
1728 #endif /* AFS_DEMAND_ATTACH_FS */
1731 FSYNC_com_VnQry(osi_socket fd, SYNC_command * com, SYNC_response * res)
1733 afs_int32 code = SYNC_OK;
1734 FSSYNC_VnQry_hdr * qry = com->payload.buf;
1739 if (com->recv_len != (sizeof(com->hdr) + sizeof(FSSYNC_VnQry_hdr))) {
1740 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1741 res->hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
1742 return SYNC_COM_ERROR;
1745 ViceLog(125, ("FSYNC_com_VnQry: fd %d got command for vol %lu vnode %lu "
1746 "uniq %lu spare %lu partName %.16s\n", (int)fd,
1747 afs_printable_uint32_lu(qry->volume),
1748 afs_printable_uint32_lu(qry->vnode),
1749 afs_printable_uint32_lu(qry->unique),
1750 afs_printable_uint32_lu(qry->spare),
1753 #ifdef AFS_DEMAND_ATTACH_FS
1754 vp = VLookupVolume_r(&error, qry->volume, NULL);
1755 #else /* !AFS_DEMAND_ATTACH_FS */
1756 vp = VGetVolume_r(&error, qry->volume);
1757 #endif /* !AFS_DEMAND_ATTACH_FS */
1760 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1765 vnp = VLookupVnode(vp, qry->vnode);
1767 res->hdr.reason = FSYNC_UNKNOWN_VNID;
1772 if (Vn_class(vnp)->residentSize > res->payload.len) {
1773 res->hdr.reason = SYNC_REASON_ENCODING_ERROR;
1778 memcpy(res->payload.buf, vnp, Vn_class(vnp)->residentSize);
1779 res->hdr.response_len += Vn_class(vnp)->residentSize;
1782 #ifndef AFS_DEMAND_ATTACH_FS
1791 FSYNC_com_StatsOp(osi_socket fd, SYNC_command * com, SYNC_response * res)
1793 afs_int32 code = SYNC_OK;
1794 FSSYNC_StatsOp_command scom;
1796 if (com->recv_len != (sizeof(com->hdr) + sizeof(FSSYNC_StatsOp_hdr))) {
1797 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1798 res->hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
1799 return SYNC_COM_ERROR;
1802 scom.hdr = &com->hdr;
1803 scom.sop = (FSSYNC_StatsOp_hdr *) com->payload.buf;
1806 ViceLog(125, ("FSYNC_com_StatsOp: fd %d got command for stats: "
1807 "{vlru_generation = %lu, hash_bucket = %lu, partName = "
1808 "%.16s}\n", (int)fd,
1809 afs_printable_uint32_lu(scom.sop->args.vlru_generation),
1810 afs_printable_uint32_lu(scom.sop->args.hash_bucket),
1811 scom.sop->args.partName));
1813 switch (com->hdr.command) {
1814 case FSYNC_VOL_STATS_GENERAL:
1815 code = FSYNC_com_StatsOpGeneral(&scom, res);
1817 #ifdef AFS_DEMAND_ATTACH_FS
1818 /* statistics for the following subsystems are only tracked
1819 * for demand attach fileservers */
1820 case FSYNC_VOL_STATS_VICEP:
1821 code = FSYNC_com_StatsOpViceP(&scom, res);
1823 case FSYNC_VOL_STATS_HASH:
1824 code = FSYNC_com_StatsOpHash(&scom, res);
1826 case FSYNC_VOL_STATS_HDR:
1827 code = FSYNC_com_StatsOpHdr(&scom, res);
1829 case FSYNC_VOL_STATS_VLRU:
1830 code = FSYNC_com_StatsOpVLRU(&scom, res);
1832 #endif /* AFS_DEMAND_ATTACH_FS */
1834 code = SYNC_BAD_COMMAND;
1841 FSYNC_com_StatsOpGeneral(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1843 afs_int32 code = SYNC_OK;
1845 memcpy(res->payload.buf, &VStats, sizeof(VStats));
1846 res->hdr.response_len += sizeof(VStats);
1851 #ifdef AFS_DEMAND_ATTACH_FS
1853 FSYNC_com_StatsOpViceP(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1855 afs_int32 code = SYNC_OK;
1856 struct DiskPartition64 * dp;
1857 struct DiskPartitionStats64 * stats;
1859 if (SYNC_verifyProtocolString(scom->sop->args.partName, sizeof(scom->sop->args.partName))) {
1860 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1865 dp = VGetPartition_r(scom->sop->args.partName, 0);
1869 stats = (struct DiskPartitionStats64 *) res->payload.buf;
1870 stats->free = dp->free;
1871 stats->totalUsable = dp->totalUsable;
1872 stats->minFree = dp->minFree;
1873 stats->f_files = dp->f_files;
1874 stats->vol_list_len = dp->vol_list.len;
1876 res->hdr.response_len += sizeof(struct DiskPartitionStats64);
1884 FSYNC_com_StatsOpHash(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1886 afs_int32 code = SYNC_OK;
1887 struct VolumeHashChainStats * stats;
1888 struct VolumeHashChainHead * head;
1890 if (scom->sop->args.hash_bucket >= VolumeHashTable.Size) {
1894 head = &VolumeHashTable.Table[scom->sop->args.hash_bucket];
1895 stats = (struct VolumeHashChainStats *) res->payload.buf;
1896 stats->table_size = VolumeHashTable.Size;
1897 stats->chain_len = head->len;
1898 stats->chain_cacheCheck = head->cacheCheck;
1899 stats->chain_busy = head->busy;
1900 AssignInt64(head->looks, &stats->chain_looks);
1901 AssignInt64(head->gets, &stats->chain_gets);
1902 AssignInt64(head->reorders, &stats->chain_reorders);
1904 res->hdr.response_len += sizeof(struct VolumeHashChainStats);
1910 FSYNC_com_StatsOpHdr(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1912 afs_int32 code = SYNC_OK;
1914 memcpy(res->payload.buf, &volume_hdr_LRU.stats, sizeof(volume_hdr_LRU.stats));
1915 res->hdr.response_len += sizeof(volume_hdr_LRU.stats);
1921 FSYNC_com_StatsOpVLRU(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1923 afs_int32 code = SYNC_OK;
1925 code = SYNC_BAD_COMMAND;
1929 #endif /* AFS_DEMAND_ATTACH_FS */
1932 * populate an FSSYNC_VolOp_info object from a command packet object.
1934 * @param[in] vcom pointer to command packet
1935 * @param[out] info pointer to info object which will be populated
1937 * @note FSSYNC_VolOp_info objects are attached to Volume objects when
1938 * a volume operation is commenced.
1943 FSYNC_com_to_info(FSSYNC_VolOp_command * vcom, FSSYNC_VolOp_info * info)
1945 memcpy(&info->com, vcom->hdr, sizeof(SYNC_command_hdr));
1946 memcpy(&info->vop, vcom->vop, sizeof(FSSYNC_VolOp_hdr));
1947 info->vol_op_state = FSSYNC_VolOpPending;
1951 * check whether command packet partition name matches volume
1952 * object's partition name.
1954 * @param[in] vcom pointer to command packet
1955 * @param[in] vp pointer to volume object
1956 * @param[in] match_anon anon matching control flag (see note below)
1958 * @return whether partitions match
1959 * @retval 0 partitions do NOT match
1960 * @retval 1 partitions match
1962 * @note if match_anon is non-zero, then this function will return a
1963 * positive match for a zero-length partition string in the
1969 FSYNC_partMatch(FSSYNC_VolOp_command * vcom, Volume * vp, int match_anon)
1971 return ((match_anon && vcom->vop->partName[0] == 0) ||
1972 (strncmp(vcom->vop->partName, V_partition(vp)->name,
1973 sizeof(vcom->vop->partName)) == 0));
1978 FSYNC_Drop(osi_socket fd)
1980 struct offlineInfo *p;
1983 char tvolName[VMAXPATHLEN];
1986 p = OfflineVolumes[FindHandler(fd)];
1987 for (i = 0; i < MAXOFFLINEVOLUMES; i++) {
1988 if (p[i].volumeID) {
1992 tvolName[0] = OS_DIRSEPC;
1993 sprintf(&tvolName[1], VFORMAT, afs_printable_uint32_lu(p[i].volumeID));
1994 vp = VAttachVolumeByName_r(&error, p[i].partName, tvolName,
2011 static int AcceptHandler = -1; /* handler id for accept, if turned on */
2016 if (AcceptHandler == -1) {
2017 osi_Assert(AddHandler(fssync_server_state.fd, FSYNC_newconnection));
2018 AcceptHandler = FindHandler(fssync_server_state.fd);
2025 if (AcceptHandler != -1) {
2026 osi_Assert(RemoveHandler(fssync_server_state.fd));
2031 /* The multiple FD handling code. */
2033 static osi_socket HandlerFD[MAXHANDLERS];
2034 static void (*HandlerProc[MAXHANDLERS]) (osi_socket);
2040 ObtainWriteLock(&FSYNC_handler_lock);
2041 for (i = 0; i < MAXHANDLERS; i++) {
2042 HandlerFD[i] = OSI_NULLSOCKET;
2045 ReleaseWriteLock(&FSYNC_handler_lock);
2048 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
2050 CallHandler(struct pollfd *fds, int nfds, int mask)
2054 ObtainReadLock(&FSYNC_handler_lock);
2055 for (i = 0; i < nfds; i++) {
2056 if (fds[i].revents & mask) {
2057 handler = FindHandler_r(fds[i].fd);
2058 ReleaseReadLock(&FSYNC_handler_lock);
2059 (*HandlerProc[handler]) (fds[i].fd);
2060 ObtainReadLock(&FSYNC_handler_lock);
2063 ReleaseReadLock(&FSYNC_handler_lock);
2067 CallHandler(fd_set * fdsetp)
2070 ObtainReadLock(&FSYNC_handler_lock);
2071 for (i = 0; i < MAXHANDLERS; i++) {
2072 if (HandlerFD[i] >= 0 && FD_ISSET(HandlerFD[i], fdsetp)) {
2073 ReleaseReadLock(&FSYNC_handler_lock);
2074 (*HandlerProc[i]) (HandlerFD[i]);
2075 ObtainReadLock(&FSYNC_handler_lock);
2078 ReleaseReadLock(&FSYNC_handler_lock);
2083 AddHandler(osi_socket afd, void (*aproc) (osi_socket))
2086 ObtainWriteLock(&FSYNC_handler_lock);
2087 for (i = 0; i < MAXHANDLERS; i++)
2088 if (HandlerFD[i] == OSI_NULLSOCKET)
2090 if (i >= MAXHANDLERS) {
2091 ReleaseWriteLock(&FSYNC_handler_lock);
2095 HandlerProc[i] = aproc;
2096 ReleaseWriteLock(&FSYNC_handler_lock);
2101 FindHandler(osi_socket afd)
2104 ObtainReadLock(&FSYNC_handler_lock);
2105 for (i = 0; i < MAXHANDLERS; i++)
2106 if (HandlerFD[i] == afd) {
2107 ReleaseReadLock(&FSYNC_handler_lock);
2110 ReleaseReadLock(&FSYNC_handler_lock); /* just in case */
2112 return -1; /* satisfy compiler */
2116 FindHandler_r(osi_socket afd)
2119 for (i = 0; i < MAXHANDLERS; i++)
2120 if (HandlerFD[i] == afd) {
2124 return -1; /* satisfy compiler */
2128 RemoveHandler(osi_socket afd)
2130 ObtainWriteLock(&FSYNC_handler_lock);
2131 HandlerFD[FindHandler_r(afd)] = OSI_NULLSOCKET;
2132 ReleaseWriteLock(&FSYNC_handler_lock);
2136 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
2138 GetHandler(struct pollfd *fds, int maxfds, int events, int *nfds)
2142 ObtainReadLock(&FSYNC_handler_lock);
2143 for (i = 0; i < MAXHANDLERS; i++)
2144 if (HandlerFD[i] != OSI_NULLSOCKET) {
2145 osi_Assert(fdi<maxfds);
2146 fds[fdi].fd = HandlerFD[i];
2147 fds[fdi].events = events;
2148 fds[fdi].revents = 0;
2152 ReleaseReadLock(&FSYNC_handler_lock);
2156 GetHandler(fd_set * fdsetp, int *maxfdp)
2161 ObtainReadLock(&FSYNC_handler_lock); /* just in case */
2162 for (i = 0; i < MAXHANDLERS; i++)
2163 if (HandlerFD[i] != OSI_NULLSOCKET) {
2164 FD_SET(HandlerFD[i], fdsetp);
2165 #ifndef AFS_NT40_ENV
2166 /* On Windows the nfds parameter to select() is ignored */
2167 if (maxfd < HandlerFD[i] || maxfd == (int)-1)
2168 maxfd = HandlerFD[i];
2169 #endif /* AFS_NT40_ENV */
2172 ReleaseReadLock(&FSYNC_handler_lock); /* just in case */
2174 #endif /* HAVE_POLL && AFS_PTHREAD_ENV */
2176 #endif /* FSSYNC_BUILD_SERVER */