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 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 */
88 #include <afs/afsint.h>
90 #include <afs/errors.h>
91 #include "daemon_com.h"
95 #include <afs/afssyscalls.h>
99 #include "partition.h"
102 #ifdef FSSYNC_BUILD_SERVER
104 /*@printflike@*/ extern void Log(const char *format, ...);
109 #define osi_Assert(e) (void)(e)
111 int (*V_BreakVolumeCallbacks) ();
113 #define MAXHANDLERS 4 /* Up to 4 clients; must be at least 2, so that
114 * move = dump+restore can run on single server */
115 #define MAXOFFLINEVOLUMES 128 /* This needs to be as big as the maximum
116 * number that would be offline for 1 operation.
117 * Current winner is salvage, which needs all
118 * cloned read-only copies offline when salvaging
119 * a single read-write volume */
121 #define MAX_BIND_TRIES 5 /* Number of times to retry socket bind */
125 static struct offlineInfo OfflineVolumes[MAXHANDLERS][MAXOFFLINEVOLUMES];
127 static int AcceptSd = -1; /* Socket used by server for accepting connections */
129 static int getport();
131 /* Forward declarations */
132 static void FSYNC_sync();
133 static void FSYNC_newconnection();
134 static void FSYNC_com();
135 static void FSYNC_Drop();
136 static void AcceptOn();
137 static void AcceptOff();
138 static void InitHandler();
139 static void CallHandler(fd_set * fdsetp);
140 static int AddHandler();
141 static int FindHandler();
142 static int FindHandler_r();
143 static int RemoveHandler();
144 static void GetHandler(fd_set * fdsetp, int *maxfdp);
148 static afs_int32 FSYNC_com_VolOp(int fd, SYNC_command * com, SYNC_response * res);
150 static afs_int32 FSYNC_com_VolOn(FSSYNC_VolOp_command * com, SYNC_response * res);
151 static afs_int32 FSYNC_com_VolOff(FSSYNC_VolOp_command * com, SYNC_response * res);
152 static afs_int32 FSYNC_com_VolMove(FSSYNC_VolOp_command * com, SYNC_response * res);
153 static afs_int32 FSYNC_com_VolBreakCBKs(FSSYNC_VolOp_command * com, SYNC_response * res);
154 static afs_int32 FSYNC_com_VolDone(FSSYNC_VolOp_command * com, SYNC_response * res);
155 static afs_int32 FSYNC_com_VolQuery(FSSYNC_VolOp_command * com, SYNC_response * res);
156 static afs_int32 FSYNC_com_VolHdrQuery(FSSYNC_VolOp_command * com, SYNC_response * res);
157 #ifdef AFS_DEMAND_ATTACH_FS
158 static afs_int32 FSYNC_com_VolOpQuery(FSSYNC_VolOp_command * com, SYNC_response * res);
159 #endif /* AFS_DEMAND_ATTACH_FS */
161 static afs_int32 FSYNC_com_StatsOp(int fd, SYNC_command * com, SYNC_response * res);
163 static afs_int32 FSYNC_com_StatsOpGeneral(FSSYNC_StatsOp_command * scom, SYNC_response * res);
164 static afs_int32 FSYNC_com_StatsOpViceP(FSSYNC_StatsOp_command * scom, SYNC_response * res);
165 static afs_int32 FSYNC_com_StatsOpHash(FSSYNC_StatsOp_command * scom, SYNC_response * res);
166 static afs_int32 FSYNC_com_StatsOpHdr(FSSYNC_StatsOp_command * scom, SYNC_response * res);
167 static afs_int32 FSYNC_com_StatsOpVLRU(FSSYNC_StatsOp_command * scom, SYNC_response * res);
170 static void FSYNC_com_to_info(FSSYNC_VolOp_command * vcom, FSSYNC_VolOp_info * info);
174 * This lock controls access to the handler array. The overhead
175 * is minimal in non-preemptive environments.
177 struct Lock FSYNC_handler_lock;
182 #ifdef AFS_PTHREAD_ENV
184 pthread_attr_t tattr;
185 #else /* AFS_PTHREAD_ENV */
187 #endif /* AFS_PTHREAD_ENV */
189 Lock_Init(&FSYNC_handler_lock);
191 #ifdef AFS_PTHREAD_ENV
192 assert(pthread_attr_init(&tattr) == 0);
193 assert(pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED) == 0);
194 assert(pthread_create(&tid, &tattr, FSYNC_sync, NULL) == 0);
195 #else /* AFS_PTHREAD_ENV */
196 assert(LWP_CreateProcess
197 (FSYNC_sync, USUAL_STACK_SIZE, USUAL_PRIORITY, (void *)0,
198 "FSYNC_sync", &pid) == LWP_SUCCESS);
199 #endif /* AFS_PTHREAD_ENV */
202 static fd_set FSYNC_readfds;
205 getport(struct sockaddr_in *addr)
209 memset(addr, 0, sizeof(*addr));
210 assert((sd = socket(AF_INET, SOCK_STREAM, 0)) >= 0);
211 #ifdef STRUCT_SOCKADDR_HAS_SA_LEN
212 addr->sin_len = sizeof(struct sockaddr_in);
214 addr->sin_addr.s_addr = htonl(0x7f000001);
215 addr->sin_family = AF_INET; /* was localhost->h_addrtype */
216 addr->sin_port = htons(2040); /* XXXX htons not _really_ neccessary */
225 struct sockaddr_in addr;
230 #ifdef AFS_PTHREAD_ENV
235 (void)signal(SIGPIPE, SIG_IGN);
238 #ifdef AFS_PTHREAD_ENV
239 /* set our 'thread-id' so that the host hold table works */
240 MUTEX_ENTER(&rx_stats_mutex); /* protects rxi_pthread_hinum */
241 tid = ++rxi_pthread_hinum;
242 MUTEX_EXIT(&rx_stats_mutex);
243 pthread_setspecific(rx_thread_id_key, (void *)tid);
244 Log("Set thread id %d for FSYNC_sync\n", tid);
245 #endif /* AFS_PTHREAD_ENV */
248 /* Let somebody else run until level > 0. That doesn't mean that
249 * all volumes have been attached. */
250 #ifdef AFS_PTHREAD_ENV
252 #else /* AFS_PTHREAD_ENV */
253 LWP_DispatchProcess();
254 #endif /* AFS_PTHREAD_ENV */
256 AcceptSd = getport(&addr);
257 /* Reuseaddr needed because system inexplicably leaves crud lying around */
259 setsockopt(AcceptSd, SOL_SOCKET, SO_REUSEADDR, (char *)&on,
262 Log("FSYNC_sync: setsockopt failed with (%d)\n", errno);
264 for (numTries = 0; numTries < MAX_BIND_TRIES; numTries++) {
266 bind(AcceptSd, (struct sockaddr *)&addr, sizeof(addr))) == 0)
268 Log("FSYNC_sync: bind failed with (%d), will sleep and retry\n",
273 listen(AcceptSd, 100);
278 GetHandler(&FSYNC_readfds, &maxfd);
279 /* Note: check for >= 1 below is essential since IOMGR_select
280 * doesn't have exactly same semantics as select.
282 #ifdef AFS_PTHREAD_ENV
283 if (select(maxfd + 1, &FSYNC_readfds, NULL, NULL, NULL) >= 1)
284 #else /* AFS_PTHREAD_ENV */
285 if (IOMGR_Select(maxfd + 1, &FSYNC_readfds, NULL, NULL, NULL) >= 1)
286 #endif /* AFS_PTHREAD_ENV */
287 CallHandler(&FSYNC_readfds);
292 FSYNC_newconnection(int afd)
294 struct sockaddr_in other;
296 junk = sizeof(other);
297 fd = accept(afd, (struct sockaddr *)&other, &junk);
299 Log("FSYNC_newconnection: accept failed, errno==%d\n", errno);
301 } else if (!AddHandler(fd, FSYNC_com)) {
303 assert(AddHandler(fd, FSYNC_com));
307 /* this function processes commands from an fssync file descriptor (fd) */
308 afs_int32 FS_cnt = 0;
314 SYNC_PROTO_BUF_DECL(com_buf);
315 SYNC_PROTO_BUF_DECL(res_buf);
317 memset(&res.hdr, 0, sizeof(res.hdr));
319 com.payload.buf = (void *)com_buf;
320 com.payload.len = SYNC_PROTO_MAX_LEN;
321 res.hdr.response_len = sizeof(res.hdr);
322 res.hdr.proto_version = FSYNC_PROTO_VERSION;
323 res.payload.len = SYNC_PROTO_MAX_LEN;
324 res.payload.buf = (void *)res_buf;
327 if (SYNC_getCom(fd, &com)) {
328 Log("FSYNC_com: read failed; dropping connection (cnt=%d)\n", FS_cnt);
333 if (com.hdr.proto_version != FSYNC_PROTO_VERSION) {
334 Log("FSYNC_com: invalid protocol version (%u)\n", com.hdr.proto_version);
335 res.hdr.response = SYNC_COM_ERROR;
336 res.hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
341 switch (com.hdr.command) {
344 case FSYNC_VOL_LISTVOLUMES:
345 case FSYNC_VOL_NEEDVOLUME:
347 case FSYNC_VOL_BREAKCBKS:
349 case FSYNC_VOL_QUERY:
350 case FSYNC_VOL_QUERY_HDR:
351 case FSYNC_VOL_QUERY_VOP:
352 res.hdr.response = FSYNC_com_VolOp(fd, &com, &res);
354 case FSYNC_VOL_STATS_GENERAL:
355 case FSYNC_VOL_STATS_VICEP:
356 case FSYNC_VOL_STATS_HASH:
357 case FSYNC_VOL_STATS_HDR:
358 case FSYNC_VOL_STATS_VLRU:
359 res.hdr.response = FSYNC_com_StatsOp(fd, &com, &res);
361 case SYNC_COM_CHANNEL_CLOSE:
362 res.hdr.response = SYNC_OK;
363 res.hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
366 res.hdr.response = SYNC_BAD_COMMAND;
372 SYNC_putRes(fd, &res);
373 if (res.hdr.flags & SYNC_FLAG_CHANNEL_SHUTDOWN) {
379 FSYNC_com_VolOp(int fd, SYNC_command * com, SYNC_response * res)
382 afs_int32 code = SYNC_OK;
383 FSSYNC_VolOp_command vcom;
385 if (com->recv_len != (sizeof(com->hdr) + sizeof(FSSYNC_VolOp_hdr))) {
386 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
387 res->hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
388 return SYNC_COM_ERROR;
391 vcom.hdr = &com->hdr;
392 vcom.vop = (FSSYNC_VolOp_hdr *) com->payload.buf;
395 vcom.volumes = OfflineVolumes[FindHandler(fd)];
396 for (vcom.v = NULL, i = 0; i < MAXOFFLINEVOLUMES; i++) {
397 if ((vcom.volumes[i].volumeID == vcom.vop->volume) &&
398 (strncmp(vcom.volumes[i].partName, vcom.vop->partName,
399 sizeof(vcom.volumes[i].partName)) == 0)) {
400 vcom.v = &vcom.volumes[i];
405 switch (com->hdr.command) {
407 code = FSYNC_com_VolOn(&vcom, res);
410 case FSYNC_VOL_NEEDVOLUME:
411 code = FSYNC_com_VolOff(&vcom, res);
413 case FSYNC_VOL_LISTVOLUMES:
417 code = FSYNC_com_VolMove(&vcom, res);
419 case FSYNC_VOL_BREAKCBKS:
420 code = FSYNC_com_VolBreakCBKs(&vcom, res);
423 code = FSYNC_com_VolDone(&vcom, res);
425 case FSYNC_VOL_QUERY:
426 code = FSYNC_com_VolQuery(&vcom, res);
428 case FSYNC_VOL_QUERY_HDR:
429 code = FSYNC_com_VolHdrQuery(&vcom, res);
431 #ifdef AFS_DEMAND_ATTACH_FS
432 case FSYNC_VOL_QUERY_VOP:
433 code = FSYNC_com_VolOpQuery(&vcom, res);
435 #endif /* AFS_DEMAND_ATTACH_FS */
437 code = SYNC_BAD_COMMAND;
444 FSYNC_com_VolOn(FSSYNC_VolOp_command * vcom, SYNC_response * res)
446 afs_int32 code = SYNC_OK;
447 char tvolName[VMAXPATHLEN];
451 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
452 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
458 This is where a detatched volume gets reattached. However in the
459 special case where the volume is merely busy, it is already
460 attatched and it is only necessary to clear the busy flag. See
461 defect #2080 for details.
464 /* is the volume already attatched? */
467 * XXX With the following enabled we had bizarre problems where the backup id would
468 * be reset to 0; that was due to the interaction between fileserver/volserver in that they
469 * both keep volumes in memory and the changes wouldn't be made to the fileserver. Some of
470 * the problems were due to refcnt changes as result of VGetVolume/VPutVolume which would call
471 * VOffline, etc. when we don't want to; someday the whole #2080 issue should be revisited to
474 vp = VGetVolume_r(&error, vcom->vop->volume);
476 /* yep, is the BUSY flag set? */
477 if (vp->specialStatus == VBUSY) {
479 /* yep, clear BUSY flag */
481 vp->specialStatus = 0;
482 /* make sure vol is online */
484 vcom->v->volumeID = 0;
485 V_inUse(vp) = 1; /* online */
494 /* so, we need to attach the volume */
497 vcom->v->volumeID = 0;
499 snprintf(&tvolName[1], sizeof(tvolName)-1, VFORMAT, vcom->vop->volume);
500 tvolName[sizeof(tvolName)-1] = '\0';
502 #ifdef AFS_DEMAND_ATTACH_FS
503 vp = VPreAttachVolumeByName_r(&error, vcom->vop->partName, tvolName,
505 if (vp && vp->pending_vol_op) {
506 VDeregisterVolOp_r(vp, vp->pending_vol_op);
508 #else /* AFS_DEMAND_ATTACH_FS */
509 vp = VAttachVolumeByName_r(&error, vcom->vop->partName, tvolName,
513 #endif /* AFS_DEMAND_ATTACH_FS */
517 res->hdr.reason = error;
525 FSYNC_com_VolOff(FSSYNC_VolOp_command * vcom, SYNC_response * res)
527 FSSYNC_VolOp_info info;
528 afs_int32 code = SYNC_OK;
533 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
534 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
539 /* not already offline, we need to find a slot for newly offline volume */
540 if (vcom->hdr->programType == debugUtility) {
541 /* debug utilities do not have their operations tracked */
545 for (i = 0; i < MAXOFFLINEVOLUMES; i++) {
546 if (vcom->volumes[i].volumeID == 0) {
547 vcom->v = &vcom->volumes[i];
557 FSYNC_com_to_info(vcom, &info);
559 #ifdef AFS_DEMAND_ATTACH_FS
560 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
562 vp = VGetVolume_r(&error, vcom->vop->volume);
566 if ((vcom->vop->partName[0] != 0) &&
567 (strncmp(vcom->vop->partName, vp->partition->name,
568 sizeof(vcom->vop->partName)) != 0)) {
569 /* volume on desired partition is not online, so we
570 * should treat this as an offline volume.
572 #ifndef AFS_DEMAND_ATTACH_FS
580 #ifdef AFS_DEMAND_ATTACH_FS
582 ProgramType type = (ProgramType) vcom->hdr->programType;
584 /* do initial filtering of requests */
586 /* enforce mutual exclusion for volume ops */
587 if (vp->pending_vol_op) {
588 if (vp->pending_vol_op->com.programType != type) {
589 Log("volume %u already checked out\n", vp->hashid);
591 Log("vp->vop = { com = { ver=%u, prog=%d, com=%d, reason=%d, len=%u, flags=0x%x }, vop = { vol=%u, part='%s' } }\n",
592 vp->pending_vol_op->com.proto_version,
593 vp->pending_vol_op->com.programType,
594 vp->pending_vol_op->com.command,
595 vp->pending_vol_op->com.reason,
596 vp->pending_vol_op->com.command_len,
597 vp->pending_vol_op->com.flags,
598 vp->pending_vol_op->vop.volume,
599 vp->pending_vol_op->vop.partName );
600 Log("vcom = { com = { ver=%u, prog=%d, com=%d, reason=%d, len=%u, flags=0x%x } , vop = { vol=%u, part='%s' } }\n",
601 vcom->hdr->proto_version,
602 vcom->hdr->programType,
605 vcom->hdr->command_len,
608 vcom->vop->partName);
609 res->hdr.reason = FSYNC_EXCLUSIVE;
612 Log("warning: volume %u recursively checked out by programType id %d\n",
613 vp->hashid, vcom->hdr->programType);
617 /* filter based upon requestor
619 * volume utilities are not allowed to check out volumes
620 * which are in an error state
622 * unknown utility programs will be denied on principal
627 /* give the salvageserver lots of liberty */
630 if ((V_attachState(vp) == VOL_STATE_ERROR) ||
631 (V_attachState(vp) == VOL_STATE_SALVAGING)) {
636 Log("bad program type passed to FSSYNC\n");
640 /* short circuit for offline volume states
641 * so we can avoid I/O penalty of attachment */
642 switch (V_attachState(vp)) {
643 case VOL_STATE_UNATTACHED:
644 case VOL_STATE_PREATTACHED:
645 case VOL_STATE_SALVAGING:
646 case VOL_STATE_ERROR:
647 /* register the volume operation metadata with the volume
649 * if the volume is currently pre-attached, attach2()
650 * will evaluate the vol op metadata to determine whether
651 * attaching the volume would be safe */
652 VRegisterVolOp_r(vp, &info);
658 /* convert to heavyweight ref */
659 nvp = VGetVolumeByVp_r(&error, vp);
661 /* register the volume operation metadata with the volume */
662 VRegisterVolOp_r(vp, &info);
665 Log("FSYNC_com_VolOff: failed to get heavyweight reference to volume %u\n",
667 res->hdr.reason = FSYNC_VOL_PKG_ERROR;
672 #endif /* AFS_DEMAND_ATTACH_FS */
675 if (VVolOpLeaveOnline_r(vp, &info)) {
676 VUpdateVolume_r(&error, vp, VOL_UPDATE_WAIT); /* At least get volume stats right */
678 Log("FSYNC: Volume %u (%s) was left on line for an external %s request\n",
679 V_id(vp), V_name(vp),
680 vcom->hdr->reason == V_CLONE ? "clone" :
681 vcom->hdr->reason == V_READONLY ? "readonly" :
682 vcom->hdr->reason == V_DUMP ? "dump" :
687 if (VVolOpSetVBusy_r(vp, &info)) {
688 vp->specialStatus = VBUSY;
691 /* remember what volume we got, so we can keep track of how
692 * many volumes the volserver or whatever is using. Note that
693 * vp is valid since leaveonline is only set when vp is valid.
696 vcom->v->volumeID = vcom->vop->volume;
697 strlcpy(vcom->v->partName, vp->partition->name, sizeof(vcom->v->partName));
700 VOffline_r(vp, "A volume utility is running.");
713 FSYNC_com_VolMove(FSSYNC_VolOp_command * vcom, SYNC_response * res)
718 /* Yuch: the "reason" for the move is the site it got moved to... */
719 /* still set specialStatus so we stop sending back VBUSY.
720 * also should still break callbacks. Note that I don't know
721 * how to tell if we should break all or not, so we just do it
722 * since it doesn't matter much if we do an extra break
723 * volume callbacks on a volume move within the same server */
724 #ifdef AFS_DEMAND_ATTACH_FS
725 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
727 vp = VGetVolume_r(&error, vcom->vop->volume);
730 vp->specialStatus = VMOVED;
731 #ifndef AFS_DEMAND_ATTACH_FS
736 if (V_BreakVolumeCallbacks) {
737 Log("fssync: volume %u moved to %x; breaking all call backs\n",
738 vcom->vop->volume, vcom->hdr->reason);
740 (*V_BreakVolumeCallbacks) (vcom->vop->volume);
748 FSYNC_com_VolDone(FSSYNC_VolOp_command * vcom, SYNC_response * res)
750 #ifdef AFS_DEMAND_ATTACH_FS
755 /* don't try to put online, this call is made only after deleting
756 * a volume, in which case we want to remove the vol # from the
757 * OfflineVolumes array only */
759 vcom->v->volumeID = 0;
761 #ifdef AFS_DEMAND_ATTACH_FS
762 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
763 if (vp && vp->pending_vol_op) {
764 VDeregisterVolOp_r(vp, vp->pending_vol_op);
772 FSYNC_com_VolBreakCBKs(FSSYNC_VolOp_command * vcom, SYNC_response * res)
774 /* if the volume is being restored, break all callbacks on it */
775 if (V_BreakVolumeCallbacks) {
776 Log("fssync: breaking all call backs for volume %u\n",
779 (*V_BreakVolumeCallbacks) (vcom->vop->volume);
786 FSYNC_com_VolQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
788 afs_int32 code = SYNC_OK;
792 #ifdef AFS_DEMAND_ATTACH_FS
793 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
794 #else /* !AFS_DEMAND_ATTACH_FS */
795 vp = VGetVolume_r(&error, vcom->vop->volume);
796 #endif /* !AFS_DEMAND_ATTACH_FS */
799 assert(sizeof(Volume) <= res->payload.len);
800 memcpy(res->payload.buf, vp, sizeof(Volume));
801 res->hdr.response_len += sizeof(Volume);
802 #ifndef AFS_DEMAND_ATTACH_FS
806 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
813 FSYNC_com_VolHdrQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
815 afs_int32 code = SYNC_OK;
820 #ifdef AFS_DEMAND_ATTACH_FS
821 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
823 (vp->header != NULL) &&
824 (V_attachFlags(vp) & VOL_HDR_ATTACHED) &&
825 (V_attachFlags(vp) & VOL_HDR_LOADED)) {
828 #else /* !AFS_DEMAND_ATTACH_FS */
829 vp = VGetVolume_r(&error, vcom->vop->volume);
830 if (vp && vp->header) {
833 #endif /* !AFS_DEMAND_ATTACH_FS */
837 assert(sizeof(VolumeDiskData) <= res->payload.len);
838 memcpy(res->payload.buf, &V_disk(vp), sizeof(VolumeDiskData));
839 res->hdr.response_len += sizeof(VolumeDiskData);
840 #ifndef AFS_DEMAND_ATTACH_FS
845 res->hdr.reason = FSYNC_HDR_NOT_ATTACHED;
847 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
854 #ifdef AFS_DEMAND_ATTACH_FS
856 FSYNC_com_VolOpQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
858 afs_int32 code = SYNC_OK;
862 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
864 if (vp && vp->pending_vol_op) {
865 assert(sizeof(FSSYNC_VolOp_info) <= res->payload.len);
866 memcpy(res->payload.buf, vp->pending_vol_op, sizeof(FSSYNC_VolOp_info));
867 res->hdr.response_len += sizeof(FSSYNC_VolOp_info);
870 res->hdr.reason = FSYNC_NO_PENDING_VOL_OP;
872 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
878 #endif /* AFS_DEMAND_ATTACH_FS */
881 FSYNC_com_StatsOp(int fd, SYNC_command * com, SYNC_response * res)
884 afs_int32 code = SYNC_OK;
885 FSSYNC_StatsOp_command scom;
887 if (com->recv_len != (sizeof(com->hdr) + sizeof(FSSYNC_StatsOp_hdr))) {
888 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
889 res->hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
890 return SYNC_COM_ERROR;
893 scom.hdr = &com->hdr;
894 scom.sop = (FSSYNC_StatsOp_hdr *) com->payload.buf;
897 switch (com->hdr.command) {
898 case FSYNC_VOL_STATS_GENERAL:
899 code = FSYNC_com_StatsOpGeneral(&scom, res);
901 #ifdef AFS_DEMAND_ATTACH_FS
902 /* statistics for the following subsystems are only tracked
903 * for demand attach fileservers */
904 case FSYNC_VOL_STATS_VICEP:
905 code = FSYNC_com_StatsOpViceP(&scom, res);
907 case FSYNC_VOL_STATS_HASH:
908 code = FSYNC_com_StatsOpHash(&scom, res);
910 case FSYNC_VOL_STATS_HDR:
911 code = FSYNC_com_StatsOpHdr(&scom, res);
913 case FSYNC_VOL_STATS_VLRU:
914 code = FSYNC_com_StatsOpVLRU(&scom, res);
916 #endif /* AFS_DEMAND_ATTACH_FS */
918 code = SYNC_BAD_COMMAND;
925 FSYNC_com_StatsOpGeneral(FSSYNC_StatsOp_command * scom, SYNC_response * res)
927 afs_int32 code = SYNC_OK;
929 memcpy(res->payload.buf, &VStats, sizeof(VStats));
930 res->hdr.response_len += sizeof(VStats);
935 #ifdef AFS_DEMAND_ATTACH_FS
937 FSYNC_com_StatsOpViceP(FSSYNC_StatsOp_command * scom, SYNC_response * res)
939 afs_int32 code = SYNC_OK;
940 struct DiskPartition * dp;
941 struct DiskPartitionStats * stats;
943 if (SYNC_verifyProtocolString(scom->sop->args.partName, sizeof(scom->sop->args.partName))) {
944 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
949 dp = VGetPartition_r(scom->sop->args.partName, 0);
953 stats = (struct DiskPartitionStats *) res->payload.buf;
954 stats->free = dp->free;
955 stats->totalUsable = dp->totalUsable;
956 stats->minFree = dp->minFree;
957 stats->f_files = dp->f_files;
958 stats->vol_list_len = dp->vol_list.len;
960 res->hdr.response_len += sizeof(struct DiskPartitionStats);
968 FSYNC_com_StatsOpHash(FSSYNC_StatsOp_command * scom, SYNC_response * res)
970 afs_int32 code = SYNC_OK;
971 struct VolumeHashChainStats * stats;
972 struct VolumeHashChainHead * head;
974 if (scom->sop->args.hash_bucket >= VolumeHashTable.Size) {
978 head = &VolumeHashTable.Table[scom->sop->args.hash_bucket];
979 stats = (struct VolumeHashChainStats *) res->payload.buf;
980 stats->table_size = VolumeHashTable.Size;
981 stats->chain_len = head->len;
982 stats->chain_cacheCheck = head->cacheCheck;
983 stats->chain_busy = head->busy;
984 AssignInt64(head->looks, &stats->chain_looks);
985 AssignInt64(head->gets, &stats->chain_gets);
986 AssignInt64(head->reorders, &stats->chain_reorders);
988 res->hdr.response_len += sizeof(struct VolumeHashChainStats);
994 FSYNC_com_StatsOpHdr(FSSYNC_StatsOp_command * scom, SYNC_response * res)
996 afs_int32 code = SYNC_OK;
998 memcpy(res->payload.buf, &volume_hdr_LRU.stats, sizeof(volume_hdr_LRU.stats));
999 res->hdr.response_len += sizeof(volume_hdr_LRU.stats);
1005 FSYNC_com_StatsOpVLRU(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1007 afs_int32 code = SYNC_OK;
1009 code = SYNC_BAD_COMMAND;
1013 #endif /* AFS_DEMAND_ATTACH_FS */
1016 FSYNC_com_to_info(FSSYNC_VolOp_command * vcom, FSSYNC_VolOp_info * info)
1018 memcpy(&info->com, vcom->hdr, sizeof(SYNC_command_hdr));
1019 memcpy(&info->vop, vcom->vop, sizeof(FSSYNC_VolOp_hdr));
1025 struct offlineInfo *p;
1028 char tvolName[VMAXPATHLEN];
1031 p = OfflineVolumes[FindHandler(fd)];
1032 for (i = 0; i < MAXOFFLINEVOLUMES; i++) {
1033 if (p[i].volumeID) {
1038 sprintf(&tvolName[1], VFORMAT, p[i].volumeID);
1039 vp = VAttachVolumeByName_r(&error, p[i].partName, tvolName,
1056 static int AcceptHandler = -1; /* handler id for accept, if turned on */
1061 if (AcceptHandler == -1) {
1062 assert(AddHandler(AcceptSd, FSYNC_newconnection));
1063 AcceptHandler = FindHandler(AcceptSd);
1070 if (AcceptHandler != -1) {
1071 assert(RemoveHandler(AcceptSd));
1076 /* The multiple FD handling code. */
1078 static int HandlerFD[MAXHANDLERS];
1079 static int (*HandlerProc[MAXHANDLERS]) ();
1085 ObtainWriteLock(&FSYNC_handler_lock);
1086 for (i = 0; i < MAXHANDLERS; i++) {
1090 ReleaseWriteLock(&FSYNC_handler_lock);
1094 CallHandler(fd_set * fdsetp)
1097 ObtainReadLock(&FSYNC_handler_lock);
1098 for (i = 0; i < MAXHANDLERS; i++) {
1099 if (HandlerFD[i] >= 0 && FD_ISSET(HandlerFD[i], fdsetp)) {
1100 ReleaseReadLock(&FSYNC_handler_lock);
1101 (*HandlerProc[i]) (HandlerFD[i]);
1102 ObtainReadLock(&FSYNC_handler_lock);
1105 ReleaseReadLock(&FSYNC_handler_lock);
1109 AddHandler(int afd, int (*aproc) ())
1112 ObtainWriteLock(&FSYNC_handler_lock);
1113 for (i = 0; i < MAXHANDLERS; i++)
1114 if (HandlerFD[i] == -1)
1116 if (i >= MAXHANDLERS) {
1117 ReleaseWriteLock(&FSYNC_handler_lock);
1121 HandlerProc[i] = aproc;
1122 ReleaseWriteLock(&FSYNC_handler_lock);
1127 FindHandler(register int afd)
1130 ObtainReadLock(&FSYNC_handler_lock);
1131 for (i = 0; i < MAXHANDLERS; i++)
1132 if (HandlerFD[i] == afd) {
1133 ReleaseReadLock(&FSYNC_handler_lock);
1136 ReleaseReadLock(&FSYNC_handler_lock); /* just in case */
1138 return -1; /* satisfy compiler */
1142 FindHandler_r(register int afd)
1145 for (i = 0; i < MAXHANDLERS; i++)
1146 if (HandlerFD[i] == afd) {
1150 return -1; /* satisfy compiler */
1154 RemoveHandler(register int afd)
1156 ObtainWriteLock(&FSYNC_handler_lock);
1157 HandlerFD[FindHandler_r(afd)] = -1;
1158 ReleaseWriteLock(&FSYNC_handler_lock);
1163 GetHandler(fd_set * fdsetp, int *maxfdp)
1166 register int maxfd = -1;
1168 ObtainReadLock(&FSYNC_handler_lock); /* just in case */
1169 for (i = 0; i < MAXHANDLERS; i++)
1170 if (HandlerFD[i] != -1) {
1171 FD_SET(HandlerFD[i], fdsetp);
1172 if (maxfd < HandlerFD[i])
1173 maxfd = HandlerFD[i];
1176 ReleaseReadLock(&FSYNC_handler_lock); /* just in case */
1179 #endif /* FSSYNC_BUILD_SERVER */