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 */
80 #include <afs/afsint.h>
82 #include <afs/errors.h>
83 #include "daemon_com.h"
87 #include <afs/afssyscalls.h>
91 #include "partition.h"
95 #endif /* HAVE_POLL */
97 #ifdef USE_UNIX_SOCKETS
99 #include <afs/afsutil.h>
100 #endif /* USE_UNIX_SOCKETS */
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 int AddHandler();
140 static int FindHandler();
141 static int FindHandler_r();
142 static int RemoveHandler();
143 #if defined(HAVE_POLL) && defined (AFS_PTHREAD_ENV)
144 static void CallHandler(struct pollfd *fds, int nfds, int mask);
145 static void GetHandler(struct pollfd *fds, int maxfds, int events, int *nfds);
147 static void CallHandler(fd_set * fdsetp);
148 static void GetHandler(fd_set * fdsetp, int *maxfdp);
152 static afs_int32 FSYNC_com_VolOp(int fd, SYNC_command * com, SYNC_response * res);
154 static afs_int32 FSYNC_com_VolOn(FSSYNC_VolOp_command * com, SYNC_response * res);
155 static afs_int32 FSYNC_com_VolOff(FSSYNC_VolOp_command * com, SYNC_response * res);
156 static afs_int32 FSYNC_com_VolMove(FSSYNC_VolOp_command * com, SYNC_response * res);
157 static afs_int32 FSYNC_com_VolBreakCBKs(FSSYNC_VolOp_command * com, SYNC_response * res);
158 static afs_int32 FSYNC_com_VolDone(FSSYNC_VolOp_command * com, SYNC_response * res);
159 static afs_int32 FSYNC_com_VolQuery(FSSYNC_VolOp_command * com, SYNC_response * res);
160 static afs_int32 FSYNC_com_VolHdrQuery(FSSYNC_VolOp_command * com, SYNC_response * res);
161 #ifdef AFS_DEMAND_ATTACH_FS
162 static afs_int32 FSYNC_com_VolOpQuery(FSSYNC_VolOp_command * com, SYNC_response * res);
163 #endif /* AFS_DEMAND_ATTACH_FS */
165 static afs_int32 FSYNC_com_StatsOp(int fd, SYNC_command * com, SYNC_response * res);
167 static afs_int32 FSYNC_com_StatsOpGeneral(FSSYNC_StatsOp_command * scom, SYNC_response * res);
168 static afs_int32 FSYNC_com_StatsOpViceP(FSSYNC_StatsOp_command * scom, SYNC_response * res);
169 static afs_int32 FSYNC_com_StatsOpHash(FSSYNC_StatsOp_command * scom, SYNC_response * res);
170 static afs_int32 FSYNC_com_StatsOpHdr(FSSYNC_StatsOp_command * scom, SYNC_response * res);
171 static afs_int32 FSYNC_com_StatsOpVLRU(FSSYNC_StatsOp_command * scom, SYNC_response * res);
174 static void FSYNC_com_to_info(FSSYNC_VolOp_command * vcom, FSSYNC_VolOp_info * info);
178 * This lock controls access to the handler array. The overhead
179 * is minimal in non-preemptive environments.
181 struct Lock FSYNC_handler_lock;
186 #ifdef AFS_PTHREAD_ENV
188 pthread_attr_t tattr;
189 #else /* AFS_PTHREAD_ENV */
191 #endif /* AFS_PTHREAD_ENV */
193 Lock_Init(&FSYNC_handler_lock);
195 #ifdef AFS_PTHREAD_ENV
196 assert(pthread_attr_init(&tattr) == 0);
197 assert(pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED) == 0);
198 assert(pthread_create(&tid, &tattr, FSYNC_sync, NULL) == 0);
199 #else /* AFS_PTHREAD_ENV */
200 assert(LWP_CreateProcess
201 (FSYNC_sync, USUAL_STACK_SIZE, USUAL_PRIORITY, (void *)0,
202 "FSYNC_sync", &pid) == LWP_SUCCESS);
203 #endif /* AFS_PTHREAD_ENV */
206 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
207 static struct pollfd FSYNC_readfds[MAXHANDLERS];
209 static fd_set FSYNC_readfds;
212 #ifdef USE_UNIX_SOCKETS
214 getport(struct sockaddr_un *addr)
217 char tbuffer[AFSDIR_PATH_MAX];
219 strcompose(tbuffer, AFSDIR_PATH_MAX, AFSDIR_SERVER_LOCAL_DIRPATH, "/",
220 "fssync.sock", NULL);
222 memset(addr, 0, sizeof(*addr));
223 addr->sun_family = AF_UNIX;
224 strncpy(addr->sun_path, tbuffer, (sizeof(struct sockaddr_un) - sizeof(short)));
225 assert((sd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0);
230 getport(struct sockaddr_in *addr)
234 memset(addr, 0, sizeof(*addr));
235 assert((sd = socket(AF_INET, SOCK_STREAM, 0)) >= 0);
236 #ifdef STRUCT_SOCKADDR_HAS_SA_LEN
237 addr->sin_len = sizeof(struct sockaddr_in);
239 addr->sin_addr.s_addr = htonl(0x7f000001);
240 addr->sin_family = AF_INET; /* was localhost->h_addrtype */
241 addr->sin_port = htons(2040); /* XXXX htons not _really_ neccessary */
251 #ifdef USE_UNIX_SOCKETS
252 struct sockaddr_un addr;
253 char tbuffer[AFSDIR_PATH_MAX];
254 #else /* USE_UNIX_SOCKETS */
255 struct sockaddr_in addr;
256 #endif /* USE_UNIX_SOCKETS */
261 #ifdef AFS_PTHREAD_ENV
266 (void)signal(SIGPIPE, SIG_IGN);
269 #ifdef AFS_PTHREAD_ENV
270 /* set our 'thread-id' so that the host hold table works */
271 MUTEX_ENTER(&rx_stats_mutex); /* protects rxi_pthread_hinum */
272 tid = ++rxi_pthread_hinum;
273 MUTEX_EXIT(&rx_stats_mutex);
274 pthread_setspecific(rx_thread_id_key, (void *)tid);
275 Log("Set thread id %d for FSYNC_sync\n", tid);
276 #endif /* AFS_PTHREAD_ENV */
278 #ifdef USE_UNIX_SOCKETS
280 strcompose(tbuffer, AFSDIR_PATH_MAX, AFSDIR_SERVER_LOCAL_DIRPATH, "/",
281 "fssync.sock", NULL);
284 #endif /* USE_UNIX_SOCKETS */
287 /* Let somebody else run until level > 0. That doesn't mean that
288 * all volumes have been attached. */
289 #ifdef AFS_PTHREAD_ENV
291 #else /* AFS_PTHREAD_ENV */
292 LWP_DispatchProcess();
293 #endif /* AFS_PTHREAD_ENV */
295 AcceptSd = getport(&addr);
296 /* Reuseaddr needed because system inexplicably leaves crud lying around */
298 setsockopt(AcceptSd, SOL_SOCKET, SO_REUSEADDR, (char *)&on,
301 Log("FSYNC_sync: setsockopt failed with (%d)\n", errno);
303 for (numTries = 0; numTries < MAX_BIND_TRIES; numTries++) {
305 bind(AcceptSd, (struct sockaddr *)&addr, sizeof(addr))) == 0)
307 Log("FSYNC_sync: bind failed with (%d), will sleep and retry\n",
312 listen(AcceptSd, 100);
316 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
318 GetHandler(FSYNC_readfds, MAXHANDLERS, POLLIN|POLLPRI, &nfds);
319 if (poll(FSYNC_readfds, nfds, -1) >=1)
320 CallHandler(FSYNC_readfds, nfds, POLLIN|POLLPRI);
323 GetHandler(&FSYNC_readfds, &maxfd);
324 /* Note: check for >= 1 below is essential since IOMGR_select
325 * doesn't have exactly same semantics as select.
327 #ifdef AFS_PTHREAD_ENV
328 if (select(maxfd + 1, &FSYNC_readfds, NULL, NULL, NULL) >= 1)
329 #else /* AFS_PTHREAD_ENV */
330 if (IOMGR_Select(maxfd + 1, &FSYNC_readfds, NULL, NULL, NULL) >= 1)
331 #endif /* AFS_PTHREAD_ENV */
332 CallHandler(&FSYNC_readfds);
338 FSYNC_newconnection(int afd)
340 #ifdef USE_UNIX_SOCKETS
341 struct sockaddr_un other;
342 #else /* USE_UNIX_SOCKETS */
343 struct sockaddr_in other;
346 junk = sizeof(other);
347 fd = accept(afd, (struct sockaddr *)&other, &junk);
349 Log("FSYNC_newconnection: accept failed, errno==%d\n", errno);
351 } else if (!AddHandler(fd, FSYNC_com)) {
353 assert(AddHandler(fd, FSYNC_com));
357 /* this function processes commands from an fssync file descriptor (fd) */
358 afs_int32 FS_cnt = 0;
364 SYNC_PROTO_BUF_DECL(com_buf);
365 SYNC_PROTO_BUF_DECL(res_buf);
367 memset(&res.hdr, 0, sizeof(res.hdr));
369 com.payload.buf = (void *)com_buf;
370 com.payload.len = SYNC_PROTO_MAX_LEN;
371 res.hdr.response_len = sizeof(res.hdr);
372 res.hdr.proto_version = FSYNC_PROTO_VERSION;
373 res.payload.len = SYNC_PROTO_MAX_LEN;
374 res.payload.buf = (void *)res_buf;
377 if (SYNC_getCom(fd, &com)) {
378 Log("FSYNC_com: read failed; dropping connection (cnt=%d)\n", FS_cnt);
383 if (com.hdr.proto_version != FSYNC_PROTO_VERSION) {
384 Log("FSYNC_com: invalid protocol version (%u)\n", com.hdr.proto_version);
385 res.hdr.response = SYNC_COM_ERROR;
386 res.hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
391 switch (com.hdr.command) {
394 case FSYNC_VOL_LISTVOLUMES:
395 case FSYNC_VOL_NEEDVOLUME:
397 case FSYNC_VOL_BREAKCBKS:
399 case FSYNC_VOL_QUERY:
400 case FSYNC_VOL_QUERY_HDR:
401 case FSYNC_VOL_QUERY_VOP:
402 res.hdr.response = FSYNC_com_VolOp(fd, &com, &res);
404 case FSYNC_VOL_STATS_GENERAL:
405 case FSYNC_VOL_STATS_VICEP:
406 case FSYNC_VOL_STATS_HASH:
407 case FSYNC_VOL_STATS_HDR:
408 case FSYNC_VOL_STATS_VLRU:
409 res.hdr.response = FSYNC_com_StatsOp(fd, &com, &res);
411 case SYNC_COM_CHANNEL_CLOSE:
412 res.hdr.response = SYNC_OK;
413 res.hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
416 res.hdr.response = SYNC_BAD_COMMAND;
422 SYNC_putRes(fd, &res);
423 if (res.hdr.flags & SYNC_FLAG_CHANNEL_SHUTDOWN) {
429 FSYNC_com_VolOp(int fd, SYNC_command * com, SYNC_response * res)
432 afs_int32 code = SYNC_OK;
433 FSSYNC_VolOp_command vcom;
435 if (com->recv_len != (sizeof(com->hdr) + sizeof(FSSYNC_VolOp_hdr))) {
436 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
437 res->hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
438 return SYNC_COM_ERROR;
441 vcom.hdr = &com->hdr;
442 vcom.vop = (FSSYNC_VolOp_hdr *) com->payload.buf;
445 vcom.volumes = OfflineVolumes[FindHandler(fd)];
446 for (vcom.v = NULL, i = 0; i < MAXOFFLINEVOLUMES; i++) {
447 if ((vcom.volumes[i].volumeID == vcom.vop->volume) &&
448 (strncmp(vcom.volumes[i].partName, vcom.vop->partName,
449 sizeof(vcom.volumes[i].partName)) == 0)) {
450 vcom.v = &vcom.volumes[i];
455 switch (com->hdr.command) {
457 code = FSYNC_com_VolOn(&vcom, res);
460 case FSYNC_VOL_NEEDVOLUME:
461 code = FSYNC_com_VolOff(&vcom, res);
463 case FSYNC_VOL_LISTVOLUMES:
467 code = FSYNC_com_VolMove(&vcom, res);
469 case FSYNC_VOL_BREAKCBKS:
470 code = FSYNC_com_VolBreakCBKs(&vcom, res);
473 code = FSYNC_com_VolDone(&vcom, res);
475 case FSYNC_VOL_QUERY:
476 code = FSYNC_com_VolQuery(&vcom, res);
478 case FSYNC_VOL_QUERY_HDR:
479 code = FSYNC_com_VolHdrQuery(&vcom, res);
481 #ifdef AFS_DEMAND_ATTACH_FS
482 case FSYNC_VOL_QUERY_VOP:
483 code = FSYNC_com_VolOpQuery(&vcom, res);
485 #endif /* AFS_DEMAND_ATTACH_FS */
487 code = SYNC_BAD_COMMAND;
494 FSYNC_com_VolOn(FSSYNC_VolOp_command * vcom, SYNC_response * res)
496 afs_int32 code = SYNC_OK;
497 char tvolName[VMAXPATHLEN];
501 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
502 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
508 This is where a detatched volume gets reattached. However in the
509 special case where the volume is merely busy, it is already
510 attatched and it is only necessary to clear the busy flag. See
511 defect #2080 for details.
514 /* is the volume already attatched? */
517 * XXX With the following enabled we had bizarre problems where the backup id would
518 * be reset to 0; that was due to the interaction between fileserver/volserver in that they
519 * both keep volumes in memory and the changes wouldn't be made to the fileserver. Some of
520 * the problems were due to refcnt changes as result of VGetVolume/VPutVolume which would call
521 * VOffline, etc. when we don't want to; someday the whole #2080 issue should be revisited to
524 vp = VGetVolume_r(&error, vcom->vop->volume);
526 /* yep, is the BUSY flag set? */
527 if (vp->specialStatus == VBUSY) {
529 /* yep, clear BUSY flag */
531 vp->specialStatus = 0;
532 /* make sure vol is online */
534 vcom->v->volumeID = 0;
535 V_inUse(vp) = 1; /* online */
544 /* so, we need to attach the volume */
547 vcom->v->volumeID = 0;
549 snprintf(&tvolName[1], sizeof(tvolName)-1, VFORMAT, vcom->vop->volume);
550 tvolName[sizeof(tvolName)-1] = '\0';
552 #ifdef AFS_DEMAND_ATTACH_FS
553 vp = VPreAttachVolumeByName_r(&error, vcom->vop->partName, tvolName,
555 if (vp && vp->pending_vol_op) {
556 VDeregisterVolOp_r(vp, vp->pending_vol_op);
558 #else /* AFS_DEMAND_ATTACH_FS */
559 vp = VAttachVolumeByName_r(&error, vcom->vop->partName, tvolName,
563 #endif /* AFS_DEMAND_ATTACH_FS */
567 res->hdr.reason = error;
575 FSYNC_com_VolOff(FSSYNC_VolOp_command * vcom, SYNC_response * res)
577 FSSYNC_VolOp_info info;
578 afs_int32 code = SYNC_OK;
583 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
584 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
589 /* not already offline, we need to find a slot for newly offline volume */
590 if (vcom->hdr->programType == debugUtility) {
591 /* debug utilities do not have their operations tracked */
595 for (i = 0; i < MAXOFFLINEVOLUMES; i++) {
596 if (vcom->volumes[i].volumeID == 0) {
597 vcom->v = &vcom->volumes[i];
607 FSYNC_com_to_info(vcom, &info);
609 #ifdef AFS_DEMAND_ATTACH_FS
610 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
612 vp = VGetVolume_r(&error, vcom->vop->volume);
616 if ((vcom->vop->partName[0] != 0) &&
617 (strncmp(vcom->vop->partName, vp->partition->name,
618 sizeof(vcom->vop->partName)) != 0)) {
619 /* volume on desired partition is not online, so we
620 * should treat this as an offline volume.
622 #ifndef AFS_DEMAND_ATTACH_FS
630 #ifdef AFS_DEMAND_ATTACH_FS
632 ProgramType type = (ProgramType) vcom->hdr->programType;
634 /* do initial filtering of requests */
636 /* enforce mutual exclusion for volume ops */
637 if (vp->pending_vol_op) {
638 if (vp->pending_vol_op->com.programType != type) {
639 Log("volume %u already checked out\n", vp->hashid);
641 Log("vp->vop = { com = { ver=%u, prog=%d, com=%d, reason=%d, len=%u, flags=0x%x }, vop = { vol=%u, part='%s' } }\n",
642 vp->pending_vol_op->com.proto_version,
643 vp->pending_vol_op->com.programType,
644 vp->pending_vol_op->com.command,
645 vp->pending_vol_op->com.reason,
646 vp->pending_vol_op->com.command_len,
647 vp->pending_vol_op->com.flags,
648 vp->pending_vol_op->vop.volume,
649 vp->pending_vol_op->vop.partName );
650 Log("vcom = { com = { ver=%u, prog=%d, com=%d, reason=%d, len=%u, flags=0x%x } , vop = { vol=%u, part='%s' } }\n",
651 vcom->hdr->proto_version,
652 vcom->hdr->programType,
655 vcom->hdr->command_len,
658 vcom->vop->partName);
659 res->hdr.reason = FSYNC_EXCLUSIVE;
662 Log("warning: volume %u recursively checked out by programType id %d\n",
663 vp->hashid, vcom->hdr->programType);
667 /* filter based upon requestor
669 * volume utilities are not allowed to check out volumes
670 * which are in an error state
672 * unknown utility programs will be denied on principal
677 /* give the salvageserver lots of liberty */
680 if ((V_attachState(vp) == VOL_STATE_ERROR) ||
681 (V_attachState(vp) == VOL_STATE_SALVAGING)) {
686 Log("bad program type passed to FSSYNC\n");
690 /* short circuit for offline volume states
691 * so we can avoid I/O penalty of attachment */
692 switch (V_attachState(vp)) {
693 case VOL_STATE_UNATTACHED:
694 case VOL_STATE_PREATTACHED:
695 case VOL_STATE_SALVAGING:
696 case VOL_STATE_ERROR:
697 /* register the volume operation metadata with the volume
699 * if the volume is currently pre-attached, attach2()
700 * will evaluate the vol op metadata to determine whether
701 * attaching the volume would be safe */
702 VRegisterVolOp_r(vp, &info);
708 /* convert to heavyweight ref */
709 nvp = VGetVolumeByVp_r(&error, vp);
711 /* register the volume operation metadata with the volume */
712 VRegisterVolOp_r(vp, &info);
715 Log("FSYNC_com_VolOff: failed to get heavyweight reference to volume %u\n",
717 res->hdr.reason = FSYNC_VOL_PKG_ERROR;
722 #endif /* AFS_DEMAND_ATTACH_FS */
725 if (VVolOpLeaveOnline_r(vp, &info)) {
726 VUpdateVolume_r(&error, vp, VOL_UPDATE_WAIT); /* At least get volume stats right */
728 Log("FSYNC: Volume %u (%s) was left on line for an external %s request\n",
729 V_id(vp), V_name(vp),
730 vcom->hdr->reason == V_CLONE ? "clone" :
731 vcom->hdr->reason == V_READONLY ? "readonly" :
732 vcom->hdr->reason == V_DUMP ? "dump" :
737 if (VVolOpSetVBusy_r(vp, &info)) {
738 vp->specialStatus = VBUSY;
741 /* remember what volume we got, so we can keep track of how
742 * many volumes the volserver or whatever is using. Note that
743 * vp is valid since leaveonline is only set when vp is valid.
746 vcom->v->volumeID = vcom->vop->volume;
747 strlcpy(vcom->v->partName, vp->partition->name, sizeof(vcom->v->partName));
750 VOffline_r(vp, "A volume utility is running.");
763 FSYNC_com_VolMove(FSSYNC_VolOp_command * vcom, SYNC_response * res)
768 /* Yuch: the "reason" for the move is the site it got moved to... */
769 /* still set specialStatus so we stop sending back VBUSY.
770 * also should still break callbacks. Note that I don't know
771 * how to tell if we should break all or not, so we just do it
772 * since it doesn't matter much if we do an extra break
773 * volume callbacks on a volume move within the same server */
774 #ifdef AFS_DEMAND_ATTACH_FS
775 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
777 vp = VGetVolume_r(&error, vcom->vop->volume);
780 vp->specialStatus = VMOVED;
781 #ifndef AFS_DEMAND_ATTACH_FS
786 if (V_BreakVolumeCallbacks) {
787 Log("fssync: volume %u moved to %x; breaking all call backs\n",
788 vcom->vop->volume, vcom->hdr->reason);
790 (*V_BreakVolumeCallbacks) (vcom->vop->volume);
798 FSYNC_com_VolDone(FSSYNC_VolOp_command * vcom, SYNC_response * res)
800 #ifdef AFS_DEMAND_ATTACH_FS
805 /* don't try to put online, this call is made only after deleting
806 * a volume, in which case we want to remove the vol # from the
807 * OfflineVolumes array only */
809 vcom->v->volumeID = 0;
811 #ifdef AFS_DEMAND_ATTACH_FS
812 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
813 if (vp && vp->pending_vol_op) {
814 VDeregisterVolOp_r(vp, vp->pending_vol_op);
822 FSYNC_com_VolBreakCBKs(FSSYNC_VolOp_command * vcom, SYNC_response * res)
824 /* if the volume is being restored, break all callbacks on it */
825 if (V_BreakVolumeCallbacks) {
826 Log("fssync: breaking all call backs for volume %u\n",
829 (*V_BreakVolumeCallbacks) (vcom->vop->volume);
836 FSYNC_com_VolQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
838 afs_int32 code = SYNC_OK;
842 #ifdef AFS_DEMAND_ATTACH_FS
843 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
844 #else /* !AFS_DEMAND_ATTACH_FS */
845 vp = VGetVolume_r(&error, vcom->vop->volume);
846 #endif /* !AFS_DEMAND_ATTACH_FS */
849 assert(sizeof(Volume) <= res->payload.len);
850 memcpy(res->payload.buf, vp, sizeof(Volume));
851 res->hdr.response_len += sizeof(Volume);
852 #ifndef AFS_DEMAND_ATTACH_FS
856 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
863 FSYNC_com_VolHdrQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
865 afs_int32 code = SYNC_OK;
870 #ifdef AFS_DEMAND_ATTACH_FS
871 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
873 (vp->header != NULL) &&
874 (V_attachFlags(vp) & VOL_HDR_ATTACHED) &&
875 (V_attachFlags(vp) & VOL_HDR_LOADED)) {
878 #else /* !AFS_DEMAND_ATTACH_FS */
879 vp = VGetVolume_r(&error, vcom->vop->volume);
880 if (vp && vp->header) {
883 #endif /* !AFS_DEMAND_ATTACH_FS */
887 assert(sizeof(VolumeDiskData) <= res->payload.len);
888 memcpy(res->payload.buf, &V_disk(vp), sizeof(VolumeDiskData));
889 res->hdr.response_len += sizeof(VolumeDiskData);
890 #ifndef AFS_DEMAND_ATTACH_FS
895 res->hdr.reason = FSYNC_HDR_NOT_ATTACHED;
897 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
904 #ifdef AFS_DEMAND_ATTACH_FS
906 FSYNC_com_VolOpQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
908 afs_int32 code = SYNC_OK;
912 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
914 if (vp && vp->pending_vol_op) {
915 assert(sizeof(FSSYNC_VolOp_info) <= res->payload.len);
916 memcpy(res->payload.buf, vp->pending_vol_op, sizeof(FSSYNC_VolOp_info));
917 res->hdr.response_len += sizeof(FSSYNC_VolOp_info);
920 res->hdr.reason = FSYNC_NO_PENDING_VOL_OP;
922 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
928 #endif /* AFS_DEMAND_ATTACH_FS */
931 FSYNC_com_StatsOp(int fd, SYNC_command * com, SYNC_response * res)
934 afs_int32 code = SYNC_OK;
935 FSSYNC_StatsOp_command scom;
937 if (com->recv_len != (sizeof(com->hdr) + sizeof(FSSYNC_StatsOp_hdr))) {
938 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
939 res->hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
940 return SYNC_COM_ERROR;
943 scom.hdr = &com->hdr;
944 scom.sop = (FSSYNC_StatsOp_hdr *) com->payload.buf;
947 switch (com->hdr.command) {
948 case FSYNC_VOL_STATS_GENERAL:
949 code = FSYNC_com_StatsOpGeneral(&scom, res);
951 #ifdef AFS_DEMAND_ATTACH_FS
952 /* statistics for the following subsystems are only tracked
953 * for demand attach fileservers */
954 case FSYNC_VOL_STATS_VICEP:
955 code = FSYNC_com_StatsOpViceP(&scom, res);
957 case FSYNC_VOL_STATS_HASH:
958 code = FSYNC_com_StatsOpHash(&scom, res);
960 case FSYNC_VOL_STATS_HDR:
961 code = FSYNC_com_StatsOpHdr(&scom, res);
963 case FSYNC_VOL_STATS_VLRU:
964 code = FSYNC_com_StatsOpVLRU(&scom, res);
966 #endif /* AFS_DEMAND_ATTACH_FS */
968 code = SYNC_BAD_COMMAND;
975 FSYNC_com_StatsOpGeneral(FSSYNC_StatsOp_command * scom, SYNC_response * res)
977 afs_int32 code = SYNC_OK;
979 memcpy(res->payload.buf, &VStats, sizeof(VStats));
980 res->hdr.response_len += sizeof(VStats);
985 #ifdef AFS_DEMAND_ATTACH_FS
987 FSYNC_com_StatsOpViceP(FSSYNC_StatsOp_command * scom, SYNC_response * res)
989 afs_int32 code = SYNC_OK;
990 struct DiskPartition * dp;
991 struct DiskPartitionStats * stats;
993 if (SYNC_verifyProtocolString(scom->sop->args.partName, sizeof(scom->sop->args.partName))) {
994 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
999 dp = VGetPartition_r(scom->sop->args.partName, 0);
1003 stats = (struct DiskPartitionStats *) res->payload.buf;
1004 stats->free = dp->free;
1005 stats->totalUsable = dp->totalUsable;
1006 stats->minFree = dp->minFree;
1007 stats->f_files = dp->f_files;
1008 stats->vol_list_len = dp->vol_list.len;
1010 res->hdr.response_len += sizeof(struct DiskPartitionStats);
1018 FSYNC_com_StatsOpHash(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1020 afs_int32 code = SYNC_OK;
1021 struct VolumeHashChainStats * stats;
1022 struct VolumeHashChainHead * head;
1024 if (scom->sop->args.hash_bucket >= VolumeHashTable.Size) {
1028 head = &VolumeHashTable.Table[scom->sop->args.hash_bucket];
1029 stats = (struct VolumeHashChainStats *) res->payload.buf;
1030 stats->table_size = VolumeHashTable.Size;
1031 stats->chain_len = head->len;
1032 stats->chain_cacheCheck = head->cacheCheck;
1033 stats->chain_busy = head->busy;
1034 AssignInt64(head->looks, &stats->chain_looks);
1035 AssignInt64(head->gets, &stats->chain_gets);
1036 AssignInt64(head->reorders, &stats->chain_reorders);
1038 res->hdr.response_len += sizeof(struct VolumeHashChainStats);
1044 FSYNC_com_StatsOpHdr(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1046 afs_int32 code = SYNC_OK;
1048 memcpy(res->payload.buf, &volume_hdr_LRU.stats, sizeof(volume_hdr_LRU.stats));
1049 res->hdr.response_len += sizeof(volume_hdr_LRU.stats);
1055 FSYNC_com_StatsOpVLRU(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1057 afs_int32 code = SYNC_OK;
1059 code = SYNC_BAD_COMMAND;
1063 #endif /* AFS_DEMAND_ATTACH_FS */
1066 FSYNC_com_to_info(FSSYNC_VolOp_command * vcom, FSSYNC_VolOp_info * info)
1068 memcpy(&info->com, vcom->hdr, sizeof(SYNC_command_hdr));
1069 memcpy(&info->vop, vcom->vop, sizeof(FSSYNC_VolOp_hdr));
1075 struct offlineInfo *p;
1078 char tvolName[VMAXPATHLEN];
1081 p = OfflineVolumes[FindHandler(fd)];
1082 for (i = 0; i < MAXOFFLINEVOLUMES; i++) {
1083 if (p[i].volumeID) {
1088 sprintf(&tvolName[1], VFORMAT, p[i].volumeID);
1089 vp = VAttachVolumeByName_r(&error, p[i].partName, tvolName,
1106 static int AcceptHandler = -1; /* handler id for accept, if turned on */
1111 if (AcceptHandler == -1) {
1112 assert(AddHandler(AcceptSd, FSYNC_newconnection));
1113 AcceptHandler = FindHandler(AcceptSd);
1120 if (AcceptHandler != -1) {
1121 assert(RemoveHandler(AcceptSd));
1126 /* The multiple FD handling code. */
1128 static int HandlerFD[MAXHANDLERS];
1129 static int (*HandlerProc[MAXHANDLERS]) ();
1135 ObtainWriteLock(&FSYNC_handler_lock);
1136 for (i = 0; i < MAXHANDLERS; i++) {
1140 ReleaseWriteLock(&FSYNC_handler_lock);
1143 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
1145 CallHandler(struct pollfd *fds, int nfds, int mask)
1149 ObtainReadLock(&FSYNC_handler_lock);
1150 for (i = 0; i < nfds; i++) {
1151 if (fds[i].revents & mask) {
1152 handler = FindHandler_r(fds[i].fd);
1153 ReleaseReadLock(&FSYNC_handler_lock);
1154 (*HandlerProc[handler]) (fds[i].fd);
1155 ObtainReadLock(&FSYNC_handler_lock);
1158 ReleaseReadLock(&FSYNC_handler_lock);
1162 CallHandler(fd_set * fdsetp)
1165 ObtainReadLock(&FSYNC_handler_lock);
1166 for (i = 0; i < MAXHANDLERS; i++) {
1167 if (HandlerFD[i] >= 0 && FD_ISSET(HandlerFD[i], fdsetp)) {
1168 ReleaseReadLock(&FSYNC_handler_lock);
1169 (*HandlerProc[i]) (HandlerFD[i]);
1170 ObtainReadLock(&FSYNC_handler_lock);
1173 ReleaseReadLock(&FSYNC_handler_lock);
1178 AddHandler(int afd, int (*aproc) ())
1181 ObtainWriteLock(&FSYNC_handler_lock);
1182 for (i = 0; i < MAXHANDLERS; i++)
1183 if (HandlerFD[i] == -1)
1185 if (i >= MAXHANDLERS) {
1186 ReleaseWriteLock(&FSYNC_handler_lock);
1190 HandlerProc[i] = aproc;
1191 ReleaseWriteLock(&FSYNC_handler_lock);
1196 FindHandler(register int afd)
1199 ObtainReadLock(&FSYNC_handler_lock);
1200 for (i = 0; i < MAXHANDLERS; i++)
1201 if (HandlerFD[i] == afd) {
1202 ReleaseReadLock(&FSYNC_handler_lock);
1205 ReleaseReadLock(&FSYNC_handler_lock); /* just in case */
1207 return -1; /* satisfy compiler */
1211 FindHandler_r(register int afd)
1214 for (i = 0; i < MAXHANDLERS; i++)
1215 if (HandlerFD[i] == afd) {
1219 return -1; /* satisfy compiler */
1223 RemoveHandler(register int afd)
1225 ObtainWriteLock(&FSYNC_handler_lock);
1226 HandlerFD[FindHandler_r(afd)] = -1;
1227 ReleaseWriteLock(&FSYNC_handler_lock);
1231 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
1233 GetHandler(struct pollfd *fds, int maxfds, int events, int *nfds)
1237 ObtainReadLock(&FSYNC_handler_lock);
1238 for (i = 0; i < MAXHANDLERS; i++)
1239 if (HandlerFD[i] != -1) {
1241 fds[fdi].fd = HandlerFD[i];
1242 fds[fdi].events = events;
1243 fds[fdi].revents = 0;
1250 GetHandler(fd_set * fdsetp, int *maxfdp)
1253 register int maxfd = -1;
1255 ObtainReadLock(&FSYNC_handler_lock); /* just in case */
1256 for (i = 0; i < MAXHANDLERS; i++)
1257 if (HandlerFD[i] != -1) {
1258 FD_SET(HandlerFD[i], fdsetp);
1259 if (maxfd < HandlerFD[i])
1260 maxfd = HandlerFD[i];
1263 ReleaseReadLock(&FSYNC_handler_lock); /* just in case */
1265 #endif /* HAVE_POLL && AFS_PTHREAD_ENV */
1267 #endif /* FSSYNC_BUILD_SERVER */