2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
9 * Portions Copyright (c) 2006-2010 Sine Nomine Associates
15 Institution: The Information Technology Center, Carnegie-Mellon University
18 #ifndef AFS_PTHREAD_ENV
19 #define USUAL_PRIORITY (LWP_MAX_PRIORITY - 2)
22 * stack size increased from 8K because the HP machine seemed to have trouble
23 * with the smaller stack
25 #define USUAL_STACK_SIZE (24 * 1024)
26 #endif /* !AFS_PTHREAD_ENV */
30 File server synchronization with external volume utilities.
31 server-side implementation
34 /* This controls the size of an fd_set; it must be defined early before
35 * the system headers define that type and the macros that operate on it.
36 * Its value should be as large as the maximum file descriptor limit we
37 * are likely to run into on any platform. Right now, that is 65536
38 * which is the default hard fd limit on Solaris 9 */
40 #define FD_SETSIZE 65536
43 #include <afsconfig.h>
44 #include <afs/param.h>
47 #include <sys/types.h>
56 #include <sys/param.h>
57 #include <sys/socket.h>
58 #include <netinet/in.h>
64 #ifdef AFS_PTHREAD_ENV
66 #else /* AFS_PTHREAD_ENV */
67 #include <afs/assert.h>
68 #endif /* AFS_PTHREAD_ENV */
73 #include <afs/afsint.h>
75 #include <afs/errors.h>
76 #include "daemon_com.h"
81 #include <afs/afssyscalls.h>
85 #include "volume_inline.h"
86 #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 /*@printflike@*/ extern void Log(const char *format, ...);
102 int (*V_BreakVolumeCallbacks) (VolumeId volume);
104 #define MAXHANDLERS 4 /* Up to 4 clients; must be at least 2, so that
105 * move = dump+restore can run on single server */
106 #define MAXOFFLINEVOLUMES 128 /* This needs to be as big as the maximum
107 * number that would be offline for 1 operation.
108 * Current winner is salvage, which needs all
109 * cloned read-only copies offline when salvaging
110 * a single read-write volume */
114 static struct offlineInfo OfflineVolumes[MAXHANDLERS][MAXOFFLINEVOLUMES];
117 * fssync server socket handle.
119 static SYNC_server_state_t fssync_server_state =
120 { -1, /* file descriptor */
121 FSSYNC_ENDPOINT_DECL, /* server endpoint */
122 FSYNC_PROTO_VERSION, /* protocol version */
123 5, /* bind() retry limit */
124 100, /* listen() queue depth */
125 "FSSYNC", /* protocol name string */
128 #ifdef AFS_DEMAND_ATTACH_FS
130 * a queue of volume pointers to salvage in the background.
132 struct fsync_salv_node {
134 Volume *vp; /**< volume to salvage */
135 unsigned char update_salv_prio; /**< whether we should update the salvage priority or not */
138 struct rx_queue head;
142 static void * FSYNC_salvageThread(void *);
143 static void FSYNC_backgroundSalvage(Volume *vp);
144 #endif /* AFS_DEMAND_ATTACH_FS */
146 /* Forward declarations */
147 static void * FSYNC_sync(void *);
148 static void FSYNC_newconnection(osi_socket afd);
149 static void FSYNC_com(osi_socket fd);
150 static void FSYNC_Drop(osi_socket fd);
151 static void AcceptOn(void);
152 static void AcceptOff(void);
153 static void InitHandler(void);
154 static int AddHandler(osi_socket fd, void (*aproc)(osi_socket));
155 static int FindHandler(osi_socket afd);
156 static int FindHandler_r(osi_socket afd);
157 static int RemoveHandler(osi_socket afd);
158 #if defined(HAVE_POLL) && defined (AFS_PTHREAD_ENV)
159 static void CallHandler(struct pollfd *fds, int nfds, int mask);
160 static void GetHandler(struct pollfd *fds, int maxfds, int events, int *nfds);
162 static void CallHandler(fd_set * fdsetp);
163 static void GetHandler(fd_set * fdsetp, int *maxfdp);
167 static afs_int32 FSYNC_com_VolOp(osi_socket fd, SYNC_command * com, SYNC_response * res);
169 #ifdef AFS_DEMAND_ATTACH_FS
170 static afs_int32 FSYNC_com_VolError(FSSYNC_VolOp_command * com, SYNC_response * res);
172 static afs_int32 FSYNC_com_VolOn(FSSYNC_VolOp_command * com, SYNC_response * res);
173 static afs_int32 FSYNC_com_VolOff(FSSYNC_VolOp_command * com, SYNC_response * res);
174 static afs_int32 FSYNC_com_VolMove(FSSYNC_VolOp_command * com, SYNC_response * res);
175 static afs_int32 FSYNC_com_VolBreakCBKs(FSSYNC_VolOp_command * com, SYNC_response * res);
176 static afs_int32 FSYNC_com_VolDone(FSSYNC_VolOp_command * com, SYNC_response * res);
177 static afs_int32 FSYNC_com_VolQuery(FSSYNC_VolOp_command * com, SYNC_response * res);
178 static afs_int32 FSYNC_com_VolHdrQuery(FSSYNC_VolOp_command * com, SYNC_response * res);
179 #ifdef AFS_DEMAND_ATTACH_FS
180 static afs_int32 FSYNC_com_VolOpQuery(FSSYNC_VolOp_command * com, SYNC_response * res);
181 static afs_int32 FSYNC_com_VGQuery(FSSYNC_VolOp_command * com, SYNC_response * res);
182 static afs_int32 FSYNC_com_VGUpdate(SYNC_command * com, SYNC_response * res);
183 static afs_int32 FSYNC_com_VGScan(FSSYNC_VolOp_command * com, SYNC_response * res);
184 static afs_int32 FSYNC_com_VGScanAll(FSSYNC_VolOp_command * com, SYNC_response * res);
185 #endif /* AFS_DEMAND_ATTACH_FS */
187 static afs_int32 FSYNC_com_VnQry(osi_socket fd, SYNC_command * com, SYNC_response * res);
189 static afs_int32 FSYNC_com_StatsOp(osi_socket fd, SYNC_command * com, SYNC_response * res);
191 static afs_int32 FSYNC_com_StatsOpGeneral(FSSYNC_StatsOp_command * scom, SYNC_response * res);
193 #ifdef AFS_DEMAND_ATTACH_FS
194 static afs_int32 FSYNC_com_StatsOpViceP(FSSYNC_StatsOp_command * scom, SYNC_response * res);
195 static afs_int32 FSYNC_com_StatsOpHash(FSSYNC_StatsOp_command * scom, SYNC_response * res);
196 static afs_int32 FSYNC_com_StatsOpHdr(FSSYNC_StatsOp_command * scom, SYNC_response * res);
197 static afs_int32 FSYNC_com_StatsOpVLRU(FSSYNC_StatsOp_command * scom, SYNC_response * res);
200 static void FSYNC_com_to_info(FSSYNC_VolOp_command * vcom, FSSYNC_VolOp_info * info);
202 static int FSYNC_partMatch(FSSYNC_VolOp_command * vcom, Volume * vp, int match_anon);
206 * This lock controls access to the handler array. The overhead
207 * is minimal in non-preemptive environments.
209 struct Lock FSYNC_handler_lock;
214 #ifdef AFS_PTHREAD_ENV
216 pthread_attr_t tattr;
217 #else /* AFS_PTHREAD_ENV */
219 #endif /* AFS_PTHREAD_ENV */
221 Lock_Init(&FSYNC_handler_lock);
223 #ifdef AFS_PTHREAD_ENV
224 assert(pthread_attr_init(&tattr) == 0);
225 assert(pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED) == 0);
226 assert(pthread_create(&tid, &tattr, FSYNC_sync, NULL) == 0);
227 #else /* AFS_PTHREAD_ENV */
228 assert(LWP_CreateProcess
229 (FSYNC_sync, USUAL_STACK_SIZE, USUAL_PRIORITY, (void *)0,
230 "FSYNC_sync", &pid) == LWP_SUCCESS);
231 #endif /* AFS_PTHREAD_ENV */
233 #ifdef AFS_DEMAND_ATTACH_FS
234 queue_Init(&fsync_salv.head);
235 assert(pthread_cond_init(&fsync_salv.cv, NULL) == 0);
236 assert(pthread_create(&tid, &tattr, FSYNC_salvageThread, NULL) == 0);
237 #endif /* AFS_DEMAND_ATTACH_FS */
240 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
241 static struct pollfd FSYNC_readfds[MAXHANDLERS];
243 static fd_set FSYNC_readfds;
248 FSYNC_sync(void * args)
252 #ifdef AFS_PTHREAD_ENV
255 SYNC_server_state_t * state = &fssync_server_state;
256 #ifdef AFS_DEMAND_ATTACH_FS
257 VThreadOptions_t * thread_opts;
261 * For non-DAFS, only wait until we begin attaching volumes (instead
262 * of waiting until all volumes are attached), since it can take
263 * awhile until VInit == 2.
266 #endif /* AFS_DEMAND_ATTACH_FS */
268 SYNC_getAddr(&state->endpoint, &state->addr);
269 SYNC_cleanupSock(state);
272 (void)signal(SIGPIPE, SIG_IGN);
275 #ifdef AFS_PTHREAD_ENV
276 /* set our 'thread-id' so that the host hold table works */
277 MUTEX_ENTER(&rx_stats_mutex); /* protects rxi_pthread_hinum */
278 tid = ++rxi_pthread_hinum;
279 MUTEX_EXIT(&rx_stats_mutex);
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 */
284 while (VInit < min_vinit) {
285 /* Let somebody else run until all volumes have been preattached
286 * (DAFS), or we have started attaching volumes (non-DAFS). This
287 * doesn't mean that all volumes have been attached.
289 #ifdef AFS_PTHREAD_ENV
291 #else /* AFS_PTHREAD_ENV */
292 LWP_DispatchProcess();
293 #endif /* AFS_PTHREAD_ENV */
295 state->fd = SYNC_getSock(&state->endpoint);
296 code = SYNC_bindSock(state);
299 #ifdef AFS_DEMAND_ATTACH_FS
301 * make sure the volume package is incapable of recursively executing
302 * salvsync calls on this thread, since there is a possibility of
305 thread_opts = malloc(sizeof(VThreadOptions_t));
306 if (thread_opts == NULL) {
307 Log("failed to allocate memory for thread-specific volume package options structure\n");
310 memcpy(thread_opts, &VThread_defaults, sizeof(VThread_defaults));
311 thread_opts->disallow_salvsync = 1;
312 assert(pthread_setspecific(VThread_key, thread_opts) == 0);
314 code = VVGCache_PkgInit();
322 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
324 GetHandler(FSYNC_readfds, MAXHANDLERS, POLLIN|POLLPRI, &nfds);
325 if (poll(FSYNC_readfds, nfds, -1) >=1)
326 CallHandler(FSYNC_readfds, nfds, POLLIN|POLLPRI);
329 GetHandler(&FSYNC_readfds, &maxfd);
330 /* Note: check for >= 1 below is essential since IOMGR_select
331 * doesn't have exactly same semantics as select.
333 #ifdef AFS_PTHREAD_ENV
334 if (select(maxfd + 1, &FSYNC_readfds, NULL, NULL, NULL) >= 1)
335 #else /* AFS_PTHREAD_ENV */
336 if (IOMGR_Select(maxfd + 1, &FSYNC_readfds, NULL, NULL, NULL) >= 1)
337 #endif /* AFS_PTHREAD_ENV */
338 CallHandler(&FSYNC_readfds);
341 return NULL; /* hush now, little gcc */
344 #ifdef AFS_DEMAND_ATTACH_FS
346 * thread for salvaging volumes in the background.
348 * Since FSSYNC handlers cannot issue SALVSYNC requests in order to avoid
349 * deadlock issues, this thread exists so code in the FSSYNC handler thread
350 * can hand off volumes to be salvaged in the background.
352 * @param[in] args unused
354 * @note DEMAND_ATTACH_FS only
357 FSYNC_salvageThread(void * args)
360 struct fsync_salv_node *node;
365 while (queue_IsEmpty(&fsync_salv.head)) {
366 VOL_CV_WAIT(&fsync_salv.cv);
369 node = queue_First(&fsync_salv.head, fsync_salv_node);
373 if (node->update_salv_prio) {
374 if (VUpdateSalvagePriority_r(vp)) {
375 ViceLog(0, ("FSYNC_salvageThread: unable to raise salvage priority "
376 "for volume %lu\n", afs_printable_uint32_lu(vp->hashid)));
383 VCancelReservation_r(vp);
392 * salvage a volume in the background.
394 * Salvages cannot be scheduled directly from the main FSYNC thread, so
395 * instead call this function to schedule a salvage asynchronously in the
396 * FSYNC_salvageThread thread.
398 * @param[in] vp volume to pointer to salvage
402 * @note DEMAND_ATTACH_FS only
405 FSYNC_backgroundSalvage(Volume *vp)
407 struct fsync_salv_node *node;
410 VCreateReservation_r(vp);
412 node = malloc(sizeof(struct fsync_salv_node));
415 /* Save this value, to know if we should VUpdateSalvagePriority_r.
416 * We need to save it here, snce VRequestSalvage_r will change it. */
417 node->update_salv_prio = vp->salvage.requested;
419 if (VRequestSalvage_r(&ec, vp, SALVSYNC_ERROR, 0)) {
420 ViceLog(0, ("FSYNC_backgroundSalvage: unable to request salvage for volume %lu\n",
421 afs_printable_uint32_lu(vp->hashid)));
424 queue_Append(&fsync_salv.head, node);
425 assert(pthread_cond_broadcast(&fsync_salv.cv) == 0);
427 #endif /* AFS_DEMAND_ATTACH_FS */
430 FSYNC_newconnection(osi_socket afd)
432 #ifdef USE_UNIX_SOCKETS
433 struct sockaddr_un other;
434 #else /* USE_UNIX_SOCKETS */
435 struct sockaddr_in other;
439 junk = sizeof(other);
440 fd = accept(afd, (struct sockaddr *)&other, &junk);
442 Log("FSYNC_newconnection: accept failed, errno==%d\n", errno);
444 } else if (!AddHandler(fd, FSYNC_com)) {
446 assert(AddHandler(fd, FSYNC_com));
450 /* this function processes commands from an fssync file descriptor (fd) */
451 afs_int32 FS_cnt = 0;
453 FSYNC_com(osi_socket fd)
457 SYNC_PROTO_BUF_DECL(com_buf);
458 SYNC_PROTO_BUF_DECL(res_buf);
460 memset(&res.hdr, 0, sizeof(res.hdr));
462 com.payload.buf = (void *)com_buf;
463 com.payload.len = SYNC_PROTO_MAX_LEN;
464 res.hdr.response_len = sizeof(res.hdr);
465 res.payload.len = SYNC_PROTO_MAX_LEN;
466 res.payload.buf = (void *)res_buf;
469 if (SYNC_getCom(&fssync_server_state, fd, &com)) {
470 Log("FSYNC_com: read failed; dropping connection (cnt=%d)\n", FS_cnt);
475 if (com.recv_len < sizeof(com.hdr)) {
476 Log("FSSYNC_com: invalid protocol message length (%u)\n", com.recv_len);
477 res.hdr.response = SYNC_COM_ERROR;
478 res.hdr.reason = SYNC_REASON_MALFORMED_PACKET;
479 res.hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
483 if (com.hdr.proto_version != FSYNC_PROTO_VERSION) {
484 Log("FSYNC_com: invalid protocol version (%u)\n", com.hdr.proto_version);
485 res.hdr.response = SYNC_COM_ERROR;
486 res.hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
490 if (com.hdr.command == SYNC_COM_CHANNEL_CLOSE) {
491 res.hdr.response = SYNC_OK;
492 res.hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
494 /* don't respond, just drop; senders of SYNC_COM_CHANNEL_CLOSE
495 * never wait for a response. */
499 res.hdr.com_seq = com.hdr.com_seq;
502 switch (com.hdr.command) {
504 case FSYNC_VOL_ATTACH:
505 case FSYNC_VOL_LEAVE_OFF:
507 case FSYNC_VOL_FORCE_ERROR:
508 case FSYNC_VOL_LISTVOLUMES:
509 case FSYNC_VOL_NEEDVOLUME:
511 case FSYNC_VOL_BREAKCBKS:
513 case FSYNC_VOL_QUERY:
514 case FSYNC_VOL_QUERY_HDR:
515 case FSYNC_VOL_QUERY_VOP:
516 #ifdef AFS_DEMAND_ATTACH_FS
519 case FSYNC_VG_SCAN_ALL:
521 res.hdr.response = FSYNC_com_VolOp(fd, &com, &res);
523 case FSYNC_VOL_STATS_GENERAL:
524 case FSYNC_VOL_STATS_VICEP:
525 case FSYNC_VOL_STATS_HASH:
526 case FSYNC_VOL_STATS_HDR:
527 case FSYNC_VOL_STATS_VLRU:
528 res.hdr.response = FSYNC_com_StatsOp(fd, &com, &res);
530 case FSYNC_VOL_QUERY_VNODE:
531 res.hdr.response = FSYNC_com_VnQry(fd, &com, &res);
533 #ifdef AFS_DEMAND_ATTACH_FS
536 res.hdr.response = FSYNC_com_VGUpdate(&com, &res);
540 res.hdr.response = SYNC_BAD_COMMAND;
546 SYNC_putRes(&fssync_server_state, fd, &res);
549 if (res.hdr.flags & SYNC_FLAG_CHANNEL_SHUTDOWN) {
555 FSYNC_com_VolOp(osi_socket fd, SYNC_command * com, SYNC_response * res)
558 afs_int32 code = SYNC_OK;
559 FSSYNC_VolOp_command vcom;
561 if (com->recv_len != (sizeof(com->hdr) + sizeof(FSSYNC_VolOp_hdr))) {
562 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
563 res->hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
564 return SYNC_COM_ERROR;
567 vcom.hdr = &com->hdr;
568 vcom.vop = (FSSYNC_VolOp_hdr *) com->payload.buf;
571 vcom.volumes = OfflineVolumes[FindHandler(fd)];
572 for (vcom.v = NULL, i = 0; i < MAXOFFLINEVOLUMES; i++) {
573 if ((vcom.volumes[i].volumeID == vcom.vop->volume) &&
574 (strncmp(vcom.volumes[i].partName, vcom.vop->partName,
575 sizeof(vcom.volumes[i].partName)) == 0)) {
576 vcom.v = &vcom.volumes[i];
581 switch (com->hdr.command) {
583 case FSYNC_VOL_ATTACH:
584 case FSYNC_VOL_LEAVE_OFF:
585 code = FSYNC_com_VolOn(&vcom, res);
588 case FSYNC_VOL_NEEDVOLUME:
589 code = FSYNC_com_VolOff(&vcom, res);
591 case FSYNC_VOL_LISTVOLUMES:
595 code = FSYNC_com_VolMove(&vcom, res);
597 case FSYNC_VOL_BREAKCBKS:
598 code = FSYNC_com_VolBreakCBKs(&vcom, res);
601 code = FSYNC_com_VolDone(&vcom, res);
603 case FSYNC_VOL_QUERY:
604 code = FSYNC_com_VolQuery(&vcom, res);
606 case FSYNC_VOL_QUERY_HDR:
607 code = FSYNC_com_VolHdrQuery(&vcom, res);
609 #ifdef AFS_DEMAND_ATTACH_FS
610 case FSYNC_VOL_FORCE_ERROR:
611 code = FSYNC_com_VolError(&vcom, res);
613 case FSYNC_VOL_QUERY_VOP:
614 code = FSYNC_com_VolOpQuery(&vcom, res);
617 code = FSYNC_com_VGQuery(&vcom, res);
620 code = FSYNC_com_VGScan(&vcom, res);
622 case FSYNC_VG_SCAN_ALL:
623 code = FSYNC_com_VGScanAll(&vcom, res);
625 #endif /* AFS_DEMAND_ATTACH_FS */
627 code = SYNC_BAD_COMMAND;
634 * service an FSYNC request to bring a volume online.
636 * @param[in] vcom pointer command object
637 * @param[out] res object in which to store response packet
639 * @return operation status
640 * @retval SYNC_OK volume transitioned online
641 * @retval SYNC_FAILED invalid command protocol message
642 * @retval SYNC_DENIED operation could not be completed
644 * @note this is an FSYNC RPC server stub
646 * @note this procedure handles the following FSSYNC command codes:
649 * - FSYNC_VOL_LEAVE_OFF
651 * @note the supplementary reason code contains additional details.
652 * When SYNC_DENIED is returned, the specific reason is
653 * placed in the response packet reason field.
658 FSYNC_com_VolOn(FSSYNC_VolOp_command * vcom, SYNC_response * res)
660 afs_int32 code = SYNC_OK;
661 #ifndef AFS_DEMAND_ATTACH_FS
662 char tvolName[VMAXPATHLEN];
667 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
668 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
673 /* so, we need to attach the volume */
675 #ifdef AFS_DEMAND_ATTACH_FS
676 /* check DAFS permissions */
677 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
679 FSYNC_partMatch(vcom, vp, 1) &&
680 vp->pending_vol_op &&
681 (vcom->hdr->programType != vp->pending_vol_op->com.programType)) {
682 /* a different program has this volume checked out. deny. */
683 Log("FSYNC_VolOn: WARNING: program type %u has attempted to manipulate "
684 "state for volume %u using command code %u while the volume is "
685 "checked out by program type %u for command code %u.\n",
686 vcom->hdr->programType,
689 vp->pending_vol_op->com.programType,
690 vp->pending_vol_op->com.command);
692 res->hdr.reason = FSYNC_EXCLUSIVE;
698 vcom->v->volumeID = 0;
701 if (vcom->hdr->command == FSYNC_VOL_LEAVE_OFF) {
702 /* nothing much to do if we're leaving the volume offline */
703 #ifdef AFS_DEMAND_ATTACH_FS
705 if (FSYNC_partMatch(vcom, vp, 1)) {
706 if ((V_attachState(vp) == VOL_STATE_UNATTACHED) ||
707 (V_attachState(vp) == VOL_STATE_PREATTACHED)) {
708 VChangeState_r(vp, VOL_STATE_UNATTACHED);
709 VDeregisterVolOp_r(vp);
712 res->hdr.reason = FSYNC_BAD_STATE;
716 res->hdr.reason = FSYNC_WRONG_PART;
720 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
726 #ifdef AFS_DEMAND_ATTACH_FS
727 /* first, check to see whether we have such a volume defined */
728 vp = VPreAttachVolumeById_r(&error,
732 VDeregisterVolOp_r(vp);
734 #else /* !AFS_DEMAND_ATTACH_FS */
736 snprintf(&tvolName[1], sizeof(tvolName)-1, VFORMAT, afs_printable_uint32_lu(vcom->vop->volume));
737 tvolName[sizeof(tvolName)-1] = '\0';
739 vp = VAttachVolumeByName_r(&error, vcom->vop->partName, tvolName,
745 res->hdr.reason = error;
747 #endif /* !AFS_DEMAND_ATTACH_FS */
754 * service an FSYNC request to take a volume offline.
756 * @param[in] vcom pointer command object
757 * @param[out] res object in which to store response packet
759 * @return operation status
760 * @retval SYNC_OK volume transitioned offline
761 * @retval SYNC_FAILED invalid command protocol message
762 * @retval SYNC_DENIED operation could not be completed
764 * @note this is an FSYNC RPC server stub
766 * @note this procedure handles the following FSSYNC command codes:
768 * - FSYNC_VOL_NEEDVOLUME
770 * @note the supplementary reason code contains additional details.
771 * When SYNC_DENIED is returned, the specific reason is
772 * placed in the response packet reason field.
777 FSYNC_com_VolOff(FSSYNC_VolOp_command * vcom, SYNC_response * res)
779 FSSYNC_VolOp_info info;
780 afs_int32 code = SYNC_OK;
784 #ifdef AFS_DEMAND_ATTACH_FS
785 Volume *nvp, *rvp = NULL;
788 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
789 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
794 /* not already offline, we need to find a slot for newly offline volume */
795 if (vcom->hdr->programType == debugUtility) {
796 /* debug utilities do not have their operations tracked */
800 for (i = 0; i < MAXOFFLINEVOLUMES; i++) {
801 if (vcom->volumes[i].volumeID == 0) {
802 vcom->v = &vcom->volumes[i];
812 FSYNC_com_to_info(vcom, &info);
814 #ifdef AFS_DEMAND_ATTACH_FS
815 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
817 vp = VGetVolume_r(&error, vcom->vop->volume);
821 if (!FSYNC_partMatch(vcom, vp, 1)) {
822 /* volume on desired partition is not online, so we
823 * should treat this as an offline volume.
825 #ifndef AFS_DEMAND_ATTACH_FS
833 #ifdef AFS_DEMAND_ATTACH_FS
835 ProgramType type = (ProgramType) vcom->hdr->programType;
837 /* do initial filtering of requests */
839 /* enforce mutual exclusion for volume ops */
840 if (vp->pending_vol_op) {
841 if (vp->pending_vol_op->com.programType != type) {
842 if (vp->pending_vol_op->com.command == FSYNC_VOL_OFF &&
843 vp->pending_vol_op->com.reason == FSYNC_SALVAGE) {
845 Log("denying offline request for volume %lu; volume is salvaging\n",
846 afs_printable_uint32_lu(vp->hashid));
848 res->hdr.reason = FSYNC_SALVAGE;
851 Log("volume %u already checked out\n", vp->hashid);
853 Log("vp->vop = { com = { ver=%u, prog=%d, com=%d, reason=%d, len=%u, flags=0x%x }, vop = { vol=%u, part='%s' } }\n",
854 vp->pending_vol_op->com.proto_version,
855 vp->pending_vol_op->com.programType,
856 vp->pending_vol_op->com.command,
857 vp->pending_vol_op->com.reason,
858 vp->pending_vol_op->com.command_len,
859 vp->pending_vol_op->com.flags,
860 vp->pending_vol_op->vop.volume,
861 vp->pending_vol_op->vop.partName );
862 Log("vcom = { com = { ver=%u, prog=%d, com=%d, reason=%d, len=%u, flags=0x%x } , vop = { vol=%u, part='%s' } }\n",
863 vcom->hdr->proto_version,
864 vcom->hdr->programType,
867 vcom->hdr->command_len,
870 vcom->vop->partName);
871 res->hdr.reason = FSYNC_EXCLUSIVE;
874 Log("warning: volume %u recursively checked out by programType id %d\n",
875 vp->hashid, vcom->hdr->programType);
879 /* wait for exclusive ops, so we have an accurate picture of the
880 * vol attach state */
881 VCreateReservation_r(vp);
882 VWaitExclusiveState_r(vp);
885 /* filter based upon requestor
887 * volume utilities / volserver are not allowed to check out
888 * volumes which are in an error state
890 * unknown utility programs will be denied on principal
894 /* it is possible for the salvageserver to checkout a
895 * volume for salvage before its scheduling request
896 * has been sent to the salvageserver */
897 if (vp->salvage.requested && !vp->salvage.scheduled) {
898 vp->salvage.scheduled = 1;
905 if (V_attachState(vp) == VOL_STATE_SALVAGING ||
906 vp->salvage.requested) {
908 Log("denying offline request for volume %lu; volume is in salvaging state\n",
909 afs_printable_uint32_lu(vp->hashid));
910 res->hdr.reason = FSYNC_SALVAGE;
912 /* the volume hasn't been checked out yet by the salvager,
913 * but we think the volume is salvaging; schedule a
914 * a salvage to update the salvage priority */
915 FSYNC_backgroundSalvage(vp);
919 if (VIsErrorState(V_attachState(vp))) {
925 Log("bad program type passed to FSSYNC\n");
929 /* short circuit for offline volume states
930 * so we can avoid I/O penalty of attachment */
931 switch (V_attachState(vp)) {
932 case VOL_STATE_UNATTACHED:
933 case VOL_STATE_PREATTACHED:
934 case VOL_STATE_SALVAGING:
935 case VOL_STATE_ERROR:
936 /* register the volume operation metadata with the volume
938 * if the volume is currently pre-attached, attach2()
939 * will evaluate the vol op metadata to determine whether
940 * attaching the volume would be safe */
941 VRegisterVolOp_r(vp, &info);
942 vp->pending_vol_op->vol_op_state = FSSYNC_VolOpRunningUnknown;
948 /* convert to heavyweight ref */
949 nvp = VGetVolumeByVp_r(&error, vp);
950 VCancelReservation_r(rvp);
955 * It's possible for VGetVolumeByVp_r to have dropped and
956 * re-acquired VOL_LOCK, so volume state may have changed
957 * back to one of the states we tested for above. Since
958 * GetVolume can return NULL in some of those states, just
959 * test for the states again here.
961 switch (V_attachState(vp)) {
962 case VOL_STATE_UNATTACHED:
963 case VOL_STATE_PREATTACHED:
964 case VOL_STATE_SALVAGING:
965 case VOL_STATE_ERROR:
966 /* register the volume operation metadata with the volume
968 * if the volume is currently pre-attached, attach2()
969 * will evaluate the vol op metadata to determine whether
970 * attaching the volume would be safe */
971 VRegisterVolOp_r(vp, &info);
972 vp->pending_vol_op->vol_op_state = FSSYNC_VolOpRunningUnknown;
978 Log("FSYNC_com_VolOff: failed to get heavyweight reference to volume %u\n",
980 res->hdr.reason = FSYNC_VOL_PKG_ERROR;
982 } else if (nvp != vp) {
983 /* i don't think this should ever happen, but just in case... */
984 Log("FSYNC_com_VolOff: warning: potentially dangerous race detected\n");
988 /* register the volume operation metadata with the volume */
989 VRegisterVolOp_r(vp, &info);
992 #endif /* AFS_DEMAND_ATTACH_FS */
995 if (VVolOpLeaveOnline_r(vp, &info)) {
996 VUpdateVolume_r(&error, vp, VOL_UPDATE_WAIT); /* At least get volume stats right */
998 Log("FSYNC: Volume %u (%s) was left on line for an external %s request\n",
999 V_id(vp), V_name(vp),
1000 vcom->hdr->reason == V_CLONE ? "clone" :
1001 vcom->hdr->reason == V_READONLY ? "readonly" :
1002 vcom->hdr->reason == V_DUMP ? "dump" :
1003 vcom->hdr->reason == FSYNC_SALVAGE ? "salvage" :
1006 #ifdef AFS_DEMAND_ATTACH_FS
1007 vp->pending_vol_op->vol_op_state = FSSYNC_VolOpRunningOnline;
1011 if (VVolOpSetVBusy_r(vp, &info)) {
1012 vp->specialStatus = VBUSY;
1015 /* remember what volume we got, so we can keep track of how
1016 * many volumes the volserver or whatever is using. Note that
1017 * vp is valid since leaveonline is only set when vp is valid.
1020 vcom->v->volumeID = vcom->vop->volume;
1021 strlcpy(vcom->v->partName, vp->partition->name, sizeof(vcom->v->partName));
1024 #ifdef AFS_DEMAND_ATTACH_FS
1025 VOfflineForVolOp_r(&error, vp, "A volume utility is running.");
1027 assert(vp->nUsers==0);
1028 vp->pending_vol_op->vol_op_state = FSSYNC_VolOpRunningOffline;
1031 VDeregisterVolOp_r(vp);
1035 VOffline_r(vp, "A volume utility is running.");
1046 #ifdef AFS_DEMAND_ATTACH_FS
1048 VCancelReservation_r(rvp);
1055 * service an FSYNC request to mark a volume as moved.
1057 * @param[in] vcom pointer command object
1058 * @param[out] res object in which to store response packet
1060 * @return operation status
1061 * @retval SYNC_OK volume marked as moved to a remote server
1062 * @retval SYNC_FAILED invalid command protocol message
1063 * @retval SYNC_DENIED current volume state does not permit this operation
1065 * @note this is an FSYNC RPC server stub
1067 * @note this operation also breaks all callbacks for the given volume
1069 * @note this procedure handles the following FSSYNC command codes:
1072 * @note the supplementary reason code contains additional details. For
1073 * instance, SYNC_OK is still returned when the partition specified
1074 * does not match the one registered in the volume object -- reason
1075 * will be FSYNC_WRONG_PART in this case.
1080 FSYNC_com_VolMove(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1082 afs_int32 code = SYNC_DENIED;
1086 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1087 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1092 /* Yuch: the "reason" for the move is the site it got moved to... */
1093 /* still set specialStatus so we stop sending back VBUSY.
1094 * also should still break callbacks. Note that I don't know
1095 * how to tell if we should break all or not, so we just do it
1096 * since it doesn't matter much if we do an extra break
1097 * volume callbacks on a volume move within the same server */
1098 #ifdef AFS_DEMAND_ATTACH_FS
1099 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
1101 vp = VGetVolume_r(&error, vcom->vop->volume);
1104 if (FSYNC_partMatch(vcom, vp, 1)) {
1105 #ifdef AFS_DEMAND_ATTACH_FS
1106 if ((V_attachState(vp) == VOL_STATE_UNATTACHED) ||
1107 (V_attachState(vp) == VOL_STATE_PREATTACHED)) {
1110 vp->specialStatus = VMOVED;
1111 #ifdef AFS_DEMAND_ATTACH_FS
1113 res->hdr.reason = FSYNC_BAD_STATE;
1117 res->hdr.reason = FSYNC_WRONG_PART;
1119 #ifndef AFS_DEMAND_ATTACH_FS
1121 #endif /* !AFS_DEMAND_ATTACH_FS */
1123 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1126 if ((code == SYNC_OK) && (V_BreakVolumeCallbacks != NULL)) {
1127 Log("fssync: volume %u moved to %x; breaking all call backs\n",
1128 vcom->vop->volume, vcom->hdr->reason);
1130 (*V_BreakVolumeCallbacks) (vcom->vop->volume);
1140 * service an FSYNC request to mark a volume as destroyed.
1142 * @param[in] vcom pointer command object
1143 * @param[out] res object in which to store response packet
1145 * @return operation status
1146 * @retval SYNC_OK volume marked as destroyed
1147 * @retval SYNC_FAILED invalid command protocol message
1148 * @retval SYNC_DENIED current volume state does not permit this operation
1150 * @note this is an FSYNC RPC server stub
1152 * @note this procedure handles the following FSSYNC command codes:
1155 * @note the supplementary reason code contains additional details. For
1156 * instance, SYNC_OK is still returned when the partition specified
1157 * does not match the one registered in the volume object -- reason
1158 * will be FSYNC_WRONG_PART in this case.
1163 FSYNC_com_VolDone(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1165 afs_int32 code = SYNC_FAILED;
1166 #ifdef AFS_DEMAND_ATTACH_FS
1171 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1172 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1176 /* don't try to put online, this call is made only after deleting
1177 * a volume, in which case we want to remove the vol # from the
1178 * OfflineVolumes array only */
1180 vcom->v->volumeID = 0;
1182 #ifdef AFS_DEMAND_ATTACH_FS
1183 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
1185 if (FSYNC_partMatch(vcom, vp, 1)) {
1186 if ((V_attachState(vp) == VOL_STATE_UNATTACHED) ||
1187 (V_attachState(vp) == VOL_STATE_PREATTACHED)) {
1188 VChangeState_r(vp, VOL_STATE_UNATTACHED);
1189 VDeregisterVolOp_r(vp);
1193 res->hdr.reason = FSYNC_BAD_STATE;
1196 code = SYNC_OK; /* XXX is this really a good idea? */
1197 res->hdr.reason = FSYNC_WRONG_PART;
1200 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1208 #ifdef AFS_DEMAND_ATTACH_FS
1210 * service an FSYNC request to transition a volume to the hard error state.
1212 * @param[in] vcom pointer command object
1213 * @param[out] res object in which to store response packet
1215 * @return operation status
1216 * @retval SYNC_OK volume transitioned to hard error state
1217 * @retval SYNC_FAILED invalid command protocol message
1218 * @retval SYNC_DENIED (see note)
1220 * @note this is an FSYNC RPC server stub
1222 * @note this procedure handles the following FSSYNC command codes:
1223 * - FSYNC_VOL_FORCE_ERROR
1225 * @note SYNC_DENIED is returned in the following cases:
1226 * - no partition name is specified (reason field set to
1227 * FSYNC_WRONG_PART).
1228 * - volume id not known to fileserver (reason field set
1229 * to FSYNC_UNKNOWN_VOLID).
1231 * @note demand attach fileserver only
1236 FSYNC_com_VolError(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1240 afs_int32 code = SYNC_FAILED;
1242 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1243 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1247 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
1249 if (FSYNC_partMatch(vcom, vp, 0)) {
1250 /* null out salvsync control state, as it's no longer relevant */
1251 memset(&vp->salvage, 0, sizeof(vp->salvage));
1252 VDeregisterVolOp_r(vp);
1254 if (vcom->hdr->reason == FSYNC_SALVAGE) {
1255 FSYNC_backgroundSalvage(vp);
1257 VChangeState_r(vp, VOL_STATE_ERROR);
1262 res->hdr.reason = FSYNC_WRONG_PART;
1265 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1271 #endif /* AFS_DEMAND_ATTACH_FS */
1274 * service an FSYNC request to break all callbacks for this volume.
1276 * @param[in] vcom pointer command object
1277 * @param[out] res object in which to store response packet
1279 * @return operation status
1280 * @retval SYNC_OK callback breaks scheduled for volume
1282 * @note this is an FSYNC RPC server stub
1284 * @note this procedure handles the following FSSYNC command codes:
1285 * - FSYNC_VOL_BREAKCBKS
1287 * @note demand attach fileserver only
1289 * @todo should do partition matching
1294 FSYNC_com_VolBreakCBKs(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1296 /* if the volume is being restored, break all callbacks on it */
1297 if (V_BreakVolumeCallbacks) {
1298 Log("fssync: breaking all call backs for volume %u\n",
1301 (*V_BreakVolumeCallbacks) (vcom->vop->volume);
1308 * service an FSYNC request to return the Volume object.
1310 * @param[in] vcom pointer command object
1311 * @param[out] res object in which to store response packet
1313 * @return operation status
1314 * @retval SYNC_OK volume object returned to caller
1315 * @retval SYNC_FAILED bad command packet, or failed to locate volume object
1317 * @note this is an FSYNC RPC server stub
1319 * @note this procedure handles the following FSSYNC command codes:
1325 FSYNC_com_VolQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1327 afs_int32 code = SYNC_FAILED;
1331 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1332 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1336 #ifdef AFS_DEMAND_ATTACH_FS
1337 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
1338 #else /* !AFS_DEMAND_ATTACH_FS */
1339 vp = VGetVolume_r(&error, vcom->vop->volume);
1340 #endif /* !AFS_DEMAND_ATTACH_FS */
1343 if (FSYNC_partMatch(vcom, vp, 1)) {
1344 if (res->payload.len >= sizeof(Volume)) {
1345 memcpy(res->payload.buf, vp, sizeof(Volume));
1346 res->hdr.response_len += sizeof(Volume);
1349 res->hdr.reason = SYNC_REASON_PAYLOAD_TOO_BIG;
1352 res->hdr.reason = FSYNC_WRONG_PART;
1354 #ifndef AFS_DEMAND_ATTACH_FS
1358 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1366 * service an FSYNC request to return the Volume header.
1368 * @param[in] vcom pointer command object
1369 * @param[out] res object in which to store response packet
1371 * @return operation status
1372 * @retval SYNC_OK volume header returned to caller
1373 * @retval SYNC_FAILED bad command packet, or failed to locate volume header
1375 * @note this is an FSYNC RPC server stub
1377 * @note this procedure handles the following FSSYNC command codes:
1378 * - FSYNC_VOL_QUERY_HDR
1383 FSYNC_com_VolHdrQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1385 afs_int32 code = SYNC_FAILED;
1389 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1390 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1393 if (res->payload.len < sizeof(VolumeDiskData)) {
1394 res->hdr.reason = SYNC_REASON_PAYLOAD_TOO_BIG;
1398 #ifdef AFS_DEMAND_ATTACH_FS
1399 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
1400 #else /* !AFS_DEMAND_ATTACH_FS */
1401 vp = VGetVolume_r(&error, vcom->vop->volume);
1405 if (FSYNC_partMatch(vcom, vp, 1)) {
1406 #ifdef AFS_DEMAND_ATTACH_FS
1407 if ((vp->header == NULL) ||
1408 !(V_attachFlags(vp) & VOL_HDR_ATTACHED) ||
1409 !(V_attachFlags(vp) & VOL_HDR_LOADED)) {
1410 res->hdr.reason = FSYNC_HDR_NOT_ATTACHED;
1413 #else /* !AFS_DEMAND_ATTACH_FS */
1414 if (!vp || !vp->header) {
1415 res->hdr.reason = FSYNC_HDR_NOT_ATTACHED;
1418 #endif /* !AFS_DEMAND_ATTACH_FS */
1420 res->hdr.reason = FSYNC_WRONG_PART;
1424 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1428 memcpy(res->payload.buf, &V_disk(vp), sizeof(VolumeDiskData));
1429 res->hdr.response_len += sizeof(VolumeDiskData);
1433 #ifndef AFS_DEMAND_ATTACH_FS
1441 #ifdef AFS_DEMAND_ATTACH_FS
1443 FSYNC_com_VolOpQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1445 afs_int32 code = SYNC_OK;
1449 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
1451 if (vp && vp->pending_vol_op) {
1452 assert(sizeof(FSSYNC_VolOp_info) <= res->payload.len);
1453 memcpy(res->payload.buf, vp->pending_vol_op, sizeof(FSSYNC_VolOp_info));
1454 res->hdr.response_len += sizeof(FSSYNC_VolOp_info);
1457 res->hdr.reason = FSYNC_NO_PENDING_VOL_OP;
1459 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1467 FSYNC_com_VGQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1469 afs_int32 code = SYNC_FAILED;
1471 struct DiskPartition64 * dp;
1473 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1474 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1478 dp = VGetPartition_r(vcom->vop->partName, 0);
1480 res->hdr.reason = FSYNC_BAD_PART;
1484 assert(sizeof(FSSYNC_VGQry_response_t) <= res->payload.len);
1486 rc = VVGCache_query_r(dp, vcom->vop->volume, res->payload.buf);
1489 res->hdr.response_len += sizeof(FSSYNC_VGQry_response_t);
1493 res->hdr.reason = FSYNC_PART_SCANNING;
1496 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1507 FSYNC_com_VGUpdate(SYNC_command * com, SYNC_response * res)
1509 afs_int32 code = SYNC_FAILED;
1510 struct DiskPartition64 * dp;
1511 FSSYNC_VGUpdate_command_t * vgucom;
1514 if (com->recv_len != (sizeof(com->hdr) + sizeof(*vgucom))) {
1515 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1516 res->hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
1517 code = SYNC_COM_ERROR;
1521 vgucom = com->payload.buf;
1523 if (SYNC_verifyProtocolString(vgucom->partName, sizeof(vgucom->partName))) {
1524 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1528 dp = VGetPartition_r(vgucom->partName, 0);
1530 res->hdr.reason = FSYNC_BAD_PART;
1534 switch(com->hdr.command) {
1536 rc = VVGCache_entry_add_r(dp, vgucom->parent, vgucom->child, NULL);
1540 rc = VVGCache_entry_del_r(dp, vgucom->parent, vgucom->child);
1544 Log("FSYNC_com_VGUpdate called improperly\n");
1549 /* EINVAL means the partition VGC doesn't exist at all; not really
1551 if (rc == 0 || rc == EINVAL) {
1556 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1558 res->hdr.reason = FSYNC_WHATEVER;
1566 FSYNC_com_VGScan(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1568 afs_int32 code = SYNC_FAILED;
1569 struct DiskPartition64 * dp;
1571 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1572 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1576 dp = VGetPartition_r(vcom->vop->partName, 0);
1578 res->hdr.reason = FSYNC_BAD_PART;
1582 if (VVGCache_scanStart_r(dp) == 0) {
1591 FSYNC_com_VGScanAll(FSSYNC_VolOp_command * com, SYNC_response * res)
1593 afs_int32 code = SYNC_FAILED;
1595 if (VVGCache_scanStart_r(NULL) == 0) {
1601 #endif /* AFS_DEMAND_ATTACH_FS */
1604 FSYNC_com_VnQry(osi_socket fd, SYNC_command * com, SYNC_response * res)
1606 afs_int32 code = SYNC_OK;
1607 FSSYNC_VnQry_hdr * qry = com->payload.buf;
1612 if (com->recv_len != (sizeof(com->hdr) + sizeof(FSSYNC_VnQry_hdr))) {
1613 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1614 res->hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
1615 return SYNC_COM_ERROR;
1618 #ifdef AFS_DEMAND_ATTACH_FS
1619 vp = VLookupVolume_r(&error, qry->volume, NULL);
1620 #else /* !AFS_DEMAND_ATTACH_FS */
1621 vp = VGetVolume_r(&error, qry->volume);
1622 #endif /* !AFS_DEMAND_ATTACH_FS */
1625 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1630 vnp = VLookupVnode(vp, qry->vnode);
1632 res->hdr.reason = FSYNC_UNKNOWN_VNID;
1637 if (Vn_class(vnp)->residentSize > res->payload.len) {
1638 res->hdr.reason = SYNC_REASON_ENCODING_ERROR;
1643 memcpy(res->payload.buf, vnp, Vn_class(vnp)->residentSize);
1644 res->hdr.response_len += Vn_class(vnp)->residentSize;
1647 #ifndef AFS_DEMAND_ATTACH_FS
1656 FSYNC_com_StatsOp(osi_socket fd, SYNC_command * com, SYNC_response * res)
1658 afs_int32 code = SYNC_OK;
1659 FSSYNC_StatsOp_command scom;
1661 if (com->recv_len != (sizeof(com->hdr) + sizeof(FSSYNC_StatsOp_hdr))) {
1662 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1663 res->hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
1664 return SYNC_COM_ERROR;
1667 scom.hdr = &com->hdr;
1668 scom.sop = (FSSYNC_StatsOp_hdr *) com->payload.buf;
1671 switch (com->hdr.command) {
1672 case FSYNC_VOL_STATS_GENERAL:
1673 code = FSYNC_com_StatsOpGeneral(&scom, res);
1675 #ifdef AFS_DEMAND_ATTACH_FS
1676 /* statistics for the following subsystems are only tracked
1677 * for demand attach fileservers */
1678 case FSYNC_VOL_STATS_VICEP:
1679 code = FSYNC_com_StatsOpViceP(&scom, res);
1681 case FSYNC_VOL_STATS_HASH:
1682 code = FSYNC_com_StatsOpHash(&scom, res);
1684 case FSYNC_VOL_STATS_HDR:
1685 code = FSYNC_com_StatsOpHdr(&scom, res);
1687 case FSYNC_VOL_STATS_VLRU:
1688 code = FSYNC_com_StatsOpVLRU(&scom, res);
1690 #endif /* AFS_DEMAND_ATTACH_FS */
1692 code = SYNC_BAD_COMMAND;
1699 FSYNC_com_StatsOpGeneral(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1701 afs_int32 code = SYNC_OK;
1703 memcpy(res->payload.buf, &VStats, sizeof(VStats));
1704 res->hdr.response_len += sizeof(VStats);
1709 #ifdef AFS_DEMAND_ATTACH_FS
1711 FSYNC_com_StatsOpViceP(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1713 afs_int32 code = SYNC_OK;
1714 struct DiskPartition64 * dp;
1715 struct DiskPartitionStats64 * stats;
1717 if (SYNC_verifyProtocolString(scom->sop->args.partName, sizeof(scom->sop->args.partName))) {
1718 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1723 dp = VGetPartition_r(scom->sop->args.partName, 0);
1727 stats = (struct DiskPartitionStats64 *) res->payload.buf;
1728 stats->free = dp->free;
1729 stats->totalUsable = dp->totalUsable;
1730 stats->minFree = dp->minFree;
1731 stats->f_files = dp->f_files;
1732 stats->vol_list_len = dp->vol_list.len;
1734 res->hdr.response_len += sizeof(struct DiskPartitionStats64);
1742 FSYNC_com_StatsOpHash(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1744 afs_int32 code = SYNC_OK;
1745 struct VolumeHashChainStats * stats;
1746 struct VolumeHashChainHead * head;
1748 if (scom->sop->args.hash_bucket >= VolumeHashTable.Size) {
1752 head = &VolumeHashTable.Table[scom->sop->args.hash_bucket];
1753 stats = (struct VolumeHashChainStats *) res->payload.buf;
1754 stats->table_size = VolumeHashTable.Size;
1755 stats->chain_len = head->len;
1756 stats->chain_cacheCheck = head->cacheCheck;
1757 stats->chain_busy = head->busy;
1758 AssignInt64(head->looks, &stats->chain_looks);
1759 AssignInt64(head->gets, &stats->chain_gets);
1760 AssignInt64(head->reorders, &stats->chain_reorders);
1762 res->hdr.response_len += sizeof(struct VolumeHashChainStats);
1768 FSYNC_com_StatsOpHdr(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1770 afs_int32 code = SYNC_OK;
1772 memcpy(res->payload.buf, &volume_hdr_LRU.stats, sizeof(volume_hdr_LRU.stats));
1773 res->hdr.response_len += sizeof(volume_hdr_LRU.stats);
1779 FSYNC_com_StatsOpVLRU(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1781 afs_int32 code = SYNC_OK;
1783 code = SYNC_BAD_COMMAND;
1787 #endif /* AFS_DEMAND_ATTACH_FS */
1790 * populate an FSSYNC_VolOp_info object from a command packet object.
1792 * @param[in] vcom pointer to command packet
1793 * @param[out] info pointer to info object which will be populated
1795 * @note FSSYNC_VolOp_info objects are attached to Volume objects when
1796 * a volume operation is commenced.
1801 FSYNC_com_to_info(FSSYNC_VolOp_command * vcom, FSSYNC_VolOp_info * info)
1803 memcpy(&info->com, vcom->hdr, sizeof(SYNC_command_hdr));
1804 memcpy(&info->vop, vcom->vop, sizeof(FSSYNC_VolOp_hdr));
1805 info->vol_op_state = FSSYNC_VolOpPending;
1809 * check whether command packet partition name matches volume
1810 * object's partition name.
1812 * @param[in] vcom pointer to command packet
1813 * @param[in] vp pointer to volume object
1814 * @param[in] match_anon anon matching control flag (see note below)
1816 * @return whether partitions match
1817 * @retval 0 partitions do NOT match
1818 * @retval 1 partitions match
1820 * @note if match_anon is non-zero, then this function will return a
1821 * positive match for a zero-length partition string in the
1827 FSYNC_partMatch(FSSYNC_VolOp_command * vcom, Volume * vp, int match_anon)
1829 return ((match_anon && vcom->vop->partName[0] == 0) ||
1830 (strncmp(vcom->vop->partName, V_partition(vp)->name,
1831 sizeof(vcom->vop->partName)) == 0));
1836 FSYNC_Drop(osi_socket fd)
1838 struct offlineInfo *p;
1841 char tvolName[VMAXPATHLEN];
1844 p = OfflineVolumes[FindHandler(fd)];
1845 for (i = 0; i < MAXOFFLINEVOLUMES; i++) {
1846 if (p[i].volumeID) {
1851 sprintf(&tvolName[1], VFORMAT, afs_printable_uint32_lu(p[i].volumeID));
1852 vp = VAttachVolumeByName_r(&error, p[i].partName, tvolName,
1869 static int AcceptHandler = -1; /* handler id for accept, if turned on */
1874 if (AcceptHandler == -1) {
1875 assert(AddHandler(fssync_server_state.fd, FSYNC_newconnection));
1876 AcceptHandler = FindHandler(fssync_server_state.fd);
1883 if (AcceptHandler != -1) {
1884 assert(RemoveHandler(fssync_server_state.fd));
1889 /* The multiple FD handling code. */
1891 static osi_socket HandlerFD[MAXHANDLERS];
1892 static void (*HandlerProc[MAXHANDLERS]) (osi_socket);
1898 ObtainWriteLock(&FSYNC_handler_lock);
1899 for (i = 0; i < MAXHANDLERS; i++) {
1903 ReleaseWriteLock(&FSYNC_handler_lock);
1906 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
1908 CallHandler(struct pollfd *fds, int nfds, int mask)
1912 ObtainReadLock(&FSYNC_handler_lock);
1913 for (i = 0; i < nfds; i++) {
1914 if (fds[i].revents & mask) {
1915 handler = FindHandler_r(fds[i].fd);
1916 ReleaseReadLock(&FSYNC_handler_lock);
1917 (*HandlerProc[handler]) (fds[i].fd);
1918 ObtainReadLock(&FSYNC_handler_lock);
1921 ReleaseReadLock(&FSYNC_handler_lock);
1925 CallHandler(fd_set * fdsetp)
1928 ObtainReadLock(&FSYNC_handler_lock);
1929 for (i = 0; i < MAXHANDLERS; i++) {
1930 if (HandlerFD[i] >= 0 && FD_ISSET(HandlerFD[i], fdsetp)) {
1931 ReleaseReadLock(&FSYNC_handler_lock);
1932 (*HandlerProc[i]) (HandlerFD[i]);
1933 ObtainReadLock(&FSYNC_handler_lock);
1936 ReleaseReadLock(&FSYNC_handler_lock);
1941 AddHandler(osi_socket afd, void (*aproc) (osi_socket))
1944 ObtainWriteLock(&FSYNC_handler_lock);
1945 for (i = 0; i < MAXHANDLERS; i++)
1946 if (HandlerFD[i] == -1)
1948 if (i >= MAXHANDLERS) {
1949 ReleaseWriteLock(&FSYNC_handler_lock);
1953 HandlerProc[i] = aproc;
1954 ReleaseWriteLock(&FSYNC_handler_lock);
1959 FindHandler(register osi_socket afd)
1962 ObtainReadLock(&FSYNC_handler_lock);
1963 for (i = 0; i < MAXHANDLERS; i++)
1964 if (HandlerFD[i] == afd) {
1965 ReleaseReadLock(&FSYNC_handler_lock);
1968 ReleaseReadLock(&FSYNC_handler_lock); /* just in case */
1970 return -1; /* satisfy compiler */
1974 FindHandler_r(register osi_socket afd)
1977 for (i = 0; i < MAXHANDLERS; i++)
1978 if (HandlerFD[i] == afd) {
1982 return -1; /* satisfy compiler */
1986 RemoveHandler(register osi_socket afd)
1988 ObtainWriteLock(&FSYNC_handler_lock);
1989 HandlerFD[FindHandler_r(afd)] = -1;
1990 ReleaseWriteLock(&FSYNC_handler_lock);
1994 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
1996 GetHandler(struct pollfd *fds, int maxfds, int events, int *nfds)
2000 ObtainReadLock(&FSYNC_handler_lock);
2001 for (i = 0; i < MAXHANDLERS; i++)
2002 if (HandlerFD[i] != -1) {
2004 fds[fdi].fd = HandlerFD[i];
2005 fds[fdi].events = events;
2006 fds[fdi].revents = 0;
2010 ReleaseReadLock(&FSYNC_handler_lock);
2014 GetHandler(fd_set * fdsetp, int *maxfdp)
2017 register int maxfd = -1;
2019 ObtainReadLock(&FSYNC_handler_lock); /* just in case */
2020 for (i = 0; i < MAXHANDLERS; i++)
2021 if (HandlerFD[i] != -1) {
2022 FD_SET(HandlerFD[i], fdsetp);
2023 #ifndef AFS_NT40_ENV
2024 /* On Windows the nfds parameter to select() is ignored */
2025 if (maxfd < HandlerFD[i] || maxfd == (int)-1)
2026 maxfd = HandlerFD[i];
2027 #endif /* AFS_NT40_ENV */
2030 ReleaseReadLock(&FSYNC_handler_lock); /* just in case */
2032 #endif /* HAVE_POLL && AFS_PTHREAD_ENV */
2034 #endif /* FSSYNC_BUILD_SERVER */