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 #include <afs/afs_assert.h>
69 #include <afs/afsint.h>
71 #include <afs/errors.h>
72 #include "daemon_com.h"
73 #include "daemon_com_inline.h"
75 #include "fssync_inline.h"
79 #include <afs/afssyscalls.h>
83 #include "volume_inline.h"
84 #include "partition.h"
90 #endif /* HAVE_POLL */
92 #ifdef USE_UNIX_SOCKETS
94 #include <afs/afsutil.h>
95 #endif /* USE_UNIX_SOCKETS */
97 #ifdef FSSYNC_BUILD_SERVER
99 int (*V_BreakVolumeCallbacks) (VolumeId volume);
101 #define MAXHANDLERS 4 /* Up to 4 clients; must be at least 2, so that
102 * move = dump+restore can run on single server */
103 #define MAXOFFLINEVOLUMES 128 /* This needs to be as big as the maximum
104 * number that would be offline for 1 operation.
105 * Current winner is salvage, which needs all
106 * cloned read-only copies offline when salvaging
107 * a single read-write volume */
111 static struct offlineInfo OfflineVolumes[MAXHANDLERS][MAXOFFLINEVOLUMES];
114 * fssync server socket handle.
116 static SYNC_server_state_t fssync_server_state =
117 { OSI_NULLSOCKET, /* file descriptor */
118 FSSYNC_ENDPOINT_DECL, /* server endpoint */
119 FSYNC_PROTO_VERSION, /* protocol version */
120 5, /* bind() retry limit */
121 100, /* listen() queue depth */
122 "FSSYNC", /* protocol name string */
125 #ifdef AFS_DEMAND_ATTACH_FS
127 * a queue of volume pointers to salvage in the background.
129 struct fsync_salv_node {
131 Volume *vp; /**< volume to salvage */
132 unsigned char update_salv_prio; /**< whether we should update the salvage priority or not */
135 struct rx_queue head;
139 static void * FSYNC_salvageThread(void *);
140 static void FSYNC_backgroundSalvage(Volume *vp);
141 #endif /* AFS_DEMAND_ATTACH_FS */
143 /* Forward declarations */
144 static void * FSYNC_sync(void *);
145 static void FSYNC_newconnection(osi_socket afd);
146 static void FSYNC_com(osi_socket fd);
147 static void FSYNC_Drop(osi_socket fd);
148 static void AcceptOn(void);
149 static void AcceptOff(void);
150 static void InitHandler(void);
151 static int AddHandler(osi_socket fd, void (*aproc)(osi_socket));
152 static int FindHandler(osi_socket afd);
153 static int FindHandler_r(osi_socket afd);
154 static int RemoveHandler(osi_socket afd);
155 #if defined(HAVE_POLL) && defined (AFS_PTHREAD_ENV)
156 static void CallHandler(struct pollfd *fds, int nfds, int mask);
157 static void GetHandler(struct pollfd *fds, int maxfds, int events, int *nfds);
159 static void CallHandler(fd_set * fdsetp);
160 static void GetHandler(fd_set * fdsetp, int *maxfdp);
164 static afs_int32 FSYNC_com_VolOp(osi_socket fd, SYNC_command * com, SYNC_response * res);
166 #ifdef AFS_DEMAND_ATTACH_FS
167 static afs_int32 FSYNC_com_VolError(FSSYNC_VolOp_command * com, SYNC_response * res);
169 static afs_int32 FSYNC_com_VolOn(FSSYNC_VolOp_command * com, SYNC_response * res);
170 static afs_int32 FSYNC_com_VolOff(FSSYNC_VolOp_command * com, SYNC_response * res);
171 static afs_int32 FSYNC_com_VolMove(FSSYNC_VolOp_command * com, SYNC_response * res);
172 static afs_int32 FSYNC_com_VolBreakCBKs(FSSYNC_VolOp_command * com, SYNC_response * res);
173 static afs_int32 FSYNC_com_VolDone(FSSYNC_VolOp_command * com, SYNC_response * res);
174 static afs_int32 FSYNC_com_VolQuery(FSSYNC_VolOp_command * com, SYNC_response * res);
175 static afs_int32 FSYNC_com_VolHdrQuery(FSSYNC_VolOp_command * com, SYNC_response * res);
176 #ifdef AFS_DEMAND_ATTACH_FS
177 static afs_int32 FSYNC_com_VGUpdate(osi_socket fd, SYNC_command * com, SYNC_response * res);
178 static afs_int32 FSYNC_com_VolOpQuery(FSSYNC_VolOp_command * com, SYNC_response * res);
179 static afs_int32 FSYNC_com_VGQuery(FSSYNC_VolOp_command * com, SYNC_response * res);
180 static afs_int32 FSYNC_com_VGScan(FSSYNC_VolOp_command * com, SYNC_response * res);
181 static afs_int32 FSYNC_com_VGScanAll(FSSYNC_VolOp_command * com, SYNC_response * res);
182 #endif /* AFS_DEMAND_ATTACH_FS */
184 static afs_int32 FSYNC_com_VnQry(osi_socket fd, SYNC_command * com, SYNC_response * res);
186 static afs_int32 FSYNC_com_StatsOp(osi_socket fd, SYNC_command * com, SYNC_response * res);
188 static afs_int32 FSYNC_com_StatsOpGeneral(FSSYNC_StatsOp_command * scom, SYNC_response * res);
190 #ifdef AFS_DEMAND_ATTACH_FS
191 static afs_int32 FSYNC_com_StatsOpViceP(FSSYNC_StatsOp_command * scom, SYNC_response * res);
192 static afs_int32 FSYNC_com_StatsOpHash(FSSYNC_StatsOp_command * scom, SYNC_response * res);
193 static afs_int32 FSYNC_com_StatsOpHdr(FSSYNC_StatsOp_command * scom, SYNC_response * res);
194 static afs_int32 FSYNC_com_StatsOpVLRU(FSSYNC_StatsOp_command * scom, SYNC_response * res);
197 static void FSYNC_com_to_info(FSSYNC_VolOp_command * vcom, FSSYNC_VolOp_info * info);
199 static int FSYNC_partMatch(FSSYNC_VolOp_command * vcom, Volume * vp, int match_anon);
203 * This lock controls access to the handler array. The overhead
204 * is minimal in non-preemptive environments.
206 struct Lock FSYNC_handler_lock;
211 #ifdef AFS_PTHREAD_ENV
213 pthread_attr_t tattr;
214 #else /* AFS_PTHREAD_ENV */
216 #endif /* AFS_PTHREAD_ENV */
218 Lock_Init(&FSYNC_handler_lock);
220 #ifdef AFS_PTHREAD_ENV
221 osi_Assert(pthread_attr_init(&tattr) == 0);
222 osi_Assert(pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED) == 0);
223 osi_Assert(pthread_create(&tid, &tattr, FSYNC_sync, NULL) == 0);
224 #else /* AFS_PTHREAD_ENV */
225 osi_Assert(LWP_CreateProcess
226 (FSYNC_sync, USUAL_STACK_SIZE, USUAL_PRIORITY, (void *)0,
227 "FSYNC_sync", &pid) == LWP_SUCCESS);
228 #endif /* AFS_PTHREAD_ENV */
230 #ifdef AFS_DEMAND_ATTACH_FS
231 queue_Init(&fsync_salv.head);
232 CV_INIT(&fsync_salv.cv, "fsync salv", CV_DEFAULT, 0);
233 osi_Assert(pthread_create(&tid, &tattr, FSYNC_salvageThread, NULL) == 0);
234 #endif /* AFS_DEMAND_ATTACH_FS */
237 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
238 static struct pollfd FSYNC_readfds[MAXHANDLERS];
240 static fd_set FSYNC_readfds;
245 FSYNC_sync(void * args)
249 #ifdef AFS_PTHREAD_ENV
252 SYNC_server_state_t * state = &fssync_server_state;
253 #ifdef AFS_DEMAND_ATTACH_FS
254 VThreadOptions_t * thread_opts;
258 * For non-DAFS, only wait until we begin attaching volumes (instead
259 * of waiting until all volumes are attached), since it can take
260 * awhile until VInit == 2.
263 #endif /* AFS_DEMAND_ATTACH_FS */
265 /* we must not be called before vol package initialization, since we use
266 * vol package mutexes and conds etc */
269 SYNC_getAddr(&state->endpoint, &state->addr);
270 SYNC_cleanupSock(state);
273 (void)signal(SIGPIPE, SIG_IGN);
276 #ifdef AFS_PTHREAD_ENV
277 /* set our 'thread-id' so that the host hold table works */
278 tid = rx_NewThreadId();
279 pthread_setspecific(rx_thread_id_key, (void *)(intptr_t)tid);
280 Log("Set thread id %d for FSYNC_sync\n", tid);
281 #endif /* AFS_PTHREAD_ENV */
285 while (VInit < min_vinit) {
286 /* Let somebody else run until all volumes have been preattached
287 * (DAFS), or we have started attaching volumes (non-DAFS). This
288 * doesn't mean that all volumes have been attached.
290 #ifdef AFS_PTHREAD_ENV
291 VOL_CV_WAIT(&vol_vinit_cond);
292 #else /* AFS_PTHREAD_ENV */
293 LWP_DispatchProcess();
294 #endif /* AFS_PTHREAD_ENV */
299 state->fd = SYNC_getSock(&state->endpoint);
300 code = SYNC_bindSock(state);
303 #ifdef AFS_DEMAND_ATTACH_FS
305 * make sure the volume package is incapable of recursively executing
306 * salvsync calls on this thread, since there is a possibility of
309 thread_opts = malloc(sizeof(VThreadOptions_t));
310 if (thread_opts == NULL) {
311 Log("failed to allocate memory for thread-specific volume package options structure\n");
314 memcpy(thread_opts, &VThread_defaults, sizeof(VThread_defaults));
315 thread_opts->disallow_salvsync = 1;
316 osi_Assert(pthread_setspecific(VThread_key, thread_opts) == 0);
318 code = VVGCache_PkgInit();
319 osi_Assert(code == 0);
326 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
328 GetHandler(FSYNC_readfds, MAXHANDLERS, POLLIN|POLLPRI, &nfds);
329 if (poll(FSYNC_readfds, nfds, -1) >=1)
330 CallHandler(FSYNC_readfds, nfds, POLLIN|POLLPRI);
333 GetHandler(&FSYNC_readfds, &maxfd);
334 /* Note: check for >= 1 below is essential since IOMGR_select
335 * doesn't have exactly same semantics as select.
337 #ifdef AFS_PTHREAD_ENV
338 if (select(maxfd + 1, &FSYNC_readfds, NULL, NULL, NULL) >= 1)
339 #else /* AFS_PTHREAD_ENV */
340 if (IOMGR_Select(maxfd + 1, &FSYNC_readfds, NULL, NULL, NULL) >= 1)
341 #endif /* AFS_PTHREAD_ENV */
342 CallHandler(&FSYNC_readfds);
345 return NULL; /* hush now, little gcc */
348 #ifdef AFS_DEMAND_ATTACH_FS
350 * thread for salvaging volumes in the background.
352 * Since FSSYNC handlers cannot issue SALVSYNC requests in order to avoid
353 * deadlock issues, this thread exists so code in the FSSYNC handler thread
354 * can hand off volumes to be salvaged in the background.
356 * @param[in] args unused
358 * @note DEMAND_ATTACH_FS only
361 FSYNC_salvageThread(void * args)
364 struct fsync_salv_node *node;
369 while (queue_IsEmpty(&fsync_salv.head)) {
370 VOL_CV_WAIT(&fsync_salv.cv);
373 node = queue_First(&fsync_salv.head, fsync_salv_node);
377 if (node->update_salv_prio) {
378 if (VUpdateSalvagePriority_r(vp)) {
379 ViceLog(0, ("FSYNC_salvageThread: unable to raise salvage priority "
380 "for volume %lu\n", afs_printable_uint32_lu(vp->hashid)));
387 VCancelReservation_r(vp);
396 * salvage a volume in the background.
398 * Salvages cannot be scheduled directly from the main FSYNC thread, so
399 * instead call this function to schedule a salvage asynchronously in the
400 * FSYNC_salvageThread thread.
402 * @param[in] vp volume to pointer to salvage
406 * @note DEMAND_ATTACH_FS only
409 FSYNC_backgroundSalvage(Volume *vp)
411 struct fsync_salv_node *node;
414 VCreateReservation_r(vp);
416 node = malloc(sizeof(struct fsync_salv_node));
419 /* Save this value, to know if we should VUpdateSalvagePriority_r.
420 * We need to save it here, snce VRequestSalvage_r will change it. */
421 node->update_salv_prio = vp->salvage.requested;
423 if (VRequestSalvage_r(&ec, vp, SALVSYNC_ERROR, 0)) {
424 ViceLog(0, ("FSYNC_backgroundSalvage: unable to request salvage for volume %lu\n",
425 afs_printable_uint32_lu(vp->hashid)));
428 queue_Append(&fsync_salv.head, node);
429 CV_BROADCAST(&fsync_salv.cv);
431 #endif /* AFS_DEMAND_ATTACH_FS */
434 FSYNC_newconnection(osi_socket afd)
436 #ifdef USE_UNIX_SOCKETS
437 struct sockaddr_un other;
438 #else /* USE_UNIX_SOCKETS */
439 struct sockaddr_in other;
443 junk = sizeof(other);
444 fd = accept(afd, (struct sockaddr *)&other, &junk);
445 if (fd == OSI_NULLSOCKET) {
446 Log("FSYNC_newconnection: accept failed, errno==%d\n", errno);
448 } else if (!AddHandler(fd, FSYNC_com)) {
450 osi_Assert(AddHandler(fd, FSYNC_com));
454 /* this function processes commands from an fssync file descriptor (fd) */
455 afs_int32 FS_cnt = 0;
457 FSYNC_com(osi_socket fd)
461 SYNC_PROTO_BUF_DECL(com_buf);
462 SYNC_PROTO_BUF_DECL(res_buf);
464 memset(&res.hdr, 0, sizeof(res.hdr));
466 com.payload.buf = (void *)com_buf;
467 com.payload.len = SYNC_PROTO_MAX_LEN;
468 res.hdr.response_len = sizeof(res.hdr);
469 res.payload.len = SYNC_PROTO_MAX_LEN;
470 res.payload.buf = (void *)res_buf;
473 if (SYNC_getCom(&fssync_server_state, fd, &com)) {
474 Log("FSYNC_com: read failed; dropping connection (cnt=%d)\n", FS_cnt);
479 if (com.recv_len < sizeof(com.hdr)) {
480 Log("FSSYNC_com: invalid protocol message length (%u)\n", com.recv_len);
481 res.hdr.response = SYNC_COM_ERROR;
482 res.hdr.reason = SYNC_REASON_MALFORMED_PACKET;
483 res.hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
487 if (com.hdr.proto_version != FSYNC_PROTO_VERSION) {
488 Log("FSYNC_com: invalid protocol version (%u)\n", com.hdr.proto_version);
489 res.hdr.response = SYNC_COM_ERROR;
490 res.hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
494 if (com.hdr.command == SYNC_COM_CHANNEL_CLOSE) {
495 res.hdr.response = SYNC_OK;
496 res.hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
498 /* don't respond, just drop; senders of SYNC_COM_CHANNEL_CLOSE
499 * never wait for a response. */
503 ViceLog(125, ("FSYNC_com: from fd %d got command %ld (%s) reason %ld (%s) "
504 "pt %ld (%s) pid %ld\n", (int)fd,
505 afs_printable_int32_ld(com.hdr.command),
506 FSYNC_com2string(com.hdr.command),
507 afs_printable_int32_ld(com.hdr.reason),
508 FSYNC_reason2string(com.hdr.reason),
509 afs_printable_int32_ld(com.hdr.programType),
510 VPTypeToString(com.hdr.programType),
511 afs_printable_int32_ld(com.hdr.pid)));
513 res.hdr.com_seq = com.hdr.com_seq;
516 switch (com.hdr.command) {
518 case FSYNC_VOL_ATTACH:
519 case FSYNC_VOL_LEAVE_OFF:
521 case FSYNC_VOL_FORCE_ERROR:
522 case FSYNC_VOL_LISTVOLUMES:
523 case FSYNC_VOL_NEEDVOLUME:
525 case FSYNC_VOL_BREAKCBKS:
527 case FSYNC_VOL_QUERY:
528 case FSYNC_VOL_QUERY_HDR:
529 case FSYNC_VOL_QUERY_VOP:
530 #ifdef AFS_DEMAND_ATTACH_FS
533 case FSYNC_VG_SCAN_ALL:
535 res.hdr.response = FSYNC_com_VolOp(fd, &com, &res);
537 case FSYNC_VOL_STATS_GENERAL:
538 case FSYNC_VOL_STATS_VICEP:
539 case FSYNC_VOL_STATS_HASH:
540 case FSYNC_VOL_STATS_HDR:
541 case FSYNC_VOL_STATS_VLRU:
542 res.hdr.response = FSYNC_com_StatsOp(fd, &com, &res);
544 case FSYNC_VOL_QUERY_VNODE:
545 res.hdr.response = FSYNC_com_VnQry(fd, &com, &res);
547 #ifdef AFS_DEMAND_ATTACH_FS
550 res.hdr.response = FSYNC_com_VGUpdate(fd, &com, &res);
554 res.hdr.response = SYNC_BAD_COMMAND;
559 ViceLog(125, ("FSYNC_com: fd %d responding with code %ld (%s) reason %ld "
561 afs_printable_int32_ld(res.hdr.response),
562 SYNC_res2string(res.hdr.response),
563 afs_printable_int32_ld(res.hdr.reason),
564 FSYNC_reason2string(res.hdr.reason)));
567 SYNC_putRes(&fssync_server_state, fd, &res);
570 if (res.hdr.flags & SYNC_FLAG_CHANNEL_SHUTDOWN) {
576 FSYNC_com_VolOp(osi_socket fd, SYNC_command * com, SYNC_response * res)
579 afs_int32 code = SYNC_OK;
580 FSSYNC_VolOp_command vcom;
582 if (com->recv_len != (sizeof(com->hdr) + sizeof(FSSYNC_VolOp_hdr))) {
583 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
584 res->hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
585 return SYNC_COM_ERROR;
588 vcom.hdr = &com->hdr;
589 vcom.vop = (FSSYNC_VolOp_hdr *) com->payload.buf;
592 vcom.volumes = OfflineVolumes[FindHandler(fd)];
593 for (vcom.v = NULL, i = 0; i < MAXOFFLINEVOLUMES; i++) {
594 if ((vcom.volumes[i].volumeID == vcom.vop->volume) &&
595 (strncmp(vcom.volumes[i].partName, vcom.vop->partName,
596 sizeof(vcom.volumes[i].partName)) == 0)) {
597 vcom.v = &vcom.volumes[i];
602 ViceLog(125, ("FSYNC_com_VolOp: fd %d got command for vol %lu part %.16s\n",
603 (int)fd, afs_printable_uint32_lu(vcom.vop->volume),
604 vcom.vop->partName));
606 switch (com->hdr.command) {
608 case FSYNC_VOL_ATTACH:
609 case FSYNC_VOL_LEAVE_OFF:
610 code = FSYNC_com_VolOn(&vcom, res);
613 case FSYNC_VOL_NEEDVOLUME:
614 code = FSYNC_com_VolOff(&vcom, res);
616 case FSYNC_VOL_LISTVOLUMES:
620 code = FSYNC_com_VolMove(&vcom, res);
622 case FSYNC_VOL_BREAKCBKS:
623 code = FSYNC_com_VolBreakCBKs(&vcom, res);
626 code = FSYNC_com_VolDone(&vcom, res);
628 case FSYNC_VOL_QUERY:
629 code = FSYNC_com_VolQuery(&vcom, res);
631 case FSYNC_VOL_QUERY_HDR:
632 code = FSYNC_com_VolHdrQuery(&vcom, res);
634 #ifdef AFS_DEMAND_ATTACH_FS
635 case FSYNC_VOL_FORCE_ERROR:
636 code = FSYNC_com_VolError(&vcom, res);
638 case FSYNC_VOL_QUERY_VOP:
639 code = FSYNC_com_VolOpQuery(&vcom, res);
642 code = FSYNC_com_VGQuery(&vcom, res);
645 code = FSYNC_com_VGScan(&vcom, res);
647 case FSYNC_VG_SCAN_ALL:
648 code = FSYNC_com_VGScanAll(&vcom, res);
650 #endif /* AFS_DEMAND_ATTACH_FS */
652 code = SYNC_BAD_COMMAND;
659 * service an FSYNC request to bring a volume online.
661 * @param[in] vcom pointer command object
662 * @param[out] res object in which to store response packet
664 * @return operation status
665 * @retval SYNC_OK volume transitioned online
666 * @retval SYNC_FAILED invalid command protocol message
667 * @retval SYNC_DENIED operation could not be completed
669 * @note this is an FSYNC RPC server stub
671 * @note this procedure handles the following FSSYNC command codes:
674 * - FSYNC_VOL_LEAVE_OFF
676 * @note the supplementary reason code contains additional details.
677 * When SYNC_DENIED is returned, the specific reason is
678 * placed in the response packet reason field.
683 FSYNC_com_VolOn(FSSYNC_VolOp_command * vcom, SYNC_response * res)
685 afs_int32 code = SYNC_OK;
686 #ifndef AFS_DEMAND_ATTACH_FS
687 char tvolName[VMAXPATHLEN];
692 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
693 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
698 /* so, we need to attach the volume */
700 #ifdef AFS_DEMAND_ATTACH_FS
701 /* check DAFS permissions */
702 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
704 FSYNC_partMatch(vcom, vp, 1) &&
705 vp->pending_vol_op &&
706 (vcom->hdr->programType != vp->pending_vol_op->com.programType)) {
707 /* a different program has this volume checked out. deny. */
708 Log("FSYNC_VolOn: WARNING: program type %u has attempted to manipulate "
709 "state for volume %u using command code %u while the volume is "
710 "checked out by program type %u for command code %u.\n",
711 vcom->hdr->programType,
714 vp->pending_vol_op->com.programType,
715 vp->pending_vol_op->com.command);
717 res->hdr.reason = FSYNC_EXCLUSIVE;
723 vcom->v->volumeID = 0;
726 if (vcom->hdr->command == FSYNC_VOL_LEAVE_OFF) {
727 /* nothing much to do if we're leaving the volume offline */
728 #ifdef AFS_DEMAND_ATTACH_FS
730 if (FSYNC_partMatch(vcom, vp, 1)) {
731 if ((V_attachState(vp) == VOL_STATE_UNATTACHED) ||
732 (V_attachState(vp) == VOL_STATE_PREATTACHED)) {
733 VChangeState_r(vp, VOL_STATE_UNATTACHED);
734 VDeregisterVolOp_r(vp);
737 res->hdr.reason = FSYNC_BAD_STATE;
741 res->hdr.reason = FSYNC_WRONG_PART;
745 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
751 #ifdef AFS_DEMAND_ATTACH_FS
752 /* first, check to see whether we have such a volume defined */
753 vp = VPreAttachVolumeById_r(&error,
757 VDeregisterVolOp_r(vp);
759 #else /* !AFS_DEMAND_ATTACH_FS */
761 snprintf(&tvolName[1], sizeof(tvolName)-1, VFORMAT, afs_printable_uint32_lu(vcom->vop->volume));
762 tvolName[sizeof(tvolName)-1] = '\0';
764 vp = VAttachVolumeByName_r(&error, vcom->vop->partName, tvolName,
770 res->hdr.reason = error;
772 #endif /* !AFS_DEMAND_ATTACH_FS */
779 * service an FSYNC request to take a volume offline.
781 * @param[in] vcom pointer command object
782 * @param[out] res object in which to store response packet
784 * @return operation status
785 * @retval SYNC_OK volume transitioned offline
786 * @retval SYNC_FAILED invalid command protocol message
787 * @retval SYNC_DENIED operation could not be completed
789 * @note this is an FSYNC RPC server stub
791 * @note this procedure handles the following FSSYNC command codes:
793 * - FSYNC_VOL_NEEDVOLUME
795 * @note the supplementary reason code contains additional details.
796 * When SYNC_DENIED is returned, the specific reason is
797 * placed in the response packet reason field.
802 FSYNC_com_VolOff(FSSYNC_VolOp_command * vcom, SYNC_response * res)
804 FSSYNC_VolOp_info info;
805 afs_int32 code = SYNC_OK;
809 #ifdef AFS_DEMAND_ATTACH_FS
810 Volume *nvp, *rvp = NULL;
813 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
814 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
819 /* not already offline, we need to find a slot for newly offline volume */
820 if (vcom->hdr->programType == debugUtility) {
821 /* debug utilities do not have their operations tracked */
825 for (i = 0; i < MAXOFFLINEVOLUMES; i++) {
826 if (vcom->volumes[i].volumeID == 0) {
827 vcom->v = &vcom->volumes[i];
837 FSYNC_com_to_info(vcom, &info);
839 #ifdef AFS_DEMAND_ATTACH_FS
840 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
842 vp = VGetVolume_r(&error, vcom->vop->volume);
846 if (!FSYNC_partMatch(vcom, vp, 1)) {
847 /* volume on desired partition is not online, so we
848 * should treat this as an offline volume.
850 #ifndef AFS_DEMAND_ATTACH_FS
858 #ifdef AFS_DEMAND_ATTACH_FS
860 ProgramType type = (ProgramType) vcom->hdr->programType;
862 /* do initial filtering of requests */
864 /* enforce mutual exclusion for volume ops */
865 if (vp->pending_vol_op) {
866 if (vp->pending_vol_op->com.programType != type) {
867 if (vp->pending_vol_op->com.command == FSYNC_VOL_OFF &&
868 vp->pending_vol_op->com.reason == FSYNC_SALVAGE) {
870 Log("denying offline request for volume %lu; volume is salvaging\n",
871 afs_printable_uint32_lu(vp->hashid));
873 res->hdr.reason = FSYNC_SALVAGE;
876 Log("volume %u already checked out\n", vp->hashid);
878 Log("vp->vop = { com = { ver=%u, prog=%d, com=%d, reason=%d, len=%u, flags=0x%x }, vop = { vol=%u, part='%s' } }\n",
879 vp->pending_vol_op->com.proto_version,
880 vp->pending_vol_op->com.programType,
881 vp->pending_vol_op->com.command,
882 vp->pending_vol_op->com.reason,
883 vp->pending_vol_op->com.command_len,
884 vp->pending_vol_op->com.flags,
885 vp->pending_vol_op->vop.volume,
886 vp->pending_vol_op->vop.partName );
887 Log("vcom = { com = { ver=%u, prog=%d, com=%d, reason=%d, len=%u, flags=0x%x } , vop = { vol=%u, part='%s' } }\n",
888 vcom->hdr->proto_version,
889 vcom->hdr->programType,
892 vcom->hdr->command_len,
895 vcom->vop->partName);
896 res->hdr.reason = FSYNC_EXCLUSIVE;
899 Log("warning: volume %u recursively checked out by programType id %d\n",
900 vp->hashid, vcom->hdr->programType);
904 /* wait for exclusive ops, so we have an accurate picture of the
905 * vol attach state */
906 VCreateReservation_r(vp);
907 VWaitExclusiveState_r(vp);
910 /* filter based upon requestor
912 * volume utilities / volserver are not allowed to check out
913 * volumes which are in an error state
915 * unknown utility programs will be denied on principal
919 /* it is possible for the salvageserver to checkout a
920 * volume for salvage before its scheduling request
921 * has been sent to the salvageserver */
922 if (vp->salvage.requested && !vp->salvage.scheduled) {
923 vp->salvage.scheduled = 1;
926 /* If the volume is in VOL_STATE_SALVAGE_REQ, we need to wait
927 * for the vol to go offline before we can give it away. Also
928 * make sure we don't come out with vp in an excl state. */
929 while (V_attachState(vp) == VOL_STATE_SALVAGE_REQ ||
930 VIsExclusiveState(V_attachState(vp))) {
932 VOL_CV_WAIT(&V_attachCV(vp));
940 if (VIsSalvaging(vp)) {
941 Log("denying offline request for volume %lu; volume is in salvaging state\n",
942 afs_printable_uint32_lu(vp->hashid));
943 res->hdr.reason = FSYNC_SALVAGE;
945 /* the volume hasn't been checked out yet by the salvager,
946 * but we think the volume is salvaging; schedule a
947 * a salvage to update the salvage priority */
948 FSYNC_backgroundSalvage(vp);
952 if (VIsErrorState(V_attachState(vp))) {
958 Log("bad program type passed to FSSYNC\n");
962 /* short circuit for offline volume states
963 * so we can avoid I/O penalty of attachment */
964 switch (V_attachState(vp)) {
965 case VOL_STATE_UNATTACHED:
966 case VOL_STATE_PREATTACHED:
967 case VOL_STATE_SALVAGING:
968 case VOL_STATE_ERROR:
969 /* register the volume operation metadata with the volume
971 * if the volume is currently pre-attached, attach2()
972 * will evaluate the vol op metadata to determine whether
973 * attaching the volume would be safe */
974 VRegisterVolOp_r(vp, &info);
975 vp->pending_vol_op->vol_op_state = FSSYNC_VolOpRunningUnknown;
981 /* convert to heavyweight ref */
982 nvp = VGetVolumeByVp_r(&error, vp);
985 * It's possible for VGetVolumeByVp_r to have dropped and
986 * re-acquired VOL_LOCK, so volume state may have changed
987 * back to one of the states we tested for above. Since
988 * GetVolume can return NULL in some of those states, just
989 * test for the states again here.
991 switch (V_attachState(vp)) {
992 case VOL_STATE_UNATTACHED:
993 case VOL_STATE_PREATTACHED:
994 case VOL_STATE_SALVAGING:
995 case VOL_STATE_ERROR:
996 /* register the volume operation metadata with the volume
998 * if the volume is currently pre-attached, attach2()
999 * will evaluate the vol op metadata to determine whether
1000 * attaching the volume would be safe */
1001 VRegisterVolOp_r(vp, &info);
1002 vp->pending_vol_op->vol_op_state = FSSYNC_VolOpRunningUnknown;
1008 Log("FSYNC_com_VolOff: failed to get heavyweight reference to volume %u\n",
1010 res->hdr.reason = FSYNC_VOL_PKG_ERROR;
1012 } else if (nvp != vp) {
1013 /* i don't think this should ever happen, but just in case... */
1014 Log("FSYNC_com_VolOff: warning: potentially dangerous race detected\n");
1018 /* kill off lightweight ref to ensure we can't deadlock against ourselves later... */
1019 VCancelReservation_r(rvp);
1022 /* register the volume operation metadata with the volume */
1023 VRegisterVolOp_r(vp, &info);
1026 #endif /* AFS_DEMAND_ATTACH_FS */
1029 if (VVolOpLeaveOnline_r(vp, &info)) {
1030 VUpdateVolume_r(&error, vp, VOL_UPDATE_WAIT); /* At least get volume stats right */
1032 Log("FSYNC: Volume %u (%s) was left on line for an external %s request\n",
1033 V_id(vp), V_name(vp),
1034 vcom->hdr->reason == V_CLONE ? "clone" :
1035 vcom->hdr->reason == V_READONLY ? "readonly" :
1036 vcom->hdr->reason == V_DUMP ? "dump" :
1037 vcom->hdr->reason == FSYNC_SALVAGE ? "salvage" :
1040 #ifdef AFS_DEMAND_ATTACH_FS
1041 vp->pending_vol_op->vol_op_state = FSSYNC_VolOpRunningOnline;
1045 if (VVolOpSetVBusy_r(vp, &info)) {
1046 vp->specialStatus = VBUSY;
1049 /* remember what volume we got, so we can keep track of how
1050 * many volumes the volserver or whatever is using. Note that
1051 * vp is valid since leaveonline is only set when vp is valid.
1054 vcom->v->volumeID = vcom->vop->volume;
1055 strlcpy(vcom->v->partName, vp->partition->name, sizeof(vcom->v->partName));
1058 #ifdef AFS_DEMAND_ATTACH_FS
1059 VOfflineForVolOp_r(&error, vp, "A volume utility is running.");
1061 osi_Assert(vp->nUsers==0);
1062 vp->pending_vol_op->vol_op_state = FSSYNC_VolOpRunningOffline;
1065 VDeregisterVolOp_r(vp);
1069 VOffline_r(vp, "A volume utility is running.");
1080 #ifdef AFS_DEMAND_ATTACH_FS
1082 VCancelReservation_r(rvp);
1089 * service an FSYNC request to mark a volume as moved.
1091 * @param[in] vcom pointer command object
1092 * @param[out] res object in which to store response packet
1094 * @return operation status
1095 * @retval SYNC_OK volume marked as moved to a remote server
1096 * @retval SYNC_FAILED invalid command protocol message
1097 * @retval SYNC_DENIED current volume state does not permit this operation
1099 * @note this is an FSYNC RPC server stub
1101 * @note this operation also breaks all callbacks for the given volume
1103 * @note this procedure handles the following FSSYNC command codes:
1106 * @note the supplementary reason code contains additional details. For
1107 * instance, SYNC_OK is still returned when the partition specified
1108 * does not match the one registered in the volume object -- reason
1109 * will be FSYNC_WRONG_PART in this case.
1114 FSYNC_com_VolMove(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1116 afs_int32 code = SYNC_DENIED;
1120 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1121 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1126 /* Yuch: the "reason" for the move is the site it got moved to... */
1127 /* still set specialStatus so we stop sending back VBUSY.
1128 * also should still break callbacks. Note that I don't know
1129 * how to tell if we should break all or not, so we just do it
1130 * since it doesn't matter much if we do an extra break
1131 * volume callbacks on a volume move within the same server */
1132 #ifdef AFS_DEMAND_ATTACH_FS
1133 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
1135 vp = VGetVolume_r(&error, vcom->vop->volume);
1138 if (FSYNC_partMatch(vcom, vp, 1)) {
1139 #ifdef AFS_DEMAND_ATTACH_FS
1140 if ((V_attachState(vp) == VOL_STATE_UNATTACHED) ||
1141 (V_attachState(vp) == VOL_STATE_PREATTACHED)) {
1144 vp->specialStatus = VMOVED;
1145 #ifdef AFS_DEMAND_ATTACH_FS
1147 res->hdr.reason = FSYNC_BAD_STATE;
1151 res->hdr.reason = FSYNC_WRONG_PART;
1153 #ifndef AFS_DEMAND_ATTACH_FS
1155 #endif /* !AFS_DEMAND_ATTACH_FS */
1157 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1160 if ((code == SYNC_OK) && (V_BreakVolumeCallbacks != NULL)) {
1161 Log("fssync: volume %u moved to %x; breaking all call backs\n",
1162 vcom->vop->volume, vcom->hdr->reason);
1164 (*V_BreakVolumeCallbacks) (vcom->vop->volume);
1174 * service an FSYNC request to mark a volume as destroyed.
1176 * @param[in] vcom pointer command object
1177 * @param[out] res object in which to store response packet
1179 * @return operation status
1180 * @retval SYNC_OK volume marked as destroyed
1181 * @retval SYNC_FAILED invalid command protocol message
1182 * @retval SYNC_DENIED current volume state does not permit this operation
1184 * @note this is an FSYNC RPC server stub
1186 * @note this procedure handles the following FSSYNC command codes:
1189 * @note the supplementary reason code contains additional details. For
1190 * instance, SYNC_OK is still returned when the partition specified
1191 * does not match the one registered in the volume object -- reason
1192 * will be FSYNC_WRONG_PART in this case.
1197 FSYNC_com_VolDone(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1199 afs_int32 code = SYNC_FAILED;
1203 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1204 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1208 /* don't try to put online, this call is made only after deleting
1209 * a volume, in which case we want to remove the vol # from the
1210 * OfflineVolumes array only */
1212 vcom->v->volumeID = 0;
1214 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
1216 if (FSYNC_partMatch(vcom, vp, 1)) {
1217 #ifdef AFS_DEMAND_ATTACH_FS
1218 if ((V_attachState(vp) == VOL_STATE_UNATTACHED) ||
1219 (V_attachState(vp) == VOL_STATE_PREATTACHED)) {
1221 /* Change state to DELETED, not UNATTACHED, so clients get
1222 * a VNOVOL error when they try to access from now on. */
1224 VChangeState_r(vp, VOL_STATE_DELETED);
1225 VDeregisterVolOp_r(vp);
1227 /* Someday we should free the vp, too, after about 2 hours,
1228 * possibly by putting the vp back on the VLRU. */
1233 res->hdr.reason = FSYNC_BAD_STATE;
1235 #else /* AFS_DEMAND_ATTACH_FS */
1236 if (!vp->specialStatus) {
1237 vp->specialStatus = VNOVOL;
1240 #endif /* !AFS_DEMAND_ATTACH_FS */
1242 code = SYNC_OK; /* XXX is this really a good idea? */
1243 res->hdr.reason = FSYNC_WRONG_PART;
1246 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1253 #ifdef AFS_DEMAND_ATTACH_FS
1255 * service an FSYNC request to transition a volume to the hard error state.
1257 * @param[in] vcom pointer command object
1258 * @param[out] res object in which to store response packet
1260 * @return operation status
1261 * @retval SYNC_OK volume transitioned to hard error state
1262 * @retval SYNC_FAILED invalid command protocol message
1263 * @retval SYNC_DENIED (see note)
1265 * @note this is an FSYNC RPC server stub
1267 * @note this procedure handles the following FSSYNC command codes:
1268 * - FSYNC_VOL_FORCE_ERROR
1270 * @note SYNC_DENIED is returned in the following cases:
1271 * - no partition name is specified (reason field set to
1272 * FSYNC_WRONG_PART).
1273 * - volume id not known to fileserver (reason field set
1274 * to FSYNC_UNKNOWN_VOLID).
1276 * @note demand attach fileserver only
1281 FSYNC_com_VolError(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1285 afs_int32 code = SYNC_FAILED;
1287 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1288 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1292 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
1294 if (!vp && vcom->hdr->reason == FSYNC_SALVAGE) {
1295 /* The requested volume doesn't seem to exist. However, it is possible
1296 * that this is triggered by trying to create or clone a volume that
1297 * was prevented from succeeding by a half-created volume in the way.
1298 * (e.g. we tried to create volume X, but volume X exists except that
1299 * its .vol header was deleted for some reason) So, still try to
1300 * a salvage for that volume ID. */
1302 Log("FSYNC_com_VolError: attempting to schedule salvage for unknown "
1303 "volume %lu part %s\n", afs_printable_uint32_lu(vcom->vop->volume),
1304 vcom->vop->partName);
1305 vp = VPreAttachVolumeById_r(&error, vcom->vop->partName,
1310 if (FSYNC_partMatch(vcom, vp, 0)) {
1311 /* null out salvsync control state, as it's no longer relevant */
1312 memset(&vp->salvage, 0, sizeof(vp->salvage));
1313 VDeregisterVolOp_r(vp);
1315 if (vcom->hdr->reason == FSYNC_SALVAGE) {
1316 FSYNC_backgroundSalvage(vp);
1318 VChangeState_r(vp, VOL_STATE_ERROR);
1323 res->hdr.reason = FSYNC_WRONG_PART;
1326 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1332 #endif /* AFS_DEMAND_ATTACH_FS */
1335 * service an FSYNC request to break all callbacks for this volume.
1337 * @param[in] vcom pointer command object
1338 * @param[out] res object in which to store response packet
1340 * @return operation status
1341 * @retval SYNC_OK callback breaks scheduled for volume
1343 * @note this is an FSYNC RPC server stub
1345 * @note this procedure handles the following FSSYNC command codes:
1346 * - FSYNC_VOL_BREAKCBKS
1348 * @note demand attach fileserver only
1350 * @todo should do partition matching
1355 FSYNC_com_VolBreakCBKs(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1357 /* if the volume is being restored, break all callbacks on it */
1358 if (V_BreakVolumeCallbacks) {
1359 Log("fssync: breaking all call backs for volume %u\n",
1362 (*V_BreakVolumeCallbacks) (vcom->vop->volume);
1369 * service an FSYNC request to return the Volume object.
1371 * @param[in] vcom pointer command object
1372 * @param[out] res object in which to store response packet
1374 * @return operation status
1375 * @retval SYNC_OK volume object returned to caller
1376 * @retval SYNC_FAILED bad command packet, or failed to locate volume object
1378 * @note this is an FSYNC RPC server stub
1380 * @note this procedure handles the following FSSYNC command codes:
1386 FSYNC_com_VolQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1388 afs_int32 code = SYNC_FAILED;
1392 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1393 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1397 #ifdef AFS_DEMAND_ATTACH_FS
1398 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
1399 #else /* !AFS_DEMAND_ATTACH_FS */
1400 vp = VGetVolume_r(&error, vcom->vop->volume);
1401 #endif /* !AFS_DEMAND_ATTACH_FS */
1404 if (FSYNC_partMatch(vcom, vp, 1)) {
1405 if (res->payload.len >= sizeof(Volume)) {
1406 memcpy(res->payload.buf, vp, sizeof(Volume));
1407 res->hdr.response_len += sizeof(Volume);
1410 res->hdr.reason = SYNC_REASON_PAYLOAD_TOO_BIG;
1413 res->hdr.reason = FSYNC_WRONG_PART;
1415 #ifndef AFS_DEMAND_ATTACH_FS
1419 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1427 * service an FSYNC request to return the Volume header.
1429 * @param[in] vcom pointer command object
1430 * @param[out] res object in which to store response packet
1432 * @return operation status
1433 * @retval SYNC_OK volume header returned to caller
1434 * @retval SYNC_FAILED bad command packet, or failed to locate volume header
1436 * @note this is an FSYNC RPC server stub
1438 * @note this procedure handles the following FSSYNC command codes:
1439 * - FSYNC_VOL_QUERY_HDR
1444 FSYNC_com_VolHdrQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1446 afs_int32 code = SYNC_FAILED;
1450 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1451 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1454 if (res->payload.len < sizeof(VolumeDiskData)) {
1455 res->hdr.reason = SYNC_REASON_PAYLOAD_TOO_BIG;
1459 #ifdef AFS_DEMAND_ATTACH_FS
1460 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
1461 #else /* !AFS_DEMAND_ATTACH_FS */
1462 vp = VGetVolume_r(&error, vcom->vop->volume);
1466 if (FSYNC_partMatch(vcom, vp, 1)) {
1467 #ifdef AFS_DEMAND_ATTACH_FS
1468 if ((vp->header == NULL) ||
1469 !(V_attachFlags(vp) & VOL_HDR_ATTACHED) ||
1470 !(V_attachFlags(vp) & VOL_HDR_LOADED)) {
1471 res->hdr.reason = FSYNC_HDR_NOT_ATTACHED;
1474 #else /* !AFS_DEMAND_ATTACH_FS */
1475 if (!vp || !vp->header) {
1476 res->hdr.reason = FSYNC_HDR_NOT_ATTACHED;
1479 #endif /* !AFS_DEMAND_ATTACH_FS */
1481 res->hdr.reason = FSYNC_WRONG_PART;
1485 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1489 memcpy(res->payload.buf, &V_disk(vp), sizeof(VolumeDiskData));
1490 res->hdr.response_len += sizeof(VolumeDiskData);
1494 #ifndef AFS_DEMAND_ATTACH_FS
1502 #ifdef AFS_DEMAND_ATTACH_FS
1504 FSYNC_com_VolOpQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1506 afs_int32 code = SYNC_OK;
1510 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
1512 if (vp && vp->pending_vol_op) {
1513 osi_Assert(sizeof(FSSYNC_VolOp_info) <= res->payload.len);
1514 memcpy(res->payload.buf, vp->pending_vol_op, sizeof(FSSYNC_VolOp_info));
1515 res->hdr.response_len += sizeof(FSSYNC_VolOp_info);
1518 res->hdr.reason = FSYNC_NO_PENDING_VOL_OP;
1520 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1528 FSYNC_com_VGQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1530 afs_int32 code = SYNC_FAILED;
1532 struct DiskPartition64 * dp;
1534 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1535 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1539 dp = VGetPartition_r(vcom->vop->partName, 0);
1541 res->hdr.reason = FSYNC_BAD_PART;
1545 osi_Assert(sizeof(FSSYNC_VGQry_response_t) <= res->payload.len);
1547 rc = VVGCache_query_r(dp, vcom->vop->volume, res->payload.buf);
1550 res->hdr.response_len += sizeof(FSSYNC_VGQry_response_t);
1554 res->hdr.reason = FSYNC_PART_SCANNING;
1557 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1568 FSYNC_com_VGUpdate(osi_socket fd, SYNC_command * com, SYNC_response * res)
1570 afs_int32 code = SYNC_FAILED;
1571 struct DiskPartition64 * dp;
1572 FSSYNC_VGUpdate_command_t * vgucom;
1575 if (com->recv_len != (sizeof(com->hdr) + sizeof(*vgucom))) {
1576 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1577 res->hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
1578 code = SYNC_COM_ERROR;
1582 vgucom = com->payload.buf;
1584 ViceLog(125, ("FSYNC_com_VGUpdate: fd %d got command for parent %lu child "
1585 "%lu partName %.16s\n", (int)fd,
1586 afs_printable_uint32_lu(vgucom->parent),
1587 afs_printable_uint32_lu(vgucom->child),
1590 if (SYNC_verifyProtocolString(vgucom->partName, sizeof(vgucom->partName))) {
1591 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1595 dp = VGetPartition_r(vgucom->partName, 0);
1597 res->hdr.reason = FSYNC_BAD_PART;
1601 switch(com->hdr.command) {
1603 rc = VVGCache_entry_add_r(dp, vgucom->parent, vgucom->child, NULL);
1607 rc = VVGCache_entry_del_r(dp, vgucom->parent, vgucom->child);
1611 Log("FSYNC_com_VGUpdate called improperly\n");
1616 /* EINVAL means the partition VGC doesn't exist at all; not really
1618 if (rc == 0 || rc == EINVAL) {
1623 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1625 res->hdr.reason = FSYNC_WHATEVER;
1633 FSYNC_com_VGScan(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1635 afs_int32 code = SYNC_FAILED;
1636 struct DiskPartition64 * dp;
1638 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1639 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1643 dp = VGetPartition_r(vcom->vop->partName, 0);
1645 res->hdr.reason = FSYNC_BAD_PART;
1649 if (VVGCache_scanStart_r(dp) == 0) {
1658 FSYNC_com_VGScanAll(FSSYNC_VolOp_command * com, SYNC_response * res)
1660 afs_int32 code = SYNC_FAILED;
1662 if (VVGCache_scanStart_r(NULL) == 0) {
1668 #endif /* AFS_DEMAND_ATTACH_FS */
1671 FSYNC_com_VnQry(osi_socket fd, SYNC_command * com, SYNC_response * res)
1673 afs_int32 code = SYNC_OK;
1674 FSSYNC_VnQry_hdr * qry = com->payload.buf;
1679 if (com->recv_len != (sizeof(com->hdr) + sizeof(FSSYNC_VnQry_hdr))) {
1680 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1681 res->hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
1682 return SYNC_COM_ERROR;
1685 ViceLog(125, ("FSYNC_com_VnQry: fd %d got command for vol %lu vnode %lu "
1686 "uniq %lu spare %lu partName %.16s\n", (int)fd,
1687 afs_printable_uint32_lu(qry->volume),
1688 afs_printable_uint32_lu(qry->vnode),
1689 afs_printable_uint32_lu(qry->unique),
1690 afs_printable_uint32_lu(qry->spare),
1693 #ifdef AFS_DEMAND_ATTACH_FS
1694 vp = VLookupVolume_r(&error, qry->volume, NULL);
1695 #else /* !AFS_DEMAND_ATTACH_FS */
1696 vp = VGetVolume_r(&error, qry->volume);
1697 #endif /* !AFS_DEMAND_ATTACH_FS */
1700 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1705 vnp = VLookupVnode(vp, qry->vnode);
1707 res->hdr.reason = FSYNC_UNKNOWN_VNID;
1712 if (Vn_class(vnp)->residentSize > res->payload.len) {
1713 res->hdr.reason = SYNC_REASON_ENCODING_ERROR;
1718 memcpy(res->payload.buf, vnp, Vn_class(vnp)->residentSize);
1719 res->hdr.response_len += Vn_class(vnp)->residentSize;
1722 #ifndef AFS_DEMAND_ATTACH_FS
1731 FSYNC_com_StatsOp(osi_socket fd, SYNC_command * com, SYNC_response * res)
1733 afs_int32 code = SYNC_OK;
1734 FSSYNC_StatsOp_command scom;
1736 if (com->recv_len != (sizeof(com->hdr) + sizeof(FSSYNC_StatsOp_hdr))) {
1737 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1738 res->hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
1739 return SYNC_COM_ERROR;
1742 scom.hdr = &com->hdr;
1743 scom.sop = (FSSYNC_StatsOp_hdr *) com->payload.buf;
1746 ViceLog(125, ("FSYNC_com_StatsOp: fd %d got command for stats: "
1747 "{vlru_generation = %lu, hash_bucket = %lu, partName = "
1748 "%.16s}\n", (int)fd,
1749 afs_printable_uint32_lu(scom.sop->args.vlru_generation),
1750 afs_printable_uint32_lu(scom.sop->args.hash_bucket),
1751 scom.sop->args.partName));
1753 switch (com->hdr.command) {
1754 case FSYNC_VOL_STATS_GENERAL:
1755 code = FSYNC_com_StatsOpGeneral(&scom, res);
1757 #ifdef AFS_DEMAND_ATTACH_FS
1758 /* statistics for the following subsystems are only tracked
1759 * for demand attach fileservers */
1760 case FSYNC_VOL_STATS_VICEP:
1761 code = FSYNC_com_StatsOpViceP(&scom, res);
1763 case FSYNC_VOL_STATS_HASH:
1764 code = FSYNC_com_StatsOpHash(&scom, res);
1766 case FSYNC_VOL_STATS_HDR:
1767 code = FSYNC_com_StatsOpHdr(&scom, res);
1769 case FSYNC_VOL_STATS_VLRU:
1770 code = FSYNC_com_StatsOpVLRU(&scom, res);
1772 #endif /* AFS_DEMAND_ATTACH_FS */
1774 code = SYNC_BAD_COMMAND;
1781 FSYNC_com_StatsOpGeneral(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1783 afs_int32 code = SYNC_OK;
1785 memcpy(res->payload.buf, &VStats, sizeof(VStats));
1786 res->hdr.response_len += sizeof(VStats);
1791 #ifdef AFS_DEMAND_ATTACH_FS
1793 FSYNC_com_StatsOpViceP(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1795 afs_int32 code = SYNC_OK;
1796 struct DiskPartition64 * dp;
1797 struct DiskPartitionStats64 * stats;
1799 if (SYNC_verifyProtocolString(scom->sop->args.partName, sizeof(scom->sop->args.partName))) {
1800 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1805 dp = VGetPartition_r(scom->sop->args.partName, 0);
1809 stats = (struct DiskPartitionStats64 *) res->payload.buf;
1810 stats->free = dp->free;
1811 stats->totalUsable = dp->totalUsable;
1812 stats->minFree = dp->minFree;
1813 stats->f_files = dp->f_files;
1814 stats->vol_list_len = dp->vol_list.len;
1816 res->hdr.response_len += sizeof(struct DiskPartitionStats64);
1824 FSYNC_com_StatsOpHash(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1826 afs_int32 code = SYNC_OK;
1827 struct VolumeHashChainStats * stats;
1828 struct VolumeHashChainHead * head;
1830 if (scom->sop->args.hash_bucket >= VolumeHashTable.Size) {
1834 head = &VolumeHashTable.Table[scom->sop->args.hash_bucket];
1835 stats = (struct VolumeHashChainStats *) res->payload.buf;
1836 stats->table_size = VolumeHashTable.Size;
1837 stats->chain_len = head->len;
1838 stats->chain_cacheCheck = head->cacheCheck;
1839 stats->chain_busy = head->busy;
1840 AssignInt64(head->looks, &stats->chain_looks);
1841 AssignInt64(head->gets, &stats->chain_gets);
1842 AssignInt64(head->reorders, &stats->chain_reorders);
1844 res->hdr.response_len += sizeof(struct VolumeHashChainStats);
1850 FSYNC_com_StatsOpHdr(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1852 afs_int32 code = SYNC_OK;
1854 memcpy(res->payload.buf, &volume_hdr_LRU.stats, sizeof(volume_hdr_LRU.stats));
1855 res->hdr.response_len += sizeof(volume_hdr_LRU.stats);
1861 FSYNC_com_StatsOpVLRU(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1863 afs_int32 code = SYNC_OK;
1865 code = SYNC_BAD_COMMAND;
1869 #endif /* AFS_DEMAND_ATTACH_FS */
1872 * populate an FSSYNC_VolOp_info object from a command packet object.
1874 * @param[in] vcom pointer to command packet
1875 * @param[out] info pointer to info object which will be populated
1877 * @note FSSYNC_VolOp_info objects are attached to Volume objects when
1878 * a volume operation is commenced.
1883 FSYNC_com_to_info(FSSYNC_VolOp_command * vcom, FSSYNC_VolOp_info * info)
1885 memcpy(&info->com, vcom->hdr, sizeof(SYNC_command_hdr));
1886 memcpy(&info->vop, vcom->vop, sizeof(FSSYNC_VolOp_hdr));
1887 info->vol_op_state = FSSYNC_VolOpPending;
1891 * check whether command packet partition name matches volume
1892 * object's partition name.
1894 * @param[in] vcom pointer to command packet
1895 * @param[in] vp pointer to volume object
1896 * @param[in] match_anon anon matching control flag (see note below)
1898 * @return whether partitions match
1899 * @retval 0 partitions do NOT match
1900 * @retval 1 partitions match
1902 * @note if match_anon is non-zero, then this function will return a
1903 * positive match for a zero-length partition string in the
1909 FSYNC_partMatch(FSSYNC_VolOp_command * vcom, Volume * vp, int match_anon)
1911 return ((match_anon && vcom->vop->partName[0] == 0) ||
1912 (strncmp(vcom->vop->partName, V_partition(vp)->name,
1913 sizeof(vcom->vop->partName)) == 0));
1918 FSYNC_Drop(osi_socket fd)
1920 struct offlineInfo *p;
1923 char tvolName[VMAXPATHLEN];
1926 p = OfflineVolumes[FindHandler(fd)];
1927 for (i = 0; i < MAXOFFLINEVOLUMES; i++) {
1928 if (p[i].volumeID) {
1933 sprintf(&tvolName[1], VFORMAT, afs_printable_uint32_lu(p[i].volumeID));
1934 vp = VAttachVolumeByName_r(&error, p[i].partName, tvolName,
1951 static int AcceptHandler = -1; /* handler id for accept, if turned on */
1956 if (AcceptHandler == -1) {
1957 osi_Assert(AddHandler(fssync_server_state.fd, FSYNC_newconnection));
1958 AcceptHandler = FindHandler(fssync_server_state.fd);
1965 if (AcceptHandler != -1) {
1966 osi_Assert(RemoveHandler(fssync_server_state.fd));
1971 /* The multiple FD handling code. */
1973 static osi_socket HandlerFD[MAXHANDLERS];
1974 static void (*HandlerProc[MAXHANDLERS]) (osi_socket);
1980 ObtainWriteLock(&FSYNC_handler_lock);
1981 for (i = 0; i < MAXHANDLERS; i++) {
1982 HandlerFD[i] = OSI_NULLSOCKET;
1985 ReleaseWriteLock(&FSYNC_handler_lock);
1988 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
1990 CallHandler(struct pollfd *fds, int nfds, int mask)
1994 ObtainReadLock(&FSYNC_handler_lock);
1995 for (i = 0; i < nfds; i++) {
1996 if (fds[i].revents & mask) {
1997 handler = FindHandler_r(fds[i].fd);
1998 ReleaseReadLock(&FSYNC_handler_lock);
1999 (*HandlerProc[handler]) (fds[i].fd);
2000 ObtainReadLock(&FSYNC_handler_lock);
2003 ReleaseReadLock(&FSYNC_handler_lock);
2007 CallHandler(fd_set * fdsetp)
2010 ObtainReadLock(&FSYNC_handler_lock);
2011 for (i = 0; i < MAXHANDLERS; i++) {
2012 if (HandlerFD[i] >= 0 && FD_ISSET(HandlerFD[i], fdsetp)) {
2013 ReleaseReadLock(&FSYNC_handler_lock);
2014 (*HandlerProc[i]) (HandlerFD[i]);
2015 ObtainReadLock(&FSYNC_handler_lock);
2018 ReleaseReadLock(&FSYNC_handler_lock);
2023 AddHandler(osi_socket afd, void (*aproc) (osi_socket))
2026 ObtainWriteLock(&FSYNC_handler_lock);
2027 for (i = 0; i < MAXHANDLERS; i++)
2028 if (HandlerFD[i] == OSI_NULLSOCKET)
2030 if (i >= MAXHANDLERS) {
2031 ReleaseWriteLock(&FSYNC_handler_lock);
2035 HandlerProc[i] = aproc;
2036 ReleaseWriteLock(&FSYNC_handler_lock);
2041 FindHandler(osi_socket afd)
2044 ObtainReadLock(&FSYNC_handler_lock);
2045 for (i = 0; i < MAXHANDLERS; i++)
2046 if (HandlerFD[i] == afd) {
2047 ReleaseReadLock(&FSYNC_handler_lock);
2050 ReleaseReadLock(&FSYNC_handler_lock); /* just in case */
2052 return -1; /* satisfy compiler */
2056 FindHandler_r(osi_socket afd)
2059 for (i = 0; i < MAXHANDLERS; i++)
2060 if (HandlerFD[i] == afd) {
2064 return -1; /* satisfy compiler */
2068 RemoveHandler(osi_socket afd)
2070 ObtainWriteLock(&FSYNC_handler_lock);
2071 HandlerFD[FindHandler_r(afd)] = OSI_NULLSOCKET;
2072 ReleaseWriteLock(&FSYNC_handler_lock);
2076 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
2078 GetHandler(struct pollfd *fds, int maxfds, int events, int *nfds)
2082 ObtainReadLock(&FSYNC_handler_lock);
2083 for (i = 0; i < MAXHANDLERS; i++)
2084 if (HandlerFD[i] != OSI_NULLSOCKET) {
2085 osi_Assert(fdi<maxfds);
2086 fds[fdi].fd = HandlerFD[i];
2087 fds[fdi].events = events;
2088 fds[fdi].revents = 0;
2092 ReleaseReadLock(&FSYNC_handler_lock);
2096 GetHandler(fd_set * fdsetp, int *maxfdp)
2101 ObtainReadLock(&FSYNC_handler_lock); /* just in case */
2102 for (i = 0; i < MAXHANDLERS; i++)
2103 if (HandlerFD[i] != OSI_NULLSOCKET) {
2104 FD_SET(HandlerFD[i], fdsetp);
2105 #ifndef AFS_NT40_ENV
2106 /* On Windows the nfds parameter to select() is ignored */
2107 if (maxfd < HandlerFD[i] || maxfd == (int)-1)
2108 maxfd = HandlerFD[i];
2109 #endif /* AFS_NT40_ENV */
2112 ReleaseReadLock(&FSYNC_handler_lock); /* just in case */
2114 #endif /* HAVE_POLL && AFS_PTHREAD_ENV */
2116 #endif /* FSSYNC_BUILD_SERVER */