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>
49 #include <afs/afsint.h>
51 #include <afs/errors.h>
52 #include "daemon_com.h"
53 #include "daemon_com_inline.h"
55 #include "fssync_inline.h"
59 #include <afs/afssyscalls.h>
63 #include "volume_inline.h"
64 #include "partition.h"
70 #endif /* HAVE_POLL */
72 #ifdef USE_UNIX_SOCKETS
74 #include <afs/afsutil.h>
75 #endif /* USE_UNIX_SOCKETS */
77 #ifdef FSSYNC_BUILD_SERVER
79 int (*V_BreakVolumeCallbacks) (VolumeId volume);
81 #define MAXHANDLERS 4 /* Up to 4 clients; must be at least 2, so that
82 * move = dump+restore can run on single server */
83 #define MAXOFFLINEVOLUMES 128 /* This needs to be as big as the maximum
84 * number that would be offline for 1 operation.
85 * Current winner is salvage, which needs all
86 * cloned read-only copies offline when salvaging
87 * a single read-write volume */
91 static struct offlineInfo OfflineVolumes[MAXHANDLERS][MAXOFFLINEVOLUMES];
94 * fssync server socket handle.
96 static SYNC_server_state_t fssync_server_state =
97 { OSI_NULLSOCKET, /* file descriptor */
98 FSSYNC_ENDPOINT_DECL, /* server endpoint */
99 FSYNC_PROTO_VERSION, /* protocol version */
100 5, /* bind() retry limit */
101 100, /* listen() queue depth */
102 "FSSYNC", /* protocol name string */
105 #ifdef AFS_DEMAND_ATTACH_FS
107 * a queue of volume pointers to salvage in the background.
109 struct fsync_salv_node {
111 Volume *vp; /**< volume to salvage */
112 unsigned char update_salv_prio; /**< whether we should update the salvage priority or not */
115 struct rx_queue head;
119 static void * FSYNC_salvageThread(void *);
120 static void FSYNC_backgroundSalvage(Volume *vp);
121 #endif /* AFS_DEMAND_ATTACH_FS */
123 /* Forward declarations */
124 static void * FSYNC_sync(void *);
125 static void FSYNC_newconnection(osi_socket afd);
126 static void FSYNC_com(osi_socket fd);
127 static void FSYNC_Drop(osi_socket fd);
128 static void AcceptOn(void);
129 static void AcceptOff(void);
130 static void InitHandler(void);
131 static int AddHandler(osi_socket fd, void (*aproc)(osi_socket));
132 static int FindHandler(osi_socket afd);
133 static int FindHandler_r(osi_socket afd);
134 static int RemoveHandler(osi_socket afd);
135 #if defined(HAVE_POLL) && defined (AFS_PTHREAD_ENV)
136 static void CallHandler(struct pollfd *fds, int nfds, int mask);
137 static void GetHandler(struct pollfd *fds, int maxfds, int events, int *nfds);
139 static void CallHandler(fd_set * fdsetp);
140 static void GetHandler(fd_set * fdsetp, int *maxfdp);
144 static afs_int32 FSYNC_com_VolOp(osi_socket fd, SYNC_command * com, SYNC_response * res);
146 #ifdef AFS_DEMAND_ATTACH_FS
147 static afs_int32 FSYNC_com_VolError(FSSYNC_VolOp_command * com, SYNC_response * res);
149 static afs_int32 FSYNC_com_VolOn(FSSYNC_VolOp_command * com, SYNC_response * res);
150 static afs_int32 FSYNC_com_VolOff(FSSYNC_VolOp_command * com, SYNC_response * res);
151 static afs_int32 FSYNC_com_VolMove(FSSYNC_VolOp_command * com, SYNC_response * res);
152 static afs_int32 FSYNC_com_VolBreakCBKs(FSSYNC_VolOp_command * com, SYNC_response * res);
153 static afs_int32 FSYNC_com_VolDone(FSSYNC_VolOp_command * com, SYNC_response * res);
154 static afs_int32 FSYNC_com_VolQuery(FSSYNC_VolOp_command * com, SYNC_response * res);
155 static afs_int32 FSYNC_com_VolHdrQuery(FSSYNC_VolOp_command * com, SYNC_response * res);
156 #ifdef AFS_DEMAND_ATTACH_FS
157 static afs_int32 FSYNC_com_VGUpdate(osi_socket fd, SYNC_command * com, SYNC_response * res);
158 static afs_int32 FSYNC_com_VolOpQuery(FSSYNC_VolOp_command * com, SYNC_response * res);
159 static afs_int32 FSYNC_com_VGQuery(FSSYNC_VolOp_command * com, SYNC_response * res);
160 static afs_int32 FSYNC_com_VGScan(FSSYNC_VolOp_command * com, SYNC_response * res);
161 static afs_int32 FSYNC_com_VGScanAll(FSSYNC_VolOp_command * com, SYNC_response * res);
162 #endif /* AFS_DEMAND_ATTACH_FS */
164 static afs_int32 FSYNC_com_VnQry(osi_socket fd, SYNC_command * com, SYNC_response * res);
166 static afs_int32 FSYNC_com_StatsOp(osi_socket fd, SYNC_command * com, SYNC_response * res);
168 static afs_int32 FSYNC_com_StatsOpGeneral(FSSYNC_StatsOp_command * scom, SYNC_response * res);
170 #ifdef AFS_DEMAND_ATTACH_FS
171 static afs_int32 FSYNC_com_StatsOpViceP(FSSYNC_StatsOp_command * scom, SYNC_response * res);
172 static afs_int32 FSYNC_com_StatsOpHash(FSSYNC_StatsOp_command * scom, SYNC_response * res);
173 static afs_int32 FSYNC_com_StatsOpHdr(FSSYNC_StatsOp_command * scom, SYNC_response * res);
174 static afs_int32 FSYNC_com_StatsOpVLRU(FSSYNC_StatsOp_command * scom, SYNC_response * res);
177 static void FSYNC_com_to_info(FSSYNC_VolOp_command * vcom, FSSYNC_VolOp_info * info);
179 static int FSYNC_partMatch(FSSYNC_VolOp_command * vcom, Volume * vp, int match_anon);
183 * This lock controls access to the handler array. The overhead
184 * is minimal in non-preemptive environments.
186 struct Lock FSYNC_handler_lock;
191 #ifdef AFS_PTHREAD_ENV
193 pthread_attr_t tattr;
194 #else /* AFS_PTHREAD_ENV */
196 #endif /* AFS_PTHREAD_ENV */
198 Lock_Init(&FSYNC_handler_lock);
200 #ifdef AFS_PTHREAD_ENV
201 osi_Assert(pthread_attr_init(&tattr) == 0);
202 osi_Assert(pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED) == 0);
203 osi_Assert(pthread_create(&tid, &tattr, FSYNC_sync, NULL) == 0);
204 #else /* AFS_PTHREAD_ENV */
205 osi_Assert(LWP_CreateProcess
206 (FSYNC_sync, USUAL_STACK_SIZE, USUAL_PRIORITY, (void *)0,
207 "FSYNC_sync", &pid) == LWP_SUCCESS);
208 #endif /* AFS_PTHREAD_ENV */
210 #ifdef AFS_DEMAND_ATTACH_FS
211 queue_Init(&fsync_salv.head);
212 CV_INIT(&fsync_salv.cv, "fsync salv", CV_DEFAULT, 0);
213 osi_Assert(pthread_create(&tid, &tattr, FSYNC_salvageThread, NULL) == 0);
214 #endif /* AFS_DEMAND_ATTACH_FS */
217 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
218 static struct pollfd FSYNC_readfds[MAXHANDLERS];
220 static fd_set FSYNC_readfds;
225 FSYNC_sync(void * args)
229 #ifdef AFS_PTHREAD_ENV
232 SYNC_server_state_t * state = &fssync_server_state;
233 #ifdef AFS_DEMAND_ATTACH_FS
234 VThreadOptions_t * thread_opts;
238 * For non-DAFS, only wait until we begin attaching volumes (instead
239 * of waiting until all volumes are attached), since it can take
240 * awhile until VInit == 2.
243 #endif /* AFS_DEMAND_ATTACH_FS */
245 /* we must not be called before vol package initialization, since we use
246 * vol package mutexes and conds etc */
249 SYNC_getAddr(&state->endpoint, &state->addr);
250 SYNC_cleanupSock(state);
253 (void)signal(SIGPIPE, SIG_IGN);
256 #ifdef AFS_PTHREAD_ENV
257 /* set our 'thread-id' so that the host hold table works */
258 tid = rx_SetThreadNum();
259 Log("Set thread id %d for FSYNC_sync\n", tid);
260 #endif /* AFS_PTHREAD_ENV */
264 while (VInit < min_vinit) {
265 /* Let somebody else run until all volumes have been preattached
266 * (DAFS), or we have started attaching volumes (non-DAFS). This
267 * doesn't mean that all volumes have been attached.
269 #ifdef AFS_PTHREAD_ENV
270 VOL_CV_WAIT(&vol_vinit_cond);
271 #else /* AFS_PTHREAD_ENV */
272 LWP_DispatchProcess();
273 #endif /* AFS_PTHREAD_ENV */
278 state->fd = SYNC_getSock(&state->endpoint);
279 code = SYNC_bindSock(state);
282 #ifdef AFS_DEMAND_ATTACH_FS
284 * make sure the volume package is incapable of recursively executing
285 * salvsync calls on this thread, since there is a possibility of
288 thread_opts = malloc(sizeof(VThreadOptions_t));
289 if (thread_opts == NULL) {
290 Log("failed to allocate memory for thread-specific volume package options structure\n");
293 memcpy(thread_opts, &VThread_defaults, sizeof(VThread_defaults));
294 thread_opts->disallow_salvsync = 1;
295 osi_Assert(pthread_setspecific(VThread_key, thread_opts) == 0);
297 code = VVGCache_PkgInit();
298 osi_Assert(code == 0);
305 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
307 GetHandler(FSYNC_readfds, MAXHANDLERS, POLLIN|POLLPRI, &nfds);
308 if (poll(FSYNC_readfds, nfds, -1) >=1)
309 CallHandler(FSYNC_readfds, nfds, POLLIN|POLLPRI);
312 #ifdef AFS_PTHREAD_ENV
313 struct timeval s_timeout;
315 GetHandler(&FSYNC_readfds, &maxfd);
316 /* Note: check for >= 1 below is essential since IOMGR_select
317 * doesn't have exactly same semantics as select.
319 #ifdef AFS_PTHREAD_ENV
320 s_timeout.tv_sec = SYNC_SELECT_TIMEOUT;
321 s_timeout.tv_usec = 0;
322 if (select(maxfd + 1, &FSYNC_readfds, NULL, NULL, &s_timeout) >= 1)
323 #else /* AFS_PTHREAD_ENV */
324 if (IOMGR_Select(maxfd + 1, &FSYNC_readfds, NULL, NULL, NULL) >= 1)
325 #endif /* AFS_PTHREAD_ENV */
326 CallHandler(&FSYNC_readfds);
329 return NULL; /* hush now, little gcc */
332 #ifdef AFS_DEMAND_ATTACH_FS
334 * thread for salvaging volumes in the background.
336 * Since FSSYNC handlers cannot issue SALVSYNC requests in order to avoid
337 * deadlock issues, this thread exists so code in the FSSYNC handler thread
338 * can hand off volumes to be salvaged in the background.
340 * @param[in] args unused
342 * @note DEMAND_ATTACH_FS only
345 FSYNC_salvageThread(void * args)
348 struct fsync_salv_node *node;
353 while (queue_IsEmpty(&fsync_salv.head)) {
354 VOL_CV_WAIT(&fsync_salv.cv);
357 node = queue_First(&fsync_salv.head, fsync_salv_node);
361 if (node->update_salv_prio) {
362 if (VUpdateSalvagePriority_r(vp)) {
363 ViceLog(0, ("FSYNC_salvageThread: unable to raise salvage priority "
364 "for volume %lu\n", afs_printable_uint32_lu(vp->hashid)));
371 VCancelReservation_r(vp);
380 * salvage a volume in the background.
382 * Salvages cannot be scheduled directly from the main FSYNC thread, so
383 * instead call this function to schedule a salvage asynchronously in the
384 * FSYNC_salvageThread thread.
386 * @param[in] vp volume to pointer to salvage
390 * @note DEMAND_ATTACH_FS only
393 FSYNC_backgroundSalvage(Volume *vp)
395 struct fsync_salv_node *node;
398 VCreateReservation_r(vp);
400 node = malloc(sizeof(struct fsync_salv_node));
403 /* Save this value, to know if we should VUpdateSalvagePriority_r.
404 * We need to save it here, snce VRequestSalvage_r will change it. */
405 node->update_salv_prio = vp->salvage.requested;
407 if (VRequestSalvage_r(&ec, vp, SALVSYNC_ERROR, 0)) {
408 ViceLog(0, ("FSYNC_backgroundSalvage: unable to request salvage for volume %lu\n",
409 afs_printable_uint32_lu(vp->hashid)));
412 queue_Append(&fsync_salv.head, node);
413 CV_BROADCAST(&fsync_salv.cv);
415 #endif /* AFS_DEMAND_ATTACH_FS */
418 FSYNC_newconnection(osi_socket afd)
420 #ifdef USE_UNIX_SOCKETS
421 struct sockaddr_un other;
422 #else /* USE_UNIX_SOCKETS */
423 struct sockaddr_in other;
427 junk = sizeof(other);
428 fd = accept(afd, (struct sockaddr *)&other, &junk);
429 if (fd == OSI_NULLSOCKET) {
430 Log("FSYNC_newconnection: accept failed, errno==%d\n", errno);
432 } else if (!AddHandler(fd, FSYNC_com)) {
434 osi_Assert(AddHandler(fd, FSYNC_com));
438 /* this function processes commands from an fssync file descriptor (fd) */
439 afs_int32 FS_cnt = 0;
441 FSYNC_com(osi_socket fd)
445 SYNC_PROTO_BUF_DECL(com_buf);
446 SYNC_PROTO_BUF_DECL(res_buf);
448 memset(&res.hdr, 0, sizeof(res.hdr));
450 com.payload.buf = (void *)com_buf;
451 com.payload.len = SYNC_PROTO_MAX_LEN;
452 res.hdr.response_len = sizeof(res.hdr);
453 res.payload.len = SYNC_PROTO_MAX_LEN;
454 res.payload.buf = (void *)res_buf;
457 if (SYNC_getCom(&fssync_server_state, fd, &com)) {
458 Log("FSYNC_com: read failed; dropping connection (cnt=%d)\n", FS_cnt);
463 if (com.recv_len < sizeof(com.hdr)) {
464 Log("FSSYNC_com: invalid protocol message length (%u)\n", com.recv_len);
465 res.hdr.response = SYNC_COM_ERROR;
466 res.hdr.reason = SYNC_REASON_MALFORMED_PACKET;
467 res.hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
471 if (com.hdr.proto_version != FSYNC_PROTO_VERSION) {
472 Log("FSYNC_com: invalid protocol version (%u)\n", com.hdr.proto_version);
473 res.hdr.response = SYNC_COM_ERROR;
474 res.hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
478 if (com.hdr.command == SYNC_COM_CHANNEL_CLOSE) {
479 res.hdr.response = SYNC_OK;
480 res.hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
482 /* don't respond, just drop; senders of SYNC_COM_CHANNEL_CLOSE
483 * never wait for a response. */
487 ViceLog(125, ("FSYNC_com: from fd %d got command %ld (%s) reason %ld (%s) "
488 "pt %ld (%s) pid %ld\n", (int)fd,
489 afs_printable_int32_ld(com.hdr.command),
490 FSYNC_com2string(com.hdr.command),
491 afs_printable_int32_ld(com.hdr.reason),
492 FSYNC_reason2string(com.hdr.reason),
493 afs_printable_int32_ld(com.hdr.programType),
494 VPTypeToString(com.hdr.programType),
495 afs_printable_int32_ld(com.hdr.pid)));
497 res.hdr.com_seq = com.hdr.com_seq;
500 switch (com.hdr.command) {
502 case FSYNC_VOL_ATTACH:
503 case FSYNC_VOL_LEAVE_OFF:
505 case FSYNC_VOL_FORCE_ERROR:
506 case FSYNC_VOL_LISTVOLUMES:
507 case FSYNC_VOL_NEEDVOLUME:
509 case FSYNC_VOL_BREAKCBKS:
511 case FSYNC_VOL_QUERY:
512 case FSYNC_VOL_QUERY_HDR:
513 #ifdef AFS_DEMAND_ATTACH_FS
514 case FSYNC_VOL_QUERY_VOP:
517 case FSYNC_VG_SCAN_ALL:
519 res.hdr.response = FSYNC_com_VolOp(fd, &com, &res);
521 case FSYNC_VOL_STATS_GENERAL:
522 case FSYNC_VOL_STATS_VICEP:
523 case FSYNC_VOL_STATS_HASH:
524 case FSYNC_VOL_STATS_HDR:
525 case FSYNC_VOL_STATS_VLRU:
526 res.hdr.response = FSYNC_com_StatsOp(fd, &com, &res);
528 case FSYNC_VOL_QUERY_VNODE:
529 res.hdr.response = FSYNC_com_VnQry(fd, &com, &res);
531 #ifdef AFS_DEMAND_ATTACH_FS
534 res.hdr.response = FSYNC_com_VGUpdate(fd, &com, &res);
538 res.hdr.response = SYNC_BAD_COMMAND;
543 ViceLog(125, ("FSYNC_com: fd %d responding with code %ld (%s) reason %ld "
545 afs_printable_int32_ld(res.hdr.response),
546 SYNC_res2string(res.hdr.response),
547 afs_printable_int32_ld(res.hdr.reason),
548 FSYNC_reason2string(res.hdr.reason)));
551 SYNC_putRes(&fssync_server_state, fd, &res);
554 if (res.hdr.flags & SYNC_FLAG_CHANNEL_SHUTDOWN) {
560 FSYNC_com_VolOp(osi_socket fd, SYNC_command * com, SYNC_response * res)
563 afs_int32 code = SYNC_OK;
564 FSSYNC_VolOp_command vcom;
566 if (com->recv_len != (sizeof(com->hdr) + sizeof(FSSYNC_VolOp_hdr))) {
567 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
568 res->hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
569 return SYNC_COM_ERROR;
572 vcom.hdr = &com->hdr;
573 vcom.vop = (FSSYNC_VolOp_hdr *) com->payload.buf;
576 vcom.volumes = OfflineVolumes[FindHandler(fd)];
577 for (vcom.v = NULL, i = 0; i < MAXOFFLINEVOLUMES; i++) {
578 if ((vcom.volumes[i].volumeID == vcom.vop->volume) &&
579 (strncmp(vcom.volumes[i].partName, vcom.vop->partName,
580 sizeof(vcom.volumes[i].partName)) == 0)) {
581 vcom.v = &vcom.volumes[i];
586 ViceLog(125, ("FSYNC_com_VolOp: fd %d got command for vol %lu part %.16s\n",
587 (int)fd, afs_printable_uint32_lu(vcom.vop->volume),
588 vcom.vop->partName));
590 switch (com->hdr.command) {
592 case FSYNC_VOL_ATTACH:
593 case FSYNC_VOL_LEAVE_OFF:
594 code = FSYNC_com_VolOn(&vcom, res);
597 case FSYNC_VOL_NEEDVOLUME:
598 code = FSYNC_com_VolOff(&vcom, res);
600 case FSYNC_VOL_LISTVOLUMES:
604 code = FSYNC_com_VolMove(&vcom, res);
606 case FSYNC_VOL_BREAKCBKS:
607 code = FSYNC_com_VolBreakCBKs(&vcom, res);
610 code = FSYNC_com_VolDone(&vcom, res);
612 case FSYNC_VOL_QUERY:
613 code = FSYNC_com_VolQuery(&vcom, res);
615 case FSYNC_VOL_QUERY_HDR:
616 code = FSYNC_com_VolHdrQuery(&vcom, res);
618 #ifdef AFS_DEMAND_ATTACH_FS
619 case FSYNC_VOL_FORCE_ERROR:
620 code = FSYNC_com_VolError(&vcom, res);
622 case FSYNC_VOL_QUERY_VOP:
623 code = FSYNC_com_VolOpQuery(&vcom, res);
626 code = FSYNC_com_VGQuery(&vcom, res);
629 code = FSYNC_com_VGScan(&vcom, res);
631 case FSYNC_VG_SCAN_ALL:
632 code = FSYNC_com_VGScanAll(&vcom, res);
634 #endif /* AFS_DEMAND_ATTACH_FS */
636 code = SYNC_BAD_COMMAND;
643 * service an FSYNC request to bring a volume online.
645 * @param[in] vcom pointer command object
646 * @param[out] res object in which to store response packet
648 * @return operation status
649 * @retval SYNC_OK volume transitioned online
650 * @retval SYNC_FAILED invalid command protocol message
651 * @retval SYNC_DENIED operation could not be completed
653 * @note this is an FSYNC RPC server stub
655 * @note this procedure handles the following FSSYNC command codes:
658 * - FSYNC_VOL_LEAVE_OFF
660 * @note the supplementary reason code contains additional details.
661 * When SYNC_DENIED is returned, the specific reason is
662 * placed in the response packet reason field.
667 FSYNC_com_VolOn(FSSYNC_VolOp_command * vcom, SYNC_response * res)
669 afs_int32 code = SYNC_OK;
670 #ifndef AFS_DEMAND_ATTACH_FS
671 char tvolName[VMAXPATHLEN];
676 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
677 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
682 /* so, we need to attach the volume */
684 #ifdef AFS_DEMAND_ATTACH_FS
685 /* check DAFS permissions */
686 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
688 FSYNC_partMatch(vcom, vp, 1) &&
689 vp->pending_vol_op &&
690 (vcom->hdr->programType != vp->pending_vol_op->com.programType)) {
691 /* a different program has this volume checked out. deny. */
692 Log("FSYNC_VolOn: WARNING: program type %u has attempted to manipulate "
693 "state for volume %u using command code %u while the volume is "
694 "checked out by program type %u for command code %u.\n",
695 vcom->hdr->programType,
698 vp->pending_vol_op->com.programType,
699 vp->pending_vol_op->com.command);
701 res->hdr.reason = FSYNC_EXCLUSIVE;
707 vcom->v->volumeID = 0;
710 if (vcom->hdr->command == FSYNC_VOL_LEAVE_OFF) {
711 /* nothing much to do if we're leaving the volume offline */
712 #ifdef AFS_DEMAND_ATTACH_FS
714 VCreateReservation_r(vp);
715 VWaitExclusiveState_r(vp);
717 if (vp && V_attachState(vp) != VOL_STATE_DELETED) {
718 if (FSYNC_partMatch(vcom, vp, 1)) {
719 if ((V_attachState(vp) == VOL_STATE_UNATTACHED) ||
720 (V_attachState(vp) == VOL_STATE_PREATTACHED)) {
721 VChangeState_r(vp, VOL_STATE_UNATTACHED);
722 VDeregisterVolOp_r(vp);
725 res->hdr.reason = FSYNC_BAD_STATE;
729 res->hdr.reason = FSYNC_WRONG_PART;
733 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
737 VCancelReservation_r(vp);
744 #ifdef AFS_DEMAND_ATTACH_FS
745 /* first, check to see whether we have such a volume defined */
746 vp = VPreAttachVolumeById_r(&error,
750 VCreateReservation_r(vp);
751 VWaitExclusiveState_r(vp);
752 VDeregisterVolOp_r(vp);
753 VCancelReservation_r(vp);
756 #else /* !AFS_DEMAND_ATTACH_FS */
757 tvolName[0] = OS_DIRSEPC;
758 snprintf(&tvolName[1], sizeof(tvolName)-1, VFORMAT, afs_printable_uint32_lu(vcom->vop->volume));
759 tvolName[sizeof(tvolName)-1] = '\0';
761 vp = VAttachVolumeByName_r(&error, vcom->vop->partName, tvolName,
767 res->hdr.reason = error;
769 #endif /* !AFS_DEMAND_ATTACH_FS */
776 * service an FSYNC request to take a volume offline.
778 * @param[in] vcom pointer command object
779 * @param[out] res object in which to store response packet
781 * @return operation status
782 * @retval SYNC_OK volume transitioned offline
783 * @retval SYNC_FAILED invalid command protocol message
784 * @retval SYNC_DENIED operation could not be completed
786 * @note this is an FSYNC RPC server stub
788 * @note this procedure handles the following FSSYNC command codes:
790 * - FSYNC_VOL_NEEDVOLUME
792 * @note the supplementary reason code contains additional details.
793 * When SYNC_DENIED is returned, the specific reason is
794 * placed in the response packet reason field.
799 FSYNC_com_VolOff(FSSYNC_VolOp_command * vcom, SYNC_response * res)
801 FSSYNC_VolOp_info info;
802 afs_int32 code = SYNC_OK;
806 #ifdef AFS_DEMAND_ATTACH_FS
807 Volume *nvp, *rvp = NULL;
810 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
811 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
816 /* not already offline, we need to find a slot for newly offline volume */
817 if (vcom->hdr->programType == debugUtility) {
818 /* debug utilities do not have their operations tracked */
822 for (i = 0; i < MAXOFFLINEVOLUMES; i++) {
823 if (vcom->volumes[i].volumeID == 0) {
824 vcom->v = &vcom->volumes[i];
834 FSYNC_com_to_info(vcom, &info);
836 #ifdef AFS_DEMAND_ATTACH_FS
837 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
839 vp = VGetVolume_r(&error, vcom->vop->volume);
843 if (!FSYNC_partMatch(vcom, vp, 1)) {
844 /* volume on desired partition is not online, so we
845 * should treat this as an offline volume.
847 #ifndef AFS_DEMAND_ATTACH_FS
855 #ifdef AFS_DEMAND_ATTACH_FS
857 ProgramType type = (ProgramType) vcom->hdr->programType;
859 /* do initial filtering of requests */
861 /* enforce mutual exclusion for volume ops */
862 if (vp->pending_vol_op) {
863 if (vp->pending_vol_op->com.programType != type) {
864 if (vp->pending_vol_op->com.command == FSYNC_VOL_OFF &&
865 vp->pending_vol_op->com.reason == FSYNC_SALVAGE) {
867 Log("denying offline request for volume %lu; volume is salvaging\n",
868 afs_printable_uint32_lu(vp->hashid));
870 res->hdr.reason = FSYNC_SALVAGE;
873 Log("volume %u already checked out\n", vp->hashid);
875 Log("vp->vop = { com = { ver=%u, prog=%d, com=%d, reason=%d, len=%u, flags=0x%x }, vop = { vol=%u, part='%s' } }\n",
876 vp->pending_vol_op->com.proto_version,
877 vp->pending_vol_op->com.programType,
878 vp->pending_vol_op->com.command,
879 vp->pending_vol_op->com.reason,
880 vp->pending_vol_op->com.command_len,
881 vp->pending_vol_op->com.flags,
882 vp->pending_vol_op->vop.volume,
883 vp->pending_vol_op->vop.partName );
884 Log("vcom = { com = { ver=%u, prog=%d, com=%d, reason=%d, len=%u, flags=0x%x } , vop = { vol=%u, part='%s' } }\n",
885 vcom->hdr->proto_version,
886 vcom->hdr->programType,
889 vcom->hdr->command_len,
892 vcom->vop->partName);
893 res->hdr.reason = FSYNC_EXCLUSIVE;
896 Log("warning: volume %u recursively checked out by programType id %d\n",
897 vp->hashid, vcom->hdr->programType);
901 /* wait for exclusive ops, so we have an accurate picture of the
902 * vol attach state */
903 VCreateReservation_r(vp);
904 VWaitExclusiveState_r(vp);
907 /* filter based upon requestor
909 * volume utilities / volserver are not allowed to check out
910 * volumes which are in an error state
912 * unknown utility programs will be denied on principal
917 /* it is possible for the salvageserver to checkout a
918 * volume for salvage before its scheduling request
919 * has been sent to the salvageserver */
920 if (vp->salvage.requested && !vp->salvage.scheduled) {
921 vp->salvage.scheduled = 1;
924 /* If the volume is in VOL_STATE_SALVAGE_REQ, we need to wait
925 * for the vol to go offline before we can give it away. Also
926 * make sure we don't come out with vp in an excl state. */
927 while (V_attachState(vp) == VOL_STATE_SALVAGE_REQ ||
928 VIsExclusiveState(V_attachState(vp))) {
930 VOL_CV_WAIT(&V_attachCV(vp));
938 if (VIsSalvaging(vp)) {
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;
976 case VOL_STATE_DELETED:
982 /* convert to heavyweight ref */
983 nvp = VGetVolumeByVp_r(&error, vp);
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;
1006 case VOL_STATE_DELETED:
1012 Log("FSYNC_com_VolOff: failed to get heavyweight reference to volume %u (state=%u, flags=0x%x)\n",
1013 vcom->vop->volume, V_attachState(vp), V_attachFlags(vp));
1014 res->hdr.reason = FSYNC_VOL_PKG_ERROR;
1016 } else if (nvp != vp) {
1017 /* i don't think this should ever happen, but just in case... */
1018 Log("FSYNC_com_VolOff: warning: potentially dangerous race detected\n");
1022 /* kill off lightweight ref to ensure we can't deadlock against ourselves later... */
1023 VCancelReservation_r(rvp);
1026 /* register the volume operation metadata with the volume */
1027 VRegisterVolOp_r(vp, &info);
1030 #endif /* AFS_DEMAND_ATTACH_FS */
1033 if (VVolOpLeaveOnline_r(vp, &info)) {
1034 VUpdateVolume_r(&error, vp, VOL_UPDATE_WAIT); /* At least get volume stats right */
1036 Log("FSYNC: Volume %u (%s) was left on line for an external %s request\n",
1037 V_id(vp), V_name(vp),
1038 vcom->hdr->reason == V_CLONE ? "clone" :
1039 vcom->hdr->reason == V_READONLY ? "readonly" :
1040 vcom->hdr->reason == V_DUMP ? "dump" :
1041 vcom->hdr->reason == FSYNC_SALVAGE ? "salvage" :
1044 #ifdef AFS_DEMAND_ATTACH_FS
1045 vp->pending_vol_op->vol_op_state = FSSYNC_VolOpRunningOnline;
1049 if (VVolOpSetVBusy_r(vp, &info)) {
1050 vp->specialStatus = VBUSY;
1053 /* remember what volume we got, so we can keep track of how
1054 * many volumes the volserver or whatever is using. Note that
1055 * vp is valid since leaveonline is only set when vp is valid.
1058 vcom->v->volumeID = vcom->vop->volume;
1059 strlcpy(vcom->v->partName, vp->partition->name, sizeof(vcom->v->partName));
1062 #ifdef AFS_DEMAND_ATTACH_FS
1063 VCreateReservation_r(vp);
1064 VOfflineForVolOp_r(&error, vp, "A volume utility is running.");
1066 osi_Assert(vp->nUsers==0);
1067 vp->pending_vol_op->vol_op_state = FSSYNC_VolOpRunningOffline;
1070 VWaitExclusiveState_r(vp);
1071 VDeregisterVolOp_r(vp);
1074 VCancelReservation_r(vp);
1076 VOffline_r(vp, "A volume utility is running.");
1087 #ifdef AFS_DEMAND_ATTACH_FS
1089 VCancelReservation_r(rvp);
1096 * service an FSYNC request to mark a volume as moved.
1098 * @param[in] vcom pointer command object
1099 * @param[out] res object in which to store response packet
1101 * @return operation status
1102 * @retval SYNC_OK volume marked as moved to a remote server
1103 * @retval SYNC_FAILED invalid command protocol message
1104 * @retval SYNC_DENIED current volume state does not permit this operation
1106 * @note this is an FSYNC RPC server stub
1108 * @note this operation also breaks all callbacks for the given volume
1110 * @note this procedure handles the following FSSYNC command codes:
1113 * @note the supplementary reason code contains additional details. For
1114 * instance, SYNC_OK is still returned when the partition specified
1115 * does not match the one registered in the volume object -- reason
1116 * will be FSYNC_WRONG_PART in this case.
1121 FSYNC_com_VolMove(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1123 afs_int32 code = SYNC_DENIED;
1127 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1128 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1133 /* Yuch: the "reason" for the move is the site it got moved to... */
1134 /* still set specialStatus so we stop sending back VBUSY.
1135 * also should still break callbacks. Note that I don't know
1136 * how to tell if we should break all or not, so we just do it
1137 * since it doesn't matter much if we do an extra break
1138 * volume callbacks on a volume move within the same server */
1139 #ifdef AFS_DEMAND_ATTACH_FS
1140 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
1142 vp = VGetVolume_r(&error, vcom->vop->volume);
1145 if (FSYNC_partMatch(vcom, vp, 1)) {
1146 #ifdef AFS_DEMAND_ATTACH_FS
1147 if ((V_attachState(vp) == VOL_STATE_UNATTACHED) ||
1148 (V_attachState(vp) == VOL_STATE_PREATTACHED)) {
1151 vp->specialStatus = VMOVED;
1152 #ifdef AFS_DEMAND_ATTACH_FS
1154 res->hdr.reason = FSYNC_BAD_STATE;
1158 res->hdr.reason = FSYNC_WRONG_PART;
1160 #ifndef AFS_DEMAND_ATTACH_FS
1162 #endif /* !AFS_DEMAND_ATTACH_FS */
1164 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1167 if ((code == SYNC_OK) && (V_BreakVolumeCallbacks != NULL)) {
1168 Log("fssync: volume %u moved to %x; breaking all call backs\n",
1169 vcom->vop->volume, vcom->hdr->reason);
1171 (*V_BreakVolumeCallbacks) (vcom->vop->volume);
1181 * service an FSYNC request to mark a volume as destroyed.
1183 * @param[in] vcom pointer command object
1184 * @param[out] res object in which to store response packet
1186 * @return operation status
1187 * @retval SYNC_OK volume marked as destroyed
1188 * @retval SYNC_FAILED invalid command protocol message
1189 * @retval SYNC_DENIED current volume state does not permit this operation
1191 * @note this is an FSYNC RPC server stub
1193 * @note this procedure handles the following FSSYNC command codes:
1196 * @note the supplementary reason code contains additional details. For
1197 * instance, SYNC_OK is still returned when the partition specified
1198 * does not match the one registered in the volume object -- reason
1199 * will be FSYNC_WRONG_PART in this case.
1204 FSYNC_com_VolDone(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1206 afs_int32 code = SYNC_FAILED;
1210 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1211 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1215 /* don't try to put online, this call is made only after deleting
1216 * a volume, in which case we want to remove the vol # from the
1217 * OfflineVolumes array only */
1219 vcom->v->volumeID = 0;
1221 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
1223 if (FSYNC_partMatch(vcom, vp, 1)) {
1224 #ifdef AFS_DEMAND_ATTACH_FS
1225 VCreateReservation_r(vp);
1226 VWaitExclusiveState_r(vp);
1228 if ((V_attachState(vp) == VOL_STATE_UNATTACHED) ||
1229 (V_attachState(vp) == VOL_STATE_PREATTACHED) ||
1230 VIsErrorState(V_attachState(vp))) {
1232 /* Change state to DELETED, not UNATTACHED, so clients get
1233 * a VNOVOL error when they try to access from now on. */
1235 VChangeState_r(vp, VOL_STATE_DELETED);
1236 VDeregisterVolOp_r(vp);
1238 /* Volume is gone; clear out old salvage stats */
1239 memset(&vp->salvage, 0, sizeof(vp->salvage));
1241 /* Someday we should free the vp, too, after about 2 hours,
1242 * possibly by putting the vp back on the VLRU. */
1245 } else if (V_attachState(vp) == VOL_STATE_DELETED) {
1246 VDeregisterVolOp_r(vp);
1247 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1251 res->hdr.reason = FSYNC_BAD_STATE;
1254 VCancelReservation_r(vp);
1256 #else /* AFS_DEMAND_ATTACH_FS */
1257 if (!vp->specialStatus) {
1258 vp->specialStatus = VNOVOL;
1261 #endif /* !AFS_DEMAND_ATTACH_FS */
1263 code = SYNC_OK; /* XXX is this really a good idea? */
1264 res->hdr.reason = FSYNC_WRONG_PART;
1267 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1274 #ifdef AFS_DEMAND_ATTACH_FS
1276 * service an FSYNC request to transition a volume to the hard error state.
1278 * @param[in] vcom pointer command object
1279 * @param[out] res object in which to store response packet
1281 * @return operation status
1282 * @retval SYNC_OK volume transitioned to hard error state
1283 * @retval SYNC_FAILED invalid command protocol message
1284 * @retval SYNC_DENIED (see note)
1286 * @note this is an FSYNC RPC server stub
1288 * @note this procedure handles the following FSSYNC command codes:
1289 * - FSYNC_VOL_FORCE_ERROR
1291 * @note SYNC_DENIED is returned in the following cases:
1292 * - no partition name is specified (reason field set to
1293 * FSYNC_WRONG_PART).
1294 * - volume id not known to fileserver (reason field set
1295 * to FSYNC_UNKNOWN_VOLID).
1297 * @note demand attach fileserver only
1302 FSYNC_com_VolError(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1306 afs_int32 code = SYNC_FAILED;
1308 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1309 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1313 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
1315 if (!vp && vcom->hdr->reason == FSYNC_SALVAGE) {
1316 /* The requested volume doesn't seem to exist. However, it is possible
1317 * that this is triggered by trying to create or clone a volume that
1318 * was prevented from succeeding by a half-created volume in the way.
1319 * (e.g. we tried to create volume X, but volume X exists except that
1320 * its .vol header was deleted for some reason) So, still try to
1321 * a salvage for that volume ID. */
1323 Log("FSYNC_com_VolError: attempting to schedule salvage for unknown "
1324 "volume %lu part %s\n", afs_printable_uint32_lu(vcom->vop->volume),
1325 vcom->vop->partName);
1326 vp = VPreAttachVolumeById_r(&error, vcom->vop->partName,
1331 if (FSYNC_partMatch(vcom, vp, 0)) {
1332 VCreateReservation_r(vp);
1333 VWaitExclusiveState_r(vp);
1334 VDeregisterVolOp_r(vp);
1336 if (vcom->hdr->reason == FSYNC_SALVAGE) {
1337 FSYNC_backgroundSalvage(vp);
1339 /* null out salvsync control state, as it's no longer relevant */
1340 memset(&vp->salvage, 0, sizeof(vp->salvage));
1341 VChangeState_r(vp, VOL_STATE_ERROR);
1344 VCancelReservation_r(vp);
1349 res->hdr.reason = FSYNC_WRONG_PART;
1352 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1358 #endif /* AFS_DEMAND_ATTACH_FS */
1361 * service an FSYNC request to break all callbacks for this volume.
1363 * @param[in] vcom pointer command object
1364 * @param[out] res object in which to store response packet
1366 * @return operation status
1367 * @retval SYNC_OK callback breaks scheduled for volume
1369 * @note this is an FSYNC RPC server stub
1371 * @note this procedure handles the following FSSYNC command codes:
1372 * - FSYNC_VOL_BREAKCBKS
1374 * @note demand attach fileserver only
1376 * @todo should do partition matching
1381 FSYNC_com_VolBreakCBKs(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1383 /* if the volume is being restored, break all callbacks on it */
1384 if (V_BreakVolumeCallbacks) {
1385 Log("fssync: breaking all call backs for volume %u\n",
1388 (*V_BreakVolumeCallbacks) (vcom->vop->volume);
1395 * service an FSYNC request to return the Volume object.
1397 * @param[in] vcom pointer command object
1398 * @param[out] res object in which to store response packet
1400 * @return operation status
1401 * @retval SYNC_OK volume object returned to caller
1402 * @retval SYNC_FAILED bad command packet, or failed to locate volume object
1404 * @note this is an FSYNC RPC server stub
1406 * @note this procedure handles the following FSSYNC command codes:
1412 FSYNC_com_VolQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1414 afs_int32 code = SYNC_FAILED;
1418 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1419 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1423 #ifdef AFS_DEMAND_ATTACH_FS
1424 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
1425 #else /* !AFS_DEMAND_ATTACH_FS */
1426 vp = VGetVolume_r(&error, vcom->vop->volume);
1427 #endif /* !AFS_DEMAND_ATTACH_FS */
1430 if (FSYNC_partMatch(vcom, vp, 1)) {
1431 if (res->payload.len >= sizeof(Volume)) {
1432 memcpy(res->payload.buf, vp, sizeof(Volume));
1433 res->hdr.response_len += sizeof(Volume);
1436 res->hdr.reason = SYNC_REASON_PAYLOAD_TOO_BIG;
1439 res->hdr.reason = FSYNC_WRONG_PART;
1441 #ifndef AFS_DEMAND_ATTACH_FS
1445 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1453 * service an FSYNC request to return the Volume header.
1455 * @param[in] vcom pointer command object
1456 * @param[out] res object in which to store response packet
1458 * @return operation status
1459 * @retval SYNC_OK volume header returned to caller
1460 * @retval SYNC_FAILED bad command packet, or failed to locate volume header
1462 * @note this is an FSYNC RPC server stub
1464 * @note this procedure handles the following FSSYNC command codes:
1465 * - FSYNC_VOL_QUERY_HDR
1470 FSYNC_com_VolHdrQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1472 afs_int32 code = SYNC_FAILED;
1476 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1477 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1480 if (res->payload.len < sizeof(VolumeDiskData)) {
1481 res->hdr.reason = SYNC_REASON_PAYLOAD_TOO_BIG;
1485 #ifdef AFS_DEMAND_ATTACH_FS
1486 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
1487 #else /* !AFS_DEMAND_ATTACH_FS */
1488 vp = VGetVolume_r(&error, vcom->vop->volume);
1492 if (FSYNC_partMatch(vcom, vp, 1)) {
1493 #ifdef AFS_DEMAND_ATTACH_FS
1494 if ((vp->header == NULL) ||
1495 !(V_attachFlags(vp) & VOL_HDR_ATTACHED) ||
1496 !(V_attachFlags(vp) & VOL_HDR_LOADED)) {
1497 res->hdr.reason = FSYNC_HDR_NOT_ATTACHED;
1500 #else /* !AFS_DEMAND_ATTACH_FS */
1501 if (!vp || !vp->header) {
1502 res->hdr.reason = FSYNC_HDR_NOT_ATTACHED;
1505 #endif /* !AFS_DEMAND_ATTACH_FS */
1507 res->hdr.reason = FSYNC_WRONG_PART;
1511 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1515 memcpy(res->payload.buf, &V_disk(vp), sizeof(VolumeDiskData));
1516 res->hdr.response_len += sizeof(VolumeDiskData);
1520 #ifndef AFS_DEMAND_ATTACH_FS
1528 #ifdef AFS_DEMAND_ATTACH_FS
1530 FSYNC_com_VolOpQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1532 afs_int32 code = SYNC_OK;
1536 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
1539 VCreateReservation_r(vp);
1540 VWaitExclusiveState_r(vp);
1543 if (vp && vp->pending_vol_op) {
1544 if (!FSYNC_partMatch(vcom, vp, 1)) {
1545 res->hdr.reason = FSYNC_WRONG_PART;
1548 osi_Assert(sizeof(FSSYNC_VolOp_info) <= res->payload.len);
1549 memcpy(res->payload.buf, vp->pending_vol_op, sizeof(FSSYNC_VolOp_info));
1550 res->hdr.response_len += sizeof(FSSYNC_VolOp_info);
1553 if (!vp || V_attachState(vp) == VOL_STATE_DELETED) {
1554 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1555 } else if (!FSYNC_partMatch(vcom, vp, 1)) {
1556 res->hdr.reason = FSYNC_WRONG_PART;
1558 res->hdr.reason = FSYNC_NO_PENDING_VOL_OP;
1564 VCancelReservation_r(vp);
1570 FSYNC_com_VGQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1572 afs_int32 code = SYNC_FAILED;
1574 struct DiskPartition64 * dp;
1576 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1577 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1581 dp = VGetPartition_r(vcom->vop->partName, 0);
1583 res->hdr.reason = FSYNC_BAD_PART;
1587 osi_Assert(sizeof(FSSYNC_VGQry_response_t) <= res->payload.len);
1589 rc = VVGCache_query_r(dp, vcom->vop->volume, res->payload.buf);
1592 res->hdr.response_len += sizeof(FSSYNC_VGQry_response_t);
1596 res->hdr.reason = FSYNC_PART_SCANNING;
1599 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1610 FSYNC_com_VGUpdate(osi_socket fd, SYNC_command * com, SYNC_response * res)
1612 afs_int32 code = SYNC_FAILED;
1613 struct DiskPartition64 * dp;
1614 FSSYNC_VGUpdate_command_t * vgucom;
1617 if (com->recv_len != (sizeof(com->hdr) + sizeof(*vgucom))) {
1618 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1619 res->hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
1620 code = SYNC_COM_ERROR;
1624 vgucom = com->payload.buf;
1626 ViceLog(125, ("FSYNC_com_VGUpdate: fd %d got command for parent %lu child "
1627 "%lu partName %.16s\n", (int)fd,
1628 afs_printable_uint32_lu(vgucom->parent),
1629 afs_printable_uint32_lu(vgucom->child),
1632 if (SYNC_verifyProtocolString(vgucom->partName, sizeof(vgucom->partName))) {
1633 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1637 dp = VGetPartition_r(vgucom->partName, 0);
1639 res->hdr.reason = FSYNC_BAD_PART;
1643 switch(com->hdr.command) {
1645 rc = VVGCache_entry_add_r(dp, vgucom->parent, vgucom->child, NULL);
1649 rc = VVGCache_entry_del_r(dp, vgucom->parent, vgucom->child);
1653 Log("FSYNC_com_VGUpdate called improperly\n");
1658 /* EINVAL means the partition VGC doesn't exist at all; not really
1660 if (rc == 0 || rc == EINVAL) {
1665 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1667 res->hdr.reason = FSYNC_WHATEVER;
1675 FSYNC_com_VGScan(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1677 afs_int32 code = SYNC_FAILED;
1678 struct DiskPartition64 * dp;
1680 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1681 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1685 dp = VGetPartition_r(vcom->vop->partName, 0);
1687 res->hdr.reason = FSYNC_BAD_PART;
1691 if (VVGCache_scanStart_r(dp) == 0) {
1700 FSYNC_com_VGScanAll(FSSYNC_VolOp_command * com, SYNC_response * res)
1702 afs_int32 code = SYNC_FAILED;
1704 if (VVGCache_scanStart_r(NULL) == 0) {
1710 #endif /* AFS_DEMAND_ATTACH_FS */
1713 FSYNC_com_VnQry(osi_socket fd, SYNC_command * com, SYNC_response * res)
1715 afs_int32 code = SYNC_OK;
1716 FSSYNC_VnQry_hdr * qry = com->payload.buf;
1721 if (com->recv_len != (sizeof(com->hdr) + sizeof(FSSYNC_VnQry_hdr))) {
1722 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1723 res->hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
1724 return SYNC_COM_ERROR;
1727 ViceLog(125, ("FSYNC_com_VnQry: fd %d got command for vol %lu vnode %lu "
1728 "uniq %lu spare %lu partName %.16s\n", (int)fd,
1729 afs_printable_uint32_lu(qry->volume),
1730 afs_printable_uint32_lu(qry->vnode),
1731 afs_printable_uint32_lu(qry->unique),
1732 afs_printable_uint32_lu(qry->spare),
1735 #ifdef AFS_DEMAND_ATTACH_FS
1736 vp = VLookupVolume_r(&error, qry->volume, NULL);
1737 #else /* !AFS_DEMAND_ATTACH_FS */
1738 vp = VGetVolume_r(&error, qry->volume);
1739 #endif /* !AFS_DEMAND_ATTACH_FS */
1742 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1747 vnp = VLookupVnode(vp, qry->vnode);
1749 res->hdr.reason = FSYNC_UNKNOWN_VNID;
1754 if (Vn_class(vnp)->residentSize > res->payload.len) {
1755 res->hdr.reason = SYNC_REASON_ENCODING_ERROR;
1760 memcpy(res->payload.buf, vnp, Vn_class(vnp)->residentSize);
1761 res->hdr.response_len += Vn_class(vnp)->residentSize;
1764 #ifndef AFS_DEMAND_ATTACH_FS
1773 FSYNC_com_StatsOp(osi_socket fd, SYNC_command * com, SYNC_response * res)
1775 afs_int32 code = SYNC_OK;
1776 FSSYNC_StatsOp_command scom;
1778 if (com->recv_len != (sizeof(com->hdr) + sizeof(FSSYNC_StatsOp_hdr))) {
1779 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1780 res->hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
1781 return SYNC_COM_ERROR;
1784 scom.hdr = &com->hdr;
1785 scom.sop = (FSSYNC_StatsOp_hdr *) com->payload.buf;
1788 ViceLog(125, ("FSYNC_com_StatsOp: fd %d got command for stats: "
1789 "{vlru_generation = %lu, hash_bucket = %lu, partName = "
1790 "%.16s}\n", (int)fd,
1791 afs_printable_uint32_lu(scom.sop->args.vlru_generation),
1792 afs_printable_uint32_lu(scom.sop->args.hash_bucket),
1793 scom.sop->args.partName));
1795 switch (com->hdr.command) {
1796 case FSYNC_VOL_STATS_GENERAL:
1797 code = FSYNC_com_StatsOpGeneral(&scom, res);
1799 #ifdef AFS_DEMAND_ATTACH_FS
1800 /* statistics for the following subsystems are only tracked
1801 * for demand attach fileservers */
1802 case FSYNC_VOL_STATS_VICEP:
1803 code = FSYNC_com_StatsOpViceP(&scom, res);
1805 case FSYNC_VOL_STATS_HASH:
1806 code = FSYNC_com_StatsOpHash(&scom, res);
1808 case FSYNC_VOL_STATS_HDR:
1809 code = FSYNC_com_StatsOpHdr(&scom, res);
1811 case FSYNC_VOL_STATS_VLRU:
1812 code = FSYNC_com_StatsOpVLRU(&scom, res);
1814 #endif /* AFS_DEMAND_ATTACH_FS */
1816 code = SYNC_BAD_COMMAND;
1823 FSYNC_com_StatsOpGeneral(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1825 afs_int32 code = SYNC_OK;
1827 memcpy(res->payload.buf, &VStats, sizeof(VStats));
1828 res->hdr.response_len += sizeof(VStats);
1833 #ifdef AFS_DEMAND_ATTACH_FS
1835 FSYNC_com_StatsOpViceP(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1837 afs_int32 code = SYNC_OK;
1838 struct DiskPartition64 * dp;
1839 struct DiskPartitionStats64 * stats;
1841 if (SYNC_verifyProtocolString(scom->sop->args.partName, sizeof(scom->sop->args.partName))) {
1842 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1847 dp = VGetPartition_r(scom->sop->args.partName, 0);
1851 stats = (struct DiskPartitionStats64 *) res->payload.buf;
1852 stats->free = dp->free;
1853 stats->totalUsable = dp->totalUsable;
1854 stats->minFree = dp->minFree;
1855 stats->f_files = dp->f_files;
1856 stats->vol_list_len = dp->vol_list.len;
1858 res->hdr.response_len += sizeof(struct DiskPartitionStats64);
1866 FSYNC_com_StatsOpHash(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1868 afs_int32 code = SYNC_OK;
1869 struct VolumeHashChainStats * stats;
1870 struct VolumeHashChainHead * head;
1872 if (scom->sop->args.hash_bucket >= VolumeHashTable.Size) {
1876 head = &VolumeHashTable.Table[scom->sop->args.hash_bucket];
1877 stats = (struct VolumeHashChainStats *) res->payload.buf;
1878 stats->table_size = VolumeHashTable.Size;
1879 stats->chain_len = head->len;
1880 stats->chain_cacheCheck = head->cacheCheck;
1881 stats->chain_busy = head->busy;
1882 AssignInt64(head->looks, &stats->chain_looks);
1883 AssignInt64(head->gets, &stats->chain_gets);
1884 AssignInt64(head->reorders, &stats->chain_reorders);
1886 res->hdr.response_len += sizeof(struct VolumeHashChainStats);
1892 FSYNC_com_StatsOpHdr(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1894 afs_int32 code = SYNC_OK;
1896 memcpy(res->payload.buf, &volume_hdr_LRU.stats, sizeof(volume_hdr_LRU.stats));
1897 res->hdr.response_len += sizeof(volume_hdr_LRU.stats);
1903 FSYNC_com_StatsOpVLRU(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1905 afs_int32 code = SYNC_OK;
1907 code = SYNC_BAD_COMMAND;
1911 #endif /* AFS_DEMAND_ATTACH_FS */
1914 * populate an FSSYNC_VolOp_info object from a command packet object.
1916 * @param[in] vcom pointer to command packet
1917 * @param[out] info pointer to info object which will be populated
1919 * @note FSSYNC_VolOp_info objects are attached to Volume objects when
1920 * a volume operation is commenced.
1925 FSYNC_com_to_info(FSSYNC_VolOp_command * vcom, FSSYNC_VolOp_info * info)
1927 memcpy(&info->com, vcom->hdr, sizeof(SYNC_command_hdr));
1928 memcpy(&info->vop, vcom->vop, sizeof(FSSYNC_VolOp_hdr));
1929 info->vol_op_state = FSSYNC_VolOpPending;
1933 * check whether command packet partition name matches volume
1934 * object's partition name.
1936 * @param[in] vcom pointer to command packet
1937 * @param[in] vp pointer to volume object
1938 * @param[in] match_anon anon matching control flag (see note below)
1940 * @return whether partitions match
1941 * @retval 0 partitions do NOT match
1942 * @retval 1 partitions match
1944 * @note if match_anon is non-zero, then this function will return a
1945 * positive match for a zero-length partition string in the
1951 FSYNC_partMatch(FSSYNC_VolOp_command * vcom, Volume * vp, int match_anon)
1953 return ((match_anon && vcom->vop->partName[0] == 0) ||
1954 (strncmp(vcom->vop->partName, V_partition(vp)->name,
1955 sizeof(vcom->vop->partName)) == 0));
1960 FSYNC_Drop(osi_socket fd)
1962 struct offlineInfo *p;
1965 char tvolName[VMAXPATHLEN];
1968 p = OfflineVolumes[FindHandler(fd)];
1969 for (i = 0; i < MAXOFFLINEVOLUMES; i++) {
1970 if (p[i].volumeID) {
1974 tvolName[0] = OS_DIRSEPC;
1975 sprintf(&tvolName[1], VFORMAT, afs_printable_uint32_lu(p[i].volumeID));
1976 vp = VAttachVolumeByName_r(&error, p[i].partName, tvolName,
1989 static int AcceptHandler = -1; /* handler id for accept, if turned on */
1994 if (AcceptHandler == -1) {
1995 osi_Assert(AddHandler(fssync_server_state.fd, FSYNC_newconnection));
1996 AcceptHandler = FindHandler(fssync_server_state.fd);
2003 if (AcceptHandler != -1) {
2004 osi_Assert(RemoveHandler(fssync_server_state.fd));
2009 /* The multiple FD handling code. */
2011 static osi_socket HandlerFD[MAXHANDLERS];
2012 static void (*HandlerProc[MAXHANDLERS]) (osi_socket);
2018 ObtainWriteLock(&FSYNC_handler_lock);
2019 for (i = 0; i < MAXHANDLERS; i++) {
2020 HandlerFD[i] = OSI_NULLSOCKET;
2023 ReleaseWriteLock(&FSYNC_handler_lock);
2026 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
2028 CallHandler(struct pollfd *fds, int nfds, int mask)
2032 ObtainReadLock(&FSYNC_handler_lock);
2033 for (i = 0; i < nfds; i++) {
2034 if (fds[i].revents & mask) {
2035 handler = FindHandler_r(fds[i].fd);
2036 ReleaseReadLock(&FSYNC_handler_lock);
2037 (*HandlerProc[handler]) (fds[i].fd);
2038 ObtainReadLock(&FSYNC_handler_lock);
2041 ReleaseReadLock(&FSYNC_handler_lock);
2045 CallHandler(fd_set * fdsetp)
2048 ObtainReadLock(&FSYNC_handler_lock);
2049 for (i = 0; i < MAXHANDLERS; i++) {
2050 if (HandlerFD[i] >= 0 && FD_ISSET(HandlerFD[i], fdsetp)) {
2051 ReleaseReadLock(&FSYNC_handler_lock);
2052 (*HandlerProc[i]) (HandlerFD[i]);
2053 ObtainReadLock(&FSYNC_handler_lock);
2056 ReleaseReadLock(&FSYNC_handler_lock);
2061 AddHandler(osi_socket afd, void (*aproc) (osi_socket))
2064 ObtainWriteLock(&FSYNC_handler_lock);
2065 for (i = 0; i < MAXHANDLERS; i++)
2066 if (HandlerFD[i] == OSI_NULLSOCKET)
2068 if (i >= MAXHANDLERS) {
2069 ReleaseWriteLock(&FSYNC_handler_lock);
2073 HandlerProc[i] = aproc;
2074 ReleaseWriteLock(&FSYNC_handler_lock);
2079 FindHandler(osi_socket afd)
2082 ObtainReadLock(&FSYNC_handler_lock);
2083 for (i = 0; i < MAXHANDLERS; i++)
2084 if (HandlerFD[i] == afd) {
2085 ReleaseReadLock(&FSYNC_handler_lock);
2088 ReleaseReadLock(&FSYNC_handler_lock); /* just in case */
2090 return -1; /* satisfy compiler */
2094 FindHandler_r(osi_socket afd)
2097 for (i = 0; i < MAXHANDLERS; i++)
2098 if (HandlerFD[i] == afd) {
2102 return -1; /* satisfy compiler */
2106 RemoveHandler(osi_socket afd)
2108 ObtainWriteLock(&FSYNC_handler_lock);
2109 HandlerFD[FindHandler_r(afd)] = OSI_NULLSOCKET;
2110 ReleaseWriteLock(&FSYNC_handler_lock);
2114 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
2116 GetHandler(struct pollfd *fds, int maxfds, int events, int *nfds)
2120 ObtainReadLock(&FSYNC_handler_lock);
2121 for (i = 0; i < MAXHANDLERS; i++)
2122 if (HandlerFD[i] != OSI_NULLSOCKET) {
2123 osi_Assert(fdi<maxfds);
2124 fds[fdi].fd = HandlerFD[i];
2125 fds[fdi].events = events;
2126 fds[fdi].revents = 0;
2130 ReleaseReadLock(&FSYNC_handler_lock);
2134 GetHandler(fd_set * fdsetp, int *maxfdp)
2139 ObtainReadLock(&FSYNC_handler_lock); /* just in case */
2140 for (i = 0; i < MAXHANDLERS; i++)
2141 if (HandlerFD[i] != OSI_NULLSOCKET) {
2142 FD_SET(HandlerFD[i], fdsetp);
2143 #ifndef AFS_NT40_ENV
2144 /* On Windows the nfds parameter to select() is ignored */
2145 if (maxfd < HandlerFD[i] || maxfd == (int)-1)
2146 maxfd = HandlerFD[i];
2147 #endif /* AFS_NT40_ENV */
2150 ReleaseReadLock(&FSYNC_handler_lock); /* just in case */
2152 #endif /* HAVE_POLL && AFS_PTHREAD_ENV */
2154 #endif /* FSSYNC_BUILD_SERVER */