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 VDeregisterVolOp_r(vp);
836 #ifdef AFS_DEMAND_ATTACH_FS
838 * force a volume into the hard error state.
841 FSYNC_com_VolError(FSSYNC_VolOp_command * vcom, SYNC_response * res)
845 afs_int32 code = SYNC_DENIED;
847 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
848 if (vp && !strcmp(VPartitionPath(V_partition(vp)), vcom->vop->partName)) {
849 memset(&vp->salvage, 0, sizeof(vp->salvage));
850 VChangeState_r(vp, VOL_STATE_ERROR);
853 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
861 FSYNC_com_VolBreakCBKs(FSSYNC_VolOp_command * vcom, SYNC_response * res)
863 /* if the volume is being restored, break all callbacks on it */
864 if (V_BreakVolumeCallbacks) {
865 Log("fssync: breaking all call backs for volume %u\n",
868 (*V_BreakVolumeCallbacks) (vcom->vop->volume);
875 FSYNC_com_VolQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
877 afs_int32 code = SYNC_OK;
881 #ifdef AFS_DEMAND_ATTACH_FS
882 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
883 #else /* !AFS_DEMAND_ATTACH_FS */
884 vp = VGetVolume_r(&error, vcom->vop->volume);
885 #endif /* !AFS_DEMAND_ATTACH_FS */
888 assert(sizeof(Volume) <= res->payload.len);
889 memcpy(res->payload.buf, vp, sizeof(Volume));
890 res->hdr.response_len += sizeof(Volume);
891 #ifndef AFS_DEMAND_ATTACH_FS
895 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
902 FSYNC_com_VolHdrQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
904 afs_int32 code = SYNC_OK;
909 #ifdef AFS_DEMAND_ATTACH_FS
910 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
912 (vp->header != NULL) &&
913 (V_attachFlags(vp) & VOL_HDR_ATTACHED) &&
914 (V_attachFlags(vp) & VOL_HDR_LOADED)) {
917 #else /* !AFS_DEMAND_ATTACH_FS */
918 vp = VGetVolume_r(&error, vcom->vop->volume);
919 if (vp && vp->header) {
922 #endif /* !AFS_DEMAND_ATTACH_FS */
926 assert(sizeof(VolumeDiskData) <= res->payload.len);
927 memcpy(res->payload.buf, &V_disk(vp), sizeof(VolumeDiskData));
928 res->hdr.response_len += sizeof(VolumeDiskData);
929 #ifndef AFS_DEMAND_ATTACH_FS
934 res->hdr.reason = FSYNC_HDR_NOT_ATTACHED;
936 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
943 #ifdef AFS_DEMAND_ATTACH_FS
945 FSYNC_com_VolOpQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
947 afs_int32 code = SYNC_OK;
951 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
953 if (vp && vp->pending_vol_op) {
954 assert(sizeof(FSSYNC_VolOp_info) <= res->payload.len);
955 memcpy(res->payload.buf, vp->pending_vol_op, sizeof(FSSYNC_VolOp_info));
956 res->hdr.response_len += sizeof(FSSYNC_VolOp_info);
959 res->hdr.reason = FSYNC_NO_PENDING_VOL_OP;
961 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
967 #endif /* AFS_DEMAND_ATTACH_FS */
970 FSYNC_com_VnQry(int fd, SYNC_command * com, SYNC_response * res)
972 afs_int32 code = SYNC_OK;
973 FSSYNC_VnQry_hdr * qry = com->payload.buf;
978 if (com->recv_len != (sizeof(com->hdr) + sizeof(FSSYNC_VnQry_hdr))) {
979 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
980 res->hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
981 return SYNC_COM_ERROR;
984 #ifdef AFS_DEMAND_ATTACH_FS
985 vp = VLookupVolume_r(&error, qry->volume, NULL);
986 #else /* !AFS_DEMAND_ATTACH_FS */
987 vp = VGetVolume_r(&error, qry->volume);
988 #endif /* !AFS_DEMAND_ATTACH_FS */
991 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
996 vnp = VLookupVnode(vp, qry->vnode);
998 res->hdr.reason = FSYNC_UNKNOWN_VNID;
1003 if (Vn_class(vnp)->residentSize > res->payload.len) {
1004 res->hdr.reason = SYNC_REASON_ENCODING_ERROR;
1009 memcpy(res->payload.buf, vnp, Vn_class(vnp)->residentSize);
1010 res->hdr.response_len += Vn_class(vnp)->residentSize;
1013 #ifndef AFS_DEMAND_ATTACH_FS
1022 FSYNC_com_StatsOp(int fd, SYNC_command * com, SYNC_response * res)
1024 afs_int32 code = SYNC_OK;
1025 FSSYNC_StatsOp_command scom;
1027 if (com->recv_len != (sizeof(com->hdr) + sizeof(FSSYNC_StatsOp_hdr))) {
1028 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1029 res->hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
1030 return SYNC_COM_ERROR;
1033 scom.hdr = &com->hdr;
1034 scom.sop = (FSSYNC_StatsOp_hdr *) com->payload.buf;
1037 switch (com->hdr.command) {
1038 case FSYNC_VOL_STATS_GENERAL:
1039 code = FSYNC_com_StatsOpGeneral(&scom, res);
1041 #ifdef AFS_DEMAND_ATTACH_FS
1042 /* statistics for the following subsystems are only tracked
1043 * for demand attach fileservers */
1044 case FSYNC_VOL_STATS_VICEP:
1045 code = FSYNC_com_StatsOpViceP(&scom, res);
1047 case FSYNC_VOL_STATS_HASH:
1048 code = FSYNC_com_StatsOpHash(&scom, res);
1050 case FSYNC_VOL_STATS_HDR:
1051 code = FSYNC_com_StatsOpHdr(&scom, res);
1053 case FSYNC_VOL_STATS_VLRU:
1054 code = FSYNC_com_StatsOpVLRU(&scom, res);
1056 #endif /* AFS_DEMAND_ATTACH_FS */
1058 code = SYNC_BAD_COMMAND;
1065 FSYNC_com_StatsOpGeneral(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1067 afs_int32 code = SYNC_OK;
1069 memcpy(res->payload.buf, &VStats, sizeof(VStats));
1070 res->hdr.response_len += sizeof(VStats);
1075 #ifdef AFS_DEMAND_ATTACH_FS
1077 FSYNC_com_StatsOpViceP(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1079 afs_int32 code = SYNC_OK;
1080 struct DiskPartition * dp;
1081 struct DiskPartitionStats * stats;
1083 if (SYNC_verifyProtocolString(scom->sop->args.partName, sizeof(scom->sop->args.partName))) {
1084 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1089 dp = VGetPartition_r(scom->sop->args.partName, 0);
1093 stats = (struct DiskPartitionStats *) res->payload.buf;
1094 stats->free = dp->free;
1095 stats->totalUsable = dp->totalUsable;
1096 stats->minFree = dp->minFree;
1097 stats->f_files = dp->f_files;
1098 stats->vol_list_len = dp->vol_list.len;
1100 res->hdr.response_len += sizeof(struct DiskPartitionStats);
1108 FSYNC_com_StatsOpHash(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1110 afs_int32 code = SYNC_OK;
1111 struct VolumeHashChainStats * stats;
1112 struct VolumeHashChainHead * head;
1114 if (scom->sop->args.hash_bucket >= VolumeHashTable.Size) {
1118 head = &VolumeHashTable.Table[scom->sop->args.hash_bucket];
1119 stats = (struct VolumeHashChainStats *) res->payload.buf;
1120 stats->table_size = VolumeHashTable.Size;
1121 stats->chain_len = head->len;
1122 stats->chain_cacheCheck = head->cacheCheck;
1123 stats->chain_busy = head->busy;
1124 AssignInt64(head->looks, &stats->chain_looks);
1125 AssignInt64(head->gets, &stats->chain_gets);
1126 AssignInt64(head->reorders, &stats->chain_reorders);
1128 res->hdr.response_len += sizeof(struct VolumeHashChainStats);
1134 FSYNC_com_StatsOpHdr(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1136 afs_int32 code = SYNC_OK;
1138 memcpy(res->payload.buf, &volume_hdr_LRU.stats, sizeof(volume_hdr_LRU.stats));
1139 res->hdr.response_len += sizeof(volume_hdr_LRU.stats);
1145 FSYNC_com_StatsOpVLRU(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1147 afs_int32 code = SYNC_OK;
1149 code = SYNC_BAD_COMMAND;
1153 #endif /* AFS_DEMAND_ATTACH_FS */
1156 FSYNC_com_to_info(FSSYNC_VolOp_command * vcom, FSSYNC_VolOp_info * info)
1158 memcpy(&info->com, vcom->hdr, sizeof(SYNC_command_hdr));
1159 memcpy(&info->vop, vcom->vop, sizeof(FSSYNC_VolOp_hdr));
1165 struct offlineInfo *p;
1168 char tvolName[VMAXPATHLEN];
1171 p = OfflineVolumes[FindHandler(fd)];
1172 for (i = 0; i < MAXOFFLINEVOLUMES; i++) {
1173 if (p[i].volumeID) {
1178 sprintf(&tvolName[1], VFORMAT, p[i].volumeID);
1179 vp = VAttachVolumeByName_r(&error, p[i].partName, tvolName,
1196 static int AcceptHandler = -1; /* handler id for accept, if turned on */
1201 if (AcceptHandler == -1) {
1202 assert(AddHandler(fssync_server_state.fd, FSYNC_newconnection));
1203 AcceptHandler = FindHandler(fssync_server_state.fd);
1210 if (AcceptHandler != -1) {
1211 assert(RemoveHandler(fssync_server_state.fd));
1216 /* The multiple FD handling code. */
1218 static int HandlerFD[MAXHANDLERS];
1219 static int (*HandlerProc[MAXHANDLERS]) ();
1225 ObtainWriteLock(&FSYNC_handler_lock);
1226 for (i = 0; i < MAXHANDLERS; i++) {
1230 ReleaseWriteLock(&FSYNC_handler_lock);
1233 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
1235 CallHandler(struct pollfd *fds, int nfds, int mask)
1239 ObtainReadLock(&FSYNC_handler_lock);
1240 for (i = 0; i < nfds; i++) {
1241 if (fds[i].revents & mask) {
1242 handler = FindHandler_r(fds[i].fd);
1243 ReleaseReadLock(&FSYNC_handler_lock);
1244 (*HandlerProc[handler]) (fds[i].fd);
1245 ObtainReadLock(&FSYNC_handler_lock);
1248 ReleaseReadLock(&FSYNC_handler_lock);
1252 CallHandler(fd_set * fdsetp)
1255 ObtainReadLock(&FSYNC_handler_lock);
1256 for (i = 0; i < MAXHANDLERS; i++) {
1257 if (HandlerFD[i] >= 0 && FD_ISSET(HandlerFD[i], fdsetp)) {
1258 ReleaseReadLock(&FSYNC_handler_lock);
1259 (*HandlerProc[i]) (HandlerFD[i]);
1260 ObtainReadLock(&FSYNC_handler_lock);
1263 ReleaseReadLock(&FSYNC_handler_lock);
1268 AddHandler(int afd, int (*aproc) ())
1271 ObtainWriteLock(&FSYNC_handler_lock);
1272 for (i = 0; i < MAXHANDLERS; i++)
1273 if (HandlerFD[i] == -1)
1275 if (i >= MAXHANDLERS) {
1276 ReleaseWriteLock(&FSYNC_handler_lock);
1280 HandlerProc[i] = aproc;
1281 ReleaseWriteLock(&FSYNC_handler_lock);
1286 FindHandler(register int afd)
1289 ObtainReadLock(&FSYNC_handler_lock);
1290 for (i = 0; i < MAXHANDLERS; i++)
1291 if (HandlerFD[i] == afd) {
1292 ReleaseReadLock(&FSYNC_handler_lock);
1295 ReleaseReadLock(&FSYNC_handler_lock); /* just in case */
1297 return -1; /* satisfy compiler */
1301 FindHandler_r(register int afd)
1304 for (i = 0; i < MAXHANDLERS; i++)
1305 if (HandlerFD[i] == afd) {
1309 return -1; /* satisfy compiler */
1313 RemoveHandler(register int afd)
1315 ObtainWriteLock(&FSYNC_handler_lock);
1316 HandlerFD[FindHandler_r(afd)] = -1;
1317 ReleaseWriteLock(&FSYNC_handler_lock);
1321 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
1323 GetHandler(struct pollfd *fds, int maxfds, int events, int *nfds)
1327 ObtainReadLock(&FSYNC_handler_lock);
1328 for (i = 0; i < MAXHANDLERS; i++)
1329 if (HandlerFD[i] != -1) {
1331 fds[fdi].fd = HandlerFD[i];
1332 fds[fdi].events = events;
1333 fds[fdi].revents = 0;
1337 ReleaseReadLock(&FSYNC_handler_lock);
1341 GetHandler(fd_set * fdsetp, int *maxfdp)
1344 register int maxfd = -1;
1346 ObtainReadLock(&FSYNC_handler_lock); /* just in case */
1347 for (i = 0; i < MAXHANDLERS; i++)
1348 if (HandlerFD[i] != -1) {
1349 FD_SET(HandlerFD[i], fdsetp);
1350 if (maxfd < HandlerFD[i])
1351 maxfd = HandlerFD[i];
1354 ReleaseReadLock(&FSYNC_handler_lock); /* just in case */
1356 #endif /* HAVE_POLL && AFS_PTHREAD_ENV */
1358 #endif /* FSSYNC_BUILD_SERVER */