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 #include <sys/poll.h>
103 #endif /* HAVE_POLL */
105 #ifdef USE_UNIX_SOCKETS
107 #include <afs/afsutil.h>
108 #endif /* USE_UNIX_SOCKETS */
110 #ifdef FSSYNC_BUILD_SERVER
112 /*@printflike@*/ extern void Log(const char *format, ...);
117 #define osi_Assert(e) (void)(e)
119 int (*V_BreakVolumeCallbacks) ();
121 #define MAXHANDLERS 4 /* Up to 4 clients; must be at least 2, so that
122 * move = dump+restore can run on single server */
123 #define MAXOFFLINEVOLUMES 128 /* This needs to be as big as the maximum
124 * number that would be offline for 1 operation.
125 * Current winner is salvage, which needs all
126 * cloned read-only copies offline when salvaging
127 * a single read-write volume */
129 #define MAX_BIND_TRIES 5 /* Number of times to retry socket bind */
133 static struct offlineInfo OfflineVolumes[MAXHANDLERS][MAXOFFLINEVOLUMES];
135 static int AcceptSd = -1; /* Socket used by server for accepting connections */
137 static int getport();
139 /* Forward declarations */
140 static void FSYNC_sync();
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_VolOn(FSSYNC_VolOp_command * com, SYNC_response * res);
163 static afs_int32 FSYNC_com_VolOff(FSSYNC_VolOp_command * com, SYNC_response * res);
164 static afs_int32 FSYNC_com_VolMove(FSSYNC_VolOp_command * com, SYNC_response * res);
165 static afs_int32 FSYNC_com_VolBreakCBKs(FSSYNC_VolOp_command * com, SYNC_response * res);
166 static afs_int32 FSYNC_com_VolDone(FSSYNC_VolOp_command * com, SYNC_response * res);
167 static afs_int32 FSYNC_com_VolQuery(FSSYNC_VolOp_command * com, SYNC_response * res);
168 static afs_int32 FSYNC_com_VolHdrQuery(FSSYNC_VolOp_command * com, SYNC_response * res);
169 #ifdef AFS_DEMAND_ATTACH_FS
170 static afs_int32 FSYNC_com_VolOpQuery(FSSYNC_VolOp_command * com, SYNC_response * res);
171 #endif /* AFS_DEMAND_ATTACH_FS */
173 static afs_int32 FSYNC_com_StatsOp(int fd, SYNC_command * com, SYNC_response * res);
175 static afs_int32 FSYNC_com_StatsOpGeneral(FSSYNC_StatsOp_command * scom, SYNC_response * res);
176 static afs_int32 FSYNC_com_StatsOpViceP(FSSYNC_StatsOp_command * scom, SYNC_response * res);
177 static afs_int32 FSYNC_com_StatsOpHash(FSSYNC_StatsOp_command * scom, SYNC_response * res);
178 static afs_int32 FSYNC_com_StatsOpHdr(FSSYNC_StatsOp_command * scom, SYNC_response * res);
179 static afs_int32 FSYNC_com_StatsOpVLRU(FSSYNC_StatsOp_command * scom, SYNC_response * res);
182 static void FSYNC_com_to_info(FSSYNC_VolOp_command * vcom, FSSYNC_VolOp_info * info);
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 assert(pthread_attr_init(&tattr) == 0);
205 assert(pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED) == 0);
206 assert(pthread_create(&tid, &tattr, FSYNC_sync, NULL) == 0);
207 #else /* AFS_PTHREAD_ENV */
208 assert(LWP_CreateProcess
209 (FSYNC_sync, USUAL_STACK_SIZE, USUAL_PRIORITY, (void *)0,
210 "FSYNC_sync", &pid) == LWP_SUCCESS);
211 #endif /* AFS_PTHREAD_ENV */
214 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
215 static struct pollfd FSYNC_readfds[MAXHANDLERS];
217 static fd_set FSYNC_readfds;
220 #ifdef USE_UNIX_SOCKETS
222 getport(struct sockaddr_un *addr)
225 char tbuffer[AFSDIR_PATH_MAX];
227 strcompose(tbuffer, AFSDIR_PATH_MAX, AFSDIR_SERVER_LOCAL_DIRPATH, "/",
228 "fssync.sock", NULL);
230 memset(addr, 0, sizeof(*addr));
231 addr->sun_family = AF_UNIX;
232 strncpy(addr->sun_path, tbuffer, (sizeof(struct sockaddr_un) - sizeof(short)));
233 assert((sd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
238 getport(struct sockaddr_in *addr)
242 memset(addr, 0, sizeof(*addr));
243 assert((sd = socket(AF_INET, SOCK_STREAM, 0)) >= 0);
244 #ifdef STRUCT_SOCKADDR_HAS_SA_LEN
245 addr->sin_len = sizeof(struct sockaddr_in);
247 addr->sin_addr.s_addr = htonl(0x7f000001);
248 addr->sin_family = AF_INET; /* was localhost->h_addrtype */
249 addr->sin_port = htons(2040); /* XXXX htons not _really_ neccessary */
259 #ifdef USE_UNIX_SOCKETS
260 struct sockaddr_un addr;
261 char tbuffer[AFSDIR_PATH_MAX];
262 #else /* USE_UNIX_SOCKETS */
263 struct sockaddr_in addr;
264 #endif /* USE_UNIX_SOCKETS */
269 #ifdef AFS_PTHREAD_ENV
274 (void)signal(SIGPIPE, SIG_IGN);
277 #ifdef AFS_PTHREAD_ENV
278 /* set our 'thread-id' so that the host hold table works */
279 MUTEX_ENTER(&rx_stats_mutex); /* protects rxi_pthread_hinum */
280 tid = ++rxi_pthread_hinum;
281 MUTEX_EXIT(&rx_stats_mutex);
282 pthread_setspecific(rx_thread_id_key, (void *)tid);
283 Log("Set thread id %d for FSYNC_sync\n", tid);
284 #endif /* AFS_PTHREAD_ENV */
286 #ifdef USE_UNIX_SOCKETS
288 strcompose(tbuffer, AFSDIR_PATH_MAX, AFSDIR_SERVER_LOCAL_DIRPATH, "/",
289 "fssync.sock", NULL);
292 #endif /* USE_UNIX_SOCKETS */
295 /* Let somebody else run until level > 0. That doesn't mean that
296 * all volumes have been attached. */
297 #ifdef AFS_PTHREAD_ENV
299 #else /* AFS_PTHREAD_ENV */
300 LWP_DispatchProcess();
301 #endif /* AFS_PTHREAD_ENV */
303 AcceptSd = getport(&addr);
304 /* Reuseaddr needed because system inexplicably leaves crud lying around */
306 setsockopt(AcceptSd, SOL_SOCKET, SO_REUSEADDR, (char *)&on,
309 Log("FSYNC_sync: setsockopt failed with (%d)\n", errno);
311 for (numTries = 0; numTries < MAX_BIND_TRIES; numTries++) {
313 bind(AcceptSd, (struct sockaddr *)&addr, sizeof(addr))) == 0)
315 Log("FSYNC_sync: bind failed with (%d), will sleep and retry\n",
320 listen(AcceptSd, 100);
324 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
326 GetHandler(FSYNC_readfds, MAXHANDLERS, POLLIN|POLLPRI, &nfds);
327 if (poll(FSYNC_readfds, nfds, -1) >=1)
328 CallHandler(FSYNC_readfds, nfds, POLLIN|POLLPRI);
331 GetHandler(&FSYNC_readfds, &maxfd);
332 /* Note: check for >= 1 below is essential since IOMGR_select
333 * doesn't have exactly same semantics as select.
335 #ifdef AFS_PTHREAD_ENV
336 if (select(maxfd + 1, &FSYNC_readfds, NULL, NULL, NULL) >= 1)
337 #else /* AFS_PTHREAD_ENV */
338 if (IOMGR_Select(maxfd + 1, &FSYNC_readfds, NULL, NULL, NULL) >= 1)
339 #endif /* AFS_PTHREAD_ENV */
340 CallHandler(&FSYNC_readfds);
346 FSYNC_newconnection(int afd)
348 #ifdef USE_UNIX_SOCKETS
349 struct sockaddr_un other;
350 #else /* USE_UNIX_SOCKETS */
351 struct sockaddr_in other;
354 junk = sizeof(other);
355 fd = accept(afd, (struct sockaddr *)&other, &junk);
357 Log("FSYNC_newconnection: accept failed, errno==%d\n", errno);
359 } else if (!AddHandler(fd, FSYNC_com)) {
361 assert(AddHandler(fd, FSYNC_com));
365 /* this function processes commands from an fssync file descriptor (fd) */
366 afs_int32 FS_cnt = 0;
372 SYNC_PROTO_BUF_DECL(com_buf);
373 SYNC_PROTO_BUF_DECL(res_buf);
375 memset(&res.hdr, 0, sizeof(res.hdr));
377 com.payload.buf = (void *)com_buf;
378 com.payload.len = SYNC_PROTO_MAX_LEN;
379 res.hdr.response_len = sizeof(res.hdr);
380 res.hdr.proto_version = FSYNC_PROTO_VERSION;
381 res.payload.len = SYNC_PROTO_MAX_LEN;
382 res.payload.buf = (void *)res_buf;
385 if (SYNC_getCom(fd, &com)) {
386 Log("FSYNC_com: read failed; dropping connection (cnt=%d)\n", FS_cnt);
391 if (com.hdr.proto_version != FSYNC_PROTO_VERSION) {
392 Log("FSYNC_com: invalid protocol version (%u)\n", com.hdr.proto_version);
393 res.hdr.response = SYNC_COM_ERROR;
394 res.hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
399 switch (com.hdr.command) {
402 case FSYNC_VOL_LISTVOLUMES:
403 case FSYNC_VOL_NEEDVOLUME:
405 case FSYNC_VOL_BREAKCBKS:
407 case FSYNC_VOL_QUERY:
408 case FSYNC_VOL_QUERY_HDR:
409 case FSYNC_VOL_QUERY_VOP:
410 res.hdr.response = FSYNC_com_VolOp(fd, &com, &res);
412 case FSYNC_VOL_STATS_GENERAL:
413 case FSYNC_VOL_STATS_VICEP:
414 case FSYNC_VOL_STATS_HASH:
415 case FSYNC_VOL_STATS_HDR:
416 case FSYNC_VOL_STATS_VLRU:
417 res.hdr.response = FSYNC_com_StatsOp(fd, &com, &res);
419 case SYNC_COM_CHANNEL_CLOSE:
420 res.hdr.response = SYNC_OK;
421 res.hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
424 res.hdr.response = SYNC_BAD_COMMAND;
430 SYNC_putRes(fd, &res);
431 if (res.hdr.flags & SYNC_FLAG_CHANNEL_SHUTDOWN) {
437 FSYNC_com_VolOp(int fd, SYNC_command * com, SYNC_response * res)
440 afs_int32 code = SYNC_OK;
441 FSSYNC_VolOp_command vcom;
443 if (com->recv_len != (sizeof(com->hdr) + sizeof(FSSYNC_VolOp_hdr))) {
444 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
445 res->hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
446 return SYNC_COM_ERROR;
449 vcom.hdr = &com->hdr;
450 vcom.vop = (FSSYNC_VolOp_hdr *) com->payload.buf;
453 vcom.volumes = OfflineVolumes[FindHandler(fd)];
454 for (vcom.v = NULL, i = 0; i < MAXOFFLINEVOLUMES; i++) {
455 if ((vcom.volumes[i].volumeID == vcom.vop->volume) &&
456 (strncmp(vcom.volumes[i].partName, vcom.vop->partName,
457 sizeof(vcom.volumes[i].partName)) == 0)) {
458 vcom.v = &vcom.volumes[i];
463 switch (com->hdr.command) {
465 code = FSYNC_com_VolOn(&vcom, res);
468 case FSYNC_VOL_NEEDVOLUME:
469 code = FSYNC_com_VolOff(&vcom, res);
471 case FSYNC_VOL_LISTVOLUMES:
475 code = FSYNC_com_VolMove(&vcom, res);
477 case FSYNC_VOL_BREAKCBKS:
478 code = FSYNC_com_VolBreakCBKs(&vcom, res);
481 code = FSYNC_com_VolDone(&vcom, res);
483 case FSYNC_VOL_QUERY:
484 code = FSYNC_com_VolQuery(&vcom, res);
486 case FSYNC_VOL_QUERY_HDR:
487 code = FSYNC_com_VolHdrQuery(&vcom, res);
489 #ifdef AFS_DEMAND_ATTACH_FS
490 case FSYNC_VOL_QUERY_VOP:
491 code = FSYNC_com_VolOpQuery(&vcom, res);
493 #endif /* AFS_DEMAND_ATTACH_FS */
495 code = SYNC_BAD_COMMAND;
502 FSYNC_com_VolOn(FSSYNC_VolOp_command * vcom, SYNC_response * res)
504 afs_int32 code = SYNC_OK;
505 char tvolName[VMAXPATHLEN];
509 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
510 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
516 This is where a detatched volume gets reattached. However in the
517 special case where the volume is merely busy, it is already
518 attatched and it is only necessary to clear the busy flag. See
519 defect #2080 for details.
522 /* is the volume already attatched? */
525 * XXX With the following enabled we had bizarre problems where the backup id would
526 * be reset to 0; that was due to the interaction between fileserver/volserver in that they
527 * both keep volumes in memory and the changes wouldn't be made to the fileserver. Some of
528 * the problems were due to refcnt changes as result of VGetVolume/VPutVolume which would call
529 * VOffline, etc. when we don't want to; someday the whole #2080 issue should be revisited to
532 vp = VGetVolume_r(&error, vcom->vop->volume);
534 /* yep, is the BUSY flag set? */
535 if (vp->specialStatus == VBUSY) {
537 /* yep, clear BUSY flag */
539 vp->specialStatus = 0;
540 /* make sure vol is online */
542 vcom->v->volumeID = 0;
543 V_inUse(vp) = 1; /* online */
552 /* so, we need to attach the volume */
555 vcom->v->volumeID = 0;
557 snprintf(&tvolName[1], sizeof(tvolName)-1, VFORMAT, vcom->vop->volume);
558 tvolName[sizeof(tvolName)-1] = '\0';
560 #ifdef AFS_DEMAND_ATTACH_FS
561 vp = VPreAttachVolumeByName_r(&error, vcom->vop->partName, tvolName,
563 if (vp && vp->pending_vol_op) {
564 VDeregisterVolOp_r(vp, vp->pending_vol_op);
566 #else /* AFS_DEMAND_ATTACH_FS */
567 vp = VAttachVolumeByName_r(&error, vcom->vop->partName, tvolName,
571 #endif /* AFS_DEMAND_ATTACH_FS */
575 res->hdr.reason = error;
583 FSYNC_com_VolOff(FSSYNC_VolOp_command * vcom, SYNC_response * res)
585 FSSYNC_VolOp_info info;
586 afs_int32 code = SYNC_OK;
591 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
592 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
597 /* not already offline, we need to find a slot for newly offline volume */
598 if (vcom->hdr->programType == debugUtility) {
599 /* debug utilities do not have their operations tracked */
603 for (i = 0; i < MAXOFFLINEVOLUMES; i++) {
604 if (vcom->volumes[i].volumeID == 0) {
605 vcom->v = &vcom->volumes[i];
615 FSYNC_com_to_info(vcom, &info);
617 #ifdef AFS_DEMAND_ATTACH_FS
618 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
620 vp = VGetVolume_r(&error, vcom->vop->volume);
624 if ((vcom->vop->partName[0] != 0) &&
625 (strncmp(vcom->vop->partName, vp->partition->name,
626 sizeof(vcom->vop->partName)) != 0)) {
627 /* volume on desired partition is not online, so we
628 * should treat this as an offline volume.
630 #ifndef AFS_DEMAND_ATTACH_FS
638 #ifdef AFS_DEMAND_ATTACH_FS
640 ProgramType type = (ProgramType) vcom->hdr->programType;
642 /* do initial filtering of requests */
644 /* enforce mutual exclusion for volume ops */
645 if (vp->pending_vol_op) {
646 if (vp->pending_vol_op->com.programType != type) {
647 Log("volume %u already checked out\n", vp->hashid);
649 Log("vp->vop = { com = { ver=%u, prog=%d, com=%d, reason=%d, len=%u, flags=0x%x }, vop = { vol=%u, part='%s' } }\n",
650 vp->pending_vol_op->com.proto_version,
651 vp->pending_vol_op->com.programType,
652 vp->pending_vol_op->com.command,
653 vp->pending_vol_op->com.reason,
654 vp->pending_vol_op->com.command_len,
655 vp->pending_vol_op->com.flags,
656 vp->pending_vol_op->vop.volume,
657 vp->pending_vol_op->vop.partName );
658 Log("vcom = { com = { ver=%u, prog=%d, com=%d, reason=%d, len=%u, flags=0x%x } , vop = { vol=%u, part='%s' } }\n",
659 vcom->hdr->proto_version,
660 vcom->hdr->programType,
663 vcom->hdr->command_len,
666 vcom->vop->partName);
667 res->hdr.reason = FSYNC_EXCLUSIVE;
670 Log("warning: volume %u recursively checked out by programType id %d\n",
671 vp->hashid, vcom->hdr->programType);
675 /* filter based upon requestor
677 * volume utilities are not allowed to check out volumes
678 * which are in an error state
680 * unknown utility programs will be denied on principal
685 /* give the salvageserver lots of liberty */
688 if ((V_attachState(vp) == VOL_STATE_ERROR) ||
689 (V_attachState(vp) == VOL_STATE_SALVAGING)) {
694 Log("bad program type passed to FSSYNC\n");
698 /* short circuit for offline volume states
699 * so we can avoid I/O penalty of attachment */
700 switch (V_attachState(vp)) {
701 case VOL_STATE_UNATTACHED:
702 case VOL_STATE_PREATTACHED:
703 case VOL_STATE_SALVAGING:
704 case VOL_STATE_ERROR:
705 /* register the volume operation metadata with the volume
707 * if the volume is currently pre-attached, attach2()
708 * will evaluate the vol op metadata to determine whether
709 * attaching the volume would be safe */
710 VRegisterVolOp_r(vp, &info);
716 /* convert to heavyweight ref */
717 nvp = VGetVolumeByVp_r(&error, vp);
719 /* register the volume operation metadata with the volume */
720 VRegisterVolOp_r(vp, &info);
723 Log("FSYNC_com_VolOff: failed to get heavyweight reference to volume %u\n",
725 res->hdr.reason = FSYNC_VOL_PKG_ERROR;
730 #endif /* AFS_DEMAND_ATTACH_FS */
733 if (VVolOpLeaveOnline_r(vp, &info)) {
734 VUpdateVolume_r(&error, vp, VOL_UPDATE_WAIT); /* At least get volume stats right */
736 Log("FSYNC: Volume %u (%s) was left on line for an external %s request\n",
737 V_id(vp), V_name(vp),
738 vcom->hdr->reason == V_CLONE ? "clone" :
739 vcom->hdr->reason == V_READONLY ? "readonly" :
740 vcom->hdr->reason == V_DUMP ? "dump" :
745 if (VVolOpSetVBusy_r(vp, &info)) {
746 vp->specialStatus = VBUSY;
749 /* remember what volume we got, so we can keep track of how
750 * many volumes the volserver or whatever is using. Note that
751 * vp is valid since leaveonline is only set when vp is valid.
754 vcom->v->volumeID = vcom->vop->volume;
755 strlcpy(vcom->v->partName, vp->partition->name, sizeof(vcom->v->partName));
758 VOffline_r(vp, "A volume utility is running.");
771 FSYNC_com_VolMove(FSSYNC_VolOp_command * vcom, SYNC_response * res)
776 /* Yuch: the "reason" for the move is the site it got moved to... */
777 /* still set specialStatus so we stop sending back VBUSY.
778 * also should still break callbacks. Note that I don't know
779 * how to tell if we should break all or not, so we just do it
780 * since it doesn't matter much if we do an extra break
781 * volume callbacks on a volume move within the same server */
782 #ifdef AFS_DEMAND_ATTACH_FS
783 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
785 vp = VGetVolume_r(&error, vcom->vop->volume);
788 vp->specialStatus = VMOVED;
789 #ifndef AFS_DEMAND_ATTACH_FS
794 if (V_BreakVolumeCallbacks) {
795 Log("fssync: volume %u moved to %x; breaking all call backs\n",
796 vcom->vop->volume, vcom->hdr->reason);
798 (*V_BreakVolumeCallbacks) (vcom->vop->volume);
806 FSYNC_com_VolDone(FSSYNC_VolOp_command * vcom, SYNC_response * res)
808 #ifdef AFS_DEMAND_ATTACH_FS
813 /* don't try to put online, this call is made only after deleting
814 * a volume, in which case we want to remove the vol # from the
815 * OfflineVolumes array only */
817 vcom->v->volumeID = 0;
819 #ifdef AFS_DEMAND_ATTACH_FS
820 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
821 if (vp && vp->pending_vol_op) {
822 VDeregisterVolOp_r(vp, vp->pending_vol_op);
830 FSYNC_com_VolBreakCBKs(FSSYNC_VolOp_command * vcom, SYNC_response * res)
832 /* if the volume is being restored, break all callbacks on it */
833 if (V_BreakVolumeCallbacks) {
834 Log("fssync: breaking all call backs for volume %u\n",
837 (*V_BreakVolumeCallbacks) (vcom->vop->volume);
844 FSYNC_com_VolQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
846 afs_int32 code = SYNC_OK;
850 #ifdef AFS_DEMAND_ATTACH_FS
851 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
852 #else /* !AFS_DEMAND_ATTACH_FS */
853 vp = VGetVolume_r(&error, vcom->vop->volume);
854 #endif /* !AFS_DEMAND_ATTACH_FS */
857 assert(sizeof(Volume) <= res->payload.len);
858 memcpy(res->payload.buf, vp, sizeof(Volume));
859 res->hdr.response_len += sizeof(Volume);
860 #ifndef AFS_DEMAND_ATTACH_FS
864 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
871 FSYNC_com_VolHdrQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
873 afs_int32 code = SYNC_OK;
878 #ifdef AFS_DEMAND_ATTACH_FS
879 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
881 (vp->header != NULL) &&
882 (V_attachFlags(vp) & VOL_HDR_ATTACHED) &&
883 (V_attachFlags(vp) & VOL_HDR_LOADED)) {
886 #else /* !AFS_DEMAND_ATTACH_FS */
887 vp = VGetVolume_r(&error, vcom->vop->volume);
888 if (vp && vp->header) {
891 #endif /* !AFS_DEMAND_ATTACH_FS */
895 assert(sizeof(VolumeDiskData) <= res->payload.len);
896 memcpy(res->payload.buf, &V_disk(vp), sizeof(VolumeDiskData));
897 res->hdr.response_len += sizeof(VolumeDiskData);
898 #ifndef AFS_DEMAND_ATTACH_FS
903 res->hdr.reason = FSYNC_HDR_NOT_ATTACHED;
905 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
912 #ifdef AFS_DEMAND_ATTACH_FS
914 FSYNC_com_VolOpQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
916 afs_int32 code = SYNC_OK;
920 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
922 if (vp && vp->pending_vol_op) {
923 assert(sizeof(FSSYNC_VolOp_info) <= res->payload.len);
924 memcpy(res->payload.buf, vp->pending_vol_op, sizeof(FSSYNC_VolOp_info));
925 res->hdr.response_len += sizeof(FSSYNC_VolOp_info);
928 res->hdr.reason = FSYNC_NO_PENDING_VOL_OP;
930 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
936 #endif /* AFS_DEMAND_ATTACH_FS */
939 FSYNC_com_StatsOp(int fd, SYNC_command * com, SYNC_response * res)
942 afs_int32 code = SYNC_OK;
943 FSSYNC_StatsOp_command scom;
945 if (com->recv_len != (sizeof(com->hdr) + sizeof(FSSYNC_StatsOp_hdr))) {
946 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
947 res->hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
948 return SYNC_COM_ERROR;
951 scom.hdr = &com->hdr;
952 scom.sop = (FSSYNC_StatsOp_hdr *) com->payload.buf;
955 switch (com->hdr.command) {
956 case FSYNC_VOL_STATS_GENERAL:
957 code = FSYNC_com_StatsOpGeneral(&scom, res);
959 #ifdef AFS_DEMAND_ATTACH_FS
960 /* statistics for the following subsystems are only tracked
961 * for demand attach fileservers */
962 case FSYNC_VOL_STATS_VICEP:
963 code = FSYNC_com_StatsOpViceP(&scom, res);
965 case FSYNC_VOL_STATS_HASH:
966 code = FSYNC_com_StatsOpHash(&scom, res);
968 case FSYNC_VOL_STATS_HDR:
969 code = FSYNC_com_StatsOpHdr(&scom, res);
971 case FSYNC_VOL_STATS_VLRU:
972 code = FSYNC_com_StatsOpVLRU(&scom, res);
974 #endif /* AFS_DEMAND_ATTACH_FS */
976 code = SYNC_BAD_COMMAND;
983 FSYNC_com_StatsOpGeneral(FSSYNC_StatsOp_command * scom, SYNC_response * res)
985 afs_int32 code = SYNC_OK;
987 memcpy(res->payload.buf, &VStats, sizeof(VStats));
988 res->hdr.response_len += sizeof(VStats);
993 #ifdef AFS_DEMAND_ATTACH_FS
995 FSYNC_com_StatsOpViceP(FSSYNC_StatsOp_command * scom, SYNC_response * res)
997 afs_int32 code = SYNC_OK;
998 struct DiskPartition * dp;
999 struct DiskPartitionStats * stats;
1001 if (SYNC_verifyProtocolString(scom->sop->args.partName, sizeof(scom->sop->args.partName))) {
1002 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1007 dp = VGetPartition_r(scom->sop->args.partName, 0);
1011 stats = (struct DiskPartitionStats *) res->payload.buf;
1012 stats->free = dp->free;
1013 stats->totalUsable = dp->totalUsable;
1014 stats->minFree = dp->minFree;
1015 stats->f_files = dp->f_files;
1016 stats->vol_list_len = dp->vol_list.len;
1018 res->hdr.response_len += sizeof(struct DiskPartitionStats);
1026 FSYNC_com_StatsOpHash(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1028 afs_int32 code = SYNC_OK;
1029 struct VolumeHashChainStats * stats;
1030 struct VolumeHashChainHead * head;
1032 if (scom->sop->args.hash_bucket >= VolumeHashTable.Size) {
1036 head = &VolumeHashTable.Table[scom->sop->args.hash_bucket];
1037 stats = (struct VolumeHashChainStats *) res->payload.buf;
1038 stats->table_size = VolumeHashTable.Size;
1039 stats->chain_len = head->len;
1040 stats->chain_cacheCheck = head->cacheCheck;
1041 stats->chain_busy = head->busy;
1042 AssignInt64(head->looks, &stats->chain_looks);
1043 AssignInt64(head->gets, &stats->chain_gets);
1044 AssignInt64(head->reorders, &stats->chain_reorders);
1046 res->hdr.response_len += sizeof(struct VolumeHashChainStats);
1052 FSYNC_com_StatsOpHdr(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1054 afs_int32 code = SYNC_OK;
1056 memcpy(res->payload.buf, &volume_hdr_LRU.stats, sizeof(volume_hdr_LRU.stats));
1057 res->hdr.response_len += sizeof(volume_hdr_LRU.stats);
1063 FSYNC_com_StatsOpVLRU(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1065 afs_int32 code = SYNC_OK;
1067 code = SYNC_BAD_COMMAND;
1071 #endif /* AFS_DEMAND_ATTACH_FS */
1074 FSYNC_com_to_info(FSSYNC_VolOp_command * vcom, FSSYNC_VolOp_info * info)
1076 memcpy(&info->com, vcom->hdr, sizeof(SYNC_command_hdr));
1077 memcpy(&info->vop, vcom->vop, sizeof(FSSYNC_VolOp_hdr));
1083 struct offlineInfo *p;
1086 char tvolName[VMAXPATHLEN];
1089 p = OfflineVolumes[FindHandler(fd)];
1090 for (i = 0; i < MAXOFFLINEVOLUMES; i++) {
1091 if (p[i].volumeID) {
1096 sprintf(&tvolName[1], VFORMAT, p[i].volumeID);
1097 vp = VAttachVolumeByName_r(&error, p[i].partName, tvolName,
1114 static int AcceptHandler = -1; /* handler id for accept, if turned on */
1119 if (AcceptHandler == -1) {
1120 assert(AddHandler(AcceptSd, FSYNC_newconnection));
1121 AcceptHandler = FindHandler(AcceptSd);
1128 if (AcceptHandler != -1) {
1129 assert(RemoveHandler(AcceptSd));
1134 /* The multiple FD handling code. */
1136 static int HandlerFD[MAXHANDLERS];
1137 static int (*HandlerProc[MAXHANDLERS]) ();
1143 ObtainWriteLock(&FSYNC_handler_lock);
1144 for (i = 0; i < MAXHANDLERS; i++) {
1148 ReleaseWriteLock(&FSYNC_handler_lock);
1151 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
1153 CallHandler(struct pollfd *fds, int nfds, int mask)
1157 ObtainReadLock(&FSYNC_handler_lock);
1158 for (i = 0; i < nfds; i++) {
1159 if (fds[i].revents & mask) {
1160 handler = FindHandler_r(fds[i].fd);
1161 ReleaseReadLock(&FSYNC_handler_lock);
1162 (*HandlerProc[handler]) (fds[i].fd);
1163 ObtainReadLock(&FSYNC_handler_lock);
1166 ReleaseReadLock(&FSYNC_handler_lock);
1170 CallHandler(fd_set * fdsetp)
1173 ObtainReadLock(&FSYNC_handler_lock);
1174 for (i = 0; i < MAXHANDLERS; i++) {
1175 if (HandlerFD[i] >= 0 && FD_ISSET(HandlerFD[i], fdsetp)) {
1176 ReleaseReadLock(&FSYNC_handler_lock);
1177 (*HandlerProc[i]) (HandlerFD[i]);
1178 ObtainReadLock(&FSYNC_handler_lock);
1181 ReleaseReadLock(&FSYNC_handler_lock);
1186 AddHandler(int afd, int (*aproc) ())
1189 ObtainWriteLock(&FSYNC_handler_lock);
1190 for (i = 0; i < MAXHANDLERS; i++)
1191 if (HandlerFD[i] == -1)
1193 if (i >= MAXHANDLERS) {
1194 ReleaseWriteLock(&FSYNC_handler_lock);
1198 HandlerProc[i] = aproc;
1199 ReleaseWriteLock(&FSYNC_handler_lock);
1204 FindHandler(register int afd)
1207 ObtainReadLock(&FSYNC_handler_lock);
1208 for (i = 0; i < MAXHANDLERS; i++)
1209 if (HandlerFD[i] == afd) {
1210 ReleaseReadLock(&FSYNC_handler_lock);
1213 ReleaseReadLock(&FSYNC_handler_lock); /* just in case */
1215 return -1; /* satisfy compiler */
1219 FindHandler_r(register int afd)
1222 for (i = 0; i < MAXHANDLERS; i++)
1223 if (HandlerFD[i] == afd) {
1227 return -1; /* satisfy compiler */
1231 RemoveHandler(register int afd)
1233 ObtainWriteLock(&FSYNC_handler_lock);
1234 HandlerFD[FindHandler_r(afd)] = -1;
1235 ReleaseWriteLock(&FSYNC_handler_lock);
1239 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
1241 GetHandler(struct pollfd *fds, int maxfds, int events, int *nfds)
1245 ObtainReadLock(&FSYNC_handler_lock);
1246 for (i = 0; i < MAXHANDLERS; i++)
1247 if (HandlerFD[i] != -1) {
1249 fds[fdi].fd = HandlerFD[i];
1250 fds[fdi].events = events;
1251 fds[fdi].revents = 0;
1258 GetHandler(fd_set * fdsetp, int *maxfdp)
1261 register int maxfd = -1;
1263 ObtainReadLock(&FSYNC_handler_lock); /* just in case */
1264 for (i = 0; i < MAXHANDLERS; i++)
1265 if (HandlerFD[i] != -1) {
1266 FD_SET(HandlerFD[i], fdsetp);
1267 if (maxfd < HandlerFD[i])
1268 maxfd = HandlerFD[i];
1271 ReleaseReadLock(&FSYNC_handler_lock); /* just in case */
1273 #endif /* HAVE_POLL && AFS_PTHREAD_ENV */
1275 #endif /* FSSYNC_BUILD_SERVER */