2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
9 * Portions Copyright (c) 2006-2010 Sine Nomine Associates
15 Institution: The Information Technology Center, Carnegie-Mellon University
18 #ifndef AFS_PTHREAD_ENV
19 #define USUAL_PRIORITY (LWP_MAX_PRIORITY - 2)
22 * stack size increased from 8K because the HP machine seemed to have trouble
23 * with the smaller stack
25 #define USUAL_STACK_SIZE (24 * 1024)
26 #endif /* !AFS_PTHREAD_ENV */
30 File server synchronization with external volume utilities.
31 server-side implementation
34 /* This controls the size of an fd_set; it must be defined early before
35 * the system headers define that type and the macros that operate on it.
36 * Its value should be as large as the maximum file descriptor limit we
37 * are likely to run into on any platform. Right now, that is 65536
38 * which is the default hard fd limit on Solaris 9 */
40 #define FD_SETSIZE 65536
43 #include <afsconfig.h>
44 #include <afs/param.h>
49 #ifdef AFS_PTHREAD_ENV
50 # include <opr/lock.h>
52 #include <afs/afsint.h>
53 #include <rx/rx_queue.h>
55 #include <afs/errors.h>
56 #include "daemon_com.h"
57 #include "daemon_com_inline.h"
59 #include "fssync_inline.h"
63 #include <afs/afssyscalls.h>
67 #include "volume_inline.h"
68 #include "partition.h"
74 #endif /* HAVE_POLL */
76 #ifdef USE_UNIX_SOCKETS
78 #include <afs/afsutil.h>
79 #endif /* USE_UNIX_SOCKETS */
81 #ifdef FSSYNC_BUILD_SERVER
83 int (*V_BreakVolumeCallbacks) (VolumeId volume);
85 #define MAXHANDLERS 4 /* Up to 4 clients; must be at least 2, so that
86 * move = dump+restore can run on single server */
87 #define MAXOFFLINEVOLUMES 128 /* This needs to be as big as the maximum
88 * number that would be offline for 1 operation.
89 * Current winner is salvage, which needs all
90 * cloned read-only copies offline when salvaging
91 * a single read-write volume */
95 static struct offlineInfo OfflineVolumes[MAXHANDLERS][MAXOFFLINEVOLUMES];
98 * fssync server socket handle.
100 static SYNC_server_state_t fssync_server_state =
101 { OSI_NULLSOCKET, /* file descriptor */
102 FSSYNC_ENDPOINT_DECL, /* server endpoint */
103 FSYNC_PROTO_VERSION, /* protocol version */
104 5, /* bind() retry limit */
105 100, /* listen() queue depth */
106 "FSSYNC", /* protocol name string */
109 #ifdef AFS_DEMAND_ATTACH_FS
111 * a queue of volume pointers to salvage in the background.
113 struct fsync_salv_node {
115 Volume *vp; /**< volume to salvage */
116 unsigned char update_salv_prio; /**< whether we should update the salvage priority or not */
119 struct rx_queue head;
123 static void * FSYNC_salvageThread(void *);
124 static void FSYNC_backgroundSalvage(Volume *vp);
125 #endif /* AFS_DEMAND_ATTACH_FS */
127 /* Forward declarations */
128 static void * FSYNC_sync(void *);
129 static void FSYNC_newconnection(osi_socket afd);
130 static void FSYNC_com(osi_socket fd);
131 static void FSYNC_Drop(osi_socket fd);
132 static void AcceptOn(void);
133 static void AcceptOff(void);
134 static void InitHandler(void);
135 static int AddHandler(osi_socket fd, void (*aproc)(osi_socket));
136 static int FindHandler(osi_socket afd);
137 static int FindHandler_r(osi_socket afd);
138 static int RemoveHandler(osi_socket afd);
139 #if defined(HAVE_POLL) && defined (AFS_PTHREAD_ENV)
140 static void CallHandler(struct pollfd *fds, int nfds, int mask);
141 static void GetHandler(struct pollfd *fds, int maxfds, int events, int *nfds);
143 static void CallHandler(fd_set * fdsetp);
144 static void GetHandler(fd_set * fdsetp, int *maxfdp);
147 static afs_int32 FSYNC_com_VolOp(osi_socket fd, SYNC_command * com, SYNC_response * res);
149 #ifdef AFS_DEMAND_ATTACH_FS
150 static afs_int32 FSYNC_com_VolError(FSSYNC_VolOp_command * com, SYNC_response * res);
152 static afs_int32 FSYNC_com_VolOn(FSSYNC_VolOp_command * com, SYNC_response * res);
153 static afs_int32 FSYNC_com_VolOff(FSSYNC_VolOp_command * com, SYNC_response * res);
154 static afs_int32 FSYNC_com_VolMove(FSSYNC_VolOp_command * com, SYNC_response * res);
155 static afs_int32 FSYNC_com_VolBreakCBKs(FSSYNC_VolOp_command * com, SYNC_response * res);
156 static afs_int32 FSYNC_com_VolDone(FSSYNC_VolOp_command * com, SYNC_response * res);
157 static afs_int32 FSYNC_com_VolQuery(FSSYNC_VolOp_command * com, SYNC_response * res);
158 static afs_int32 FSYNC_com_VolHdrQuery(FSSYNC_VolOp_command * com, SYNC_response * res);
159 #ifdef AFS_DEMAND_ATTACH_FS
160 static afs_int32 FSYNC_com_VGUpdate(osi_socket fd, SYNC_command * com, SYNC_response * res);
161 static afs_int32 FSYNC_com_VolOpQuery(FSSYNC_VolOp_command * com, SYNC_response * res);
162 static afs_int32 FSYNC_com_VGQuery(FSSYNC_VolOp_command * com, SYNC_response * res);
163 static afs_int32 FSYNC_com_VGScan(FSSYNC_VolOp_command * com, SYNC_response * res);
164 static afs_int32 FSYNC_com_VGScanAll(FSSYNC_VolOp_command * com, SYNC_response * res);
165 #endif /* AFS_DEMAND_ATTACH_FS */
167 static afs_int32 FSYNC_com_VnQry(osi_socket fd, SYNC_command * com, SYNC_response * res);
169 static afs_int32 FSYNC_com_StatsOp(osi_socket fd, SYNC_command * com, SYNC_response * res);
171 static afs_int32 FSYNC_com_StatsOpGeneral(FSSYNC_StatsOp_command * scom, SYNC_response * res);
173 #ifdef AFS_DEMAND_ATTACH_FS
174 static afs_int32 FSYNC_com_StatsOpViceP(FSSYNC_StatsOp_command * scom, SYNC_response * res);
175 static afs_int32 FSYNC_com_StatsOpHash(FSSYNC_StatsOp_command * scom, SYNC_response * res);
176 static afs_int32 FSYNC_com_StatsOpHdr(FSSYNC_StatsOp_command * scom, SYNC_response * res);
177 static afs_int32 FSYNC_com_StatsOpVLRU(FSSYNC_StatsOp_command * scom, SYNC_response * res);
180 static void FSYNC_com_to_info(FSSYNC_VolOp_command * vcom, FSSYNC_VolOp_info * info);
182 static int FSYNC_partMatch(FSSYNC_VolOp_command * vcom, Volume * vp, int match_anon);
186 * This lock controls access to the handler array. The overhead
187 * is minimal in non-preemptive environments.
189 struct Lock FSYNC_handler_lock;
194 #ifdef AFS_PTHREAD_ENV
196 pthread_attr_t tattr;
197 #else /* AFS_PTHREAD_ENV */
199 #endif /* AFS_PTHREAD_ENV */
201 Lock_Init(&FSYNC_handler_lock);
203 #ifdef AFS_PTHREAD_ENV
204 opr_Verify(pthread_attr_init(&tattr) == 0);
205 opr_Verify(pthread_attr_setdetachstate(&tattr,
206 PTHREAD_CREATE_DETACHED) == 0);
207 opr_Verify(pthread_create(&tid, &tattr, FSYNC_sync, NULL) == 0);
208 #else /* AFS_PTHREAD_ENV */
209 opr_Verify(LWP_CreateProcess(FSYNC_sync, USUAL_STACK_SIZE,
210 USUAL_PRIORITY, NULL,
211 "FSYNC_sync", &pid) == LWP_SUCCESS);
212 #endif /* AFS_PTHREAD_ENV */
214 #ifdef AFS_DEMAND_ATTACH_FS
215 queue_Init(&fsync_salv.head);
216 opr_cv_init(&fsync_salv.cv);
217 opr_Verify(pthread_create(&tid, &tattr, FSYNC_salvageThread, NULL) == 0);
218 #endif /* AFS_DEMAND_ATTACH_FS */
221 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
222 static struct pollfd FSYNC_readfds[MAXHANDLERS];
224 static fd_set FSYNC_readfds;
229 FSYNC_sync(void * args)
233 #ifdef AFS_PTHREAD_ENV
236 SYNC_server_state_t * state = &fssync_server_state;
237 #ifdef AFS_DEMAND_ATTACH_FS
238 VThreadOptions_t * thread_opts;
242 * For non-DAFS, only wait until we begin attaching volumes (instead
243 * of waiting until all volumes are attached), since it can take
244 * awhile until VInit == 2.
247 #endif /* AFS_DEMAND_ATTACH_FS */
249 /* we must not be called before vol package initialization, since we use
250 * vol package mutexes and conds etc */
253 SYNC_getAddr(&state->endpoint, &state->addr);
254 SYNC_cleanupSock(state);
257 (void)signal(SIGPIPE, SIG_IGN);
260 #ifdef AFS_PTHREAD_ENV
261 /* set our 'thread-id' so that the host hold table works */
262 tid = rx_SetThreadNum();
263 Log("Set thread id %d for FSYNC_sync\n", tid);
264 afs_pthread_setname_self("FSYNC_sync");
265 #endif /* AFS_PTHREAD_ENV */
269 while (VInit < min_vinit) {
270 /* Let somebody else run until all volumes have been preattached
271 * (DAFS), or we have started attaching volumes (non-DAFS). This
272 * doesn't mean that all volumes have been attached.
274 #ifdef AFS_PTHREAD_ENV
275 VOL_CV_WAIT(&vol_vinit_cond);
276 #else /* AFS_PTHREAD_ENV */
277 LWP_DispatchProcess();
278 #endif /* AFS_PTHREAD_ENV */
283 state->fd = SYNC_getSock(&state->endpoint);
284 code = SYNC_bindSock(state);
287 #ifdef AFS_DEMAND_ATTACH_FS
289 * make sure the volume package is incapable of recursively executing
290 * salvsync calls on this thread, since there is a possibility of
293 thread_opts = malloc(sizeof(VThreadOptions_t));
294 if (thread_opts == NULL) {
295 Log("failed to allocate memory for thread-specific volume package options structure\n");
298 memcpy(thread_opts, &VThread_defaults, sizeof(VThread_defaults));
299 thread_opts->disallow_salvsync = 1;
300 opr_Verify(pthread_setspecific(VThread_key, thread_opts) == 0);
302 code = VVGCache_PkgInit();
303 opr_Assert(code == 0);
310 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
312 GetHandler(FSYNC_readfds, MAXHANDLERS, POLLIN|POLLPRI, &nfds);
313 if (poll(FSYNC_readfds, nfds, -1) >=1)
314 CallHandler(FSYNC_readfds, nfds, POLLIN|POLLPRI);
317 #ifdef AFS_PTHREAD_ENV
318 struct timeval s_timeout;
320 GetHandler(&FSYNC_readfds, &maxfd);
321 /* Note: check for >= 1 below is essential since IOMGR_select
322 * doesn't have exactly same semantics as select.
324 #ifdef AFS_PTHREAD_ENV
325 s_timeout.tv_sec = SYNC_SELECT_TIMEOUT;
326 s_timeout.tv_usec = 0;
327 if (select(maxfd + 1, &FSYNC_readfds, NULL, NULL, &s_timeout) >= 1)
328 #else /* AFS_PTHREAD_ENV */
329 if (IOMGR_Select(maxfd + 1, &FSYNC_readfds, NULL, NULL, NULL) >= 1)
330 #endif /* AFS_PTHREAD_ENV */
331 CallHandler(&FSYNC_readfds);
334 return NULL; /* hush now, little gcc */
337 #ifdef AFS_DEMAND_ATTACH_FS
339 * thread for salvaging volumes in the background.
341 * Since FSSYNC handlers cannot issue SALVSYNC requests in order to avoid
342 * deadlock issues, this thread exists so code in the FSSYNC handler thread
343 * can hand off volumes to be salvaged in the background.
345 * @param[in] args unused
347 * @note DEMAND_ATTACH_FS only
350 FSYNC_salvageThread(void * args)
353 struct fsync_salv_node *node;
358 while (queue_IsEmpty(&fsync_salv.head)) {
359 VOL_CV_WAIT(&fsync_salv.cv);
362 node = queue_First(&fsync_salv.head, fsync_salv_node);
366 if (node->update_salv_prio) {
367 if (VUpdateSalvagePriority_r(vp)) {
368 ViceLog(0, ("FSYNC_salvageThread: unable to raise salvage priority "
369 "for volume %" AFS_VOLID_FMT "\n", afs_printable_VolumeId_lu(vp->hashid)));
376 VCancelReservation_r(vp);
385 * salvage a volume in the background.
387 * Salvages cannot be scheduled directly from the main FSYNC thread, so
388 * instead call this function to schedule a salvage asynchronously in the
389 * FSYNC_salvageThread thread.
391 * @param[in] vp volume to pointer to salvage
395 * @note DEMAND_ATTACH_FS only
398 FSYNC_backgroundSalvage(Volume *vp)
400 struct fsync_salv_node *node;
403 VCreateReservation_r(vp);
405 node = malloc(sizeof(struct fsync_salv_node));
408 /* Save this value, to know if we should VUpdateSalvagePriority_r.
409 * We need to save it here, snce VRequestSalvage_r will change it. */
410 node->update_salv_prio = vp->salvage.requested;
412 if (VRequestSalvage_r(&ec, vp, SALVSYNC_ERROR, 0)) {
413 ViceLog(0, ("FSYNC_backgroundSalvage: unable to request salvage for volume %" AFS_VOLID_FMT "\n",
414 afs_printable_VolumeId_lu(vp->hashid)));
417 queue_Append(&fsync_salv.head, node);
418 opr_cv_broadcast(&fsync_salv.cv);
420 #endif /* AFS_DEMAND_ATTACH_FS */
423 FSYNC_newconnection(osi_socket afd)
425 #ifdef USE_UNIX_SOCKETS
426 struct sockaddr_un other;
427 #else /* USE_UNIX_SOCKETS */
428 struct sockaddr_in other;
432 junk = sizeof(other);
433 fd = accept(afd, (struct sockaddr *)&other, &junk);
434 if (fd == OSI_NULLSOCKET) {
435 Log("FSYNC_newconnection: accept failed, errno==%d\n", errno);
437 } else if (!AddHandler(fd, FSYNC_com)) {
439 opr_Verify(AddHandler(fd, FSYNC_com));
443 /* this function processes commands from an fssync file descriptor (fd) */
444 afs_int32 FS_cnt = 0;
446 FSYNC_com(osi_socket fd)
450 SYNC_PROTO_BUF_DECL(com_buf);
451 SYNC_PROTO_BUF_DECL(res_buf);
453 memset(&res.hdr, 0, sizeof(res.hdr));
455 com.payload.buf = (void *)com_buf;
456 com.payload.len = SYNC_PROTO_MAX_LEN;
457 res.hdr.response_len = sizeof(res.hdr);
458 res.payload.len = SYNC_PROTO_MAX_LEN;
459 res.payload.buf = (void *)res_buf;
462 if (SYNC_getCom(&fssync_server_state, fd, &com)) {
463 Log("FSYNC_com: read failed; dropping connection (cnt=%d)\n", FS_cnt);
468 if (com.recv_len < sizeof(com.hdr)) {
469 Log("FSSYNC_com: invalid protocol message length (%u)\n", com.recv_len);
470 res.hdr.response = SYNC_COM_ERROR;
471 res.hdr.reason = SYNC_REASON_MALFORMED_PACKET;
472 res.hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
476 if (com.hdr.proto_version != FSYNC_PROTO_VERSION) {
477 Log("FSYNC_com: invalid protocol version (%u)\n", com.hdr.proto_version);
478 res.hdr.response = SYNC_COM_ERROR;
479 res.hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
483 if (com.hdr.command == SYNC_COM_CHANNEL_CLOSE) {
484 res.hdr.response = SYNC_OK;
485 res.hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
487 /* don't respond, just drop; senders of SYNC_COM_CHANNEL_CLOSE
488 * never wait for a response. */
492 ViceLog(125, ("FSYNC_com: from fd %d got command %ld (%s) reason %ld (%s) "
493 "pt %ld (%s) pid %ld\n", (int)fd,
494 afs_printable_int32_ld(com.hdr.command),
495 FSYNC_com2string(com.hdr.command),
496 afs_printable_int32_ld(com.hdr.reason),
497 FSYNC_reason2string(com.hdr.reason),
498 afs_printable_int32_ld(com.hdr.programType),
499 VPTypeToString(com.hdr.programType),
500 afs_printable_int32_ld(com.hdr.pid)));
502 res.hdr.com_seq = com.hdr.com_seq;
505 switch (com.hdr.command) {
507 case FSYNC_VOL_ATTACH:
508 case FSYNC_VOL_LEAVE_OFF:
510 case FSYNC_VOL_FORCE_ERROR:
511 case FSYNC_VOL_LISTVOLUMES:
512 case FSYNC_VOL_NEEDVOLUME:
514 case FSYNC_VOL_BREAKCBKS:
516 case FSYNC_VOL_QUERY:
517 case FSYNC_VOL_QUERY_HDR:
518 #ifdef AFS_DEMAND_ATTACH_FS
519 case FSYNC_VOL_QUERY_VOP:
522 case FSYNC_VG_SCAN_ALL:
524 res.hdr.response = FSYNC_com_VolOp(fd, &com, &res);
526 case FSYNC_VOL_STATS_GENERAL:
527 case FSYNC_VOL_STATS_VICEP:
528 case FSYNC_VOL_STATS_HASH:
529 case FSYNC_VOL_STATS_HDR:
530 case FSYNC_VOL_STATS_VLRU:
531 res.hdr.response = FSYNC_com_StatsOp(fd, &com, &res);
533 case FSYNC_VOL_QUERY_VNODE:
534 res.hdr.response = FSYNC_com_VnQry(fd, &com, &res);
536 #ifdef AFS_DEMAND_ATTACH_FS
539 res.hdr.response = FSYNC_com_VGUpdate(fd, &com, &res);
543 res.hdr.response = SYNC_BAD_COMMAND;
548 ViceLog(125, ("FSYNC_com: fd %d responding with code %ld (%s) reason %ld "
550 afs_printable_int32_ld(res.hdr.response),
551 SYNC_res2string(res.hdr.response),
552 afs_printable_int32_ld(res.hdr.reason),
553 FSYNC_reason2string(res.hdr.reason)));
556 SYNC_putRes(&fssync_server_state, fd, &res);
559 if (res.hdr.flags & SYNC_FLAG_CHANNEL_SHUTDOWN) {
565 FSYNC_com_VolOp(osi_socket fd, SYNC_command * com, SYNC_response * res)
568 afs_int32 code = SYNC_OK;
569 FSSYNC_VolOp_command vcom;
571 if (com->recv_len != (sizeof(com->hdr) + sizeof(FSSYNC_VolOp_hdr))) {
572 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
573 res->hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
574 return SYNC_COM_ERROR;
577 vcom.hdr = &com->hdr;
578 vcom.vop = (FSSYNC_VolOp_hdr *) com->payload.buf;
581 vcom.volumes = OfflineVolumes[FindHandler(fd)];
582 for (vcom.v = NULL, i = 0; i < MAXOFFLINEVOLUMES; i++) {
583 if ((vcom.volumes[i].volumeID == vcom.vop->volume) &&
584 (strncmp(vcom.volumes[i].partName, vcom.vop->partName,
585 sizeof(vcom.volumes[i].partName)) == 0)) {
586 vcom.v = &vcom.volumes[i];
591 ViceLog(125, ("FSYNC_com_VolOp: fd %d got command for vol %lu part %.16s\n",
592 (int)fd, afs_printable_uint32_lu(vcom.vop->volume),
593 vcom.vop->partName));
595 switch (com->hdr.command) {
597 case FSYNC_VOL_ATTACH:
598 case FSYNC_VOL_LEAVE_OFF:
599 code = FSYNC_com_VolOn(&vcom, res);
602 case FSYNC_VOL_NEEDVOLUME:
603 code = FSYNC_com_VolOff(&vcom, res);
605 case FSYNC_VOL_LISTVOLUMES:
609 code = FSYNC_com_VolMove(&vcom, res);
611 case FSYNC_VOL_BREAKCBKS:
612 code = FSYNC_com_VolBreakCBKs(&vcom, res);
615 code = FSYNC_com_VolDone(&vcom, res);
617 case FSYNC_VOL_QUERY:
618 code = FSYNC_com_VolQuery(&vcom, res);
620 case FSYNC_VOL_QUERY_HDR:
621 code = FSYNC_com_VolHdrQuery(&vcom, res);
623 #ifdef AFS_DEMAND_ATTACH_FS
624 case FSYNC_VOL_FORCE_ERROR:
625 code = FSYNC_com_VolError(&vcom, res);
627 case FSYNC_VOL_QUERY_VOP:
628 code = FSYNC_com_VolOpQuery(&vcom, res);
631 code = FSYNC_com_VGQuery(&vcom, res);
634 code = FSYNC_com_VGScan(&vcom, res);
636 case FSYNC_VG_SCAN_ALL:
637 code = FSYNC_com_VGScanAll(&vcom, res);
639 #endif /* AFS_DEMAND_ATTACH_FS */
641 code = SYNC_BAD_COMMAND;
648 * service an FSYNC request to bring a volume online.
650 * @param[in] vcom pointer command object
651 * @param[out] res object in which to store response packet
653 * @return operation status
654 * @retval SYNC_OK volume transitioned online
655 * @retval SYNC_FAILED invalid command protocol message
656 * @retval SYNC_DENIED operation could not be completed
658 * @note this is an FSYNC RPC server stub
660 * @note this procedure handles the following FSSYNC command codes:
663 * - FSYNC_VOL_LEAVE_OFF
665 * @note the supplementary reason code contains additional details.
666 * When SYNC_DENIED is returned, the specific reason is
667 * placed in the response packet reason field.
672 FSYNC_com_VolOn(FSSYNC_VolOp_command * vcom, SYNC_response * res)
674 afs_int32 code = SYNC_OK;
675 #ifndef AFS_DEMAND_ATTACH_FS
676 char tvolName[VMAXPATHLEN];
681 /* Verify the partition name is null terminated. */
682 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
683 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
688 /* so, we need to attach the volume */
690 #ifdef AFS_DEMAND_ATTACH_FS
691 /* Verify the partition name is not empty. */
692 if (*vcom->vop->partName == 0) {
693 res->hdr.reason = FSYNC_BAD_PART;
698 /* check DAFS permissions */
699 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
701 FSYNC_partMatch(vcom, vp, 1) &&
702 vp->pending_vol_op &&
703 (vcom->hdr->programType != vp->pending_vol_op->com.programType)) {
704 /* a different program has this volume checked out. deny. */
705 Log("FSYNC_VolOn: WARNING: program type %u has attempted to manipulate "
706 "state for volume %" AFS_VOLID_FMT " using command code %u while the volume is "
707 "checked out by program type %u for command code %u.\n",
708 vcom->hdr->programType,
709 afs_printable_VolumeId_lu(vcom->vop->volume),
711 vp->pending_vol_op->com.programType,
712 vp->pending_vol_op->com.command);
714 res->hdr.reason = FSYNC_EXCLUSIVE;
720 vcom->v->volumeID = 0;
723 if (vcom->hdr->command == FSYNC_VOL_LEAVE_OFF) {
724 /* nothing much to do if we're leaving the volume offline */
725 #ifdef AFS_DEMAND_ATTACH_FS
727 VCreateReservation_r(vp);
728 VWaitExclusiveState_r(vp);
730 if (vp && V_attachState(vp) != VOL_STATE_DELETED) {
731 if (FSYNC_partMatch(vcom, vp, 1)) {
732 if ((V_attachState(vp) == VOL_STATE_UNATTACHED) ||
733 (V_attachState(vp) == VOL_STATE_PREATTACHED)) {
734 VChangeState_r(vp, VOL_STATE_UNATTACHED);
735 VDeregisterVolOp_r(vp);
738 res->hdr.reason = FSYNC_BAD_STATE;
742 res->hdr.reason = FSYNC_WRONG_PART;
746 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
750 VCancelReservation_r(vp);
757 #ifdef AFS_DEMAND_ATTACH_FS
760 FSYNC_partMatch(vcom, vp, 0) &&
761 vp->pending_vol_op &&
762 vp->pending_vol_op->vol_op_state == FSSYNC_VolOpRunningOnline &&
763 V_attachState(vp) == VOL_STATE_ATTACHED) {
765 /* noop; the volume stayed online for the volume operation and we were
766 * simply told that the vol op is done. The vp we already have is fine,
767 * so avoid confusing volume routines with trying to preattach an
768 * attached volume. */
771 /* first, check to see whether we have such a volume defined */
772 vp = VPreAttachVolumeById_r(&error,
778 VCreateReservation_r(vp);
779 VWaitExclusiveState_r(vp);
780 VDeregisterVolOp_r(vp);
781 VCancelReservation_r(vp);
784 #else /* !AFS_DEMAND_ATTACH_FS */
785 tvolName[0] = OS_DIRSEPC;
786 snprintf(&tvolName[1], sizeof(tvolName)-1, VFORMAT, afs_printable_VolumeId_lu(vcom->vop->volume));
787 tvolName[sizeof(tvolName)-1] = '\0';
789 vp = VAttachVolumeByName_r(&error, vcom->vop->partName, tvolName,
793 #endif /* !AFS_DEMAND_ATTACH_FS */
796 res->hdr.reason = error;
804 * service an FSYNC request to take a volume offline.
806 * @param[in] vcom pointer command object
807 * @param[out] res object in which to store response packet
809 * @return operation status
810 * @retval SYNC_OK volume transitioned offline
811 * @retval SYNC_FAILED invalid command protocol message
812 * @retval SYNC_DENIED operation could not be completed
814 * @note this is an FSYNC RPC server stub
816 * @note this procedure handles the following FSSYNC command codes:
818 * - FSYNC_VOL_NEEDVOLUME
820 * @note the supplementary reason code contains additional details.
821 * When SYNC_DENIED is returned, the specific reason is
822 * placed in the response packet reason field.
827 FSYNC_com_VolOff(FSSYNC_VolOp_command * vcom, SYNC_response * res)
829 FSSYNC_VolOp_info info;
830 afs_int32 code = SYNC_OK;
834 #ifdef AFS_DEMAND_ATTACH_FS
835 Volume *nvp, *rvp = NULL;
838 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
839 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
844 /* not already offline, we need to find a slot for newly offline volume */
845 if (vcom->hdr->programType == debugUtility) {
846 /* debug utilities do not have their operations tracked */
850 for (i = 0; i < MAXOFFLINEVOLUMES; i++) {
851 if (vcom->volumes[i].volumeID == 0) {
852 vcom->v = &vcom->volumes[i];
862 FSYNC_com_to_info(vcom, &info);
864 #ifdef AFS_DEMAND_ATTACH_FS
865 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
867 vp = VGetVolume_r(&error, vcom->vop->volume);
871 if (!FSYNC_partMatch(vcom, vp, 1)) {
872 /* volume on desired partition is not online, so we
873 * should treat this as an offline volume.
875 #ifndef AFS_DEMAND_ATTACH_FS
883 #ifdef AFS_DEMAND_ATTACH_FS
885 ProgramType type = (ProgramType) vcom->hdr->programType;
887 /* do initial filtering of requests */
889 /* enforce mutual exclusion for volume ops */
890 if (vp->pending_vol_op) {
891 if (vp->pending_vol_op->com.programType != type) {
892 if (vp->pending_vol_op->com.command == FSYNC_VOL_OFF &&
893 vp->pending_vol_op->com.reason == FSYNC_SALVAGE) {
895 Log("denying offline request for volume %" AFS_VOLID_FMT "; volume is salvaging\n",
896 afs_printable_VolumeId_lu(vp->hashid));
898 res->hdr.reason = FSYNC_SALVAGE;
901 Log("volume %" AFS_VOLID_FMT " already checked out\n",
902 afs_printable_VolumeId_lu(vp->hashid));
904 Log("vp->vop = { com = { ver=%u, prog=%d, com=%d, reason=%d, len=%u, flags=0x%x }, vop = { vol=%" AFS_VOLID_FMT ", part='%s' } }\n",
905 vp->pending_vol_op->com.proto_version,
906 vp->pending_vol_op->com.programType,
907 vp->pending_vol_op->com.command,
908 vp->pending_vol_op->com.reason,
909 vp->pending_vol_op->com.command_len,
910 vp->pending_vol_op->com.flags,
911 afs_printable_VolumeId_lu(vp->pending_vol_op->vop.volume),
912 vp->pending_vol_op->vop.partName );
913 Log("vcom = { com = { ver=%u, prog=%d, com=%d, reason=%d, len=%u, flags=0x%x } , vop = { vol=%" AFS_VOLID_FMT ", part='%s' } }\n",
914 vcom->hdr->proto_version,
915 vcom->hdr->programType,
918 vcom->hdr->command_len,
920 afs_printable_VolumeId_lu(vcom->vop->volume),
921 vcom->vop->partName);
922 res->hdr.reason = FSYNC_EXCLUSIVE;
925 Log("warning: volume %" AFS_VOLID_FMT " recursively checked out by programType id %d\n",
926 afs_printable_VolumeId_lu(vp->hashid), vcom->hdr->programType);
930 /* wait for exclusive ops, so we have an accurate picture of the
931 * vol attach state */
932 VCreateReservation_r(vp);
933 VWaitExclusiveState_r(vp);
936 /* filter based upon requestor
938 * volume utilities / volserver are not allowed to check out
939 * volumes which are in an error state
941 * unknown utility programs will be denied on principal
946 /* it is possible for the salvageserver to checkout a
947 * volume for salvage before its scheduling request
948 * has been sent to the salvageserver */
949 if (vp->salvage.requested && !vp->salvage.scheduled) {
950 vp->salvage.scheduled = 1;
953 /* If the volume is in VOL_STATE_SALVAGE_REQ, we need to wait
954 * for the vol to go offline before we can give it away. Also
955 * make sure we don't come out with vp in an excl state. */
956 while (V_attachState(vp) == VOL_STATE_SALVAGE_REQ ||
957 VIsExclusiveState(V_attachState(vp))) {
959 VOL_CV_WAIT(&V_attachCV(vp));
967 if (VIsSalvaging(vp)) {
968 Log("denying offline request for volume %" AFS_VOLID_FMT "; volume is in salvaging state\n",
969 afs_printable_VolumeId_lu(vp->hashid));
970 res->hdr.reason = FSYNC_SALVAGE;
972 /* the volume hasn't been checked out yet by the salvager,
973 * but we think the volume is salvaging; schedule a
974 * a salvage to update the salvage priority */
975 FSYNC_backgroundSalvage(vp);
979 if (VIsErrorState(V_attachState(vp))) {
985 Log("bad program type passed to FSSYNC\n");
989 /* short circuit for offline volume states
990 * so we can avoid I/O penalty of attachment */
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;
1005 case VOL_STATE_DELETED:
1011 /* convert to heavyweight ref */
1012 nvp = VGetVolumeByVp_r(&error, vp);
1015 * It's possible for VGetVolumeByVp_r to have dropped and
1016 * re-acquired VOL_LOCK, so volume state may have changed
1017 * back to one of the states we tested for above. Since
1018 * GetVolume can return NULL in some of those states, just
1019 * test for the states again here.
1021 switch (V_attachState(vp)) {
1022 case VOL_STATE_UNATTACHED:
1023 case VOL_STATE_PREATTACHED:
1024 case VOL_STATE_SALVAGING:
1025 case VOL_STATE_ERROR:
1026 /* register the volume operation metadata with the volume
1028 * if the volume is currently pre-attached, attach2()
1029 * will evaluate the vol op metadata to determine whether
1030 * attaching the volume would be safe */
1031 VRegisterVolOp_r(vp, &info);
1032 vp->pending_vol_op->vol_op_state = FSSYNC_VolOpRunningUnknown;
1035 case VOL_STATE_DELETED:
1041 Log("FSYNC_com_VolOff: failed to get heavyweight reference to volume %" AFS_VOLID_FMT " (state=%u, flags=0x%x)\n",
1042 afs_printable_VolumeId_lu(vcom->vop->volume),
1043 V_attachState(vp), V_attachFlags(vp));
1044 res->hdr.reason = FSYNC_VOL_PKG_ERROR;
1046 } else if (nvp != vp) {
1047 /* i don't think this should ever happen, but just in case... */
1048 Log("FSYNC_com_VolOff: warning: potentially dangerous race detected\n");
1052 /* kill off lightweight ref to ensure we can't deadlock against ourselves later... */
1053 VCancelReservation_r(rvp);
1056 /* register the volume operation metadata with the volume */
1057 VRegisterVolOp_r(vp, &info);
1060 #endif /* AFS_DEMAND_ATTACH_FS */
1063 if (VVolOpLeaveOnline_r(vp, &info)) {
1064 VUpdateVolume_r(&error, vp, VOL_UPDATE_WAIT); /* At least get volume stats right */
1065 if (GetLogLevel() > 0) {
1066 Log("FSYNC: Volume %" AFS_VOLID_FMT " (%s) was left on line for an external %s request\n",
1067 afs_printable_VolumeId_lu(V_id(vp)), V_name(vp),
1068 vcom->hdr->reason == V_CLONE ? "clone" :
1069 vcom->hdr->reason == V_READONLY ? "readonly" :
1070 vcom->hdr->reason == V_DUMP ? "dump" :
1071 vcom->hdr->reason == FSYNC_SALVAGE ? "salvage" :
1074 #ifdef AFS_DEMAND_ATTACH_FS
1075 vp->pending_vol_op->vol_op_state = FSSYNC_VolOpRunningOnline;
1079 if (VVolOpSetVBusy_r(vp, &info)) {
1080 vp->specialStatus = VBUSY;
1083 /* remember what volume we got, so we can keep track of how
1084 * many volumes the volserver or whatever is using. Note that
1085 * vp is valid since leaveonline is only set when vp is valid.
1088 vcom->v->volumeID = vcom->vop->volume;
1089 strlcpy(vcom->v->partName, vp->partition->name, sizeof(vcom->v->partName));
1092 #ifdef AFS_DEMAND_ATTACH_FS
1093 VCreateReservation_r(vp);
1094 VOfflineForVolOp_r(&error, vp, "A volume utility is running.");
1096 opr_Assert(vp->nUsers==0);
1097 vp->pending_vol_op->vol_op_state = FSSYNC_VolOpRunningOffline;
1100 VWaitExclusiveState_r(vp);
1101 VDeregisterVolOp_r(vp);
1104 VCancelReservation_r(vp);
1106 VOffline_r(vp, "A volume utility is running.");
1117 #ifdef AFS_DEMAND_ATTACH_FS
1119 VCancelReservation_r(rvp);
1126 * service an FSYNC request to mark a volume as moved.
1128 * @param[in] vcom pointer command object
1129 * @param[out] res object in which to store response packet
1131 * @return operation status
1132 * @retval SYNC_OK volume marked as moved to a remote server
1133 * @retval SYNC_FAILED invalid command protocol message
1134 * @retval SYNC_DENIED current volume state does not permit this operation
1136 * @note this is an FSYNC RPC server stub
1138 * @note this operation also breaks all callbacks for the given volume
1140 * @note this procedure handles the following FSSYNC command codes:
1143 * @note the supplementary reason code contains additional details. For
1144 * instance, SYNC_OK is still returned when the partition specified
1145 * does not match the one registered in the volume object -- reason
1146 * will be FSYNC_WRONG_PART in this case.
1151 FSYNC_com_VolMove(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1153 afs_int32 code = SYNC_DENIED;
1157 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1158 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1163 /* Yuch: the "reason" for the move is the site it got moved to... */
1164 /* still set specialStatus so we stop sending back VBUSY.
1165 * also should still break callbacks. Note that I don't know
1166 * how to tell if we should break all or not, so we just do it
1167 * since it doesn't matter much if we do an extra break
1168 * volume callbacks on a volume move within the same server */
1169 #ifdef AFS_DEMAND_ATTACH_FS
1170 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
1172 vp = VGetVolume_r(&error, vcom->vop->volume);
1175 if (FSYNC_partMatch(vcom, vp, 1)) {
1176 #ifdef AFS_DEMAND_ATTACH_FS
1177 if ((V_attachState(vp) == VOL_STATE_UNATTACHED) ||
1178 (V_attachState(vp) == VOL_STATE_PREATTACHED)) {
1181 vp->specialStatus = VMOVED;
1182 #ifdef AFS_DEMAND_ATTACH_FS
1184 res->hdr.reason = FSYNC_BAD_STATE;
1188 res->hdr.reason = FSYNC_WRONG_PART;
1190 #ifndef AFS_DEMAND_ATTACH_FS
1192 #endif /* !AFS_DEMAND_ATTACH_FS */
1194 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1197 if ((code == SYNC_OK) && (V_BreakVolumeCallbacks != NULL)) {
1198 Log("fssync: volume %" AFS_VOLID_FMT " moved to %x; breaking all call backs\n",
1199 afs_printable_VolumeId_lu(vcom->vop->volume), vcom->hdr->reason);
1201 (*V_BreakVolumeCallbacks) (vcom->vop->volume);
1211 * service an FSYNC request to mark a volume as destroyed.
1213 * @param[in] vcom pointer command object
1214 * @param[out] res object in which to store response packet
1216 * @return operation status
1217 * @retval SYNC_OK volume marked as destroyed
1218 * @retval SYNC_FAILED invalid command protocol message
1219 * @retval SYNC_DENIED current volume state does not permit this operation
1221 * @note this is an FSYNC RPC server stub
1223 * @note this procedure handles the following FSSYNC command codes:
1226 * @note the supplementary reason code contains additional details. For
1227 * instance, SYNC_OK is still returned when the partition specified
1228 * does not match the one registered in the volume object -- reason
1229 * will be FSYNC_WRONG_PART in this case.
1234 FSYNC_com_VolDone(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1236 afs_int32 code = SYNC_FAILED;
1240 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1241 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1245 /* don't try to put online, this call is made only after deleting
1246 * a volume, in which case we want to remove the vol # from the
1247 * OfflineVolumes array only */
1249 vcom->v->volumeID = 0;
1251 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
1253 if (FSYNC_partMatch(vcom, vp, 1)) {
1254 #ifdef AFS_DEMAND_ATTACH_FS
1255 VCreateReservation_r(vp);
1256 VWaitExclusiveState_r(vp);
1258 if ((V_attachState(vp) == VOL_STATE_UNATTACHED) ||
1259 (V_attachState(vp) == VOL_STATE_PREATTACHED) ||
1260 VIsErrorState(V_attachState(vp))) {
1262 /* Change state to DELETED, not UNATTACHED, so clients get
1263 * a VNOVOL error when they try to access from now on. */
1265 VChangeState_r(vp, VOL_STATE_DELETED);
1266 VDeregisterVolOp_r(vp);
1268 /* Volume is gone; clear out old salvage stats */
1269 memset(&vp->salvage, 0, sizeof(vp->salvage));
1271 /* Someday we should free the vp, too, after about 2 hours,
1272 * possibly by putting the vp back on the VLRU. */
1275 } else if (V_attachState(vp) == VOL_STATE_DELETED) {
1276 VDeregisterVolOp_r(vp);
1277 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1281 res->hdr.reason = FSYNC_BAD_STATE;
1284 VCancelReservation_r(vp);
1286 #else /* AFS_DEMAND_ATTACH_FS */
1287 if (!vp->specialStatus) {
1288 vp->specialStatus = VNOVOL;
1291 #endif /* !AFS_DEMAND_ATTACH_FS */
1293 code = SYNC_OK; /* XXX is this really a good idea? */
1294 res->hdr.reason = FSYNC_WRONG_PART;
1297 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1304 #ifdef AFS_DEMAND_ATTACH_FS
1306 * service an FSYNC request to transition a volume to the hard error state.
1308 * @param[in] vcom pointer command object
1309 * @param[out] res object in which to store response packet
1311 * @return operation status
1312 * @retval SYNC_OK volume transitioned to hard error state
1313 * @retval SYNC_FAILED invalid command protocol message
1314 * @retval SYNC_DENIED (see note)
1316 * @note this is an FSYNC RPC server stub
1318 * @note this procedure handles the following FSSYNC command codes:
1319 * - FSYNC_VOL_FORCE_ERROR
1321 * @note SYNC_DENIED is returned in the following cases:
1322 * - no partition name is specified (reason field set to
1323 * FSYNC_WRONG_PART).
1324 * - volume id not known to fileserver (reason field set
1325 * to FSYNC_UNKNOWN_VOLID).
1327 * @note demand attach fileserver only
1332 FSYNC_com_VolError(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1336 afs_int32 code = SYNC_FAILED;
1338 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1339 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1343 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
1345 if (!vp && vcom->hdr->reason == FSYNC_SALVAGE) {
1346 /* The requested volume doesn't seem to exist. However, it is possible
1347 * that this is triggered by trying to create or clone a volume that
1348 * was prevented from succeeding by a half-created volume in the way.
1349 * (e.g. we tried to create volume X, but volume X exists except that
1350 * its .vol header was deleted for some reason) So, still try to
1351 * a salvage for that volume ID. */
1353 Log("FSYNC_com_VolError: attempting to schedule salvage for unknown "
1354 "volume %lu part %s\n", afs_printable_uint32_lu(vcom->vop->volume),
1355 vcom->vop->partName);
1356 vp = VPreAttachVolumeById_r(&error, vcom->vop->partName,
1361 if (FSYNC_partMatch(vcom, vp, 0)) {
1362 VCreateReservation_r(vp);
1363 VWaitExclusiveState_r(vp);
1364 VDeregisterVolOp_r(vp);
1366 if (vcom->hdr->reason == FSYNC_SALVAGE) {
1367 FSYNC_backgroundSalvage(vp);
1369 /* null out salvsync control state, as it's no longer relevant */
1370 memset(&vp->salvage, 0, sizeof(vp->salvage));
1371 VChangeState_r(vp, VOL_STATE_ERROR);
1374 VCancelReservation_r(vp);
1379 res->hdr.reason = FSYNC_WRONG_PART;
1382 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1388 #endif /* AFS_DEMAND_ATTACH_FS */
1391 * service an FSYNC request to break all callbacks for this volume.
1393 * @param[in] vcom pointer command object
1394 * @param[out] res object in which to store response packet
1396 * @return operation status
1397 * @retval SYNC_OK callback breaks scheduled for volume
1399 * @note this is an FSYNC RPC server stub
1401 * @note this procedure handles the following FSSYNC command codes:
1402 * - FSYNC_VOL_BREAKCBKS
1404 * @note demand attach fileserver only
1406 * @todo should do partition matching
1411 FSYNC_com_VolBreakCBKs(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1413 /* if the volume is being restored, break all callbacks on it */
1414 if (V_BreakVolumeCallbacks) {
1415 Log("fssync: breaking all call backs for volume %" AFS_VOLID_FMT "\n",
1416 afs_printable_VolumeId_lu(vcom->vop->volume));
1418 (*V_BreakVolumeCallbacks) (vcom->vop->volume);
1425 * service an FSYNC request to return the Volume object.
1427 * @param[in] vcom pointer command object
1428 * @param[out] res object in which to store response packet
1430 * @return operation status
1431 * @retval SYNC_OK volume object returned to caller
1432 * @retval SYNC_FAILED bad command packet, or failed to locate volume object
1434 * @note this is an FSYNC RPC server stub
1436 * @note this procedure handles the following FSSYNC command codes:
1442 FSYNC_com_VolQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1444 afs_int32 code = SYNC_FAILED;
1448 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1449 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1453 #ifdef AFS_DEMAND_ATTACH_FS
1454 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
1455 #else /* !AFS_DEMAND_ATTACH_FS */
1456 vp = VGetVolume_r(&error, vcom->vop->volume);
1457 #endif /* !AFS_DEMAND_ATTACH_FS */
1460 if (FSYNC_partMatch(vcom, vp, 1)) {
1461 if (res->payload.len >= sizeof(Volume)) {
1462 memcpy(res->payload.buf, vp, sizeof(Volume));
1463 res->hdr.response_len += sizeof(Volume);
1466 res->hdr.reason = SYNC_REASON_PAYLOAD_TOO_BIG;
1469 res->hdr.reason = FSYNC_WRONG_PART;
1471 #ifndef AFS_DEMAND_ATTACH_FS
1475 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1483 * service an FSYNC request to return the Volume header.
1485 * @param[in] vcom pointer command object
1486 * @param[out] res object in which to store response packet
1488 * @return operation status
1489 * @retval SYNC_OK volume header returned to caller
1490 * @retval SYNC_FAILED bad command packet, or failed to locate volume header
1492 * @note this is an FSYNC RPC server stub
1494 * @note this procedure handles the following FSSYNC command codes:
1495 * - FSYNC_VOL_QUERY_HDR
1500 FSYNC_com_VolHdrQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1502 afs_int32 code = SYNC_FAILED;
1506 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1507 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1510 if (res->payload.len < sizeof(VolumeDiskData)) {
1511 res->hdr.reason = SYNC_REASON_PAYLOAD_TOO_BIG;
1515 #ifdef AFS_DEMAND_ATTACH_FS
1516 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
1517 #else /* !AFS_DEMAND_ATTACH_FS */
1518 vp = VGetVolume_r(&error, vcom->vop->volume);
1522 if (FSYNC_partMatch(vcom, vp, 1)) {
1523 #ifdef AFS_DEMAND_ATTACH_FS
1524 if ((vp->header == NULL) ||
1525 !(V_attachFlags(vp) & VOL_HDR_ATTACHED) ||
1526 !(V_attachFlags(vp) & VOL_HDR_LOADED)) {
1527 res->hdr.reason = FSYNC_HDR_NOT_ATTACHED;
1530 #else /* !AFS_DEMAND_ATTACH_FS */
1531 if (!vp || !vp->header) {
1532 res->hdr.reason = FSYNC_HDR_NOT_ATTACHED;
1535 #endif /* !AFS_DEMAND_ATTACH_FS */
1537 res->hdr.reason = FSYNC_WRONG_PART;
1541 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1545 memcpy(res->payload.buf, &V_disk(vp), sizeof(VolumeDiskData));
1546 res->hdr.response_len += sizeof(VolumeDiskData);
1550 #ifndef AFS_DEMAND_ATTACH_FS
1558 #ifdef AFS_DEMAND_ATTACH_FS
1560 FSYNC_com_VolOpQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1562 afs_int32 code = SYNC_OK;
1566 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
1569 VCreateReservation_r(vp);
1570 VWaitExclusiveState_r(vp);
1573 if (vp && vp->pending_vol_op) {
1574 if (!FSYNC_partMatch(vcom, vp, 1)) {
1575 res->hdr.reason = FSYNC_WRONG_PART;
1578 opr_Assert(sizeof(FSSYNC_VolOp_info) <= res->payload.len);
1579 memcpy(res->payload.buf, vp->pending_vol_op, sizeof(FSSYNC_VolOp_info));
1580 res->hdr.response_len += sizeof(FSSYNC_VolOp_info);
1583 if (!vp || V_attachState(vp) == VOL_STATE_DELETED) {
1584 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1585 } else if (!FSYNC_partMatch(vcom, vp, 1)) {
1586 res->hdr.reason = FSYNC_WRONG_PART;
1588 res->hdr.reason = FSYNC_NO_PENDING_VOL_OP;
1594 VCancelReservation_r(vp);
1600 FSYNC_com_VGQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1602 afs_int32 code = SYNC_FAILED;
1604 struct DiskPartition64 * dp;
1606 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1607 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1611 dp = VGetPartition_r(vcom->vop->partName, 0);
1613 res->hdr.reason = FSYNC_BAD_PART;
1617 opr_Assert(sizeof(FSSYNC_VGQry_response_t) <= res->payload.len);
1619 rc = VVGCache_query_r(dp, vcom->vop->volume, res->payload.buf);
1622 res->hdr.response_len += sizeof(FSSYNC_VGQry_response_t);
1626 res->hdr.reason = FSYNC_PART_SCANNING;
1629 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1640 FSYNC_com_VGUpdate(osi_socket fd, SYNC_command * com, SYNC_response * res)
1642 afs_int32 code = SYNC_FAILED;
1643 struct DiskPartition64 * dp;
1644 FSSYNC_VGUpdate_command_t * vgucom;
1647 if (com->recv_len != (sizeof(com->hdr) + sizeof(*vgucom))) {
1648 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1649 res->hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
1650 code = SYNC_COM_ERROR;
1654 vgucom = com->payload.buf;
1656 ViceLog(125, ("FSYNC_com_VGUpdate: fd %d got command for parent %lu child "
1657 "%lu partName %.16s\n", (int)fd,
1658 afs_printable_uint32_lu(vgucom->parent),
1659 afs_printable_uint32_lu(vgucom->child),
1662 if (SYNC_verifyProtocolString(vgucom->partName, sizeof(vgucom->partName))) {
1663 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1667 dp = VGetPartition_r(vgucom->partName, 0);
1669 res->hdr.reason = FSYNC_BAD_PART;
1673 switch(com->hdr.command) {
1675 rc = VVGCache_entry_add_r(dp, vgucom->parent, vgucom->child, NULL);
1679 rc = VVGCache_entry_del_r(dp, vgucom->parent, vgucom->child);
1683 Log("FSYNC_com_VGUpdate called improperly\n");
1688 /* EINVAL means the partition VGC doesn't exist at all; not really
1690 if (rc == 0 || rc == EINVAL) {
1695 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1697 res->hdr.reason = FSYNC_WHATEVER;
1705 FSYNC_com_VGScan(FSSYNC_VolOp_command * vcom, SYNC_response * res)
1707 afs_int32 code = SYNC_FAILED;
1708 struct DiskPartition64 * dp;
1710 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
1711 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1715 dp = VGetPartition_r(vcom->vop->partName, 0);
1717 res->hdr.reason = FSYNC_BAD_PART;
1721 if (VVGCache_scanStart_r(dp) == 0) {
1730 FSYNC_com_VGScanAll(FSSYNC_VolOp_command * com, SYNC_response * res)
1732 afs_int32 code = SYNC_FAILED;
1734 if (VVGCache_scanStart_r(NULL) == 0) {
1740 #endif /* AFS_DEMAND_ATTACH_FS */
1743 FSYNC_com_VnQry(osi_socket fd, SYNC_command * com, SYNC_response * res)
1745 afs_int32 code = SYNC_OK;
1746 FSSYNC_VnQry_hdr * qry = com->payload.buf;
1751 if (com->recv_len != (sizeof(com->hdr) + sizeof(FSSYNC_VnQry_hdr))) {
1752 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1753 res->hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
1754 return SYNC_COM_ERROR;
1757 ViceLog(125, ("FSYNC_com_VnQry: fd %d got command for vol %lu vnode %lu "
1758 "uniq %lu spare %lu partName %.16s\n", (int)fd,
1759 afs_printable_uint32_lu(qry->volume),
1760 afs_printable_uint32_lu(qry->vnode),
1761 afs_printable_uint32_lu(qry->unique),
1762 afs_printable_uint32_lu(qry->spare),
1765 #ifdef AFS_DEMAND_ATTACH_FS
1766 vp = VLookupVolume_r(&error, qry->volume, NULL);
1767 #else /* !AFS_DEMAND_ATTACH_FS */
1768 vp = VGetVolume_r(&error, qry->volume);
1769 #endif /* !AFS_DEMAND_ATTACH_FS */
1772 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
1777 vnp = VLookupVnode(vp, qry->vnode);
1779 res->hdr.reason = FSYNC_UNKNOWN_VNID;
1784 if (Vn_class(vnp)->residentSize > res->payload.len) {
1785 res->hdr.reason = SYNC_REASON_ENCODING_ERROR;
1790 memcpy(res->payload.buf, vnp, Vn_class(vnp)->residentSize);
1791 res->hdr.response_len += Vn_class(vnp)->residentSize;
1794 #ifndef AFS_DEMAND_ATTACH_FS
1803 FSYNC_com_StatsOp(osi_socket fd, SYNC_command * com, SYNC_response * res)
1805 afs_int32 code = SYNC_OK;
1806 FSSYNC_StatsOp_command scom;
1808 if (com->recv_len != (sizeof(com->hdr) + sizeof(FSSYNC_StatsOp_hdr))) {
1809 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1810 res->hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
1811 return SYNC_COM_ERROR;
1814 scom.hdr = &com->hdr;
1815 scom.sop = (FSSYNC_StatsOp_hdr *) com->payload.buf;
1818 ViceLog(125, ("FSYNC_com_StatsOp: fd %d got command for stats: "
1819 "{vlru_generation = %lu, hash_bucket = %lu, partName = "
1820 "%.16s}\n", (int)fd,
1821 afs_printable_uint32_lu(scom.sop->args.vlru_generation),
1822 afs_printable_uint32_lu(scom.sop->args.hash_bucket),
1823 scom.sop->args.partName));
1825 switch (com->hdr.command) {
1826 case FSYNC_VOL_STATS_GENERAL:
1827 code = FSYNC_com_StatsOpGeneral(&scom, res);
1829 #ifdef AFS_DEMAND_ATTACH_FS
1830 /* statistics for the following subsystems are only tracked
1831 * for demand attach fileservers */
1832 case FSYNC_VOL_STATS_VICEP:
1833 code = FSYNC_com_StatsOpViceP(&scom, res);
1835 case FSYNC_VOL_STATS_HASH:
1836 code = FSYNC_com_StatsOpHash(&scom, res);
1838 case FSYNC_VOL_STATS_HDR:
1839 code = FSYNC_com_StatsOpHdr(&scom, res);
1841 case FSYNC_VOL_STATS_VLRU:
1842 code = FSYNC_com_StatsOpVLRU(&scom, res);
1844 #endif /* AFS_DEMAND_ATTACH_FS */
1846 code = SYNC_BAD_COMMAND;
1853 FSYNC_com_StatsOpGeneral(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1855 afs_int32 code = SYNC_OK;
1857 memcpy(res->payload.buf, &VStats, sizeof(VStats));
1858 res->hdr.response_len += sizeof(VStats);
1863 #ifdef AFS_DEMAND_ATTACH_FS
1865 FSYNC_com_StatsOpViceP(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1867 afs_int32 code = SYNC_OK;
1868 struct DiskPartition64 * dp;
1869 struct DiskPartitionStats64 * stats;
1871 if (SYNC_verifyProtocolString(scom->sop->args.partName, sizeof(scom->sop->args.partName))) {
1872 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1877 dp = VGetPartition_r(scom->sop->args.partName, 0);
1881 stats = (struct DiskPartitionStats64 *) res->payload.buf;
1882 stats->free = dp->free;
1883 stats->totalUsable = dp->totalUsable;
1884 stats->minFree = dp->minFree;
1885 stats->f_files = dp->f_files;
1886 stats->vol_list_len = dp->vol_list.len;
1888 res->hdr.response_len += sizeof(struct DiskPartitionStats64);
1896 FSYNC_com_StatsOpHash(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1898 afs_int32 code = SYNC_OK;
1899 struct VolumeHashChainStats * stats;
1900 struct VolumeHashChainHead * head;
1902 if (scom->sop->args.hash_bucket >= VolumeHashTable.Size) {
1906 head = &VolumeHashTable.Table[scom->sop->args.hash_bucket];
1907 stats = (struct VolumeHashChainStats *) res->payload.buf;
1908 stats->table_size = VolumeHashTable.Size;
1909 stats->chain_len = head->len;
1910 stats->chain_cacheCheck = head->cacheCheck;
1911 stats->chain_busy = head->busy;
1912 AssignInt64(head->looks, &stats->chain_looks);
1913 AssignInt64(head->gets, &stats->chain_gets);
1914 AssignInt64(head->reorders, &stats->chain_reorders);
1916 res->hdr.response_len += sizeof(struct VolumeHashChainStats);
1922 FSYNC_com_StatsOpHdr(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1924 afs_int32 code = SYNC_OK;
1926 memcpy(res->payload.buf, &volume_hdr_LRU.stats, sizeof(volume_hdr_LRU.stats));
1927 res->hdr.response_len += sizeof(volume_hdr_LRU.stats);
1933 FSYNC_com_StatsOpVLRU(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1935 afs_int32 code = SYNC_OK;
1937 code = SYNC_BAD_COMMAND;
1941 #endif /* AFS_DEMAND_ATTACH_FS */
1944 * populate an FSSYNC_VolOp_info object from a command packet object.
1946 * @param[in] vcom pointer to command packet
1947 * @param[out] info pointer to info object which will be populated
1949 * @note FSSYNC_VolOp_info objects are attached to Volume objects when
1950 * a volume operation is commenced.
1955 FSYNC_com_to_info(FSSYNC_VolOp_command * vcom, FSSYNC_VolOp_info * info)
1957 memcpy(&info->com, vcom->hdr, sizeof(SYNC_command_hdr));
1958 memcpy(&info->vop, vcom->vop, sizeof(FSSYNC_VolOp_hdr));
1959 info->vol_op_state = FSSYNC_VolOpPending;
1963 * check whether command packet partition name matches volume
1964 * object's partition name.
1966 * @param[in] vcom pointer to command packet
1967 * @param[in] vp pointer to volume object
1968 * @param[in] match_anon anon matching control flag (see note below)
1970 * @return whether partitions match
1971 * @retval 0 partitions do NOT match
1972 * @retval 1 partitions match
1974 * @note if match_anon is non-zero, then this function will return a
1975 * positive match for a zero-length partition string in the
1981 FSYNC_partMatch(FSSYNC_VolOp_command * vcom, Volume * vp, int match_anon)
1983 return ((match_anon && vcom->vop->partName[0] == 0) ||
1984 (strncmp(vcom->vop->partName, V_partition(vp)->name,
1985 sizeof(vcom->vop->partName)) == 0));
1990 FSYNC_Drop(osi_socket fd)
1992 struct offlineInfo *p;
1995 #ifndef AFS_DEMAND_ATTACH_FS
1996 char tvolName[VMAXPATHLEN];
2000 p = OfflineVolumes[FindHandler(fd)];
2001 for (i = 0; i < MAXOFFLINEVOLUMES; i++) {
2002 if (p[i].volumeID) {
2005 #ifdef AFS_DEMAND_ATTACH_FS
2006 vp = VPreAttachVolumeById_r(&error, p[i].partName, p[i].volumeID);
2008 VCreateReservation_r(vp);
2009 VWaitExclusiveState_r(vp);
2010 VDeregisterVolOp_r(vp);
2011 VCancelReservation_r(vp);
2014 tvolName[0] = OS_DIRSEPC;
2015 sprintf(&tvolName[1], VFORMAT, afs_printable_VolumeId_lu(p[i].volumeID));
2016 vp = VAttachVolumeByName_r(&error, p[i].partName, tvolName,
2020 #endif /* !AFS_DEMAND_ATTACH_FS */
2030 static int AcceptHandler = -1; /* handler id for accept, if turned on */
2035 if (AcceptHandler == -1) {
2036 opr_Verify(AddHandler(fssync_server_state.fd, FSYNC_newconnection));
2037 AcceptHandler = FindHandler(fssync_server_state.fd);
2044 if (AcceptHandler != -1) {
2045 opr_Verify(RemoveHandler(fssync_server_state.fd));
2050 /* The multiple FD handling code. */
2052 static osi_socket HandlerFD[MAXHANDLERS];
2053 static void (*HandlerProc[MAXHANDLERS]) (osi_socket);
2059 ObtainWriteLock(&FSYNC_handler_lock);
2060 for (i = 0; i < MAXHANDLERS; i++) {
2061 HandlerFD[i] = OSI_NULLSOCKET;
2064 ReleaseWriteLock(&FSYNC_handler_lock);
2067 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
2069 CallHandler(struct pollfd *fds, int nfds, int mask)
2073 ObtainReadLock(&FSYNC_handler_lock);
2074 for (i = 0; i < nfds; i++) {
2075 if (fds[i].revents & mask) {
2076 handler = FindHandler_r(fds[i].fd);
2077 ReleaseReadLock(&FSYNC_handler_lock);
2078 (*HandlerProc[handler]) (fds[i].fd);
2079 ObtainReadLock(&FSYNC_handler_lock);
2082 ReleaseReadLock(&FSYNC_handler_lock);
2086 CallHandler(fd_set * fdsetp)
2089 ObtainReadLock(&FSYNC_handler_lock);
2090 for (i = 0; i < MAXHANDLERS; i++) {
2091 if (HandlerFD[i] >= 0 && FD_ISSET(HandlerFD[i], fdsetp)) {
2092 ReleaseReadLock(&FSYNC_handler_lock);
2093 (*HandlerProc[i]) (HandlerFD[i]);
2094 ObtainReadLock(&FSYNC_handler_lock);
2097 ReleaseReadLock(&FSYNC_handler_lock);
2102 AddHandler(osi_socket afd, void (*aproc) (osi_socket))
2105 ObtainWriteLock(&FSYNC_handler_lock);
2106 for (i = 0; i < MAXHANDLERS; i++)
2107 if (HandlerFD[i] == OSI_NULLSOCKET)
2109 if (i >= MAXHANDLERS) {
2110 ReleaseWriteLock(&FSYNC_handler_lock);
2114 HandlerProc[i] = aproc;
2115 ReleaseWriteLock(&FSYNC_handler_lock);
2120 FindHandler(osi_socket afd)
2123 ObtainReadLock(&FSYNC_handler_lock);
2124 for (i = 0; i < MAXHANDLERS; i++)
2125 if (HandlerFD[i] == afd) {
2126 ReleaseReadLock(&FSYNC_handler_lock);
2129 ReleaseReadLock(&FSYNC_handler_lock); /* just in case */
2131 return -1; /* satisfy compiler */
2135 FindHandler_r(osi_socket afd)
2138 for (i = 0; i < MAXHANDLERS; i++)
2139 if (HandlerFD[i] == afd) {
2143 return -1; /* satisfy compiler */
2147 RemoveHandler(osi_socket afd)
2149 ObtainWriteLock(&FSYNC_handler_lock);
2150 HandlerFD[FindHandler_r(afd)] = OSI_NULLSOCKET;
2151 ReleaseWriteLock(&FSYNC_handler_lock);
2155 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
2157 GetHandler(struct pollfd *fds, int maxfds, int events, int *nfds)
2161 ObtainReadLock(&FSYNC_handler_lock);
2162 for (i = 0; i < MAXHANDLERS; i++)
2163 if (HandlerFD[i] != OSI_NULLSOCKET) {
2164 opr_Assert(fdi<maxfds);
2165 fds[fdi].fd = HandlerFD[i];
2166 fds[fdi].events = events;
2167 fds[fdi].revents = 0;
2171 ReleaseReadLock(&FSYNC_handler_lock);
2175 GetHandler(fd_set * fdsetp, int *maxfdp)
2180 ObtainReadLock(&FSYNC_handler_lock); /* just in case */
2181 for (i = 0; i < MAXHANDLERS; i++)
2182 if (HandlerFD[i] != OSI_NULLSOCKET) {
2183 FD_SET(HandlerFD[i], fdsetp);
2184 #ifndef AFS_NT40_ENV
2185 /* On Windows the nfds parameter to select() is ignored */
2186 if (maxfd < HandlerFD[i] || maxfd == (int)-1)
2187 maxfd = HandlerFD[i];
2188 #endif /* AFS_NT40_ENV */
2191 ReleaseReadLock(&FSYNC_handler_lock); /* just in case */
2193 #endif /* HAVE_POLL && AFS_PTHREAD_ENV */
2195 #endif /* FSSYNC_BUILD_SERVER */