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-2008 Sine Nomine Associates
15 Institution: The Information Technology Center, Carnegie-Mellon University
20 /* All this is going away in early 1989 */
21 int newVLDB; /* Compatibility flag */
24 static int newVLDB = 1;
27 #ifndef AFS_PTHREAD_ENV
28 #define USUAL_PRIORITY (LWP_MAX_PRIORITY - 2)
31 * stack size increased from 8K because the HP machine seemed to have trouble
32 * with the smaller stack
34 #define USUAL_STACK_SIZE (24 * 1024)
35 #endif /* !AFS_PTHREAD_ENV */
39 File server synchronization with external volume utilities.
40 server-side implementation
43 /* This controls the size of an fd_set; it must be defined early before
44 * the system headers define that type and the macros that operate on it.
45 * Its value should be as large as the maximum file descriptor limit we
46 * are likely to run into on any platform. Right now, that is 65536
47 * which is the default hard fd limit on Solaris 9 */
49 #define FD_SETSIZE 65536
52 #include <afsconfig.h>
53 #include <afs/param.h>
58 #include <sys/types.h>
64 #include <sys/param.h>
65 #include <sys/socket.h>
66 #include <netinet/in.h>
71 #ifdef AFS_PTHREAD_ENV
73 #else /* AFS_PTHREAD_ENV */
74 #include <afs/assert.h>
75 #endif /* AFS_PTHREAD_ENV */
80 #include <afs/afsint.h>
82 #include <afs/errors.h>
83 #include "daemon_com.h"
87 #include <afs/afssyscalls.h>
91 #include "volume_inline.h"
92 #include "partition.h"
96 #endif /* HAVE_POLL */
98 #ifdef USE_UNIX_SOCKETS
100 #include <afs/afsutil.h>
101 #endif /* USE_UNIX_SOCKETS */
103 #ifdef FSSYNC_BUILD_SERVER
105 /*@printflike@*/ extern void Log(const char *format, ...);
110 #define osi_Assert(e) (void)(e)
112 int (*V_BreakVolumeCallbacks) ();
114 #define MAXHANDLERS 4 /* Up to 4 clients; must be at least 2, so that
115 * move = dump+restore can run on single server */
116 #define MAXOFFLINEVOLUMES 128 /* This needs to be as big as the maximum
117 * number that would be offline for 1 operation.
118 * Current winner is salvage, which needs all
119 * cloned read-only copies offline when salvaging
120 * a single read-write volume */
124 static struct offlineInfo OfflineVolumes[MAXHANDLERS][MAXOFFLINEVOLUMES];
127 * fssync server socket handle.
129 static SYNC_server_state_t fssync_server_state =
130 { -1, /* file descriptor */
131 FSSYNC_ENDPOINT_DECL, /* server endpoint */
132 FSYNC_PROTO_VERSION, /* protocol version */
133 5, /* bind() retry limit */
134 100, /* listen() queue depth */
135 "FSSYNC", /* protocol name string */
139 /* Forward declarations */
140 static void * FSYNC_sync(void *);
141 static void FSYNC_newconnection();
142 static void FSYNC_com();
143 static void FSYNC_Drop();
144 static void AcceptOn();
145 static void AcceptOff();
146 static void InitHandler();
147 static int AddHandler();
148 static int FindHandler();
149 static int FindHandler_r();
150 static int RemoveHandler();
151 #if defined(HAVE_POLL) && defined (AFS_PTHREAD_ENV)
152 static void CallHandler(struct pollfd *fds, int nfds, int mask);
153 static void GetHandler(struct pollfd *fds, int maxfds, int events, int *nfds);
155 static void CallHandler(fd_set * fdsetp);
156 static void GetHandler(fd_set * fdsetp, int *maxfdp);
160 static afs_int32 FSYNC_com_VolOp(int fd, SYNC_command * com, SYNC_response * res);
162 static afs_int32 FSYNC_com_VolError(FSSYNC_VolOp_command * com, SYNC_response * res);
163 static afs_int32 FSYNC_com_VolOn(FSSYNC_VolOp_command * com, SYNC_response * res);
164 static afs_int32 FSYNC_com_VolOff(FSSYNC_VolOp_command * com, SYNC_response * res);
165 static afs_int32 FSYNC_com_VolMove(FSSYNC_VolOp_command * com, SYNC_response * res);
166 static afs_int32 FSYNC_com_VolBreakCBKs(FSSYNC_VolOp_command * com, SYNC_response * res);
167 static afs_int32 FSYNC_com_VolDone(FSSYNC_VolOp_command * com, SYNC_response * res);
168 static afs_int32 FSYNC_com_VolQuery(FSSYNC_VolOp_command * com, SYNC_response * res);
169 static afs_int32 FSYNC_com_VolHdrQuery(FSSYNC_VolOp_command * com, SYNC_response * res);
170 #ifdef AFS_DEMAND_ATTACH_FS
171 static afs_int32 FSYNC_com_VolOpQuery(FSSYNC_VolOp_command * com, SYNC_response * res);
172 #endif /* AFS_DEMAND_ATTACH_FS */
174 static afs_int32 FSYNC_com_VnQry(int fd, SYNC_command * com, SYNC_response * res);
176 static afs_int32 FSYNC_com_StatsOp(int fd, SYNC_command * com, SYNC_response * res);
178 static afs_int32 FSYNC_com_StatsOpGeneral(FSSYNC_StatsOp_command * scom, SYNC_response * res);
179 static afs_int32 FSYNC_com_StatsOpViceP(FSSYNC_StatsOp_command * scom, SYNC_response * res);
180 static afs_int32 FSYNC_com_StatsOpHash(FSSYNC_StatsOp_command * scom, SYNC_response * res);
181 static afs_int32 FSYNC_com_StatsOpHdr(FSSYNC_StatsOp_command * scom, SYNC_response * res);
182 static afs_int32 FSYNC_com_StatsOpVLRU(FSSYNC_StatsOp_command * scom, SYNC_response * res);
185 static void FSYNC_com_to_info(FSSYNC_VolOp_command * vcom, FSSYNC_VolOp_info * info);
189 * This lock controls access to the handler array. The overhead
190 * is minimal in non-preemptive environments.
192 struct Lock FSYNC_handler_lock;
197 #ifdef AFS_PTHREAD_ENV
199 pthread_attr_t tattr;
200 #else /* AFS_PTHREAD_ENV */
202 #endif /* AFS_PTHREAD_ENV */
204 Lock_Init(&FSYNC_handler_lock);
206 #ifdef AFS_PTHREAD_ENV
207 assert(pthread_attr_init(&tattr) == 0);
208 assert(pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED) == 0);
209 assert(pthread_create(&tid, &tattr, FSYNC_sync, NULL) == 0);
210 #else /* AFS_PTHREAD_ENV */
211 assert(LWP_CreateProcess
212 (FSYNC_sync, USUAL_STACK_SIZE, USUAL_PRIORITY, (void *)0,
213 "FSYNC_sync", &pid) == LWP_SUCCESS);
214 #endif /* AFS_PTHREAD_ENV */
217 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
218 static struct pollfd FSYNC_readfds[MAXHANDLERS];
220 static fd_set FSYNC_readfds;
225 FSYNC_sync(void * args)
227 #ifdef USE_UNIX_SOCKETS
228 char tbuffer[AFSDIR_PATH_MAX];
229 #endif /* USE_UNIX_SOCKETS */
234 #ifdef AFS_PTHREAD_ENV
237 SYNC_server_state_t * state = &fssync_server_state;
239 SYNC_getAddr(&state->endpoint, &state->addr);
240 SYNC_cleanupSock(state);
243 (void)signal(SIGPIPE, SIG_IGN);
246 #ifdef AFS_PTHREAD_ENV
247 /* set our 'thread-id' so that the host hold table works */
248 MUTEX_ENTER(&rx_stats_mutex); /* protects rxi_pthread_hinum */
249 tid = ++rxi_pthread_hinum;
250 MUTEX_EXIT(&rx_stats_mutex);
251 pthread_setspecific(rx_thread_id_key, (void *)tid);
252 Log("Set thread id %d for FSYNC_sync\n", tid);
253 #endif /* AFS_PTHREAD_ENV */
256 /* Let somebody else run until level > 0. That doesn't mean that
257 * all volumes have been attached. */
258 #ifdef AFS_PTHREAD_ENV
260 #else /* AFS_PTHREAD_ENV */
261 LWP_DispatchProcess();
262 #endif /* AFS_PTHREAD_ENV */
265 state->fd = SYNC_getSock(&state->endpoint);
266 code = SYNC_bindSock(state);
273 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
275 GetHandler(FSYNC_readfds, MAXHANDLERS, POLLIN|POLLPRI, &nfds);
276 if (poll(FSYNC_readfds, nfds, -1) >=1)
277 CallHandler(FSYNC_readfds, nfds, POLLIN|POLLPRI);
280 GetHandler(&FSYNC_readfds, &maxfd);
281 /* Note: check for >= 1 below is essential since IOMGR_select
282 * doesn't have exactly same semantics as select.
284 #ifdef AFS_PTHREAD_ENV
285 if (select(maxfd + 1, &FSYNC_readfds, NULL, NULL, NULL) >= 1)
286 #else /* AFS_PTHREAD_ENV */
287 if (IOMGR_Select(maxfd + 1, &FSYNC_readfds, NULL, NULL, NULL) >= 1)
288 #endif /* AFS_PTHREAD_ENV */
289 CallHandler(&FSYNC_readfds);
295 FSYNC_newconnection(int afd)
297 #ifdef USE_UNIX_SOCKETS
298 struct sockaddr_un other;
299 #else /* USE_UNIX_SOCKETS */
300 struct sockaddr_in other;
303 junk = sizeof(other);
304 fd = accept(afd, (struct sockaddr *)&other, &junk);
306 Log("FSYNC_newconnection: accept failed, errno==%d\n", errno);
308 } else if (!AddHandler(fd, FSYNC_com)) {
310 assert(AddHandler(fd, FSYNC_com));
314 /* this function processes commands from an fssync file descriptor (fd) */
315 afs_int32 FS_cnt = 0;
321 SYNC_PROTO_BUF_DECL(com_buf);
322 SYNC_PROTO_BUF_DECL(res_buf);
324 memset(&res.hdr, 0, sizeof(res.hdr));
326 com.payload.buf = (void *)com_buf;
327 com.payload.len = SYNC_PROTO_MAX_LEN;
328 res.hdr.response_len = sizeof(res.hdr);
329 res.hdr.proto_version = FSYNC_PROTO_VERSION;
330 res.payload.len = SYNC_PROTO_MAX_LEN;
331 res.payload.buf = (void *)res_buf;
334 if (SYNC_getCom(fd, &com)) {
335 Log("FSYNC_com: read failed; dropping connection (cnt=%d)\n", FS_cnt);
340 if (com.recv_len < sizeof(com.hdr)) {
341 Log("FSSYNC_com: invalid protocol message length (%u)\n", com.recv_len);
342 res.hdr.response = SYNC_COM_ERROR;
343 res.hdr.reason = SYNC_REASON_MALFORMED_PACKET;
344 res.hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
348 if (com.hdr.proto_version != FSYNC_PROTO_VERSION) {
349 Log("FSYNC_com: invalid protocol version (%u)\n", com.hdr.proto_version);
350 res.hdr.response = SYNC_COM_ERROR;
351 res.hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
355 if (com.hdr.command == SYNC_COM_CHANNEL_CLOSE) {
356 res.hdr.response = SYNC_OK;
357 res.hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
363 switch (com.hdr.command) {
365 case FSYNC_VOL_ATTACH:
366 case FSYNC_VOL_LEAVE_OFF:
368 case FSYNC_VOL_FORCE_ERROR:
369 case FSYNC_VOL_LISTVOLUMES:
370 case FSYNC_VOL_NEEDVOLUME:
372 case FSYNC_VOL_BREAKCBKS:
374 case FSYNC_VOL_QUERY:
375 case FSYNC_VOL_QUERY_HDR:
376 case FSYNC_VOL_QUERY_VOP:
377 res.hdr.response = FSYNC_com_VolOp(fd, &com, &res);
379 case FSYNC_VOL_STATS_GENERAL:
380 case FSYNC_VOL_STATS_VICEP:
381 case FSYNC_VOL_STATS_HASH:
382 case FSYNC_VOL_STATS_HDR:
383 case FSYNC_VOL_STATS_VLRU:
384 res.hdr.response = FSYNC_com_StatsOp(fd, &com, &res);
386 case FSYNC_VOL_QUERY_VNODE:
387 res.hdr.response = FSYNC_com_VnQry(fd, &com, &res);
390 res.hdr.response = SYNC_BAD_COMMAND;
396 SYNC_putRes(fd, &res);
397 if (res.hdr.flags & SYNC_FLAG_CHANNEL_SHUTDOWN) {
403 FSYNC_com_VolOp(int fd, SYNC_command * com, SYNC_response * res)
406 afs_int32 code = SYNC_OK;
407 FSSYNC_VolOp_command vcom;
409 if (com->recv_len != (sizeof(com->hdr) + sizeof(FSSYNC_VolOp_hdr))) {
410 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
411 res->hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
412 return SYNC_COM_ERROR;
415 vcom.hdr = &com->hdr;
416 vcom.vop = (FSSYNC_VolOp_hdr *) com->payload.buf;
419 vcom.volumes = OfflineVolumes[FindHandler(fd)];
420 for (vcom.v = NULL, i = 0; i < MAXOFFLINEVOLUMES; i++) {
421 if ((vcom.volumes[i].volumeID == vcom.vop->volume) &&
422 (strncmp(vcom.volumes[i].partName, vcom.vop->partName,
423 sizeof(vcom.volumes[i].partName)) == 0)) {
424 vcom.v = &vcom.volumes[i];
429 switch (com->hdr.command) {
431 case FSYNC_VOL_ATTACH:
432 case FSYNC_VOL_LEAVE_OFF:
433 code = FSYNC_com_VolOn(&vcom, res);
436 case FSYNC_VOL_NEEDVOLUME:
437 code = FSYNC_com_VolOff(&vcom, res);
439 case FSYNC_VOL_LISTVOLUMES:
443 code = FSYNC_com_VolMove(&vcom, res);
445 case FSYNC_VOL_BREAKCBKS:
446 code = FSYNC_com_VolBreakCBKs(&vcom, res);
449 code = FSYNC_com_VolDone(&vcom, res);
451 case FSYNC_VOL_QUERY:
452 code = FSYNC_com_VolQuery(&vcom, res);
454 case FSYNC_VOL_QUERY_HDR:
455 code = FSYNC_com_VolHdrQuery(&vcom, res);
457 #ifdef AFS_DEMAND_ATTACH_FS
458 case FSYNC_VOL_FORCE_ERROR:
459 code = FSYNC_com_VolError(&vcom, res);
461 case FSYNC_VOL_QUERY_VOP:
462 code = FSYNC_com_VolOpQuery(&vcom, res);
464 #endif /* AFS_DEMAND_ATTACH_FS */
466 code = SYNC_BAD_COMMAND;
473 FSYNC_com_VolOn(FSSYNC_VolOp_command * vcom, SYNC_response * res)
475 afs_int32 code = SYNC_OK;
476 char tvolName[VMAXPATHLEN];
480 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
481 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
487 This is where a detatched volume gets reattached. However in the
488 special case where the volume is merely busy, it is already
489 attatched and it is only necessary to clear the busy flag. See
490 defect #2080 for details.
493 /* is the volume already attatched? */
496 * XXX With the following enabled we had bizarre problems where the backup id would
497 * be reset to 0; that was due to the interaction between fileserver/volserver in that they
498 * both keep volumes in memory and the changes wouldn't be made to the fileserver. Some of
499 * the problems were due to refcnt changes as result of VGetVolume/VPutVolume which would call
500 * VOffline, etc. when we don't want to; someday the whole #2080 issue should be revisited to
503 vp = VGetVolume_r(&error, vcom->vop->volume);
505 /* yep, is the BUSY flag set? */
506 if (vp->specialStatus == VBUSY) {
508 /* yep, clear BUSY flag */
510 vp->specialStatus = 0;
511 /* make sure vol is online */
513 vcom->v->volumeID = 0;
514 V_inUse(vp) = 1; /* online */
523 /* so, we need to attach the volume */
525 #ifdef AFS_DEMAND_ATTACH_FS
526 /* check DAFS permissions */
527 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
528 if (vp && !strcmp(VPartitionPath(V_partition(vp)), vcom->vop->partName) &&
529 vp->pending_vol_op &&
530 (vcom->hdr->programType != vp->pending_vol_op->com.programType)) {
531 /* a different program has this volume checked out. deny. */
532 Log("FSYNC_VolOn: WARNING: program type %u has attempted to manipulate "
533 "state for volume %u using command code %u while the volume is "
534 "checked out by program type %u for command code %u.\n",
535 vcom->hdr->programType,
538 vp->pending_vol_op->com.programType,
539 vp->pending_vol_op->com.command);
541 res->hdr.reason = FSYNC_EXCLUSIVE;
547 vcom->v->volumeID = 0;
550 if (vcom->hdr->command == FSYNC_VOL_LEAVE_OFF) {
551 /* nothing much to do if we're leaving the volume offline */
552 #ifdef AFS_DEMAND_ATTACH_FS
554 !strcmp(VPartitionPath(V_partition(vp)), vcom->vop->partName)) {
555 VDeregisterVolOp_r(vp);
556 VChangeState_r(vp, VOL_STATE_UNATTACHED);
562 #ifdef AFS_DEMAND_ATTACH_FS
563 /* first, check to see whether we have such a volume defined */
564 vp = VPreAttachVolumeById_r(&error,
568 VDeregisterVolOp_r(vp);
570 #else /* !AFS_DEMAND_ATTACH_FS */
572 snprintf(&tvolName[1], sizeof(tvolName)-1, VFORMAT, vcom->vop->volume);
573 tvolName[sizeof(tvolName)-1] = '\0';
575 vp = VAttachVolumeByName_r(&error, vcom->vop->partName, tvolName,
581 res->hdr.reason = error;
583 #endif /* !AFS_DEMAND_ATTACH_FS */
590 FSYNC_com_VolOff(FSSYNC_VolOp_command * vcom, SYNC_response * res)
592 FSSYNC_VolOp_info info;
593 afs_int32 code = SYNC_OK;
598 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
599 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
604 /* not already offline, we need to find a slot for newly offline volume */
605 if (vcom->hdr->programType == debugUtility) {
606 /* debug utilities do not have their operations tracked */
610 for (i = 0; i < MAXOFFLINEVOLUMES; i++) {
611 if (vcom->volumes[i].volumeID == 0) {
612 vcom->v = &vcom->volumes[i];
622 FSYNC_com_to_info(vcom, &info);
624 #ifdef AFS_DEMAND_ATTACH_FS
625 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
627 vp = VGetVolume_r(&error, vcom->vop->volume);
631 if ((vcom->vop->partName[0] != 0) &&
632 (strncmp(vcom->vop->partName, vp->partition->name,
633 sizeof(vcom->vop->partName)) != 0)) {
634 /* volume on desired partition is not online, so we
635 * should treat this as an offline volume.
637 #ifndef AFS_DEMAND_ATTACH_FS
645 #ifdef AFS_DEMAND_ATTACH_FS
647 ProgramType type = (ProgramType) vcom->hdr->programType;
649 /* do initial filtering of requests */
651 /* enforce mutual exclusion for volume ops */
652 if (vp->pending_vol_op) {
653 if (vp->pending_vol_op->com.programType != type) {
654 Log("volume %u already checked out\n", vp->hashid);
656 Log("vp->vop = { com = { ver=%u, prog=%d, com=%d, reason=%d, len=%u, flags=0x%x }, vop = { vol=%u, part='%s' } }\n",
657 vp->pending_vol_op->com.proto_version,
658 vp->pending_vol_op->com.programType,
659 vp->pending_vol_op->com.command,
660 vp->pending_vol_op->com.reason,
661 vp->pending_vol_op->com.command_len,
662 vp->pending_vol_op->com.flags,
663 vp->pending_vol_op->vop.volume,
664 vp->pending_vol_op->vop.partName );
665 Log("vcom = { com = { ver=%u, prog=%d, com=%d, reason=%d, len=%u, flags=0x%x } , vop = { vol=%u, part='%s' } }\n",
666 vcom->hdr->proto_version,
667 vcom->hdr->programType,
670 vcom->hdr->command_len,
673 vcom->vop->partName);
674 res->hdr.reason = FSYNC_EXCLUSIVE;
677 Log("warning: volume %u recursively checked out by programType id %d\n",
678 vp->hashid, vcom->hdr->programType);
682 /* filter based upon requestor
684 * volume utilities are not allowed to check out volumes
685 * which are in an error state
687 * unknown utility programs will be denied on principal
692 /* give the salvageserver lots of liberty */
695 if ((V_attachState(vp) == VOL_STATE_ERROR) ||
696 (V_attachState(vp) == VOL_STATE_SALVAGING)) {
701 Log("bad program type passed to FSSYNC\n");
705 /* short circuit for offline volume states
706 * so we can avoid I/O penalty of attachment */
707 switch (V_attachState(vp)) {
708 case VOL_STATE_UNATTACHED:
709 case VOL_STATE_PREATTACHED:
710 case VOL_STATE_SALVAGING:
711 case VOL_STATE_ERROR:
712 /* register the volume operation metadata with the volume
714 * if the volume is currently pre-attached, attach2()
715 * will evaluate the vol op metadata to determine whether
716 * attaching the volume would be safe */
717 VRegisterVolOp_r(vp, &info);
723 /* convert to heavyweight ref */
724 nvp = VGetVolumeByVp_r(&error, vp);
726 /* register the volume operation metadata with the volume */
727 VRegisterVolOp_r(vp, &info);
730 Log("FSYNC_com_VolOff: failed to get heavyweight reference to volume %u\n",
732 res->hdr.reason = FSYNC_VOL_PKG_ERROR;
737 #endif /* AFS_DEMAND_ATTACH_FS */
740 if (VVolOpLeaveOnline_r(vp, &info)) {
741 VUpdateVolume_r(&error, vp, VOL_UPDATE_WAIT); /* At least get volume stats right */
743 Log("FSYNC: Volume %u (%s) was left on line for an external %s request\n",
744 V_id(vp), V_name(vp),
745 vcom->hdr->reason == V_CLONE ? "clone" :
746 vcom->hdr->reason == V_READONLY ? "readonly" :
747 vcom->hdr->reason == V_DUMP ? "dump" :
752 if (VVolOpSetVBusy_r(vp, &info)) {
753 vp->specialStatus = VBUSY;
756 /* remember what volume we got, so we can keep track of how
757 * many volumes the volserver or whatever is using. Note that
758 * vp is valid since leaveonline is only set when vp is valid.
761 vcom->v->volumeID = vcom->vop->volume;
762 strlcpy(vcom->v->partName, vp->partition->name, sizeof(vcom->v->partName));
765 VOffline_r(vp, "A volume utility is running.");
778 FSYNC_com_VolMove(FSSYNC_VolOp_command * vcom, SYNC_response * res)
783 /* Yuch: the "reason" for the move is the site it got moved to... */
784 /* still set specialStatus so we stop sending back VBUSY.
785 * also should still break callbacks. Note that I don't know
786 * how to tell if we should break all or not, so we just do it
787 * since it doesn't matter much if we do an extra break
788 * volume callbacks on a volume move within the same server */
789 #ifdef AFS_DEMAND_ATTACH_FS
790 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
792 vp = VGetVolume_r(&error, vcom->vop->volume);
795 vp->specialStatus = VMOVED;
796 #ifndef AFS_DEMAND_ATTACH_FS
801 if (V_BreakVolumeCallbacks) {
802 Log("fssync: volume %u moved to %x; breaking all call backs\n",
803 vcom->vop->volume, vcom->hdr->reason);
805 (*V_BreakVolumeCallbacks) (vcom->vop->volume);
813 FSYNC_com_VolDone(FSSYNC_VolOp_command * vcom, SYNC_response * res)
815 #ifdef AFS_DEMAND_ATTACH_FS
820 /* don't try to put online, this call is made only after deleting
821 * a volume, in which case we want to remove the vol # from the
822 * OfflineVolumes array only */
824 vcom->v->volumeID = 0;
826 #ifdef AFS_DEMAND_ATTACH_FS
827 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
829 VChangeState_r(vp, VOL_STATE_UNATTACHED);
830 VDeregisterVolOp_r(vp);
837 #ifdef AFS_DEMAND_ATTACH_FS
839 * force a volume into the hard error state.
842 FSYNC_com_VolError(FSSYNC_VolOp_command * vcom, SYNC_response * res)
846 afs_int32 code = SYNC_DENIED;
848 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
849 if (vp && !strcmp(VPartitionPath(V_partition(vp)), vcom->vop->partName)) {
850 memset(&vp->salvage, 0, sizeof(vp->salvage));
851 VChangeState_r(vp, VOL_STATE_ERROR);
854 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
862 FSYNC_com_VolBreakCBKs(FSSYNC_VolOp_command * vcom, SYNC_response * res)
864 /* if the volume is being restored, break all callbacks on it */
865 if (V_BreakVolumeCallbacks) {
866 Log("fssync: breaking all call backs for volume %u\n",
869 (*V_BreakVolumeCallbacks) (vcom->vop->volume);
876 FSYNC_com_VolQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
878 afs_int32 code = SYNC_OK;
882 #ifdef AFS_DEMAND_ATTACH_FS
883 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
884 #else /* !AFS_DEMAND_ATTACH_FS */
885 vp = VGetVolume_r(&error, vcom->vop->volume);
886 #endif /* !AFS_DEMAND_ATTACH_FS */
889 assert(sizeof(Volume) <= res->payload.len);
890 memcpy(res->payload.buf, vp, sizeof(Volume));
891 res->hdr.response_len += sizeof(Volume);
892 #ifndef AFS_DEMAND_ATTACH_FS
896 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
903 FSYNC_com_VolHdrQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
905 afs_int32 code = SYNC_OK;
910 #ifdef AFS_DEMAND_ATTACH_FS
911 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
913 (vp->header != NULL) &&
914 (V_attachFlags(vp) & VOL_HDR_ATTACHED) &&
915 (V_attachFlags(vp) & VOL_HDR_LOADED)) {
918 #else /* !AFS_DEMAND_ATTACH_FS */
919 vp = VGetVolume_r(&error, vcom->vop->volume);
920 if (vp && vp->header) {
923 #endif /* !AFS_DEMAND_ATTACH_FS */
927 assert(sizeof(VolumeDiskData) <= res->payload.len);
928 memcpy(res->payload.buf, &V_disk(vp), sizeof(VolumeDiskData));
929 res->hdr.response_len += sizeof(VolumeDiskData);
930 #ifndef AFS_DEMAND_ATTACH_FS
935 res->hdr.reason = FSYNC_HDR_NOT_ATTACHED;
937 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
944 #ifdef AFS_DEMAND_ATTACH_FS
946 FSYNC_com_VolOpQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
948 afs_int32 code = SYNC_OK;
952 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
954 if (vp && vp->pending_vol_op) {
955 assert(sizeof(FSSYNC_VolOp_info) <= res->payload.len);
956 memcpy(res->payload.buf, vp->pending_vol_op, sizeof(FSSYNC_VolOp_info));
957 res->hdr.response_len += sizeof(FSSYNC_VolOp_info);
960 res->hdr.reason = FSYNC_NO_PENDING_VOL_OP;
962 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
968 #endif /* AFS_DEMAND_ATTACH_FS */
971 FSYNC_com_VnQry(int fd, SYNC_command * com, SYNC_response * res)
973 afs_int32 code = SYNC_OK;
974 FSSYNC_VnQry_hdr * qry = com->payload.buf;
979 if (com->recv_len != (sizeof(com->hdr) + sizeof(FSSYNC_VnQry_hdr))) {
980 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
981 res->hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
982 return SYNC_COM_ERROR;
985 #ifdef AFS_DEMAND_ATTACH_FS
986 vp = VLookupVolume_r(&error, qry->volume, NULL);
987 #else /* !AFS_DEMAND_ATTACH_FS */
988 vp = VGetVolume_r(&error, qry->volume);
989 #endif /* !AFS_DEMAND_ATTACH_FS */
992 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
997 vnp = VLookupVnode(vp, qry->vnode);
999 res->hdr.reason = FSYNC_UNKNOWN_VNID;
1004 if (Vn_class(vnp)->residentSize > res->payload.len) {
1005 res->hdr.reason = SYNC_REASON_ENCODING_ERROR;
1010 memcpy(res->payload.buf, vnp, Vn_class(vnp)->residentSize);
1011 res->hdr.response_len += Vn_class(vnp)->residentSize;
1014 #ifndef AFS_DEMAND_ATTACH_FS
1023 FSYNC_com_StatsOp(int fd, SYNC_command * com, SYNC_response * res)
1025 afs_int32 code = SYNC_OK;
1026 FSSYNC_StatsOp_command scom;
1028 if (com->recv_len != (sizeof(com->hdr) + sizeof(FSSYNC_StatsOp_hdr))) {
1029 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1030 res->hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
1031 return SYNC_COM_ERROR;
1034 scom.hdr = &com->hdr;
1035 scom.sop = (FSSYNC_StatsOp_hdr *) com->payload.buf;
1038 switch (com->hdr.command) {
1039 case FSYNC_VOL_STATS_GENERAL:
1040 code = FSYNC_com_StatsOpGeneral(&scom, res);
1042 #ifdef AFS_DEMAND_ATTACH_FS
1043 /* statistics for the following subsystems are only tracked
1044 * for demand attach fileservers */
1045 case FSYNC_VOL_STATS_VICEP:
1046 code = FSYNC_com_StatsOpViceP(&scom, res);
1048 case FSYNC_VOL_STATS_HASH:
1049 code = FSYNC_com_StatsOpHash(&scom, res);
1051 case FSYNC_VOL_STATS_HDR:
1052 code = FSYNC_com_StatsOpHdr(&scom, res);
1054 case FSYNC_VOL_STATS_VLRU:
1055 code = FSYNC_com_StatsOpVLRU(&scom, res);
1057 #endif /* AFS_DEMAND_ATTACH_FS */
1059 code = SYNC_BAD_COMMAND;
1066 FSYNC_com_StatsOpGeneral(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1068 afs_int32 code = SYNC_OK;
1070 memcpy(res->payload.buf, &VStats, sizeof(VStats));
1071 res->hdr.response_len += sizeof(VStats);
1076 #ifdef AFS_DEMAND_ATTACH_FS
1078 FSYNC_com_StatsOpViceP(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1080 afs_int32 code = SYNC_OK;
1081 struct DiskPartition * dp;
1082 struct DiskPartitionStats * stats;
1084 if (SYNC_verifyProtocolString(scom->sop->args.partName, sizeof(scom->sop->args.partName))) {
1085 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1090 dp = VGetPartition_r(scom->sop->args.partName, 0);
1094 stats = (struct DiskPartitionStats *) res->payload.buf;
1095 stats->free = dp->free;
1096 stats->totalUsable = dp->totalUsable;
1097 stats->minFree = dp->minFree;
1098 stats->f_files = dp->f_files;
1099 stats->vol_list_len = dp->vol_list.len;
1101 res->hdr.response_len += sizeof(struct DiskPartitionStats);
1109 FSYNC_com_StatsOpHash(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1111 afs_int32 code = SYNC_OK;
1112 struct VolumeHashChainStats * stats;
1113 struct VolumeHashChainHead * head;
1115 if (scom->sop->args.hash_bucket >= VolumeHashTable.Size) {
1119 head = &VolumeHashTable.Table[scom->sop->args.hash_bucket];
1120 stats = (struct VolumeHashChainStats *) res->payload.buf;
1121 stats->table_size = VolumeHashTable.Size;
1122 stats->chain_len = head->len;
1123 stats->chain_cacheCheck = head->cacheCheck;
1124 stats->chain_busy = head->busy;
1125 AssignInt64(head->looks, &stats->chain_looks);
1126 AssignInt64(head->gets, &stats->chain_gets);
1127 AssignInt64(head->reorders, &stats->chain_reorders);
1129 res->hdr.response_len += sizeof(struct VolumeHashChainStats);
1135 FSYNC_com_StatsOpHdr(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1137 afs_int32 code = SYNC_OK;
1139 memcpy(res->payload.buf, &volume_hdr_LRU.stats, sizeof(volume_hdr_LRU.stats));
1140 res->hdr.response_len += sizeof(volume_hdr_LRU.stats);
1146 FSYNC_com_StatsOpVLRU(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1148 afs_int32 code = SYNC_OK;
1150 code = SYNC_BAD_COMMAND;
1154 #endif /* AFS_DEMAND_ATTACH_FS */
1157 FSYNC_com_to_info(FSSYNC_VolOp_command * vcom, FSSYNC_VolOp_info * info)
1159 memcpy(&info->com, vcom->hdr, sizeof(SYNC_command_hdr));
1160 memcpy(&info->vop, vcom->vop, sizeof(FSSYNC_VolOp_hdr));
1166 struct offlineInfo *p;
1169 char tvolName[VMAXPATHLEN];
1172 p = OfflineVolumes[FindHandler(fd)];
1173 for (i = 0; i < MAXOFFLINEVOLUMES; i++) {
1174 if (p[i].volumeID) {
1179 sprintf(&tvolName[1], VFORMAT, p[i].volumeID);
1180 vp = VAttachVolumeByName_r(&error, p[i].partName, tvolName,
1197 static int AcceptHandler = -1; /* handler id for accept, if turned on */
1202 if (AcceptHandler == -1) {
1203 assert(AddHandler(fssync_server_state.fd, FSYNC_newconnection));
1204 AcceptHandler = FindHandler(fssync_server_state.fd);
1211 if (AcceptHandler != -1) {
1212 assert(RemoveHandler(fssync_server_state.fd));
1217 /* The multiple FD handling code. */
1219 static int HandlerFD[MAXHANDLERS];
1220 static int (*HandlerProc[MAXHANDLERS]) ();
1226 ObtainWriteLock(&FSYNC_handler_lock);
1227 for (i = 0; i < MAXHANDLERS; i++) {
1231 ReleaseWriteLock(&FSYNC_handler_lock);
1234 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
1236 CallHandler(struct pollfd *fds, int nfds, int mask)
1240 ObtainReadLock(&FSYNC_handler_lock);
1241 for (i = 0; i < nfds; i++) {
1242 if (fds[i].revents & mask) {
1243 handler = FindHandler_r(fds[i].fd);
1244 ReleaseReadLock(&FSYNC_handler_lock);
1245 (*HandlerProc[handler]) (fds[i].fd);
1246 ObtainReadLock(&FSYNC_handler_lock);
1249 ReleaseReadLock(&FSYNC_handler_lock);
1253 CallHandler(fd_set * fdsetp)
1256 ObtainReadLock(&FSYNC_handler_lock);
1257 for (i = 0; i < MAXHANDLERS; i++) {
1258 if (HandlerFD[i] >= 0 && FD_ISSET(HandlerFD[i], fdsetp)) {
1259 ReleaseReadLock(&FSYNC_handler_lock);
1260 (*HandlerProc[i]) (HandlerFD[i]);
1261 ObtainReadLock(&FSYNC_handler_lock);
1264 ReleaseReadLock(&FSYNC_handler_lock);
1269 AddHandler(int afd, int (*aproc) ())
1272 ObtainWriteLock(&FSYNC_handler_lock);
1273 for (i = 0; i < MAXHANDLERS; i++)
1274 if (HandlerFD[i] == -1)
1276 if (i >= MAXHANDLERS) {
1277 ReleaseWriteLock(&FSYNC_handler_lock);
1281 HandlerProc[i] = aproc;
1282 ReleaseWriteLock(&FSYNC_handler_lock);
1287 FindHandler(register int afd)
1290 ObtainReadLock(&FSYNC_handler_lock);
1291 for (i = 0; i < MAXHANDLERS; i++)
1292 if (HandlerFD[i] == afd) {
1293 ReleaseReadLock(&FSYNC_handler_lock);
1296 ReleaseReadLock(&FSYNC_handler_lock); /* just in case */
1298 return -1; /* satisfy compiler */
1302 FindHandler_r(register int afd)
1305 for (i = 0; i < MAXHANDLERS; i++)
1306 if (HandlerFD[i] == afd) {
1310 return -1; /* satisfy compiler */
1314 RemoveHandler(register int afd)
1316 ObtainWriteLock(&FSYNC_handler_lock);
1317 HandlerFD[FindHandler_r(afd)] = -1;
1318 ReleaseWriteLock(&FSYNC_handler_lock);
1322 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
1324 GetHandler(struct pollfd *fds, int maxfds, int events, int *nfds)
1328 ObtainReadLock(&FSYNC_handler_lock);
1329 for (i = 0; i < MAXHANDLERS; i++)
1330 if (HandlerFD[i] != -1) {
1332 fds[fdi].fd = HandlerFD[i];
1333 fds[fdi].events = events;
1334 fds[fdi].revents = 0;
1338 ReleaseReadLock(&FSYNC_handler_lock);
1342 GetHandler(fd_set * fdsetp, int *maxfdp)
1345 register int maxfd = -1;
1347 ObtainReadLock(&FSYNC_handler_lock); /* just in case */
1348 for (i = 0; i < MAXHANDLERS; i++)
1349 if (HandlerFD[i] != -1) {
1350 FD_SET(HandlerFD[i], fdsetp);
1351 if (maxfd < HandlerFD[i])
1352 maxfd = HandlerFD[i];
1355 ReleaseReadLock(&FSYNC_handler_lock); /* just in case */
1357 #endif /* HAVE_POLL && AFS_PTHREAD_ENV */
1359 #endif /* FSSYNC_BUILD_SERVER */