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, ...);
107 int (*V_BreakVolumeCallbacks) ();
109 #define MAXHANDLERS 4 /* Up to 4 clients; must be at least 2, so that
110 * move = dump+restore can run on single server */
111 #define MAXOFFLINEVOLUMES 128 /* This needs to be as big as the maximum
112 * number that would be offline for 1 operation.
113 * Current winner is salvage, which needs all
114 * cloned read-only copies offline when salvaging
115 * a single read-write volume */
119 static struct offlineInfo OfflineVolumes[MAXHANDLERS][MAXOFFLINEVOLUMES];
122 * fssync server socket handle.
124 static SYNC_server_state_t fssync_server_state =
125 { -1, /* file descriptor */
126 FSSYNC_ENDPOINT_DECL, /* server endpoint */
127 FSYNC_PROTO_VERSION, /* protocol version */
128 5, /* bind() retry limit */
129 100, /* listen() queue depth */
130 "FSSYNC", /* protocol name string */
134 /* Forward declarations */
135 static void * FSYNC_sync(void *);
136 static void FSYNC_newconnection();
137 static void FSYNC_com();
138 static void FSYNC_Drop();
139 static void AcceptOn();
140 static void AcceptOff();
141 static void InitHandler();
142 static int AddHandler();
143 static int FindHandler();
144 static int FindHandler_r();
145 static int RemoveHandler();
146 #if defined(HAVE_POLL) && defined (AFS_PTHREAD_ENV)
147 static void CallHandler(struct pollfd *fds, int nfds, int mask);
148 static void GetHandler(struct pollfd *fds, int maxfds, int events, int *nfds);
150 static void CallHandler(fd_set * fdsetp);
151 static void GetHandler(fd_set * fdsetp, int *maxfdp);
155 static afs_int32 FSYNC_com_VolOp(int fd, SYNC_command * com, SYNC_response * res);
157 static afs_int32 FSYNC_com_VolError(FSSYNC_VolOp_command * com, SYNC_response * res);
158 static afs_int32 FSYNC_com_VolOn(FSSYNC_VolOp_command * com, SYNC_response * res);
159 static afs_int32 FSYNC_com_VolOff(FSSYNC_VolOp_command * com, SYNC_response * res);
160 static afs_int32 FSYNC_com_VolMove(FSSYNC_VolOp_command * com, SYNC_response * res);
161 static afs_int32 FSYNC_com_VolBreakCBKs(FSSYNC_VolOp_command * com, SYNC_response * res);
162 static afs_int32 FSYNC_com_VolDone(FSSYNC_VolOp_command * com, SYNC_response * res);
163 static afs_int32 FSYNC_com_VolQuery(FSSYNC_VolOp_command * com, SYNC_response * res);
164 static afs_int32 FSYNC_com_VolHdrQuery(FSSYNC_VolOp_command * com, SYNC_response * res);
165 #ifdef AFS_DEMAND_ATTACH_FS
166 static afs_int32 FSYNC_com_VolOpQuery(FSSYNC_VolOp_command * com, SYNC_response * res);
167 #endif /* AFS_DEMAND_ATTACH_FS */
169 static afs_int32 FSYNC_com_VnQry(int fd, SYNC_command * com, SYNC_response * res);
171 static afs_int32 FSYNC_com_StatsOp(int fd, SYNC_command * com, SYNC_response * res);
173 static afs_int32 FSYNC_com_StatsOpGeneral(FSSYNC_StatsOp_command * scom, SYNC_response * res);
174 static afs_int32 FSYNC_com_StatsOpViceP(FSSYNC_StatsOp_command * scom, SYNC_response * res);
175 static afs_int32 FSYNC_com_StatsOpHash(FSSYNC_StatsOp_command * scom, SYNC_response * res);
176 static afs_int32 FSYNC_com_StatsOpHdr(FSSYNC_StatsOp_command * scom, SYNC_response * res);
177 static afs_int32 FSYNC_com_StatsOpVLRU(FSSYNC_StatsOp_command * scom, SYNC_response * res);
180 static void FSYNC_com_to_info(FSSYNC_VolOp_command * vcom, FSSYNC_VolOp_info * info);
184 * This lock controls access to the handler array. The overhead
185 * is minimal in non-preemptive environments.
187 struct Lock FSYNC_handler_lock;
192 #ifdef AFS_PTHREAD_ENV
194 pthread_attr_t tattr;
195 #else /* AFS_PTHREAD_ENV */
197 #endif /* AFS_PTHREAD_ENV */
199 Lock_Init(&FSYNC_handler_lock);
201 #ifdef AFS_PTHREAD_ENV
202 assert(pthread_attr_init(&tattr) == 0);
203 assert(pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED) == 0);
204 assert(pthread_create(&tid, &tattr, FSYNC_sync, NULL) == 0);
205 #else /* AFS_PTHREAD_ENV */
206 assert(LWP_CreateProcess
207 (FSYNC_sync, USUAL_STACK_SIZE, USUAL_PRIORITY, (void *)0,
208 "FSYNC_sync", &pid) == LWP_SUCCESS);
209 #endif /* AFS_PTHREAD_ENV */
212 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
213 static struct pollfd FSYNC_readfds[MAXHANDLERS];
215 static fd_set FSYNC_readfds;
220 FSYNC_sync(void * args)
222 #ifdef USE_UNIX_SOCKETS
223 char tbuffer[AFSDIR_PATH_MAX];
224 #endif /* USE_UNIX_SOCKETS */
229 #ifdef AFS_PTHREAD_ENV
232 SYNC_server_state_t * state = &fssync_server_state;
234 SYNC_getAddr(&state->endpoint, &state->addr);
235 SYNC_cleanupSock(state);
238 (void)signal(SIGPIPE, SIG_IGN);
241 #ifdef AFS_PTHREAD_ENV
242 /* set our 'thread-id' so that the host hold table works */
243 MUTEX_ENTER(&rx_stats_mutex); /* protects rxi_pthread_hinum */
244 tid = ++rxi_pthread_hinum;
245 MUTEX_EXIT(&rx_stats_mutex);
246 pthread_setspecific(rx_thread_id_key, (void *)tid);
247 Log("Set thread id %d for FSYNC_sync\n", tid);
248 #endif /* AFS_PTHREAD_ENV */
251 /* Let somebody else run until level > 0. That doesn't mean that
252 * all volumes have been attached. */
253 #ifdef AFS_PTHREAD_ENV
255 #else /* AFS_PTHREAD_ENV */
256 LWP_DispatchProcess();
257 #endif /* AFS_PTHREAD_ENV */
260 state->fd = SYNC_getSock(&state->endpoint);
261 code = SYNC_bindSock(state);
268 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
270 GetHandler(FSYNC_readfds, MAXHANDLERS, POLLIN|POLLPRI, &nfds);
271 if (poll(FSYNC_readfds, nfds, -1) >=1)
272 CallHandler(FSYNC_readfds, nfds, POLLIN|POLLPRI);
275 GetHandler(&FSYNC_readfds, &maxfd);
276 /* Note: check for >= 1 below is essential since IOMGR_select
277 * doesn't have exactly same semantics as select.
279 #ifdef AFS_PTHREAD_ENV
280 if (select(maxfd + 1, &FSYNC_readfds, NULL, NULL, NULL) >= 1)
281 #else /* AFS_PTHREAD_ENV */
282 if (IOMGR_Select(maxfd + 1, &FSYNC_readfds, NULL, NULL, NULL) >= 1)
283 #endif /* AFS_PTHREAD_ENV */
284 CallHandler(&FSYNC_readfds);
290 FSYNC_newconnection(int afd)
292 #ifdef USE_UNIX_SOCKETS
293 struct sockaddr_un other;
294 #else /* USE_UNIX_SOCKETS */
295 struct sockaddr_in other;
298 junk = sizeof(other);
299 fd = accept(afd, (struct sockaddr *)&other, &junk);
301 Log("FSYNC_newconnection: accept failed, errno==%d\n", errno);
303 } else if (!AddHandler(fd, FSYNC_com)) {
305 assert(AddHandler(fd, FSYNC_com));
309 /* this function processes commands from an fssync file descriptor (fd) */
310 afs_int32 FS_cnt = 0;
316 SYNC_PROTO_BUF_DECL(com_buf);
317 SYNC_PROTO_BUF_DECL(res_buf);
319 memset(&res.hdr, 0, sizeof(res.hdr));
321 com.payload.buf = (void *)com_buf;
322 com.payload.len = SYNC_PROTO_MAX_LEN;
323 res.hdr.response_len = sizeof(res.hdr);
324 res.hdr.proto_version = FSYNC_PROTO_VERSION;
325 res.payload.len = SYNC_PROTO_MAX_LEN;
326 res.payload.buf = (void *)res_buf;
329 if (SYNC_getCom(fd, &com)) {
330 Log("FSYNC_com: read failed; dropping connection (cnt=%d)\n", FS_cnt);
335 if (com.recv_len < sizeof(com.hdr)) {
336 Log("FSSYNC_com: invalid protocol message length (%u)\n", com.recv_len);
337 res.hdr.response = SYNC_COM_ERROR;
338 res.hdr.reason = SYNC_REASON_MALFORMED_PACKET;
339 res.hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
343 if (com.hdr.proto_version != FSYNC_PROTO_VERSION) {
344 Log("FSYNC_com: invalid protocol version (%u)\n", com.hdr.proto_version);
345 res.hdr.response = SYNC_COM_ERROR;
346 res.hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
350 if (com.hdr.command == SYNC_COM_CHANNEL_CLOSE) {
351 res.hdr.response = SYNC_OK;
352 res.hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
358 switch (com.hdr.command) {
360 case FSYNC_VOL_ATTACH:
361 case FSYNC_VOL_LEAVE_OFF:
363 case FSYNC_VOL_FORCE_ERROR:
364 case FSYNC_VOL_LISTVOLUMES:
365 case FSYNC_VOL_NEEDVOLUME:
367 case FSYNC_VOL_BREAKCBKS:
369 case FSYNC_VOL_QUERY:
370 case FSYNC_VOL_QUERY_HDR:
371 case FSYNC_VOL_QUERY_VOP:
372 res.hdr.response = FSYNC_com_VolOp(fd, &com, &res);
374 case FSYNC_VOL_STATS_GENERAL:
375 case FSYNC_VOL_STATS_VICEP:
376 case FSYNC_VOL_STATS_HASH:
377 case FSYNC_VOL_STATS_HDR:
378 case FSYNC_VOL_STATS_VLRU:
379 res.hdr.response = FSYNC_com_StatsOp(fd, &com, &res);
381 case FSYNC_VOL_QUERY_VNODE:
382 res.hdr.response = FSYNC_com_VnQry(fd, &com, &res);
385 res.hdr.response = SYNC_BAD_COMMAND;
391 SYNC_putRes(fd, &res);
392 if (res.hdr.flags & SYNC_FLAG_CHANNEL_SHUTDOWN) {
398 FSYNC_com_VolOp(int fd, SYNC_command * com, SYNC_response * res)
401 afs_int32 code = SYNC_OK;
402 FSSYNC_VolOp_command vcom;
404 if (com->recv_len != (sizeof(com->hdr) + sizeof(FSSYNC_VolOp_hdr))) {
405 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
406 res->hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
407 return SYNC_COM_ERROR;
410 vcom.hdr = &com->hdr;
411 vcom.vop = (FSSYNC_VolOp_hdr *) com->payload.buf;
414 vcom.volumes = OfflineVolumes[FindHandler(fd)];
415 for (vcom.v = NULL, i = 0; i < MAXOFFLINEVOLUMES; i++) {
416 if ((vcom.volumes[i].volumeID == vcom.vop->volume) &&
417 (strncmp(vcom.volumes[i].partName, vcom.vop->partName,
418 sizeof(vcom.volumes[i].partName)) == 0)) {
419 vcom.v = &vcom.volumes[i];
424 switch (com->hdr.command) {
426 case FSYNC_VOL_ATTACH:
427 case FSYNC_VOL_LEAVE_OFF:
428 code = FSYNC_com_VolOn(&vcom, res);
431 case FSYNC_VOL_NEEDVOLUME:
432 code = FSYNC_com_VolOff(&vcom, res);
434 case FSYNC_VOL_LISTVOLUMES:
438 code = FSYNC_com_VolMove(&vcom, res);
440 case FSYNC_VOL_BREAKCBKS:
441 code = FSYNC_com_VolBreakCBKs(&vcom, res);
444 code = FSYNC_com_VolDone(&vcom, res);
446 case FSYNC_VOL_QUERY:
447 code = FSYNC_com_VolQuery(&vcom, res);
449 case FSYNC_VOL_QUERY_HDR:
450 code = FSYNC_com_VolHdrQuery(&vcom, res);
452 #ifdef AFS_DEMAND_ATTACH_FS
453 case FSYNC_VOL_FORCE_ERROR:
454 code = FSYNC_com_VolError(&vcom, res);
456 case FSYNC_VOL_QUERY_VOP:
457 code = FSYNC_com_VolOpQuery(&vcom, res);
459 #endif /* AFS_DEMAND_ATTACH_FS */
461 code = SYNC_BAD_COMMAND;
468 FSYNC_com_VolOn(FSSYNC_VolOp_command * vcom, SYNC_response * res)
470 afs_int32 code = SYNC_OK;
471 char tvolName[VMAXPATHLEN];
475 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
476 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
482 This is where a detatched volume gets reattached. However in the
483 special case where the volume is merely busy, it is already
484 attatched and it is only necessary to clear the busy flag. See
485 defect #2080 for details.
488 /* is the volume already attatched? */
491 * XXX With the following enabled we had bizarre problems where the backup id would
492 * be reset to 0; that was due to the interaction between fileserver/volserver in that they
493 * both keep volumes in memory and the changes wouldn't be made to the fileserver. Some of
494 * the problems were due to refcnt changes as result of VGetVolume/VPutVolume which would call
495 * VOffline, etc. when we don't want to; someday the whole #2080 issue should be revisited to
498 vp = VGetVolume_r(&error, vcom->vop->volume);
500 /* yep, is the BUSY flag set? */
501 if (vp->specialStatus == VBUSY) {
503 /* yep, clear BUSY flag */
505 vp->specialStatus = 0;
506 /* make sure vol is online */
508 vcom->v->volumeID = 0;
509 V_inUse(vp) = 1; /* online */
518 /* so, we need to attach the volume */
520 #ifdef AFS_DEMAND_ATTACH_FS
521 /* check DAFS permissions */
522 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
523 if (vp && !strcmp(VPartitionPath(V_partition(vp)), vcom->vop->partName) &&
524 vp->pending_vol_op &&
525 (vcom->hdr->programType != vp->pending_vol_op->com.programType)) {
526 /* a different program has this volume checked out. deny. */
527 Log("FSYNC_VolOn: WARNING: program type %u has attempted to manipulate "
528 "state for volume %u using command code %u while the volume is "
529 "checked out by program type %u for command code %u.\n",
530 vcom->hdr->programType,
533 vp->pending_vol_op->com.programType,
534 vp->pending_vol_op->com.command);
536 res->hdr.reason = FSYNC_EXCLUSIVE;
542 vcom->v->volumeID = 0;
545 if (vcom->hdr->command == FSYNC_VOL_LEAVE_OFF) {
546 /* nothing much to do if we're leaving the volume offline */
547 #ifdef AFS_DEMAND_ATTACH_FS
549 !strcmp(VPartitionPath(V_partition(vp)), vcom->vop->partName)) {
550 VDeregisterVolOp_r(vp);
551 VChangeState_r(vp, VOL_STATE_UNATTACHED);
557 #ifdef AFS_DEMAND_ATTACH_FS
558 /* first, check to see whether we have such a volume defined */
559 vp = VPreAttachVolumeById_r(&error,
563 VDeregisterVolOp_r(vp);
565 #else /* !AFS_DEMAND_ATTACH_FS */
567 snprintf(&tvolName[1], sizeof(tvolName)-1, VFORMAT, vcom->vop->volume);
568 tvolName[sizeof(tvolName)-1] = '\0';
570 vp = VAttachVolumeByName_r(&error, vcom->vop->partName, tvolName,
576 res->hdr.reason = error;
578 #endif /* !AFS_DEMAND_ATTACH_FS */
585 FSYNC_com_VolOff(FSSYNC_VolOp_command * vcom, SYNC_response * res)
587 FSSYNC_VolOp_info info;
588 afs_int32 code = SYNC_OK;
593 if (SYNC_verifyProtocolString(vcom->vop->partName, sizeof(vcom->vop->partName))) {
594 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
599 /* not already offline, we need to find a slot for newly offline volume */
600 if (vcom->hdr->programType == debugUtility) {
601 /* debug utilities do not have their operations tracked */
605 for (i = 0; i < MAXOFFLINEVOLUMES; i++) {
606 if (vcom->volumes[i].volumeID == 0) {
607 vcom->v = &vcom->volumes[i];
617 FSYNC_com_to_info(vcom, &info);
619 #ifdef AFS_DEMAND_ATTACH_FS
620 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
622 vp = VGetVolume_r(&error, vcom->vop->volume);
626 if ((vcom->vop->partName[0] != 0) &&
627 (strncmp(vcom->vop->partName, vp->partition->name,
628 sizeof(vcom->vop->partName)) != 0)) {
629 /* volume on desired partition is not online, so we
630 * should treat this as an offline volume.
632 #ifndef AFS_DEMAND_ATTACH_FS
640 #ifdef AFS_DEMAND_ATTACH_FS
642 ProgramType type = (ProgramType) vcom->hdr->programType;
644 /* do initial filtering of requests */
646 /* enforce mutual exclusion for volume ops */
647 if (vp->pending_vol_op) {
648 if (vp->pending_vol_op->com.programType != type) {
649 Log("volume %u already checked out\n", vp->hashid);
651 Log("vp->vop = { com = { ver=%u, prog=%d, com=%d, reason=%d, len=%u, flags=0x%x }, vop = { vol=%u, part='%s' } }\n",
652 vp->pending_vol_op->com.proto_version,
653 vp->pending_vol_op->com.programType,
654 vp->pending_vol_op->com.command,
655 vp->pending_vol_op->com.reason,
656 vp->pending_vol_op->com.command_len,
657 vp->pending_vol_op->com.flags,
658 vp->pending_vol_op->vop.volume,
659 vp->pending_vol_op->vop.partName );
660 Log("vcom = { com = { ver=%u, prog=%d, com=%d, reason=%d, len=%u, flags=0x%x } , vop = { vol=%u, part='%s' } }\n",
661 vcom->hdr->proto_version,
662 vcom->hdr->programType,
665 vcom->hdr->command_len,
668 vcom->vop->partName);
669 res->hdr.reason = FSYNC_EXCLUSIVE;
672 Log("warning: volume %u recursively checked out by programType id %d\n",
673 vp->hashid, vcom->hdr->programType);
677 /* filter based upon requestor
679 * volume utilities are not allowed to check out volumes
680 * which are in an error state
682 * unknown utility programs will be denied on principal
687 /* give the salvageserver lots of liberty */
690 if ((V_attachState(vp) == VOL_STATE_ERROR) ||
691 (V_attachState(vp) == VOL_STATE_SALVAGING)) {
696 Log("bad program type passed to FSSYNC\n");
700 /* short circuit for offline volume states
701 * so we can avoid I/O penalty of attachment */
702 switch (V_attachState(vp)) {
703 case VOL_STATE_UNATTACHED:
704 case VOL_STATE_PREATTACHED:
705 case VOL_STATE_SALVAGING:
706 case VOL_STATE_ERROR:
707 /* register the volume operation metadata with the volume
709 * if the volume is currently pre-attached, attach2()
710 * will evaluate the vol op metadata to determine whether
711 * attaching the volume would be safe */
712 VRegisterVolOp_r(vp, &info);
718 /* convert to heavyweight ref */
719 nvp = VGetVolumeByVp_r(&error, vp);
721 /* register the volume operation metadata with the volume */
722 VRegisterVolOp_r(vp, &info);
725 Log("FSYNC_com_VolOff: failed to get heavyweight reference to volume %u\n",
727 res->hdr.reason = FSYNC_VOL_PKG_ERROR;
732 #endif /* AFS_DEMAND_ATTACH_FS */
735 if (VVolOpLeaveOnline_r(vp, &info)) {
736 VUpdateVolume_r(&error, vp, VOL_UPDATE_WAIT); /* At least get volume stats right */
738 Log("FSYNC: Volume %u (%s) was left on line for an external %s request\n",
739 V_id(vp), V_name(vp),
740 vcom->hdr->reason == V_CLONE ? "clone" :
741 vcom->hdr->reason == V_READONLY ? "readonly" :
742 vcom->hdr->reason == V_DUMP ? "dump" :
747 if (VVolOpSetVBusy_r(vp, &info)) {
748 vp->specialStatus = VBUSY;
751 /* remember what volume we got, so we can keep track of how
752 * many volumes the volserver or whatever is using. Note that
753 * vp is valid since leaveonline is only set when vp is valid.
756 vcom->v->volumeID = vcom->vop->volume;
757 strlcpy(vcom->v->partName, vp->partition->name, sizeof(vcom->v->partName));
760 VOffline_r(vp, "A volume utility is running.");
773 FSYNC_com_VolMove(FSSYNC_VolOp_command * vcom, SYNC_response * res)
778 /* Yuch: the "reason" for the move is the site it got moved to... */
779 /* still set specialStatus so we stop sending back VBUSY.
780 * also should still break callbacks. Note that I don't know
781 * how to tell if we should break all or not, so we just do it
782 * since it doesn't matter much if we do an extra break
783 * volume callbacks on a volume move within the same server */
784 #ifdef AFS_DEMAND_ATTACH_FS
785 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
787 vp = VGetVolume_r(&error, vcom->vop->volume);
790 vp->specialStatus = VMOVED;
791 #ifndef AFS_DEMAND_ATTACH_FS
796 if (V_BreakVolumeCallbacks) {
797 Log("fssync: volume %u moved to %x; breaking all call backs\n",
798 vcom->vop->volume, vcom->hdr->reason);
800 (*V_BreakVolumeCallbacks) (vcom->vop->volume);
808 FSYNC_com_VolDone(FSSYNC_VolOp_command * vcom, SYNC_response * res)
810 #ifdef AFS_DEMAND_ATTACH_FS
815 /* don't try to put online, this call is made only after deleting
816 * a volume, in which case we want to remove the vol # from the
817 * OfflineVolumes array only */
819 vcom->v->volumeID = 0;
821 #ifdef AFS_DEMAND_ATTACH_FS
822 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
824 VChangeState_r(vp, VOL_STATE_UNATTACHED);
825 VDeregisterVolOp_r(vp);
832 #ifdef AFS_DEMAND_ATTACH_FS
834 * force a volume into the hard error state.
837 FSYNC_com_VolError(FSSYNC_VolOp_command * vcom, SYNC_response * res)
841 afs_int32 code = SYNC_DENIED;
843 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
844 if (vp && !strcmp(VPartitionPath(V_partition(vp)), vcom->vop->partName)) {
845 memset(&vp->salvage, 0, sizeof(vp->salvage));
846 VChangeState_r(vp, VOL_STATE_ERROR);
849 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
857 FSYNC_com_VolBreakCBKs(FSSYNC_VolOp_command * vcom, SYNC_response * res)
859 /* if the volume is being restored, break all callbacks on it */
860 if (V_BreakVolumeCallbacks) {
861 Log("fssync: breaking all call backs for volume %u\n",
864 (*V_BreakVolumeCallbacks) (vcom->vop->volume);
871 FSYNC_com_VolQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
873 afs_int32 code = SYNC_OK;
877 #ifdef AFS_DEMAND_ATTACH_FS
878 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
879 #else /* !AFS_DEMAND_ATTACH_FS */
880 vp = VGetVolume_r(&error, vcom->vop->volume);
881 #endif /* !AFS_DEMAND_ATTACH_FS */
884 assert(sizeof(Volume) <= res->payload.len);
885 memcpy(res->payload.buf, vp, sizeof(Volume));
886 res->hdr.response_len += sizeof(Volume);
887 #ifndef AFS_DEMAND_ATTACH_FS
891 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
898 FSYNC_com_VolHdrQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
900 afs_int32 code = SYNC_OK;
905 #ifdef AFS_DEMAND_ATTACH_FS
906 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
908 (vp->header != NULL) &&
909 (V_attachFlags(vp) & VOL_HDR_ATTACHED) &&
910 (V_attachFlags(vp) & VOL_HDR_LOADED)) {
913 #else /* !AFS_DEMAND_ATTACH_FS */
914 vp = VGetVolume_r(&error, vcom->vop->volume);
915 if (vp && vp->header) {
918 #endif /* !AFS_DEMAND_ATTACH_FS */
922 assert(sizeof(VolumeDiskData) <= res->payload.len);
923 memcpy(res->payload.buf, &V_disk(vp), sizeof(VolumeDiskData));
924 res->hdr.response_len += sizeof(VolumeDiskData);
925 #ifndef AFS_DEMAND_ATTACH_FS
930 res->hdr.reason = FSYNC_HDR_NOT_ATTACHED;
932 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
939 #ifdef AFS_DEMAND_ATTACH_FS
941 FSYNC_com_VolOpQuery(FSSYNC_VolOp_command * vcom, SYNC_response * res)
943 afs_int32 code = SYNC_OK;
947 vp = VLookupVolume_r(&error, vcom->vop->volume, NULL);
949 if (vp && vp->pending_vol_op) {
950 assert(sizeof(FSSYNC_VolOp_info) <= res->payload.len);
951 memcpy(res->payload.buf, vp->pending_vol_op, sizeof(FSSYNC_VolOp_info));
952 res->hdr.response_len += sizeof(FSSYNC_VolOp_info);
955 res->hdr.reason = FSYNC_NO_PENDING_VOL_OP;
957 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
963 #endif /* AFS_DEMAND_ATTACH_FS */
966 FSYNC_com_VnQry(int fd, SYNC_command * com, SYNC_response * res)
968 afs_int32 code = SYNC_OK;
969 FSSYNC_VnQry_hdr * qry = com->payload.buf;
974 if (com->recv_len != (sizeof(com->hdr) + sizeof(FSSYNC_VnQry_hdr))) {
975 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
976 res->hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
977 return SYNC_COM_ERROR;
980 #ifdef AFS_DEMAND_ATTACH_FS
981 vp = VLookupVolume_r(&error, qry->volume, NULL);
982 #else /* !AFS_DEMAND_ATTACH_FS */
983 vp = VGetVolume_r(&error, qry->volume);
984 #endif /* !AFS_DEMAND_ATTACH_FS */
987 res->hdr.reason = FSYNC_UNKNOWN_VOLID;
992 vnp = VLookupVnode(vp, qry->vnode);
994 res->hdr.reason = FSYNC_UNKNOWN_VNID;
999 if (Vn_class(vnp)->residentSize > res->payload.len) {
1000 res->hdr.reason = SYNC_REASON_ENCODING_ERROR;
1005 memcpy(res->payload.buf, vnp, Vn_class(vnp)->residentSize);
1006 res->hdr.response_len += Vn_class(vnp)->residentSize;
1009 #ifndef AFS_DEMAND_ATTACH_FS
1018 FSYNC_com_StatsOp(int fd, SYNC_command * com, SYNC_response * res)
1020 afs_int32 code = SYNC_OK;
1021 FSSYNC_StatsOp_command scom;
1023 if (com->recv_len != (sizeof(com->hdr) + sizeof(FSSYNC_StatsOp_hdr))) {
1024 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1025 res->hdr.flags |= SYNC_FLAG_CHANNEL_SHUTDOWN;
1026 return SYNC_COM_ERROR;
1029 scom.hdr = &com->hdr;
1030 scom.sop = (FSSYNC_StatsOp_hdr *) com->payload.buf;
1033 switch (com->hdr.command) {
1034 case FSYNC_VOL_STATS_GENERAL:
1035 code = FSYNC_com_StatsOpGeneral(&scom, res);
1037 #ifdef AFS_DEMAND_ATTACH_FS
1038 /* statistics for the following subsystems are only tracked
1039 * for demand attach fileservers */
1040 case FSYNC_VOL_STATS_VICEP:
1041 code = FSYNC_com_StatsOpViceP(&scom, res);
1043 case FSYNC_VOL_STATS_HASH:
1044 code = FSYNC_com_StatsOpHash(&scom, res);
1046 case FSYNC_VOL_STATS_HDR:
1047 code = FSYNC_com_StatsOpHdr(&scom, res);
1049 case FSYNC_VOL_STATS_VLRU:
1050 code = FSYNC_com_StatsOpVLRU(&scom, res);
1052 #endif /* AFS_DEMAND_ATTACH_FS */
1054 code = SYNC_BAD_COMMAND;
1061 FSYNC_com_StatsOpGeneral(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1063 afs_int32 code = SYNC_OK;
1065 memcpy(res->payload.buf, &VStats, sizeof(VStats));
1066 res->hdr.response_len += sizeof(VStats);
1071 #ifdef AFS_DEMAND_ATTACH_FS
1073 FSYNC_com_StatsOpViceP(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1075 afs_int32 code = SYNC_OK;
1076 struct DiskPartition64 * dp;
1077 struct DiskPartitionStats64 * stats;
1079 if (SYNC_verifyProtocolString(scom->sop->args.partName, sizeof(scom->sop->args.partName))) {
1080 res->hdr.reason = SYNC_REASON_MALFORMED_PACKET;
1085 dp = VGetPartition_r(scom->sop->args.partName, 0);
1089 stats = (struct DiskPartitionStats64 *) res->payload.buf;
1090 stats->free = dp->free;
1091 stats->totalUsable = dp->totalUsable;
1092 stats->minFree = dp->minFree;
1093 stats->f_files = dp->f_files;
1094 stats->vol_list_len = dp->vol_list.len;
1096 res->hdr.response_len += sizeof(struct DiskPartitionStats64);
1104 FSYNC_com_StatsOpHash(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1106 afs_int32 code = SYNC_OK;
1107 struct VolumeHashChainStats * stats;
1108 struct VolumeHashChainHead * head;
1110 if (scom->sop->args.hash_bucket >= VolumeHashTable.Size) {
1114 head = &VolumeHashTable.Table[scom->sop->args.hash_bucket];
1115 stats = (struct VolumeHashChainStats *) res->payload.buf;
1116 stats->table_size = VolumeHashTable.Size;
1117 stats->chain_len = head->len;
1118 stats->chain_cacheCheck = head->cacheCheck;
1119 stats->chain_busy = head->busy;
1120 AssignInt64(head->looks, &stats->chain_looks);
1121 AssignInt64(head->gets, &stats->chain_gets);
1122 AssignInt64(head->reorders, &stats->chain_reorders);
1124 res->hdr.response_len += sizeof(struct VolumeHashChainStats);
1130 FSYNC_com_StatsOpHdr(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1132 afs_int32 code = SYNC_OK;
1134 memcpy(res->payload.buf, &volume_hdr_LRU.stats, sizeof(volume_hdr_LRU.stats));
1135 res->hdr.response_len += sizeof(volume_hdr_LRU.stats);
1141 FSYNC_com_StatsOpVLRU(FSSYNC_StatsOp_command * scom, SYNC_response * res)
1143 afs_int32 code = SYNC_OK;
1145 code = SYNC_BAD_COMMAND;
1149 #endif /* AFS_DEMAND_ATTACH_FS */
1152 FSYNC_com_to_info(FSSYNC_VolOp_command * vcom, FSSYNC_VolOp_info * info)
1154 memcpy(&info->com, vcom->hdr, sizeof(SYNC_command_hdr));
1155 memcpy(&info->vop, vcom->vop, sizeof(FSSYNC_VolOp_hdr));
1161 struct offlineInfo *p;
1164 char tvolName[VMAXPATHLEN];
1167 p = OfflineVolumes[FindHandler(fd)];
1168 for (i = 0; i < MAXOFFLINEVOLUMES; i++) {
1169 if (p[i].volumeID) {
1174 sprintf(&tvolName[1], VFORMAT, p[i].volumeID);
1175 vp = VAttachVolumeByName_r(&error, p[i].partName, tvolName,
1192 static int AcceptHandler = -1; /* handler id for accept, if turned on */
1197 if (AcceptHandler == -1) {
1198 assert(AddHandler(fssync_server_state.fd, FSYNC_newconnection));
1199 AcceptHandler = FindHandler(fssync_server_state.fd);
1206 if (AcceptHandler != -1) {
1207 assert(RemoveHandler(fssync_server_state.fd));
1212 /* The multiple FD handling code. */
1214 static int HandlerFD[MAXHANDLERS];
1215 static int (*HandlerProc[MAXHANDLERS]) ();
1221 ObtainWriteLock(&FSYNC_handler_lock);
1222 for (i = 0; i < MAXHANDLERS; i++) {
1226 ReleaseWriteLock(&FSYNC_handler_lock);
1229 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
1231 CallHandler(struct pollfd *fds, int nfds, int mask)
1235 ObtainReadLock(&FSYNC_handler_lock);
1236 for (i = 0; i < nfds; i++) {
1237 if (fds[i].revents & mask) {
1238 handler = FindHandler_r(fds[i].fd);
1239 ReleaseReadLock(&FSYNC_handler_lock);
1240 (*HandlerProc[handler]) (fds[i].fd);
1241 ObtainReadLock(&FSYNC_handler_lock);
1244 ReleaseReadLock(&FSYNC_handler_lock);
1248 CallHandler(fd_set * fdsetp)
1251 ObtainReadLock(&FSYNC_handler_lock);
1252 for (i = 0; i < MAXHANDLERS; i++) {
1253 if (HandlerFD[i] >= 0 && FD_ISSET(HandlerFD[i], fdsetp)) {
1254 ReleaseReadLock(&FSYNC_handler_lock);
1255 (*HandlerProc[i]) (HandlerFD[i]);
1256 ObtainReadLock(&FSYNC_handler_lock);
1259 ReleaseReadLock(&FSYNC_handler_lock);
1264 AddHandler(int afd, int (*aproc) ())
1267 ObtainWriteLock(&FSYNC_handler_lock);
1268 for (i = 0; i < MAXHANDLERS; i++)
1269 if (HandlerFD[i] == -1)
1271 if (i >= MAXHANDLERS) {
1272 ReleaseWriteLock(&FSYNC_handler_lock);
1276 HandlerProc[i] = aproc;
1277 ReleaseWriteLock(&FSYNC_handler_lock);
1282 FindHandler(register int afd)
1285 ObtainReadLock(&FSYNC_handler_lock);
1286 for (i = 0; i < MAXHANDLERS; i++)
1287 if (HandlerFD[i] == afd) {
1288 ReleaseReadLock(&FSYNC_handler_lock);
1291 ReleaseReadLock(&FSYNC_handler_lock); /* just in case */
1293 return -1; /* satisfy compiler */
1297 FindHandler_r(register int afd)
1300 for (i = 0; i < MAXHANDLERS; i++)
1301 if (HandlerFD[i] == afd) {
1305 return -1; /* satisfy compiler */
1309 RemoveHandler(register int afd)
1311 ObtainWriteLock(&FSYNC_handler_lock);
1312 HandlerFD[FindHandler_r(afd)] = -1;
1313 ReleaseWriteLock(&FSYNC_handler_lock);
1317 #if defined(HAVE_POLL) && defined(AFS_PTHREAD_ENV)
1319 GetHandler(struct pollfd *fds, int maxfds, int events, int *nfds)
1323 ObtainReadLock(&FSYNC_handler_lock);
1324 for (i = 0; i < MAXHANDLERS; i++)
1325 if (HandlerFD[i] != -1) {
1327 fds[fdi].fd = HandlerFD[i];
1328 fds[fdi].events = events;
1329 fds[fdi].revents = 0;
1333 ReleaseReadLock(&FSYNC_handler_lock);
1337 GetHandler(fd_set * fdsetp, int *maxfdp)
1340 register int maxfd = -1;
1342 ObtainReadLock(&FSYNC_handler_lock); /* just in case */
1343 for (i = 0; i < MAXHANDLERS; i++)
1344 if (HandlerFD[i] != -1) {
1345 FD_SET(HandlerFD[i], fdsetp);
1346 if (maxfd < HandlerFD[i])
1347 maxfd = HandlerFD[i];
1350 ReleaseReadLock(&FSYNC_handler_lock); /* just in case */
1352 #endif /* HAVE_POLL && AFS_PTHREAD_ENV */
1354 #endif /* FSSYNC_BUILD_SERVER */