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
10 /* afs_fileprocs.c - Complete File Server request routines */
12 /* Information Technology Center */
13 /* Carnegie Mellon University */
17 /* Function - A set of routines to handle the various file Server */
18 /* requests; these routines are invoked by rxgen. */
20 /* ********************************************************************** */
23 * in Check_PermissionRights, certain privileges are afforded to the owner
24 * of the volume, or the owner of a file. Are these considered "use of
28 #include <afsconfig.h>
29 #include <afs/param.h>
38 #undef SHARED /* XXX */
43 #include <sys/param.h>
45 #include <netinet/in.h>
47 #include <sys/ioctl.h>
48 #include <sys/socket.h>
58 #ifndef AFS_LINUX20_ENV
60 #include <netinet/if_ether.h>
64 /* included early because of name conflict on IOPEN */
65 #include <sys/inode.h>
69 #endif /* AFS_HPUX_ENV */
73 #include <afs/assert.h>
76 #include <afs/afsint.h>
77 #include <afs/vldbint.h>
78 #include <afs/errors.h>
79 #include <afs/ihandle.h>
80 #include <afs/vnode.h>
81 #include <afs/volume.h>
83 #include <afs/ptclient.h>
84 #include <afs/prs_fs.h>
86 #include <rx/rx_globals.h>
88 #if ! defined(AFS_SGI_ENV) && ! defined(AFS_AIX32_ENV) && ! defined(AFS_NT40_ENV) && ! defined(AFS_LINUX20_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_XBSD_ENV)
91 #if !defined(AFS_NT40_ENV)
94 #if !defined(AFS_SGI_ENV) && !defined(AFS_NT40_ENV)
96 #include <sys/statfs.h>
97 #include <sys/lockf.h>
99 #if !defined(AFS_SUN5_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_XBSD_ENV)
104 #include <afs/cellconfig.h>
105 #include <afs/keys.h>
107 #include <afs/auth.h>
109 #include <afs/partition.h>
110 #include "viced_prototypes.h"
113 #include <afs/unified_afs.h>
114 #include <afs/audit.h>
115 #include <afs/afsutil.h>
118 extern void SetDirHandle(register DirHandle * dir, register Vnode * vnode);
119 extern void FidZap(DirHandle * file);
120 extern void FidZero(DirHandle * file);
122 #ifdef AFS_PTHREAD_ENV
123 pthread_mutex_t fileproc_glock_mutex;
124 #endif /* AFS_PTHREAD_ENV */
127 #define afs_stat stat64
128 #define afs_fstat fstat64
129 #define afs_open open64
130 #else /* !O_LARGEFILE */
131 #define afs_stat stat
132 #define afs_fstat fstat
133 #define afs_open open
134 #endif /* !O_LARGEFILE */
137 /* Useful local defines used by this module */
140 #define MustNOTBeDIR 1
144 #define TVS_SSTATUS 2
147 #define TVS_MKDIR 0x10
149 #define CHK_FETCH 0x10
150 #define CHK_FETCHDATA 0x10
151 #define CHK_FETCHACL 0x11
152 #define CHK_FETCHSTATUS 0x12
153 #define CHK_STOREDATA 0x00
154 #define CHK_STOREACL 0x01
155 #define CHK_STORESTATUS 0x02
157 #define OWNERREAD 0400
158 #define OWNERWRITE 0200
159 #define OWNEREXEC 0100
160 #ifdef USE_GROUP_PERMS
161 #define GROUPREAD 0040
162 #define GROUPWRITE 0020
163 #define GROUPREXEC 0010
166 /* The following errors were not defined in NT. They are given unique
167 * names here to avoid any potential collision.
169 #define FSERR_ELOOP 90
170 #define FSERR_EOPNOTSUPP 122
171 #define FSERR_ECONNREFUSED 130
173 #define NOTACTIVECALL 0
176 #define CREATE_SGUID_ADMIN_ONLY 1
178 extern struct afsconf_dir *confDir;
179 extern afs_int32 dataVersionHigh;
182 static struct AFSCallStatistics AFSCallStats;
183 #if FS_STATS_DETAILED
184 struct fs_stats_FullPerfStats afs_FullPerfStats;
185 extern int AnonymousID;
186 #endif /* FS_STATS_DETAILED */
187 #if OPENAFS_VOL_STATS
188 static const char nullString[] = "";
189 #endif /* OPENAFS_VOL_STATS */
192 afs_int32 NothingYet;
195 struct afs_FSStats afs_fsstats;
197 void ResetDebug(), SetDebug(), Terminate();
202 afs_int32 BlocksSpare = 1024; /* allow 1 MB overruns */
204 extern afs_int32 implicitAdminRights;
205 extern afs_int32 readonlyServer;
208 * Externals used by the xstat code.
210 extern int VolumeCacheSize, VolumeGets, VolumeReplacements;
211 extern int CEs, CEBlocks;
213 extern int HTs, HTBlocks;
215 afs_int32 FetchData_RXStyle(Volume * volptr, Vnode * targetptr,
216 register struct rx_call *Call, afs_sfsize_t Pos,
217 afs_sfsize_t Len, afs_int32 Int64Mode,
218 #if FS_STATS_DETAILED
219 afs_sfsize_t * a_bytesToFetchP,
220 afs_sfsize_t * a_bytesFetchedP
221 #endif /* FS_STATS_DETAILED */
224 afs_int32 StoreData_RXStyle(Volume * volptr, Vnode * targetptr,
225 struct AFSFid *Fid, struct client *client,
226 register struct rx_call *Call, afs_fsize_t Pos,
227 afs_fsize_t Length, afs_fsize_t FileLength,
229 #if FS_STATS_DETAILED
230 afs_sfsize_t * a_bytesToStoreP,
231 afs_sfsize_t * a_bytesStoredP
232 #endif /* FS_STATS_DETAILED */
235 #ifdef AFS_SGI_XFS_IOPS_ENV
236 #include <afs/xfsattrs.h>
238 GetLinkCount(Volume * avp, struct stat *astat)
240 if (!strcmp("xfs", astat->st_fstype)) {
241 return (astat->st_mode & AFS_XFS_MODE_LINK_MASK);
243 return astat->st_nlink;
246 #define GetLinkCount(V, S) (S)->st_nlink
250 SpareComp(Volume * avolp)
252 register afs_int32 temp;
256 temp = V_maxquota(avolp);
258 /* no matter; doesn't check in this case */
262 temp = (temp * PctSpare) / 100;
273 * Set the volume synchronization parameter for this volume. If it changes,
274 * the Cache Manager knows that the volume must be purged from the stat cache.
277 SetVolumeSync(register struct AFSVolSync *async, register Volume * avol)
280 /* date volume instance was created */
283 async->spare1 = avol->header->diskstuff.creationDate;
296 * Note that this function always returns a held host, so
297 * that CallPostamble can block without the host's disappearing.
298 * Call returns rx connection in passed in *tconn
301 CallPreamble(register struct rx_call *acall, int activecall,
302 struct rx_connection **tconn)
305 struct client *tclient;
308 char hoststr[16], hoststr2[16];
310 ViceLog(0, ("CallPreamble: unexpected null tconn!\n"));
313 *tconn = rx_ConnectionOf(acall);
317 tclient = h_FindClient_r(*tconn);
318 if (tclient->prfail == 1) { /* couldn't get the CPS */
320 h_ReleaseClient_r(tclient);
321 ViceLog(0, ("CallPreamble: Couldn't get CPS. Fail\n"));
325 retry_flag = 0; /* Retry once */
327 /* Take down the old connection and re-read the key file */
329 ("CallPreamble: Couldn't get CPS. Reconnect to ptserver\n"));
331 code = pr_Initialize(2, AFSDIR_SERVER_ETC_DIRPATH, 0);
334 h_ReleaseClient_r(tclient);
336 ViceLog(0, ("CallPreamble: couldn't reconnect to ptserver\n"));
340 tclient->prfail = 2; /* Means re-eval client's cps */
341 h_ReleaseClient_r(tclient);
345 thost = tclient->host;
346 tclient->LastCall = thost->LastCall = FT_ApproxTime();
347 if (activecall) /* For all but "GetTime", "GetStats", and "GetCaps" calls */
348 thost->ActiveCall = thost->LastCall;
351 if (thost->hostFlags & HOSTDELETED) {
353 ("Discarded a packet for deleted host %s:%d\n",
354 afs_inet_ntoa_r(thost->host, hoststr), ntohs(thost->port)));
355 code = VBUSY; /* raced, so retry */
356 } else if ((thost->hostFlags & VENUSDOWN)
357 || (thost->hostFlags & HFE_LATER)) {
358 if (BreakDelayedCallBacks_r(thost)) {
360 ("BreakDelayedCallbacks FAILED for host %s:%d which IS UP. Connection from %s:%d. Possible network or routing failure.\n",
361 afs_inet_ntoa_r(thost->host, hoststr), ntohs(thost->port), afs_inet_ntoa_r(rxr_HostOf(*tconn), hoststr2),
362 ntohs(rxr_PortOf(*tconn))));
363 if (MultiProbeAlternateAddress_r(thost)) {
365 ("MultiProbe failed to find new address for host %s:%d\n",
366 afs_inet_ntoa_r(thost->host, hoststr),
367 ntohs(thost->port)));
371 ("MultiProbe found new address for host %s:%d\n",
372 afs_inet_ntoa_r(thost->host, hoststr),
373 ntohs(thost->port)));
374 if (BreakDelayedCallBacks_r(thost)) {
376 ("BreakDelayedCallbacks FAILED AGAIN for host %s:%d which IS UP. Connection from %s:%d. Possible network or routing failure.\n",
377 afs_inet_ntoa_r(thost->host, hoststr), ntohs(thost->port), afs_inet_ntoa_r(rxr_HostOf(*tconn), hoststr2),
378 ntohs(rxr_PortOf(*tconn))));
387 h_ReleaseClient_r(tclient);
396 CallPostamble(register struct rx_connection *aconn, afs_int32 ret)
399 struct client *tclient;
403 tclient = h_FindClient_r(aconn);
404 thost = tclient->host;
405 if (thost->hostFlags & HERRORTRANS)
407 h_ReleaseClient_r(tclient);
410 return (translate ? sys_error_to_et(ret) : ret);
414 * Returns the volume and vnode pointers associated with file Fid; the lock
415 * type on the vnode is set to lock. Note that both volume/vnode's ref counts
416 * are incremented and they must be eventualy released.
419 CheckVnode(AFSFid * fid, Volume ** volptr, Vnode ** vptr, int lock)
423 static struct timeval restartedat = { 0, 0 };
425 if (fid->Volume == 0 || fid->Vnode == 0) /* not: || fid->Unique == 0) */
427 if ((*volptr) == 0) {
432 *volptr = VGetVolume(&errorCode, (afs_int32) fid->Volume);
437 if ((errorCode == VOFFLINE) && (VInit < 2)) {
438 /* The volume we want may not be attached yet because
439 * the volume initialization is not yet complete.
440 * We can do several things:
441 * 1. return -1, which will cause users to see
442 * "connection timed out". This is more or
443 * less the same as always, except that the servers
444 * may appear to bounce up and down while they
445 * are actually restarting.
446 * 2. return VBUSY which will cause clients to
447 * sleep and retry for 6.5 - 15 minutes, depending
448 * on what version of the CM they are running. If
449 * the file server takes longer than that interval
450 * to attach the desired volume, then the application
451 * will see an ENODEV or EIO. This approach has
452 * the advantage that volumes which have been attached
453 * are immediately available, it keeps the server's
454 * immediate backlog low, and the call is interruptible
455 * by the user. Users see "waiting for busy volume."
456 * 3. sleep here and retry. Some people like this approach
457 * because there is no danger of seeing errors. However,
458 * this approach only works with a bounded number of
459 * clients, since the pending queues will grow without
460 * stopping. It might be better to find a way to take
461 * this call and stick it back on a queue in order to
462 * recycle this thread for a different request.
463 * 4. Return a new error code, which new cache managers will
464 * know enough to interpret as "sleep and retry", without
465 * the upper bound of 6-15 minutes that is imposed by the
466 * VBUSY handling. Users will see "waiting for
467 * busy volume," so they know that something is
468 * happening. Old cache managers must be able to do
469 * something reasonable with this, for instance, mark the
470 * server down. Fortunately, any error code < 0
471 * will elicit that behavior. See #1.
472 * 5. Some combination of the above. I like doing #2 for 10
473 * minutes, followed by #4. 3.1b and 3.2 cache managers
474 * will be fine as long as the restart period is
475 * not longer than 6.5 minutes, otherwise they may
476 * return ENODEV to users. 3.3 cache managers will be
477 * fine for 10 minutes, then will return
478 * ETIMEDOUT. 3.4 cache managers will just wait
479 * until the call works or fails definitively.
480 * NB. The problem with 2,3,4,5 is that old clients won't
481 * fail over to an alternate read-only replica while this
482 * server is restarting. 3.4 clients will fail over right away.
484 if (restartedat.tv_sec == 0) {
485 /* I'm not really worried about when we restarted, I'm */
486 /* just worried about when the first VBUSY was returned. */
487 TM_GetTimeOfDay(&restartedat, 0);
490 afs_perfstats.fs_nBusies++;
493 return (busyonrst ? VBUSY : VRESTARTING);
496 TM_GetTimeOfDay(&now, 0);
497 if ((now.tv_sec - restartedat.tv_sec) < (11 * 60)) {
500 afs_perfstats.fs_nBusies++;
503 return (busyonrst ? VBUSY : VRESTARTING);
505 return (VRESTARTING);
509 /* allow read operations on busy volume */
510 else if (errorCode == VBUSY && lock == READ_LOCK) {
513 } else if (errorCode)
520 *vptr = VGetVnode(&errorCode, *volptr, fid->Vnode, lock);
523 if ((*vptr)->disk.uniquifier != fid->Unique) {
524 VPutVnode(&fileCode, *vptr);
525 assert(fileCode == 0);
527 return (VNOVNODE); /* return the right error code, at least */
533 * This routine returns the ACL associated with the targetptr. If the
534 * targetptr isn't a directory, we access its parent dir and get the ACL
535 * thru the parent; in such case the parent's vnode is returned in
539 SetAccessList(Vnode ** targetptr, Volume ** volume,
540 struct acl_accessList **ACL, int *ACLSize, Vnode ** parent,
541 AFSFid * Fid, int Lock)
543 if ((*targetptr)->disk.type == vDirectory) {
545 *ACL = VVnodeACL(*targetptr);
546 *ACLSize = VAclSize(*targetptr);
554 parentvnode = (*targetptr)->disk.parent;
555 VPutVnode(&errorCode, *targetptr);
559 *parent = VGetVnode(&errorCode, *volume, parentvnode, READ_LOCK);
562 *ACL = VVnodeACL(*parent);
563 *ACLSize = VAclSize(*parent);
564 if ((errorCode = CheckVnode(Fid, volume, targetptr, Lock)) != 0)
566 if ((*targetptr)->disk.parent != parentvnode) {
567 VPutVnode(&errorCode, *parent);
579 * Compare the directory's ACL with the user's access rights in the client
580 * connection and return the user's and everybody else's access permissions
581 * in rights and anyrights, respectively
584 GetRights(struct client *client, struct acl_accessList *ACL,
585 afs_int32 * rights, afs_int32 * anyrights)
587 extern prlist SystemAnyUserCPS;
588 afs_int32 hrights = 0;
589 #ifndef AFS_PTHREAD_ENV
593 if (acl_CheckRights(ACL, &SystemAnyUserCPS, anyrights) != 0) {
595 ViceLog(0, ("CheckRights failed\n"));
600 ObtainWriteLock(&client->lock);
601 acl_CheckRights(ACL, &client->CPS, rights);
602 ReleaseWriteLock(&client->lock);
604 /* wait if somebody else is already doing the getCPS call */
606 while (client->host->hostFlags & HCPS_INPROGRESS) {
607 client->host->hostFlags |= HCPS_WAITING; /* I am waiting */
608 #ifdef AFS_PTHREAD_ENV
609 pthread_cond_wait(&client->host->cond, &host_glock_mutex);
610 #else /* AFS_PTHREAD_ENV */
612 LWP_WaitProcess(&(client->host->hostFlags))) != LWP_SUCCESS)
613 ViceLog(0, ("LWP_WaitProcess returned %d\n", code));
614 #endif /* AFS_PTHREAD_ENV */
617 if (client->host->hcps.prlist_len && !client->host->hcps.prlist_val) {
619 ("CheckRights: len=%u, for host=0x%x\n",
620 client->host->hcps.prlist_len, client->host->host));
622 acl_CheckRights(ACL, &client->host->hcps, &hrights);
624 /* Allow system:admin the rights given with the -implicit option */
625 if (acl_IsAMember(SystemId, &client->CPS))
626 *rights |= implicitAdminRights;
628 *anyrights |= hrights;
635 * VanillaUser returns 1 (true) if the user is a vanilla user (i.e., not
636 * a System:Administrator)
639 VanillaUser(struct client *client)
641 if (acl_IsAMember(SystemId, &client->CPS))
642 return (0); /* not a system administrator, then you're "vanilla" */
649 * This unusual afs_int32-parameter routine encapsulates all volume package related
650 * operations together in a single function; it's called by almost all AFS
654 GetVolumePackage(struct rx_connection *tcon, AFSFid * Fid, Volume ** volptr,
655 Vnode ** targetptr, int chkforDir, Vnode ** parent,
656 struct client **client, int locktype, afs_int32 * rights,
657 afs_int32 * anyrights)
659 struct acl_accessList *aCL; /* Internal access List */
660 int aCLSize; /* size of the access list */
661 int errorCode = 0; /* return code to caller */
663 if ((errorCode = CheckVnode(Fid, volptr, targetptr, locktype)))
666 if (chkforDir == MustNOTBeDIR
667 && ((*targetptr)->disk.type == vDirectory))
669 else if (chkforDir == MustBeDIR
670 && ((*targetptr)->disk.type != vDirectory))
674 SetAccessList(targetptr, volptr, &aCL, &aCLSize, parent,
675 (chkforDir == MustBeDIR ? (AFSFid *) 0 : Fid),
676 (chkforDir == MustBeDIR ? 0 : locktype))) != 0)
678 if (chkforDir == MustBeDIR)
679 assert((*parent) == 0);
680 if ((errorCode = GetClient(tcon, client)) != 0)
684 assert(GetRights(*client, aCL, rights, anyrights) == 0);
685 /* ok, if this is not a dir, set the PRSFS_ADMINISTER bit iff we're the owner */
686 if ((*targetptr)->disk.type != vDirectory) {
687 /* anyuser can't be owner, so only have to worry about rights, not anyrights */
688 if ((*targetptr)->disk.owner == (*client)->ViceId)
689 (*rights) |= PRSFS_ADMINISTER;
691 (*rights) &= ~PRSFS_ADMINISTER;
693 #ifdef ADMIN_IMPLICIT_LOOKUP
694 /* admins get automatic lookup on everything */
695 if (!VanillaUser(*client))
696 (*rights) |= PRSFS_LOOKUP;
697 #endif /* ADMIN_IMPLICIT_LOOKUP */
700 } /*GetVolumePackage */
704 * This is the opposite of GetVolumePackage(), and is always used at the end of
705 * AFS calls to put back all used vnodes and the volume in the proper order!
708 PutVolumePackage(Vnode * parentwhentargetnotdir, Vnode * targetptr,
709 Vnode * parentptr, Volume * volptr)
711 int fileCode = 0; /* Error code returned by the volume package */
713 if (parentwhentargetnotdir) {
714 VPutVnode(&fileCode, parentwhentargetnotdir);
715 assert(!fileCode || (fileCode == VSALVAGE));
718 VPutVnode(&fileCode, targetptr);
719 assert(!fileCode || (fileCode == VSALVAGE));
722 VPutVnode(&fileCode, parentptr);
723 assert(!fileCode || (fileCode == VSALVAGE));
728 } /*PutVolumePackage */
731 VolumeOwner(register struct client *client, register Vnode * targetptr)
733 afs_int32 owner = V_owner(targetptr->volumePtr); /* get volume owner */
736 return (client->ViceId == owner);
739 * We don't have to check for host's cps since only regular
740 * viceid are volume owners.
742 return (acl_IsAMember(owner, &client->CPS));
748 VolumeRootVnode(Vnode * targetptr)
750 return ((targetptr->vnodeNumber == ROOTVNODE)
751 && (targetptr->disk.uniquifier == 1));
753 } /*VolumeRootVnode */
756 * Check if target file has the proper access permissions for the Fetch
757 * (FetchData, FetchACL, FetchStatus) and Store (StoreData, StoreACL,
758 * StoreStatus) related calls
760 /* this code should probably just set a "priv" flag where all the audit events
761 * are now, and only generate the audit event once at the end of the routine,
762 * thus only generating the event if all the checks succeed, but only because
763 * of the privilege XXX
766 Check_PermissionRights(Vnode * targetptr, struct client *client,
767 afs_int32 rights, int CallingRoutine,
768 AFSStoreStatus * InStatus)
771 #define OWNSp(client, target) ((client)->ViceId == (target)->disk.owner)
772 #define CHOWN(i,t) (((i)->Mask & AFS_SETOWNER) &&((i)->Owner != (t)->disk.owner))
773 #define CHGRP(i,t) (((i)->Mask & AFS_SETGROUP) &&((i)->Group != (t)->disk.group))
775 if (CallingRoutine & CHK_FETCH) {
776 if (CallingRoutine == CHK_FETCHDATA || VanillaUser(client)) {
777 if (targetptr->disk.type == vDirectory
778 || targetptr->disk.type == vSymlink) {
779 if (!(rights & PRSFS_LOOKUP)
780 #ifdef ADMIN_IMPLICIT_LOOKUP
781 /* grant admins fetch on all directories */
782 && VanillaUser(client)
783 #endif /* ADMIN_IMPLICIT_LOOKUP */
784 && !VolumeOwner(client, targetptr))
787 /* must have read access, or be owner and have insert access */
788 if (!(rights & PRSFS_READ)
789 && !(OWNSp(client, targetptr) && (rights & PRSFS_INSERT)))
792 if (CallingRoutine == CHK_FETCHDATA
793 && targetptr->disk.type == vFile)
794 #ifdef USE_GROUP_PERMS
795 if (!OWNSp(client, targetptr)
796 && !acl_IsAMember(targetptr->disk.owner, &client->CPS)) {
798 (((GROUPREAD | GROUPEXEC) & targetptr->disk.modeBits)
802 (((OWNERREAD | OWNEREXEC) & targetptr->disk.modeBits)
807 * The check with the ownership below is a kludge to allow
808 * reading of files created with no read permission. The owner
809 * of the file is always allowed to read it.
811 if ((client->ViceId != targetptr->disk.owner)
812 && VanillaUser(client))
814 (((OWNERREAD | OWNEREXEC) & targetptr->disk.
815 modeBits) ? 0 : EACCES);
817 } else { /* !VanillaUser(client) && !FetchData */
819 osi_audit(PrivilegeEvent, 0, AUD_ID,
820 (client ? client->ViceId : 0), AUD_INT, CallingRoutine,
823 } else { /* a store operation */
824 if ((rights & PRSFS_INSERT) && OWNSp(client, targetptr)
825 && (CallingRoutine != CHK_STOREACL)
826 && (targetptr->disk.type == vFile)) {
827 /* bypass protection checks on first store after a create
828 * for the creator; also prevent chowns during this time
829 * unless you are a system administrator */
830 /****** InStatus->Owner && UnixModeBits better be SET!! */
831 if (CHOWN(InStatus, targetptr) || CHGRP(InStatus, targetptr)) {
834 else if (VanillaUser(client))
835 return (EPERM); /* Was EACCES */
837 osi_audit(PrivilegeEvent, 0, AUD_ID,
838 (client ? client->ViceId : 0), AUD_INT,
839 CallingRoutine, AUD_END);
842 if (CallingRoutine != CHK_STOREDATA && !VanillaUser(client)) {
843 osi_audit(PrivilegeEvent, 0, AUD_ID,
844 (client ? client->ViceId : 0), AUD_INT,
845 CallingRoutine, AUD_END);
847 if (readonlyServer) {
850 if (CallingRoutine == CHK_STOREACL) {
851 if (!(rights & PRSFS_ADMINISTER)
852 && !VolumeOwner(client, targetptr))
854 } else { /* store data or status */
855 /* watch for chowns and chgrps */
856 if (CHOWN(InStatus, targetptr)
857 || CHGRP(InStatus, targetptr)) {
860 else if (VanillaUser(client))
861 return (EPERM); /* Was EACCES */
863 osi_audit(PrivilegeEvent, 0, AUD_ID,
864 (client ? client->ViceId : 0), AUD_INT,
865 CallingRoutine, AUD_END);
867 /* must be sysadmin to set suid/sgid bits */
868 if ((InStatus->Mask & AFS_SETMODE) &&
870 (InStatus->UnixModeBits & 0xc00) != 0) {
872 (InStatus->UnixModeBits & (S_ISUID | S_ISGID)) != 0) {
876 if (VanillaUser(client))
879 osi_audit(PrivSetID, 0, AUD_ID,
880 (client ? client->ViceId : 0), AUD_INT,
881 CallingRoutine, AUD_END);
883 if (CallingRoutine == CHK_STOREDATA) {
886 if (!(rights & PRSFS_WRITE))
888 /* Next thing is tricky. We want to prevent people
889 * from writing files sans 0200 bit, but we want
890 * creating new files with 0444 mode to work. We
891 * don't check the 0200 bit in the "you are the owner"
892 * path above, but here we check the bit. However, if
893 * you're a system administrator, we ignore the 0200
894 * bit anyway, since you may have fchowned the file,
896 #ifdef USE_GROUP_PERMS
897 if ((targetptr->disk.type == vFile)
898 && VanillaUser(client)) {
899 if (!OWNSp(client, targetptr)
900 && !acl_IsAMember(targetptr->disk.owner,
903 ((GROUPWRITE & targetptr->disk.modeBits)
907 ((OWNERWRITE & targetptr->disk.modeBits)
912 if ((targetptr->disk.type != vDirectory)
913 && (!(targetptr->disk.modeBits & OWNERWRITE))) {
916 if (VanillaUser(client))
919 osi_audit(PrivilegeEvent, 0, AUD_ID,
920 (client ? client->ViceId : 0),
921 AUD_INT, CallingRoutine, AUD_END);
923 } else { /* a status store */
926 if (targetptr->disk.type == vDirectory) {
927 if (!(rights & PRSFS_DELETE)
928 && !(rights & PRSFS_INSERT))
930 } else { /* a file or symlink */
931 if (!(rights & PRSFS_WRITE))
941 } /*Check_PermissionRights */
945 * The Access List information is converted from its internal form in the
946 * target's vnode buffer (or its parent vnode buffer if not a dir), to an
947 * external form and returned back to the caller, via the AccessList
951 RXFetch_AccessList(Vnode * targetptr, Vnode * parentwhentargetnotdir,
952 struct AFSOpaque *AccessList)
954 char *eACL; /* External access list placeholder */
957 ((targetptr->disk.type ==
958 vDirectory ? VVnodeACL(targetptr) :
959 VVnodeACL(parentwhentargetnotdir)), &eACL) != 0) {
962 if ((strlen(eACL) + 1) > AFSOPAQUEMAX) {
963 acl_FreeExternalACL(&eACL);
966 strcpy((char *)(AccessList->AFSOpaque_val), (char *)eACL);
967 AccessList->AFSOpaque_len = strlen(eACL) + 1;
969 acl_FreeExternalACL(&eACL);
972 } /*RXFetch_AccessList */
976 * The Access List information is converted from its external form in the
977 * input AccessList structure to the internal representation and copied into
978 * the target dir's vnode storage.
981 RXStore_AccessList(Vnode * targetptr, struct AFSOpaque *AccessList)
983 struct acl_accessList *newACL; /* PlaceHolder for new access list */
985 if (acl_Internalize(AccessList->AFSOpaque_val, &newACL) != 0)
987 if ((newACL->size + 4) > VAclSize(targetptr))
989 memcpy((char *)VVnodeACL(targetptr), (char *)newACL, (int)(newACL->size));
990 acl_FreeACL(&newACL);
993 } /*RXStore_AccessList */
997 Fetch_AccessList(Vnode * targetptr, Vnode * parentwhentargetnotdir,
998 struct AFSAccessList *AccessList)
1000 char *eACL; /* External access list placeholder */
1002 assert(acl_Externalize
1003 ((targetptr->disk.type ==
1004 vDirectory ? VVnodeACL(targetptr) :
1005 VVnodeACL(parentwhentargetnotdir)), &eACL) == 0);
1006 if ((strlen(eACL) + 1) > AccessList->MaxSeqLen) {
1007 acl_FreeExternalACL(&eACL);
1010 strcpy((char *)(AccessList->SeqBody), (char *)eACL);
1011 AccessList->SeqLen = strlen(eACL) + 1;
1013 acl_FreeExternalACL(&eACL);
1016 } /*Fetch_AccessList */
1019 * The Access List information is converted from its external form in the
1020 * input AccessList structure to the internal representation and copied into
1021 * the target dir's vnode storage.
1024 Store_AccessList(Vnode * targetptr, struct AFSAccessList *AccessList)
1026 struct acl_accessList *newACL; /* PlaceHolder for new access list */
1028 if (acl_Internalize(AccessList->SeqBody, &newACL) != 0)
1030 if ((newACL->size + 4) > VAclSize(targetptr))
1032 memcpy((char *)VVnodeACL(targetptr), (char *)newACL, (int)(newACL->size));
1033 acl_FreeACL(&newACL);
1036 } /*Store_AccessList */
1039 /* In our current implementation, each successive data store (new file
1040 * data version) creates a new inode. This function creates the new
1041 * inode, copies the old inode's contents to the new one, remove the old
1042 * inode (i.e. decrement inode count -- if it's currently used the delete
1043 * will be delayed), and modify some fields (i.e. vnode's
1044 * disk.inodeNumber and cloned)
1046 #define COPYBUFFSIZE 8192
1048 CopyOnWrite(Vnode * targetptr, Volume * volptr)
1050 Inode ino, nearInode;
1053 register afs_fsize_t size;
1054 register int length;
1056 int rc; /* return code */
1057 IHandle_t *newH; /* Use until finished copying, then cp to vnode. */
1058 FdHandle_t *targFdP; /* Source Inode file handle */
1059 FdHandle_t *newFdP; /* Dest Inode file handle */
1061 if (targetptr->disk.type == vDirectory)
1062 DFlush(); /* just in case? */
1064 VN_GET_LEN(size, targetptr);
1065 buff = (char *)malloc(COPYBUFFSIZE);
1070 ino = VN_GET_INO(targetptr);
1071 assert(VALID_INO(ino));
1072 targFdP = IH_OPEN(targetptr->handle);
1073 if (targFdP == NULL) {
1076 ("CopyOnWrite failed: Failed to open target vnode %u in volume %u (errno = %d)\n",
1077 targetptr->vnodeNumber, V_id(volptr), rc));
1079 VTakeOffline(volptr);
1083 nearInode = VN_GET_INO(targetptr);
1085 IH_CREATE(V_linkHandle(volptr), V_device(volptr),
1086 VPartitionPath(V_partition(volptr)), nearInode,
1087 V_id(volptr), targetptr->vnodeNumber,
1088 targetptr->disk.uniquifier,
1089 (int)targetptr->disk.dataVersion);
1090 if (!VALID_INO(ino)) {
1092 ("CopyOnWrite failed: Partition %s that contains volume %u may be out of free inodes(errno = %d)\n",
1093 volptr->partition->name, V_id(volptr), errno));
1098 IH_INIT(newH, V_device(volptr), V_id(volptr), ino);
1099 newFdP = IH_OPEN(newH);
1100 assert(newFdP != NULL);
1103 if (size > COPYBUFFSIZE) { /* more than a buffer */
1104 length = COPYBUFFSIZE;
1105 size -= COPYBUFFSIZE;
1110 rdlen = FDH_READ(targFdP, buff, length);
1111 if (rdlen == length)
1112 wrlen = FDH_WRITE(newFdP, buff, length);
1115 /* Callers of this function are not prepared to recover
1116 * from error that put the filesystem in an inconsistent
1117 * state. Make sure that we force the volume off-line if
1118 * we some error other than ENOSPC - 4.29.99)
1120 * In case we are unable to write the required bytes, and the
1121 * error code indicates that the disk is full, we roll-back to
1122 * the initial state.
1124 if ((rdlen != length) || (wrlen != length))
1125 if ((wrlen < 0) && (errno == ENOSPC)) { /* disk full */
1127 ("CopyOnWrite failed: Partition %s containing volume %u is full\n",
1128 volptr->partition->name, V_id(volptr)));
1129 /* remove destination inode which was partially copied till now */
1130 FDH_REALLYCLOSE(newFdP);
1132 FDH_REALLYCLOSE(targFdP);
1133 rc = IH_DEC(V_linkHandle(volptr), ino, V_parentId(volptr));
1136 ("CopyOnWrite failed: error %u after i_dec on disk full, volume %u in partition %s needs salvage\n",
1137 rc, V_id(volptr), volptr->partition->name));
1138 VTakeOffline(volptr);
1144 ("CopyOnWrite failed: volume %u in partition %s (tried reading %u, read %u, wrote %u, errno %u) volume needs salvage\n",
1145 V_id(volptr), volptr->partition->name, length, rdlen,
1147 #ifdef FAST_RESTART /* if running in no-salvage, don't core the server */
1148 ViceLog(0, ("CopyOnWrite failed: taking volume offline\n"));
1149 #else /* Avoid further corruption and try to get a core. */
1152 /* Decrement this inode so salvager doesn't find it. */
1153 FDH_REALLYCLOSE(newFdP);
1155 FDH_REALLYCLOSE(targFdP);
1156 rc = IH_DEC(V_linkHandle(volptr), ino, V_parentId(volptr));
1158 VTakeOffline(volptr);
1161 #ifndef AFS_PTHREAD_ENV
1163 #endif /* !AFS_PTHREAD_ENV */
1165 FDH_REALLYCLOSE(targFdP);
1166 rc = IH_DEC(V_linkHandle(volptr), VN_GET_INO(targetptr),
1167 V_parentId(volptr));
1169 IH_RELEASE(targetptr->handle);
1171 rc = FDH_SYNC(newFdP);
1174 targetptr->handle = newH;
1175 VN_SET_INO(targetptr, ino);
1176 targetptr->disk.cloned = 0;
1177 /* Internal change to vnode, no user level change to volume - def 5445 */
1178 targetptr->changed_oldTime = 1;
1180 return 0; /* success */
1185 * Common code to handle with removing the Name (file when it's called from
1186 * SAFS_RemoveFile() or an empty dir when called from SAFS_rmdir()) from a
1187 * given directory, parentptr.
1189 int DT1 = 0, DT0 = 0;
1191 DeleteTarget(Vnode * parentptr, Volume * volptr, Vnode ** targetptr,
1192 DirHandle * dir, AFSFid * fileFid, char *Name, int ChkForDir)
1194 DirHandle childdir; /* Handle for dir package I/O */
1198 /* watch for invalid names */
1199 if (!strcmp(Name, ".") || !strcmp(Name, ".."))
1201 if (parentptr->disk.cloned) {
1202 ViceLog(25, ("DeleteTarget : CopyOnWrite called\n"));
1203 if ((errorCode = CopyOnWrite(parentptr, volptr))) {
1205 ("DeleteTarget %s: CopyOnWrite failed %d\n", Name,
1211 /* check that the file is in the directory */
1212 SetDirHandle(dir, parentptr);
1213 if (Lookup(dir, Name, fileFid))
1215 fileFid->Volume = V_id(volptr);
1217 /* just-in-case check for something causing deadlock */
1218 if (fileFid->Vnode == parentptr->vnodeNumber)
1221 *targetptr = VGetVnode(&errorCode, volptr, fileFid->Vnode, WRITE_LOCK);
1225 if (ChkForDir == MustBeDIR) {
1226 if ((*targetptr)->disk.type != vDirectory)
1228 } else if ((*targetptr)->disk.type == vDirectory)
1231 /*assert((*targetptr)->disk.uniquifier == fileFid->Unique); */
1233 * If the uniquifiers dont match then instead of asserting
1234 * take the volume offline and return VSALVAGE
1236 if ((*targetptr)->disk.uniquifier != fileFid->Unique) {
1237 VTakeOffline(volptr);
1238 errorCode = VSALVAGE;
1242 if (ChkForDir == MustBeDIR) {
1243 SetDirHandle(&childdir, *targetptr);
1244 if (IsEmpty(&childdir) != 0)
1247 (*targetptr)->delete = 1;
1248 } else if ((--(*targetptr)->disk.linkCount) == 0)
1249 (*targetptr)->delete = 1;
1250 if ((*targetptr)->delete) {
1251 if (VN_GET_INO(*targetptr)) {
1253 IH_REALLYCLOSE((*targetptr)->handle);
1255 IH_DEC(V_linkHandle(volptr), VN_GET_INO(*targetptr),
1256 V_parentId(volptr));
1257 IH_RELEASE((*targetptr)->handle);
1258 if (errorCode == -1) {
1260 ("DT: inode=%s, name=%s, errno=%d\n",
1261 PrintInode(NULL, VN_GET_INO(*targetptr)), Name,
1263 if (errno != ENOENT)
1266 ("Volume %u now offline, must be salvaged.\n",
1268 VTakeOffline(volptr);
1275 VN_SET_INO(*targetptr, (Inode) 0);
1277 afs_fsize_t adjLength;
1278 VN_GET_LEN(adjLength, *targetptr);
1279 VAdjustDiskUsage(&errorCode, volptr, -(int)nBlocks(adjLength), 0);
1283 (*targetptr)->changed_newTime = 1; /* Status change of deleted file/dir */
1285 code = Delete(dir, (char *)Name);
1288 ("Error %d deleting %s\n", code,
1289 (((*targetptr)->disk.type ==
1290 Directory) ? "directory" : "file")));
1292 ("Volume %u now offline, must be salvaged.\n",
1294 VTakeOffline(volptr);
1306 * This routine updates the parent directory's status block after the
1307 * specified operation (i.e. RemoveFile(), CreateFile(), Rename(),
1308 * SymLink(), Link(), MakeDir(), RemoveDir()) on one of its children has
1312 Update_ParentVnodeStatus(Vnode * parentptr, Volume * volptr, DirHandle * dir,
1313 int author, int linkcount,
1314 #if FS_STATS_DETAILED
1315 char a_inSameNetwork
1316 #endif /* FS_STATS_DETAILED */
1319 afs_fsize_t newlength; /* Holds new directory length */
1320 afs_fsize_t parentLength;
1322 #if FS_STATS_DETAILED
1323 Date currDate; /*Current date */
1324 int writeIdx; /*Write index to bump */
1325 int timeIdx; /*Authorship time index to bump */
1326 #endif /* FS_STATS_DETAILED */
1328 parentptr->disk.dataVersion++;
1329 newlength = (afs_fsize_t) Length(dir);
1331 * This is a called on both dir removals (i.e. remove, removedir, rename) but also in dir additions
1332 * (create, symlink, link, makedir) so we need to check if we have enough space
1333 * XXX But we still don't check the error since we're dealing with dirs here and really the increase
1334 * of a new entry would be too tiny to worry about failures (since we have all the existing cushion)
1336 VN_GET_LEN(parentLength, parentptr);
1337 if (nBlocks(newlength) != nBlocks(parentLength)) {
1338 VAdjustDiskUsage(&errorCode, volptr,
1339 (nBlocks(newlength) - nBlocks(parentLength)),
1340 (nBlocks(newlength) - nBlocks(parentLength)));
1342 VN_SET_LEN(parentptr, newlength);
1344 #if FS_STATS_DETAILED
1346 * Update directory write stats for this volume. Note that the auth
1347 * counter is located immediately after its associated ``distance''
1350 if (a_inSameNetwork)
1351 writeIdx = VOL_STATS_SAME_NET;
1353 writeIdx = VOL_STATS_DIFF_NET;
1354 V_stat_writes(volptr, writeIdx)++;
1355 if (author != AnonymousID) {
1356 V_stat_writes(volptr, writeIdx + 1)++;
1360 * Update the volume's authorship information in response to this
1361 * directory operation. Get the current time, decide to which time
1362 * slot this operation belongs, and bump the appropriate slot.
1364 currDate = (FT_ApproxTime() - parentptr->disk.unixModifyTime);
1366 (currDate < VOL_STATS_TIME_CAP_0 ? VOL_STATS_TIME_IDX_0 : currDate <
1367 VOL_STATS_TIME_CAP_1 ? VOL_STATS_TIME_IDX_1 : currDate <
1368 VOL_STATS_TIME_CAP_2 ? VOL_STATS_TIME_IDX_2 : currDate <
1369 VOL_STATS_TIME_CAP_3 ? VOL_STATS_TIME_IDX_3 : currDate <
1370 VOL_STATS_TIME_CAP_4 ? VOL_STATS_TIME_IDX_4 : VOL_STATS_TIME_IDX_5);
1371 if (parentptr->disk.author == author) {
1372 V_stat_dirSameAuthor(volptr, timeIdx)++;
1374 V_stat_dirDiffAuthor(volptr, timeIdx)++;
1376 #endif /* FS_STATS_DETAILED */
1378 parentptr->disk.author = author;
1379 parentptr->disk.linkCount = linkcount;
1380 parentptr->disk.unixModifyTime = FT_ApproxTime(); /* This should be set from CLIENT!! */
1381 parentptr->disk.serverModifyTime = FT_ApproxTime();
1382 parentptr->changed_newTime = 1; /* vnode changed, write it back. */
1387 * Update the target file's (or dir's) status block after the specified
1388 * operation is complete. Note that some other fields maybe updated by
1389 * the individual module.
1392 /* XXX INCOMPLETE - More attention is needed here! */
1394 Update_TargetVnodeStatus(Vnode * targetptr, afs_uint32 Caller,
1395 struct client *client, AFSStoreStatus * InStatus,
1396 Vnode * parentptr, Volume * volptr,
1399 #if FS_STATS_DETAILED
1400 Date currDate; /*Current date */
1401 int writeIdx; /*Write index to bump */
1402 int timeIdx; /*Authorship time index to bump */
1403 #endif /* FS_STATS_DETAILED */
1405 if (Caller & (TVS_CFILE | TVS_SLINK | TVS_MKDIR)) { /* initialize new file */
1406 targetptr->disk.parent = parentptr->vnodeNumber;
1407 VN_SET_LEN(targetptr, length);
1408 /* targetptr->disk.group = 0; save some cycles */
1409 targetptr->disk.modeBits = 0777;
1410 targetptr->disk.owner = client->ViceId;
1411 targetptr->disk.dataVersion = 0; /* consistent with the client */
1412 targetptr->disk.linkCount = (Caller & TVS_MKDIR ? 2 : 1);
1413 /* the inode was created in Alloc_NewVnode() */
1415 #if FS_STATS_DETAILED
1417 * Update file write stats for this volume. Note that the auth
1418 * counter is located immediately after its associated ``distance''
1421 if (client->InSameNetwork)
1422 writeIdx = VOL_STATS_SAME_NET;
1424 writeIdx = VOL_STATS_DIFF_NET;
1425 V_stat_writes(volptr, writeIdx)++;
1426 if (client->ViceId != AnonymousID) {
1427 V_stat_writes(volptr, writeIdx + 1)++;
1431 * We only count operations that DON'T involve creating new objects
1432 * (files, symlinks, directories) or simply setting status as
1433 * authorship-change operations.
1435 if (!(Caller & (TVS_CFILE | TVS_SLINK | TVS_MKDIR | TVS_SSTATUS))) {
1437 * Update the volume's authorship information in response to this
1438 * file operation. Get the current time, decide to which time
1439 * slot this operation belongs, and bump the appropriate slot.
1441 currDate = (FT_ApproxTime() - targetptr->disk.unixModifyTime);
1444 VOL_STATS_TIME_CAP_0 ? VOL_STATS_TIME_IDX_0 : currDate <
1445 VOL_STATS_TIME_CAP_1 ? VOL_STATS_TIME_IDX_1 : currDate <
1446 VOL_STATS_TIME_CAP_2 ? VOL_STATS_TIME_IDX_2 : currDate <
1447 VOL_STATS_TIME_CAP_3 ? VOL_STATS_TIME_IDX_3 : currDate <
1448 VOL_STATS_TIME_CAP_4 ? VOL_STATS_TIME_IDX_4 :
1449 VOL_STATS_TIME_IDX_5);
1450 if (targetptr->disk.author == client->ViceId) {
1451 V_stat_fileSameAuthor(volptr, timeIdx)++;
1453 V_stat_fileDiffAuthor(volptr, timeIdx)++;
1456 #endif /* FS_STATS_DETAILED */
1458 if (!(Caller & TVS_SSTATUS))
1459 targetptr->disk.author = client->ViceId;
1460 if (Caller & TVS_SDATA) {
1461 targetptr->disk.dataVersion++;
1462 if (VanillaUser(client)) {
1463 targetptr->disk.modeBits &= ~04000; /* turn off suid for file. */
1464 #ifdef CREATE_SGUID_ADMIN_ONLY
1465 targetptr->disk.modeBits &= ~02000; /* turn off sgid for file. */
1469 if (Caller & TVS_SSTATUS) { /* update time on non-status change */
1470 /* store status, must explicitly request to change the date */
1471 if (InStatus->Mask & AFS_SETMODTIME)
1472 targetptr->disk.unixModifyTime = InStatus->ClientModTime;
1473 } else { /* other: date always changes, but perhaps to what is specified by caller */
1474 targetptr->disk.unixModifyTime =
1475 (InStatus->Mask & AFS_SETMODTIME ? InStatus->
1476 ClientModTime : FT_ApproxTime());
1478 if (InStatus->Mask & AFS_SETOWNER) {
1479 /* admin is allowed to do chmod, chown as well as chown, chmod. */
1480 if (VanillaUser(client)) {
1481 targetptr->disk.modeBits &= ~04000; /* turn off suid for file. */
1482 #ifdef CREATE_SGUID_ADMIN_ONLY
1483 targetptr->disk.modeBits &= ~02000; /* turn off sgid for file. */
1486 targetptr->disk.owner = InStatus->Owner;
1487 if (VolumeRootVnode(targetptr)) {
1488 Error errorCode = 0; /* what should be done with this? */
1490 V_owner(targetptr->volumePtr) = InStatus->Owner;
1491 VUpdateVolume(&errorCode, targetptr->volumePtr);
1494 if (InStatus->Mask & AFS_SETMODE) {
1495 int modebits = InStatus->UnixModeBits;
1496 #define CREATE_SGUID_ADMIN_ONLY 1
1497 #ifdef CREATE_SGUID_ADMIN_ONLY
1498 if (VanillaUser(client))
1499 modebits = modebits & 0777;
1501 if (VanillaUser(client)) {
1502 targetptr->disk.modeBits = modebits;
1504 targetptr->disk.modeBits = modebits;
1507 osi_audit(PrivSetID, 0, AUD_ID, client->ViceId, AUD_INT,
1508 CHK_STOREDATA, AUD_END);
1512 osi_audit(PrivSetID, 0, AUD_ID, client->ViceId, AUD_INT,
1513 CHK_STORESTATUS, AUD_END);
1520 targetptr->disk.serverModifyTime = FT_ApproxTime();
1521 if (InStatus->Mask & AFS_SETGROUP)
1522 targetptr->disk.group = InStatus->Group;
1523 /* vnode changed : to be written back by VPutVnode */
1524 targetptr->changed_newTime = 1;
1526 } /*Update_TargetVnodeStatus */
1530 * Fills the CallBack structure with the expiration time and type of callback
1531 * structure. Warning: this function is currently incomplete.
1534 SetCallBackStruct(afs_uint32 CallBackTime, struct AFSCallBack *CallBack)
1536 /* CallBackTime could not be 0 */
1537 if (CallBackTime == 0) {
1538 ViceLog(0, ("WARNING: CallBackTime == 0!\n"));
1539 CallBack->ExpirationTime = 0;
1541 CallBack->ExpirationTime = CallBackTime - FT_ApproxTime();
1542 CallBack->CallBackVersion = CALLBACK_VERSION;
1543 CallBack->CallBackType = CB_SHARED; /* The default for now */
1545 } /*SetCallBackStruct */
1549 * Adjusts (Subtract) "length" number of blocks from the volume's disk
1550 * allocation; if some error occured (exceeded volume quota or partition
1551 * was full, or whatever), it frees the space back and returns the code.
1552 * We usually pre-adjust the volume space to make sure that there's
1553 * enough space before consuming some.
1556 AdjustDiskUsage(Volume * volptr, afs_sfsize_t length,
1557 afs_sfsize_t checkLength)
1562 VAdjustDiskUsage(&rc, volptr, length, checkLength);
1564 VAdjustDiskUsage(&nc, volptr, -length, 0);
1565 if (rc == VOVERQUOTA) {
1567 ("Volume %u (%s) is full\n", V_id(volptr),
1571 if (rc == VDISKFULL) {
1573 ("Partition %s that contains volume %u is full\n",
1574 volptr->partition->name, V_id(volptr)));
1577 ViceLog(0, ("Got error return %d from VAdjustDiskUsage\n", rc));
1582 } /*AdjustDiskUsage */
1585 * Common code that handles the creation of a new file (SAFS_CreateFile and
1586 * SAFS_Symlink) or a new dir (SAFS_MakeDir)
1589 Alloc_NewVnode(Vnode * parentptr, DirHandle * dir, Volume * volptr,
1590 Vnode ** targetptr, char *Name, struct AFSFid *OutFid,
1591 int FileType, afs_sfsize_t BlocksPreallocatedForVnode)
1593 int errorCode = 0; /* Error code returned back */
1596 Inode nearInode; /* hint for inode allocation in solaris */
1599 AdjustDiskUsage(volptr, BlocksPreallocatedForVnode,
1600 BlocksPreallocatedForVnode))) {
1602 ("Insufficient space to allocate %lld blocks\n",
1603 (afs_intmax_t) BlocksPreallocatedForVnode));
1607 *targetptr = VAllocVnode(&errorCode, volptr, FileType);
1608 if (errorCode != 0) {
1609 VAdjustDiskUsage(&temp, volptr, -BlocksPreallocatedForVnode, 0);
1612 OutFid->Volume = V_id(volptr);
1613 OutFid->Vnode = (*targetptr)->vnodeNumber;
1614 OutFid->Unique = (*targetptr)->disk.uniquifier;
1616 nearInode = VN_GET_INO(parentptr); /* parent is also in same vol */
1618 /* create the inode now itself */
1620 IH_CREATE(V_linkHandle(volptr), V_device(volptr),
1621 VPartitionPath(V_partition(volptr)), nearInode,
1622 V_id(volptr), (*targetptr)->vnodeNumber,
1623 (*targetptr)->disk.uniquifier, 1);
1625 /* error in creating inode */
1626 if (!VALID_INO(inode)) {
1628 ("Volume : %u vnode = %u Failed to create inode: errno = %d\n",
1629 (*targetptr)->volumePtr->header->diskstuff.id,
1630 (*targetptr)->vnodeNumber, errno));
1631 VAdjustDiskUsage(&temp, volptr, -BlocksPreallocatedForVnode, 0);
1632 (*targetptr)->delete = 1; /* delete vnode */
1635 VN_SET_INO(*targetptr, inode);
1636 IH_INIT(((*targetptr)->handle), V_device(volptr), V_id(volptr), inode);
1638 /* copy group from parent dir */
1639 (*targetptr)->disk.group = parentptr->disk.group;
1641 if (parentptr->disk.cloned) {
1642 ViceLog(25, ("Alloc_NewVnode : CopyOnWrite called\n"));
1643 if ((errorCode = CopyOnWrite(parentptr, volptr))) { /* disk full */
1644 ViceLog(25, ("Alloc_NewVnode : CopyOnWrite failed\n"));
1645 /* delete the vnode previously allocated */
1646 (*targetptr)->delete = 1;
1647 VAdjustDiskUsage(&temp, volptr, -BlocksPreallocatedForVnode, 0);
1648 IH_REALLYCLOSE((*targetptr)->handle);
1649 if (IH_DEC(V_linkHandle(volptr), inode, V_parentId(volptr)))
1651 ("Alloc_NewVnode: partition %s idec %s failed\n",
1652 volptr->partition->name, PrintInode(NULL, inode)));
1653 IH_RELEASE((*targetptr)->handle);
1659 /* add the name to the directory */
1660 SetDirHandle(dir, parentptr);
1661 if ((errorCode = Create(dir, (char *)Name, OutFid))) {
1662 (*targetptr)->delete = 1;
1663 VAdjustDiskUsage(&temp, volptr, -BlocksPreallocatedForVnode, 0);
1664 IH_REALLYCLOSE((*targetptr)->handle);
1665 if (IH_DEC(V_linkHandle(volptr), inode, V_parentId(volptr)))
1667 ("Alloc_NewVnode: partition %s idec %s failed\n",
1668 volptr->partition->name, PrintInode(NULL, inode)));
1669 IH_RELEASE((*targetptr)->handle);
1675 } /*Alloc_NewVnode */
1679 * Handle all the lock-related code (SAFS_SetLock, SAFS_ExtendLock and
1683 HandleLocking(Vnode * targetptr, afs_int32 rights, ViceLockType LockingType)
1685 int Time; /* Used for time */
1686 int writeVnode = targetptr->changed_oldTime; /* save original status */
1688 /* Does the caller has Lock priviledges; root extends locks, however */
1689 if (LockingType != LockExtend && !(rights & PRSFS_LOCK))
1691 targetptr->changed_oldTime = 1; /* locking doesn't affect any time stamp */
1692 Time = FT_ApproxTime();
1693 switch (LockingType) {
1696 if (Time > targetptr->disk.lock.lockTime)
1697 targetptr->disk.lock.lockTime = targetptr->disk.lock.lockCount =
1699 Time += AFS_LOCKWAIT;
1700 if (LockingType == LockRead) {
1701 if (targetptr->disk.lock.lockCount >= 0) {
1702 ++(targetptr->disk.lock.lockCount);
1703 targetptr->disk.lock.lockTime = Time;
1707 if (targetptr->disk.lock.lockCount == 0) {
1708 targetptr->disk.lock.lockCount = -1;
1709 targetptr->disk.lock.lockTime = Time;
1715 Time += AFS_LOCKWAIT;
1716 if (targetptr->disk.lock.lockCount != 0)
1717 targetptr->disk.lock.lockTime = Time;
1722 if ((--targetptr->disk.lock.lockCount) <= 0)
1723 targetptr->disk.lock.lockCount = targetptr->disk.lock.lockTime =
1727 targetptr->changed_oldTime = writeVnode; /* restore old status */
1728 ViceLog(0, ("Illegal Locking type %d\n", LockingType));
1731 } /*HandleLocking */
1733 /* Checks if caller has the proper AFS and Unix (WRITE) access permission to the target directory; Prfs_Mode refers to the AFS Mode operation while rights contains the caller's access permissions to the directory. */
1736 CheckWriteMode(Vnode * targetptr, afs_int32 rights, int Prfs_Mode)
1740 if (!(rights & Prfs_Mode))
1742 if ((targetptr->disk.type != vDirectory)
1743 && (!(targetptr->disk.modeBits & OWNERWRITE)))
1749 * If some flags (i.e. min or max quota) are set, the volume's in disk
1750 * label is updated; Name, OfflineMsg, and Motd are also reflected in the
1751 * update, if applicable.
1754 RXUpdate_VolumeStatus(Volume * volptr, AFSStoreVolumeStatus * StoreVolStatus,
1755 char *Name, char *OfflineMsg, char *Motd)
1757 Error errorCode = 0;
1759 if (StoreVolStatus->Mask & AFS_SETMINQUOTA)
1760 V_minquota(volptr) = StoreVolStatus->MinQuota;
1761 if (StoreVolStatus->Mask & AFS_SETMAXQUOTA)
1762 V_maxquota(volptr) = StoreVolStatus->MaxQuota;
1763 if (strlen(OfflineMsg) > 0) {
1764 strcpy(V_offlineMessage(volptr), OfflineMsg);
1766 if (strlen(Name) > 0) {
1767 strcpy(V_name(volptr), Name);
1769 #if OPENAFS_VOL_STATS
1771 * We don't overwrite the motd field, since it's now being used
1775 if (strlen(Motd) > 0) {
1776 strcpy(V_motd(volptr), Motd);
1778 #endif /* FS_STATS_DETAILED */
1779 VUpdateVolume(&errorCode, volptr);
1782 } /*RXUpdate_VolumeStatus */
1787 Update_VolumeStatus(Volume * volptr, VolumeStatus * StoreVolStatus,
1788 struct BBS *Name, struct BBS *OfflineMsg,
1791 Error errorCode = 0;
1793 if (StoreVolStatus->MinQuota > -1)
1794 V_minquota(volptr) = StoreVolStatus->MinQuota;
1795 if (StoreVolStatus->MaxQuota > -1)
1796 V_maxquota(volptr) = StoreVolStatus->MaxQuota;
1797 if (OfflineMsg->SeqLen > 1)
1798 strcpy(V_offlineMessage(volptr), OfflineMsg->SeqBody);
1799 if (Name->SeqLen > 1)
1800 strcpy(V_name(volptr), Name->SeqBody);
1801 #if OPENAFS_VOL_STATS
1803 * We don't overwrite the motd field, since it's now being used
1807 if (Motd->SeqLen > 1)
1808 strcpy(V_motd(volptr), Motd->SeqBody);
1809 #endif /* FS_STATS_DETAILED */
1810 VUpdateVolume(&errorCode, volptr);
1813 } /*Update_VolumeStatus */
1817 * Get internal volume-related statistics from the Volume disk label
1818 * structure and put it into the VolumeStatus structure, status; it's
1819 * used by both SAFS_GetVolumeStatus and SAFS_SetVolumeStatus to return
1820 * the volume status to the caller.
1823 GetVolumeStatus(VolumeStatus * status, struct BBS *name, struct BBS *offMsg,
1824 struct BBS *motd, Volume * volptr)
1826 status->Vid = V_id(volptr);
1827 status->ParentId = V_parentId(volptr);
1828 status->Online = V_inUse(volptr);
1829 status->InService = V_inService(volptr);
1830 status->Blessed = V_blessed(volptr);
1831 status->NeedsSalvage = V_needsSalvaged(volptr);
1832 if (VolumeWriteable(volptr))
1833 status->Type = ReadWrite;
1835 status->Type = ReadOnly;
1836 status->MinQuota = V_minquota(volptr);
1837 status->MaxQuota = V_maxquota(volptr);
1838 status->BlocksInUse = V_diskused(volptr);
1839 status->PartBlocksAvail = volptr->partition->free;
1840 status->PartMaxBlocks = volptr->partition->totalUsable;
1841 strncpy(name->SeqBody, V_name(volptr), (int)name->MaxSeqLen);
1842 name->SeqLen = strlen(V_name(volptr)) + 1;
1843 if (name->SeqLen > name->MaxSeqLen)
1844 name->SeqLen = name->MaxSeqLen;
1845 strncpy(offMsg->SeqBody, V_offlineMessage(volptr), (int)name->MaxSeqLen);
1846 offMsg->SeqLen = strlen(V_offlineMessage(volptr)) + 1;
1847 if (offMsg->SeqLen > offMsg->MaxSeqLen)
1848 offMsg->SeqLen = offMsg->MaxSeqLen;
1850 /*Don't do anything with the motd field */
1851 strncpy(motd->SeqBody, nullString, (int)offMsg->MaxSeqLen);
1852 motd->SeqLen = strlen(nullString) + 1;
1854 if (motd->SeqLen > motd->MaxSeqLen)
1855 motd->SeqLen = motd->MaxSeqLen;
1857 } /*GetVolumeStatus */
1860 RXGetVolumeStatus(AFSFetchVolumeStatus * status, char **name, char **offMsg,
1861 char **motd, Volume * volptr)
1865 status->Vid = V_id(volptr);
1866 status->ParentId = V_parentId(volptr);
1867 status->Online = V_inUse(volptr);
1868 status->InService = V_inService(volptr);
1869 status->Blessed = V_blessed(volptr);
1870 status->NeedsSalvage = V_needsSalvaged(volptr);
1871 if (VolumeWriteable(volptr))
1872 status->Type = ReadWrite;
1874 status->Type = ReadOnly;
1875 status->MinQuota = V_minquota(volptr);
1876 status->MaxQuota = V_maxquota(volptr);
1877 status->BlocksInUse = V_diskused(volptr);
1878 status->PartBlocksAvail = volptr->partition->free;
1879 status->PartMaxBlocks = volptr->partition->totalUsable;
1881 /* now allocate and copy these things; they're freed by the RXGEN stub */
1882 temp = strlen(V_name(volptr)) + 1;
1883 *name = malloc(temp);
1885 ViceLog(0, ("Failed malloc in RXGetVolumeStatus\n"));
1888 strcpy(*name, V_name(volptr));
1889 temp = strlen(V_offlineMessage(volptr)) + 1;
1890 *offMsg = malloc(temp);
1892 ViceLog(0, ("Failed malloc in RXGetVolumeStatus\n"));
1895 strcpy(*offMsg, V_offlineMessage(volptr));
1896 #if OPENAFS_VOL_STATS
1899 ViceLog(0, ("Failed malloc in RXGetVolumeStatus\n"));
1902 strcpy(*motd, nullString);
1904 temp = strlen(V_motd(volptr)) + 1;
1905 *motd = malloc(temp);
1907 ViceLog(0, ("Failed malloc in RXGetVolumeStatus\n"));
1910 strcpy(*motd, V_motd(volptr));
1911 #endif /* FS_STATS_DETAILED */
1913 } /*RXGetVolumeStatus */
1917 FileNameOK(register char *aname)
1919 register afs_int32 i, tc;
1922 /* watch for @sys on the right */
1923 if (strcmp(aname + i - 4, "@sys") == 0)
1926 while ((tc = *aname++)) {
1928 return 0; /* very bad character to encounter */
1930 return 1; /* file name is ok */
1935 /* Debugging tool to print Volume Statu's contents */
1937 PrintVolumeStatus(VolumeStatus * status)
1939 ViceLog(5, ("Volume header contains:\n"));
1941 ("Vid = %u, Parent = %u, Online = %d, InService = %d, Blessed = %d, NeedsSalvage = %d\n",
1942 status->Vid, status->ParentId, status->Online, status->InService,
1943 status->Blessed, status->NeedsSalvage));
1945 ("MinQuota = %d, MaxQuota = %d\n", status->MinQuota,
1948 ("Type = %d, BlocksInUse = %d, PartBlocksAvail = %d, PartMaxBlocks = %d\n",
1949 status->Type, status->BlocksInUse, status->PartBlocksAvail,
1950 status->PartMaxBlocks));
1952 } /*PrintVolumeStatus */
1956 * This variant of symlink is expressly to support the AFS/DFS translator
1957 * and is not supported by the AFS fileserver. We just return EINVAL.
1958 * The cache manager should not generate this call to an AFS cache manager.
1961 SRXAFS_DFSSymlink(struct rx_call *acall, struct AFSFid *DirFid, char *Name,
1962 char *LinkContents, struct AFSStoreStatus *InStatus,
1963 struct AFSFid *OutFid, struct AFSFetchStatus *OutFidStatus,
1964 struct AFSFetchStatus *OutDirStatus,
1965 struct AFSCallBack *CallBack, struct AFSVolSync *Sync)
1971 SRXAFS_ResidencyCmd(struct rx_call * acall, struct AFSFid * Fid,
1972 struct ResidencyCmdInputs * Inputs,
1973 struct ResidencyCmdOutputs * Outputs)
1978 static struct afs_buffer {
1979 struct afs_buffer *next;
1980 } *freeBufferList = 0;
1981 static int afs_buffersAlloced = 0;
1984 FreeSendBuffer(register struct afs_buffer *adata)
1987 afs_buffersAlloced--;
1988 adata->next = freeBufferList;
1989 freeBufferList = adata;
1993 } /*FreeSendBuffer */
1995 /* allocate space for sender */
1999 register struct afs_buffer *tp;
2002 afs_buffersAlloced++;
2003 if (!freeBufferList) {
2006 tmp = malloc(sendBufSize);
2008 ViceLog(0, ("Failed malloc in AllocSendBuffer\n"));
2013 tp = freeBufferList;
2014 freeBufferList = tp->next;
2018 } /*AllocSendBuffer */
2021 * This routine returns the status info associated with the targetptr vnode
2022 * in the AFSFetchStatus structure. Some of the newer fields, such as
2023 * SegSize and Group are not yet implemented
2027 GetStatus(Vnode * targetptr, AFSFetchStatus * status, afs_int32 rights,
2028 afs_int32 anyrights, Vnode * parentptr)
2030 /* initialize return status from a vnode */
2031 status->InterfaceVersion = 1;
2032 status->SyncCounter = status->dataVersionHigh = status->lockCount =
2033 status->errorCode = 0;
2034 status->ResidencyMask = 1; /* means for MR-AFS: file in /vicepr-partition */
2035 if (targetptr->disk.type == vFile)
2036 status->FileType = File;
2037 else if (targetptr->disk.type == vDirectory)
2038 status->FileType = Directory;
2039 else if (targetptr->disk.type == vSymlink)
2040 status->FileType = SymbolicLink;
2042 status->FileType = Invalid; /*invalid type field */
2043 status->LinkCount = targetptr->disk.linkCount;
2045 afs_fsize_t targetLen;
2046 VN_GET_LEN(targetLen, targetptr);
2047 SplitOffsetOrSize(targetLen, status->Length_hi, status->Length);
2049 status->DataVersion = targetptr->disk.dataVersion;
2050 status->Author = targetptr->disk.author;
2051 status->Owner = targetptr->disk.owner;
2052 status->CallerAccess = rights;
2053 status->AnonymousAccess = anyrights;
2054 status->UnixModeBits = targetptr->disk.modeBits;
2055 status->ClientModTime = targetptr->disk.unixModifyTime; /* This might need rework */
2056 status->ParentVnode =
2057 (status->FileType ==
2058 Directory ? targetptr->vnodeNumber : parentptr->vnodeNumber);
2059 status->ParentUnique =
2060 (status->FileType ==
2061 Directory ? targetptr->disk.uniquifier : parentptr->disk.uniquifier);
2062 status->ServerModTime = targetptr->disk.serverModifyTime;
2063 status->Group = targetptr->disk.group;
2064 status->lockCount = targetptr->disk.lock.lockCount;
2065 status->errorCode = 0;
2071 common_FetchData64(struct rx_call *acall, struct AFSFid *Fid,
2072 afs_sfsize_t Pos, afs_sfsize_t Len,
2073 struct AFSFetchStatus *OutStatus,
2074 struct AFSCallBack *CallBack, struct AFSVolSync *Sync,
2077 Vnode *targetptr = 0; /* pointer to vnode to fetch */
2078 Vnode *parentwhentargetnotdir = 0; /* parent vnode if vptr is a file */
2079 Vnode tparentwhentargetnotdir; /* parent vnode for GetStatus */
2080 int errorCode = 0; /* return code to caller */
2081 int fileCode = 0; /* return code from vol package */
2082 Volume *volptr = 0; /* pointer to the volume */
2083 struct client *client; /* pointer to the client data */
2084 struct rx_connection *tcon; /* the connection we're part of */
2085 afs_int32 rights, anyrights; /* rights for this and any user */
2086 struct client *t_client = NULL; /* tmp ptr to client data */
2087 struct in_addr logHostAddr; /* host ip holder for inet_ntoa */
2088 #if FS_STATS_DETAILED
2089 struct fs_stats_opTimingData *opP; /* Ptr to this op's timing struct */
2090 struct fs_stats_xferData *xferP; /* Ptr to this op's byte size struct */
2091 struct timeval opStartTime, opStopTime; /* Start/stop times for RPC op */
2092 struct timeval xferStartTime, xferStopTime; /* Start/stop times for xfer portion */
2093 struct timeval elapsedTime; /* Transfer time */
2094 afs_sfsize_t bytesToXfer; /* # bytes to xfer */
2095 afs_sfsize_t bytesXferred; /* # bytes actually xferred */
2096 int readIdx; /* Index of read stats array to bump */
2097 static afs_int32 tot_bytesXferred; /* shared access protected by FS_LOCK */
2100 * Set our stats pointers, remember when the RPC operation started, and
2101 * tally the operation.
2103 opP = &(afs_FullPerfStats.det.rpcOpTimes[FS_STATS_RPCIDX_FETCHDATA]);
2104 xferP = &(afs_FullPerfStats.det.xferOpTimes[FS_STATS_XFERIDX_FETCHDATA]);
2108 TM_GetTimeOfDay(&opStartTime, 0);
2109 #endif /* FS_STATS_DETAILED */
2112 ("SRXAFS_FetchData, Fid = %u.%u.%u\n", Fid->Volume, Fid->Vnode,
2115 AFSCallStats.FetchData++, AFSCallStats.TotalCalls++;
2117 if ((errorCode = CallPreamble(acall, ACTIVECALL, &tcon)))
2120 /* Get ptr to client data for user Id for logging */
2121 t_client = (struct client *)rx_GetSpecific(tcon, rxcon_client_key);
2122 logHostAddr.s_addr = rxr_HostOf(tcon);
2124 ("SRXAFS_FetchData, Fid = %u.%u.%u, Host %s:%d, Id %d\n",
2125 Fid->Volume, Fid->Vnode, Fid->Unique, inet_ntoa(logHostAddr),
2126 rxr_PortOf(tcon), t_client->ViceId));
2128 * Get volume/vnode for the fetched file; caller's access rights to
2129 * it are also returned
2132 GetVolumePackage(tcon, Fid, &volptr, &targetptr, DONTCHECK,
2133 &parentwhentargetnotdir, &client, READ_LOCK,
2134 &rights, &anyrights)))
2137 SetVolumeSync(Sync, volptr);
2139 #if FS_STATS_DETAILED
2141 * Remember that another read operation was performed.
2144 if (client->InSameNetwork)
2145 readIdx = VOL_STATS_SAME_NET;
2147 readIdx = VOL_STATS_DIFF_NET;
2148 V_stat_reads(volptr, readIdx)++;
2149 if (client->ViceId != AnonymousID) {
2150 V_stat_reads(volptr, readIdx + 1)++;
2153 #endif /* FS_STATS_DETAILED */
2154 /* Check whether the caller has permission access to fetch the data */
2156 Check_PermissionRights(targetptr, client, rights, CHK_FETCHDATA, 0)))
2160 * Drop the read lock on the parent directory after saving the parent
2161 * vnode information we need to pass to GetStatus
2163 if (parentwhentargetnotdir != NULL) {
2164 tparentwhentargetnotdir = *parentwhentargetnotdir;
2165 VPutVnode(&fileCode, parentwhentargetnotdir);
2166 assert(!fileCode || (fileCode == VSALVAGE));
2167 parentwhentargetnotdir = NULL;
2169 #if FS_STATS_DETAILED
2171 * Remember when the data transfer started.
2173 TM_GetTimeOfDay(&xferStartTime, 0);
2174 #endif /* FS_STATS_DETAILED */
2176 /* actually do the data transfer */
2177 #if FS_STATS_DETAILED
2179 FetchData_RXStyle(volptr, targetptr, acall, Pos, Len, type,
2180 &bytesToXfer, &bytesXferred);
2183 FetchData_RXStyle(volptr, targetptr, acall, Pos, Len, type)))
2185 #endif /* FS_STATS_DETAILED */
2187 #if FS_STATS_DETAILED
2189 * At this point, the data transfer is done, for good or ill. Remember
2190 * when the transfer ended, bump the number of successes/failures, and
2191 * integrate the transfer size and elapsed time into the stats. If the
2192 * operation failed, we jump to the appropriate point.
2194 TM_GetTimeOfDay(&xferStopTime, 0);
2196 (xferP->numXfers)++;
2198 (xferP->numSuccesses)++;
2201 * Bump the xfer sum by the number of bytes actually sent, NOT the
2204 tot_bytesXferred += bytesXferred;
2205 (xferP->sumBytes) += (tot_bytesXferred >> 10);
2206 tot_bytesXferred &= 0x3FF;
2207 if (bytesXferred < xferP->minBytes)
2208 xferP->minBytes = bytesXferred;
2209 if (bytesXferred > xferP->maxBytes)
2210 xferP->maxBytes = bytesXferred;
2213 * Tally the size of the object. Note: we tally the actual size,
2214 * NOT the number of bytes that made it out over the wire.
2216 if (bytesToXfer <= FS_STATS_MAXBYTES_BUCKET0)
2217 (xferP->count[0])++;
2218 else if (bytesToXfer <= FS_STATS_MAXBYTES_BUCKET1)
2219 (xferP->count[1])++;
2220 else if (bytesToXfer <= FS_STATS_MAXBYTES_BUCKET2)
2221 (xferP->count[2])++;
2222 else if (bytesToXfer <= FS_STATS_MAXBYTES_BUCKET3)
2223 (xferP->count[3])++;
2224 else if (bytesToXfer <= FS_STATS_MAXBYTES_BUCKET4)
2225 (xferP->count[4])++;
2226 else if (bytesToXfer <= FS_STATS_MAXBYTES_BUCKET5)
2227 (xferP->count[5])++;
2228 else if (bytesToXfer <= FS_STATS_MAXBYTES_BUCKET6)
2229 (xferP->count[6])++;
2230 else if (bytesToXfer <= FS_STATS_MAXBYTES_BUCKET7)
2231 (xferP->count[7])++;
2233 (xferP->count[8])++;
2235 fs_stats_GetDiff(elapsedTime, xferStartTime, xferStopTime);
2236 fs_stats_AddTo((xferP->sumTime), elapsedTime);
2237 fs_stats_SquareAddTo((xferP->sqrTime), elapsedTime);
2238 if (fs_stats_TimeLessThan(elapsedTime, (xferP->minTime))) {
2239 fs_stats_TimeAssign((xferP->minTime), elapsedTime);
2241 if (fs_stats_TimeGreaterThan(elapsedTime, (xferP->maxTime))) {
2242 fs_stats_TimeAssign((xferP->maxTime), elapsedTime);
2247 * Finally, go off to tell our caller the bad news in case the
2252 #endif /* FS_STATS_DETAILED */
2254 /* write back the OutStatus from the target vnode */
2255 GetStatus(targetptr, OutStatus, rights, anyrights,
2256 &tparentwhentargetnotdir);
2258 /* if a r/w volume, promise a callback to the caller */
2259 if (VolumeWriteable(volptr))
2260 SetCallBackStruct(AddCallBack(client->host, Fid), CallBack);
2262 struct AFSFid myFid;
2263 memset(&myFid, 0, sizeof(struct AFSFid));
2264 myFid.Volume = Fid->Volume;
2265 SetCallBackStruct(AddVolCallBack(client->host, &myFid), CallBack);
2269 /* Update and store volume/vnode and parent vnodes back */
2270 (void)PutVolumePackage(parentwhentargetnotdir, targetptr, (Vnode *) 0,
2272 ViceLog(2, ("SRXAFS_FetchData returns %d\n", errorCode));
2273 errorCode = CallPostamble(tcon, errorCode);
2275 #if FS_STATS_DETAILED
2276 TM_GetTimeOfDay(&opStopTime, 0);
2277 if (errorCode == 0) {
2279 (opP->numSuccesses)++;
2280 fs_stats_GetDiff(elapsedTime, opStartTime, opStopTime);
2281 fs_stats_AddTo((opP->sumTime), elapsedTime);
2282 fs_stats_SquareAddTo((opP->sqrTime), elapsedTime);
2283 if (fs_stats_TimeLessThan(elapsedTime, (opP->minTime))) {
2284 fs_stats_TimeAssign((opP->minTime), elapsedTime);
2286 if (fs_stats_TimeGreaterThan(elapsedTime, (opP->maxTime))) {
2287 fs_stats_TimeAssign((opP->maxTime), elapsedTime);
2291 #endif /* FS_STATS_DETAILED */
2293 osi_auditU(acall, FetchDataEvent, errorCode,
2294 AUD_ID, t_client ? t_client->ViceId : 0,
2295 AUD_FID, Fid, AUD_END);
2298 } /*SRXAFS_FetchData */
2301 SRXAFS_FetchData(struct rx_call * acall, struct AFSFid * Fid, afs_int32 Pos,
2302 afs_int32 Len, struct AFSFetchStatus * OutStatus,
2303 struct AFSCallBack * CallBack, struct AFSVolSync * Sync)
2305 return common_FetchData64(acall, Fid, Pos, Len, OutStatus, CallBack,
2310 SRXAFS_FetchData64(struct rx_call * acall, struct AFSFid * Fid, afs_int64 Pos,
2311 afs_int64 Len, struct AFSFetchStatus * OutStatus,
2312 struct AFSCallBack * CallBack, struct AFSVolSync * Sync)
2315 afs_sfsize_t tPos, tLen;
2317 #ifdef AFS_64BIT_ENV
2318 #ifndef AFS_LARGEFILE_ENV
2319 if (Pos + Len > 0x7fffffff)
2321 #endif /* !AFS_LARGEFILE_ENV */
2322 tPos = (afs_sfsize_t) Pos;
2323 tLen = (afs_sfsize_t) Len;
2324 #else /* AFS_64BIT_ENV */
2325 if (Pos.high || Len.high)
2329 #endif /* AFS_64BIT_ENV */
2332 common_FetchData64(acall, Fid, tPos, tLen, OutStatus, CallBack, Sync,
2338 SRXAFS_FetchACL(struct rx_call * acall, struct AFSFid * Fid,
2339 struct AFSOpaque * AccessList,
2340 struct AFSFetchStatus * OutStatus, struct AFSVolSync * Sync)
2342 Vnode *targetptr = 0; /* pointer to vnode to fetch */
2343 Vnode *parentwhentargetnotdir = 0; /* parent vnode if targetptr is a file */
2344 int errorCode = 0; /* return error code to caller */
2345 Volume *volptr = 0; /* pointer to the volume */
2346 struct client *client; /* pointer to the client data */
2347 afs_int32 rights, anyrights; /* rights for this and any user */
2348 struct rx_connection *tcon = rx_ConnectionOf(acall);
2349 struct client *t_client = NULL; /* tmp ptr to client data */
2350 struct in_addr logHostAddr; /* host ip holder for inet_ntoa */
2351 #if FS_STATS_DETAILED
2352 struct fs_stats_opTimingData *opP; /* Ptr to this op's timing struct */
2353 struct timeval opStartTime, opStopTime; /* Start/stop times for RPC op */
2354 struct timeval elapsedTime; /* Transfer time */
2357 * Set our stats pointer, remember when the RPC operation started, and
2358 * tally the operation.
2360 opP = &(afs_FullPerfStats.det.rpcOpTimes[FS_STATS_RPCIDX_FETCHACL]);
2364 TM_GetTimeOfDay(&opStartTime, 0);
2365 #endif /* FS_STATS_DETAILED */
2368 ("SAFS_FetchACL, Fid = %u.%u.%u\n", Fid->Volume, Fid->Vnode,
2371 AFSCallStats.FetchACL++, AFSCallStats.TotalCalls++;
2373 if ((errorCode = CallPreamble(acall, ACTIVECALL, &tcon)))
2376 /* Get ptr to client data for user Id for logging */
2377 t_client = (struct client *)rx_GetSpecific(tcon, rxcon_client_key);
2378 logHostAddr.s_addr = rxr_HostOf(tcon);
2380 ("SAFS_FetchACL, Fid = %u.%u.%u, Host %s:%d, Id %d\n", Fid->Volume,
2381 Fid->Vnode, Fid->Unique, inet_ntoa(logHostAddr),
2382 rxr_PortOf(tcon), t_client->ViceId));
2384 AccessList->AFSOpaque_len = 0;
2385 AccessList->AFSOpaque_val = malloc(AFSOPAQUEMAX);
2386 if (!AccessList->AFSOpaque_val) {
2387 ViceLog(0, ("Failed malloc in SRXAFS_FetchACL\n"));
2392 * Get volume/vnode for the fetched file; caller's access rights to it
2396 GetVolumePackage(tcon, Fid, &volptr, &targetptr, DONTCHECK,
2397 &parentwhentargetnotdir, &client, READ_LOCK,
2398 &rights, &anyrights)))
2401 SetVolumeSync(Sync, volptr);
2403 /* Check whether we have permission to fetch the ACL */
2405 Check_PermissionRights(targetptr, client, rights, CHK_FETCHACL, 0)))
2408 /* Get the Access List from the dir's vnode */
2410 RXFetch_AccessList(targetptr, parentwhentargetnotdir, AccessList)))
2413 /* Get OutStatus back From the target Vnode */
2414 GetStatus(targetptr, OutStatus, rights, anyrights,
2415 parentwhentargetnotdir);
2418 /* Update and store volume/vnode and parent vnodes back */
2419 (void)PutVolumePackage(parentwhentargetnotdir, targetptr, (Vnode *) 0,
2422 ("SAFS_FetchACL returns %d (ACL=%s)\n", errorCode,
2423 AccessList->AFSOpaque_val));
2424 errorCode = CallPostamble(tcon, errorCode);
2426 #if FS_STATS_DETAILED
2427 TM_GetTimeOfDay(&opStopTime, 0);
2428 if (errorCode == 0) {
2430 (opP->numSuccesses)++;
2431 fs_stats_GetDiff(elapsedTime, opStartTime, opStopTime);
2432 fs_stats_AddTo((opP->sumTime), elapsedTime);
2433 fs_stats_SquareAddTo((opP->sqrTime), elapsedTime);
2434 if (fs_stats_TimeLessThan(elapsedTime, (opP->minTime))) {
2435 fs_stats_TimeAssign((opP->minTime), elapsedTime);
2437 if (fs_stats_TimeGreaterThan(elapsedTime, (opP->maxTime))) {
2438 fs_stats_TimeAssign((opP->maxTime), elapsedTime);
2442 #endif /* FS_STATS_DETAILED */
2444 osi_auditU(acall, FetchACLEvent, errorCode,
2445 AUD_ID, t_client ? t_client->ViceId : 0,
2447 AUD_ACL, AccessList->AFSOpaque_val, AUD_END);
2449 } /*SRXAFS_FetchACL */
2453 * This routine is called exclusively by SRXAFS_FetchStatus(), and should be
2454 * merged into it when possible.
2458 SAFSS_FetchStatus(struct rx_call *acall, struct AFSFid *Fid,
2459 struct AFSFetchStatus *OutStatus,
2460 struct AFSCallBack *CallBack, struct AFSVolSync *Sync)
2462 Vnode *targetptr = 0; /* pointer to vnode to fetch */
2463 Vnode *parentwhentargetnotdir = 0; /* parent vnode if targetptr is a file */
2464 int errorCode = 0; /* return code to caller */
2465 Volume *volptr = 0; /* pointer to the volume */
2466 struct client *client; /* pointer to the client data */
2467 afs_int32 rights, anyrights; /* rights for this and any user */
2468 struct client *t_client = NULL; /* tmp ptr to client data */
2469 struct in_addr logHostAddr; /* host ip holder for inet_ntoa */
2470 struct rx_connection *tcon = rx_ConnectionOf(acall);
2472 /* Get ptr to client data for user Id for logging */
2473 t_client = (struct client *)rx_GetSpecific(tcon, rxcon_client_key);
2474 logHostAddr.s_addr = rxr_HostOf(tcon);
2476 ("SAFS_FetchStatus, Fid = %u.%u.%u, Host %s:%d, Id %d\n",
2477 Fid->Volume, Fid->Vnode, Fid->Unique, inet_ntoa(logHostAddr),
2478 rxr_PortOf(tcon), t_client->ViceId));
2480 AFSCallStats.FetchStatus++, AFSCallStats.TotalCalls++;
2483 * Get volume/vnode for the fetched file; caller's rights to it are
2487 GetVolumePackage(tcon, Fid, &volptr, &targetptr, DONTCHECK,
2488 &parentwhentargetnotdir, &client, READ_LOCK,
2489 &rights, &anyrights)))
2490 goto Bad_FetchStatus;
2492 /* set volume synchronization information */
2493 SetVolumeSync(Sync, volptr);
2495 /* Are we allowed to fetch Fid's status? */
2496 if (targetptr->disk.type != vDirectory) {
2498 Check_PermissionRights(targetptr, client, rights,
2499 CHK_FETCHSTATUS, 0))) {
2500 if (rx_GetCallAbortCode(acall) == errorCode)
2501 rx_SetCallAbortCode(acall, 0);
2502 goto Bad_FetchStatus;
2506 /* set OutStatus From the Fid */
2507 GetStatus(targetptr, OutStatus, rights, anyrights,
2508 parentwhentargetnotdir);
2510 /* If a r/w volume, also set the CallBack state */
2511 if (VolumeWriteable(volptr))
2512 SetCallBackStruct(AddCallBack(client->host, Fid), CallBack);
2514 struct AFSFid myFid;
2515 memset(&myFid, 0, sizeof(struct AFSFid));
2516 myFid.Volume = Fid->Volume;
2517 SetCallBackStruct(AddVolCallBack(client->host, &myFid), CallBack);
2521 /* Update and store volume/vnode and parent vnodes back */
2522 (void)PutVolumePackage(parentwhentargetnotdir, targetptr, (Vnode *) 0,
2524 ViceLog(2, ("SAFS_FetchStatus returns %d\n", errorCode));
2527 } /*SAFSS_FetchStatus */
2531 SRXAFS_BulkStatus(struct rx_call * acall, struct AFSCBFids * Fids,
2532 struct AFSBulkStats * OutStats, struct AFSCBs * CallBacks,
2533 struct AFSVolSync * Sync)
2537 Vnode *targetptr = 0; /* pointer to vnode to fetch */
2538 Vnode *parentwhentargetnotdir = 0; /* parent vnode if targetptr is a file */
2539 int errorCode = 0; /* return code to caller */
2540 Volume *volptr = 0; /* pointer to the volume */
2541 struct client *client; /* pointer to the client data */
2542 afs_int32 rights, anyrights; /* rights for this and any user */
2543 register struct AFSFid *tfid; /* file id we're dealing with now */
2544 struct rx_connection *tcon = rx_ConnectionOf(acall);
2545 struct client *t_client = NULL; /* tmp pointer to the client data */
2546 #if FS_STATS_DETAILED
2547 struct fs_stats_opTimingData *opP; /* Ptr to this op's timing struct */
2548 struct timeval opStartTime, opStopTime; /* Start/stop times for RPC op */
2549 struct timeval elapsedTime; /* Transfer time */
2552 * Set our stats pointer, remember when the RPC operation started, and
2553 * tally the operation.
2555 opP = &(afs_FullPerfStats.det.rpcOpTimes[FS_STATS_RPCIDX_BULKSTATUS]);
2559 TM_GetTimeOfDay(&opStartTime, 0);
2560 #endif /* FS_STATS_DETAILED */
2562 ViceLog(1, ("SAFS_BulkStatus\n"));
2564 AFSCallStats.TotalCalls++;
2566 nfiles = Fids->AFSCBFids_len; /* # of files in here */
2567 if (nfiles <= 0) { /* Sanity check */
2569 goto Audit_and_Return;
2572 /* allocate space for return output parameters */
2573 OutStats->AFSBulkStats_val = (struct AFSFetchStatus *)
2574 malloc(nfiles * sizeof(struct AFSFetchStatus));
2575 if (!OutStats->AFSBulkStats_val) {
2576 ViceLog(0, ("Failed malloc in SRXAFS_BulkStatus\n"));
2579 OutStats->AFSBulkStats_len = nfiles;
2580 CallBacks->AFSCBs_val = (struct AFSCallBack *)
2581 malloc(nfiles * sizeof(struct AFSCallBack));
2582 if (!CallBacks->AFSCBs_val) {
2583 ViceLog(0, ("Failed malloc in SRXAFS_BulkStatus\n"));
2586 CallBacks->AFSCBs_len = nfiles;
2588 if ((errorCode = CallPreamble(acall, ACTIVECALL, &tcon)))
2589 goto Bad_BulkStatus;
2591 tfid = Fids->AFSCBFids_val;
2592 for (i = 0; i < nfiles; i++, tfid++) {
2594 * Get volume/vnode for the fetched file; caller's rights to it
2598 GetVolumePackage(tcon, tfid, &volptr, &targetptr, DONTCHECK,
2599 &parentwhentargetnotdir, &client, READ_LOCK,
2600 &rights, &anyrights)))
2601 goto Bad_BulkStatus;
2602 /* set volume synchronization information, but only once per call */
2604 SetVolumeSync(Sync, volptr);
2606 /* Are we allowed to fetch Fid's status? */
2607 if (targetptr->disk.type != vDirectory) {
2609 Check_PermissionRights(targetptr, client, rights,
2610 CHK_FETCHSTATUS, 0))) {
2611 if (rx_GetCallAbortCode(acall) == errorCode)
2612 rx_SetCallAbortCode(acall, 0);
2613 goto Bad_BulkStatus;
2617 /* set OutStatus From the Fid */
2618 GetStatus(targetptr, &OutStats->AFSBulkStats_val[i], rights,
2619 anyrights, parentwhentargetnotdir);
2621 /* If a r/w volume, also set the CallBack state */
2622 if (VolumeWriteable(volptr))
2623 SetCallBackStruct(AddBulkCallBack(client->host, tfid),
2624 &CallBacks->AFSCBs_val[i]);
2626 struct AFSFid myFid;
2627 memset(&myFid, 0, sizeof(struct AFSFid));
2628 myFid.Volume = tfid->Volume;
2629 SetCallBackStruct(AddVolCallBack(client->host, &myFid),
2630 &CallBacks->AFSCBs_val[i]);
2633 /* put back the file ID and volume */
2634 (void)PutVolumePackage(parentwhentargetnotdir, targetptr, (Vnode *) 0,
2636 parentwhentargetnotdir = (Vnode *) 0;
2637 targetptr = (Vnode *) 0;
2638 volptr = (Volume *) 0;
2642 /* Update and store volume/vnode and parent vnodes back */
2643 (void)PutVolumePackage(parentwhentargetnotdir, targetptr, (Vnode *) 0,
2645 errorCode = CallPostamble(tcon, errorCode);
2647 t_client = (struct client *)rx_GetSpecific(tcon, rxcon_client_key);
2649 #if FS_STATS_DETAILED
2650 TM_GetTimeOfDay(&opStopTime, 0);
2651 if (errorCode == 0) {
2653 (opP->numSuccesses)++;
2654 fs_stats_GetDiff(elapsedTime, opStartTime, opStopTime);
2655 fs_stats_AddTo((opP->sumTime), elapsedTime);
2656 fs_stats_SquareAddTo((opP->sqrTime), elapsedTime);
2657 if (fs_stats_TimeLessThan(elapsedTime, (opP->minTime))) {
2658 fs_stats_TimeAssign((opP->minTime), elapsedTime);
2660 if (fs_stats_TimeGreaterThan(elapsedTime, (opP->maxTime))) {
2661 fs_stats_TimeAssign((opP->maxTime), elapsedTime);
2665 #endif /* FS_STATS_DETAILED */
2668 ViceLog(2, ("SAFS_BulkStatus returns %d\n", errorCode));
2669 osi_auditU(acall, BulkFetchStatusEvent, errorCode,
2670 AUD_ID, t_client ? t_client->ViceId : 0,
2671 AUD_FIDS, Fids, AUD_END);
2674 } /*SRXAFS_BulkStatus */
2678 SRXAFS_InlineBulkStatus(struct rx_call * acall, struct AFSCBFids * Fids,
2679 struct AFSBulkStats * OutStats,
2680 struct AFSCBs * CallBacks, struct AFSVolSync * Sync)
2684 Vnode *targetptr = 0; /* pointer to vnode to fetch */
2685 Vnode *parentwhentargetnotdir = 0; /* parent vnode if targetptr is a file */
2686 int errorCode = 0; /* return code to caller */
2687 Volume *volptr = 0; /* pointer to the volume */
2688 struct client *client; /* pointer to the client data */
2689 afs_int32 rights, anyrights; /* rights for this and any user */
2690 register struct AFSFid *tfid; /* file id we're dealing with now */
2691 struct rx_connection *tcon;
2692 struct client *t_client = NULL; /* tmp ptr to client data */
2693 AFSFetchStatus *tstatus;
2694 #if FS_STATS_DETAILED
2695 struct fs_stats_opTimingData *opP; /* Ptr to this op's timing struct */
2696 struct timeval opStartTime, opStopTime; /* Start/stop times for RPC op */
2697 struct timeval elapsedTime; /* Transfer time */
2700 * Set our stats pointer, remember when the RPC operation started, and
2701 * tally the operation.
2703 opP = &(afs_FullPerfStats.det.rpcOpTimes[FS_STATS_RPCIDX_BULKSTATUS]);
2707 TM_GetTimeOfDay(&opStartTime, 0);
2708 #endif /* FS_STATS_DETAILED */
2710 ViceLog(1, ("SAFS_InlineBulkStatus\n"));
2712 AFSCallStats.TotalCalls++;
2714 nfiles = Fids->AFSCBFids_len; /* # of files in here */
2715 if (nfiles <= 0) { /* Sanity check */
2717 goto Audit_and_Return;
2720 /* allocate space for return output parameters */
2721 OutStats->AFSBulkStats_val = (struct AFSFetchStatus *)
2722 malloc(nfiles * sizeof(struct AFSFetchStatus));
2723 if (!OutStats->AFSBulkStats_val) {
2724 ViceLog(0, ("Failed malloc in SRXAFS_FetchStatus\n"));
2727 OutStats->AFSBulkStats_len = nfiles;
2728 CallBacks->AFSCBs_val = (struct AFSCallBack *)
2729 malloc(nfiles * sizeof(struct AFSCallBack));
2730 if (!CallBacks->AFSCBs_val) {
2731 ViceLog(0, ("Failed malloc in SRXAFS_FetchStatus\n"));
2734 CallBacks->AFSCBs_len = nfiles;
2736 if ((errorCode = CallPreamble(acall, ACTIVECALL, &tcon))) {
2737 goto Bad_InlineBulkStatus;
2740 tfid = Fids->AFSCBFids_val;
2741 for (i = 0; i < nfiles; i++, tfid++) {
2743 * Get volume/vnode for the fetched file; caller's rights to it
2747 GetVolumePackage(tcon, tfid, &volptr, &targetptr, DONTCHECK,
2748 &parentwhentargetnotdir, &client, READ_LOCK,
2749 &rights, &anyrights))) {
2750 tstatus = &OutStats->AFSBulkStats_val[i];
2751 tstatus->errorCode = errorCode;
2752 PutVolumePackage(parentwhentargetnotdir, targetptr, (Vnode *) 0, volptr);
2753 parentwhentargetnotdir = (Vnode *) 0;
2754 targetptr = (Vnode *) 0;
2755 volptr = (Volume *) 0;
2759 /* set volume synchronization information, but only once per call */
2761 SetVolumeSync(Sync, volptr);
2763 /* Are we allowed to fetch Fid's status? */
2764 if (targetptr->disk.type != vDirectory) {
2766 Check_PermissionRights(targetptr, client, rights,
2767 CHK_FETCHSTATUS, 0))) {
2768 tstatus = &OutStats->AFSBulkStats_val[i];
2769 tstatus->errorCode = errorCode;
2770 (void)PutVolumePackage(parentwhentargetnotdir, targetptr,
2771 (Vnode *) 0, volptr);
2772 parentwhentargetnotdir = (Vnode *) 0;
2773 targetptr = (Vnode *) 0;
2774 volptr = (Volume *) 0;
2779 /* set OutStatus From the Fid */
2780 GetStatus(targetptr,
2781 (struct AFSFetchStatus *)&OutStats->AFSBulkStats_val[i],
2782 rights, anyrights, parentwhentargetnotdir);
2784 /* If a r/w volume, also set the CallBack state */
2785 if (VolumeWriteable(volptr))
2786 SetCallBackStruct(AddBulkCallBack(client->host, tfid),
2787 &CallBacks->AFSCBs_val[i]);
2789 struct AFSFid myFid;
2790 memset(&myFid, 0, sizeof(struct AFSFid));
2791 myFid.Volume = tfid->Volume;
2792 SetCallBackStruct(AddVolCallBack(client->host, &myFid),
2793 &CallBacks->AFSCBs_val[i]);
2796 /* put back the file ID and volume */
2797 (void)PutVolumePackage(parentwhentargetnotdir, targetptr, (Vnode *) 0,
2799 parentwhentargetnotdir = (Vnode *) 0;
2800 targetptr = (Vnode *) 0;
2801 volptr = (Volume *) 0;
2804 Bad_InlineBulkStatus:
2805 /* Update and store volume/vnode and parent vnodes back */
2806 (void)PutVolumePackage(parentwhentargetnotdir, targetptr, (Vnode *) 0,
2808 errorCode = CallPostamble(tcon, errorCode);
2810 t_client = (struct client *)rx_GetSpecific(tcon, rxcon_client_key);
2812 #if FS_STATS_DETAILED
2813 TM_GetTimeOfDay(&opStopTime, 0);
2814 if (errorCode == 0) {
2816 (opP->numSuccesses)++;
2817 fs_stats_GetDiff(elapsedTime, opStartTime, opStopTime);
2818 fs_stats_AddTo((opP->sumTime), elapsedTime);
2819 fs_stats_SquareAddTo((opP->sqrTime), elapsedTime);
2820 if (fs_stats_TimeLessThan(elapsedTime, (opP->minTime))) {
2821 fs_stats_TimeAssign((opP->minTime), elapsedTime);
2823 if (fs_stats_TimeGreaterThan(elapsedTime, (opP->maxTime))) {
2824 fs_stats_TimeAssign((opP->maxTime), elapsedTime);
2828 #endif /* FS_STATS_DETAILED */
2831 ViceLog(2, ("SAFS_InlineBulkStatus returns %d\n", errorCode));
2832 osi_auditU(acall, InlineBulkFetchStatusEvent, errorCode,
2833 AUD_ID, t_client ? t_client->ViceId : 0,
2834 AUD_FIDS, Fids, AUD_END);
2837 } /*SRXAFS_InlineBulkStatus */
2841 SRXAFS_FetchStatus(struct rx_call * acall, struct AFSFid * Fid,
2842 struct AFSFetchStatus * OutStatus,
2843 struct AFSCallBack * CallBack, struct AFSVolSync * Sync)
2846 struct rx_connection *tcon;
2847 struct client *t_client = NULL; /* tmp ptr to client data */
2848 #if FS_STATS_DETAILED
2849 struct fs_stats_opTimingData *opP; /* Ptr to this op's timing struct */
2850 struct timeval opStartTime, opStopTime; /* Start/stop times for RPC op */
2851 struct timeval elapsedTime; /* Transfer time */
2854 * Set our stats pointer, remember when the RPC operation started, and
2855 * tally the operation.
2857 opP = &(afs_FullPerfStats.det.rpcOpTimes[FS_STATS_RPCIDX_FETCHSTATUS]);
2861 TM_GetTimeOfDay(&opStartTime, 0);
2862 #endif /* FS_STATS_DETAILED */
2864 if ((code = CallPreamble(acall, ACTIVECALL, &tcon)))
2865 goto Bad_FetchStatus;
2867 code = SAFSS_FetchStatus(acall, Fid, OutStatus, CallBack, Sync);
2870 code = CallPostamble(tcon, code);
2872 t_client = (struct client *)rx_GetSpecific(tcon, rxcon_client_key);
2874 #if FS_STATS_DETAILED
2875 TM_GetTimeOfDay(&opStopTime, 0);
2878 (opP->numSuccesses)++;
2879 fs_stats_GetDiff(elapsedTime, opStartTime, opStopTime);
2880 fs_stats_AddTo((opP->sumTime), elapsedTime);
2881 fs_stats_SquareAddTo((opP->sqrTime), elapsedTime);
2882 if (fs_stats_TimeLessThan(elapsedTime, (opP->minTime))) {
2883 fs_stats_TimeAssign((opP->minTime), elapsedTime);
2885 if (fs_stats_TimeGreaterThan(elapsedTime, (opP->maxTime))) {
2886 fs_stats_TimeAssign((opP->maxTime), elapsedTime);
2890 #endif /* FS_STATS_DETAILED */
2892 osi_auditU(acall, FetchStatusEvent, code,
2893 AUD_ID, t_client ? t_client->ViceId : 0,
2894 AUD_FID, Fid, AUD_END);
2897 } /*SRXAFS_FetchStatus */
2901 common_StoreData64(struct rx_call *acall, struct AFSFid *Fid,
2902 struct AFSStoreStatus *InStatus, afs_fsize_t Pos,
2903 afs_fsize_t Length, afs_fsize_t FileLength,
2904 struct AFSFetchStatus *OutStatus, struct AFSVolSync *Sync)
2906 Vnode *targetptr = 0; /* pointer to input fid */
2907 Vnode *parentwhentargetnotdir = 0; /* parent of Fid to get ACL */
2908 Vnode tparentwhentargetnotdir; /* parent vnode for GetStatus */
2909 int errorCode = 0; /* return code for caller */
2910 int fileCode = 0; /* return code from vol package */
2911 Volume *volptr = 0; /* pointer to the volume header */
2912 struct client *client; /* pointer to client structure */
2913 afs_int32 rights, anyrights; /* rights for this and any user */
2914 struct client *t_client = NULL; /* tmp ptr to client data */
2915 struct in_addr logHostAddr; /* host ip holder for inet_ntoa */
2916 struct rx_connection *tcon;
2917 #if FS_STATS_DETAILED
2918 struct fs_stats_opTimingData *opP; /* Ptr to this op's timing struct */
2919 struct fs_stats_xferData *xferP; /* Ptr to this op's byte size struct */
2920 struct timeval opStartTime, opStopTime; /* Start/stop times for RPC op */
2921 struct timeval xferStartTime, xferStopTime; /* Start/stop times for xfer portion */
2922 struct timeval elapsedTime; /* Transfer time */
2923 afs_sfsize_t bytesToXfer; /* # bytes to xfer */
2924 afs_sfsize_t bytesXferred; /* # bytes actually xfer */
2925 static afs_int32 tot_bytesXferred; /* shared access protected by FS_LOCK */
2928 * Set our stats pointers, remember when the RPC operation started, and
2929 * tally the operation.
2931 opP = &(afs_FullPerfStats.det.rpcOpTimes[FS_STATS_RPCIDX_STOREDATA]);
2932 xferP = &(afs_FullPerfStats.det.xferOpTimes[FS_STATS_XFERIDX_STOREDATA]);
2937 ("StoreData: Fid = %u.%u.%u\n", Fid->Volume, Fid->Vnode,
2939 TM_GetTimeOfDay(&opStartTime, 0);
2940 #endif /* FS_STATS_DETAILED */
2943 AFSCallStats.StoreData++, AFSCallStats.TotalCalls++;
2945 if ((errorCode = CallPreamble(acall, ACTIVECALL, &tcon)))
2948 /* Get ptr to client data for user Id for logging */
2949 t_client = (struct client *)rx_GetSpecific(tcon, rxcon_client_key);
2950 logHostAddr.s_addr = rxr_HostOf(tcon);
2952 ("StoreData: Fid = %u.%u.%u, Host %s:%d, Id %d\n", Fid->Volume,
2953 Fid->Vnode, Fid->Unique, inet_ntoa(logHostAddr),
2954 rxr_PortOf(tcon), t_client->ViceId));
2957 * Get associated volume/vnode for the stored file; caller's rights
2961 GetVolumePackage(tcon, Fid, &volptr, &targetptr, MustNOTBeDIR,
2962 &parentwhentargetnotdir, &client, WRITE_LOCK,
2963 &rights, &anyrights))) {
2967 /* set volume synchronization information */
2968 SetVolumeSync(Sync, volptr);
2970 if ((targetptr->disk.type == vSymlink)) {
2971 /* Should we return a better error code here??? */
2976 /* Check if we're allowed to store the data */
2978 Check_PermissionRights(targetptr, client, rights, CHK_STOREDATA,
2984 * Drop the read lock on the parent directory after saving the parent
2985 * vnode information we need to pass to GetStatus
2987 if (parentwhentargetnotdir != NULL) {
2988 tparentwhentargetnotdir = *parentwhentargetnotdir;
2989 VPutVnode(&fileCode, parentwhentargetnotdir);
2990 assert(!fileCode || (fileCode == VSALVAGE));
2991 parentwhentargetnotdir = NULL;
2993 #if FS_STATS_DETAILED
2995 * Remember when the data transfer started.
2997 TM_GetTimeOfDay(&xferStartTime, 0);
2998 #endif /* FS_STATS_DETAILED */
3000 /* Do the actual storing of the data */
3001 #if FS_STATS_DETAILED
3003 StoreData_RXStyle(volptr, targetptr, Fid, client, acall, Pos, Length,
3004 FileLength, (InStatus->Mask & AFS_FSYNC),
3005 &bytesToXfer, &bytesXferred);
3008 StoreData_RXStyle(volptr, targetptr, Fid, client, acall, Pos, Length,
3009 FileLength, (InStatus->Mask & AFS_FSYNC));
3010 if (errorCode && (!targetptr->changed_newTime))
3012 #endif /* FS_STATS_DETAILED */
3013 #if FS_STATS_DETAILED
3015 * At this point, the data transfer is done, for good or ill. Remember
3016 * when the transfer ended, bump the number of successes/failures, and
3017 * integrate the transfer size and elapsed time into the stats. If the
3018 * operation failed, we jump to the appropriate point.
3020 TM_GetTimeOfDay(&xferStopTime, 0);
3022 (xferP->numXfers)++;
3024 (xferP->numSuccesses)++;
3027 * Bump the xfer sum by the number of bytes actually sent, NOT the
3030 tot_bytesXferred += bytesXferred;
3031 (xferP->sumBytes) += (tot_bytesXferred >> 10);
3032 tot_bytesXferred &= 0x3FF;
3033 if (bytesXferred < xferP->minBytes)
3034 xferP->minBytes = bytesXferred;
3035 if (bytesXferred > xferP->maxBytes)
3036 xferP->maxBytes = bytesXferred;
3039 * Tally the size of the object. Note: we tally the actual size,
3040 * NOT the number of bytes that made it out over the wire.
3042 if (bytesToXfer <= FS_STATS_MAXBYTES_BUCKET0)
3043 (xferP->count[0])++;
3044 else if (bytesToXfer <= FS_STATS_MAXBYTES_BUCKET1)
3045 (xferP->count[1])++;
3046 else if (bytesToXfer <= FS_STATS_MAXBYTES_BUCKET2)
3047 (xferP->count[2])++;
3048 else if (bytesToXfer <= FS_STATS_MAXBYTES_BUCKET3)
3049 (xferP->count[3])++;
3050 else if (bytesToXfer <= FS_STATS_MAXBYTES_BUCKET4)
3051 (xferP->count[4])++;
3052 else if (bytesToXfer <= FS_STATS_MAXBYTES_BUCKET5)
3053 (xferP->count[5])++;
3054 else if (bytesToXfer <= FS_STATS_MAXBYTES_BUCKET6)
3055 (xferP->count[6])++;
3056 else if (bytesToXfer <= FS_STATS_MAXBYTES_BUCKET7)
3057 (xferP->count[7])++;
3059 (xferP->count[8])++;
3061 fs_stats_GetDiff(elapsedTime, xferStartTime, xferStopTime);
3062 fs_stats_AddTo((xferP->sumTime), elapsedTime);
3063 fs_stats_SquareAddTo((xferP->sqrTime), elapsedTime);
3064 if (fs_stats_TimeLessThan(elapsedTime, (xferP->minTime))) {
3065 fs_stats_TimeAssign((xferP->minTime), elapsedTime);
3067 if (fs_stats_TimeGreaterThan(elapsedTime, (xferP->maxTime))) {
3068 fs_stats_TimeAssign((xferP->maxTime), elapsedTime);
3073 * Finally, go off to tell our caller the bad news in case the
3076 if (errorCode && (!targetptr->changed_newTime))
3078 #endif /* FS_STATS_DETAILED */
3080 /* Update the status of the target's vnode */
3081 Update_TargetVnodeStatus(targetptr, TVS_SDATA, client, InStatus,
3082 targetptr, volptr, 0);
3084 /* Get the updated File's status back to the caller */
3085 GetStatus(targetptr, OutStatus, rights, anyrights,
3086 &tparentwhentargetnotdir);
3089 /* Update and store volume/vnode and parent vnodes back */
3090 (void)PutVolumePackage(parentwhentargetnotdir, targetptr, (Vnode *) 0,
3092 ViceLog(2, ("SAFS_StoreData returns %d\n", errorCode));
3094 errorCode = CallPostamble(tcon, errorCode);
3096 #if FS_STATS_DETAILED
3097 TM_GetTimeOfDay(&opStopTime, 0);
3098 if (errorCode == 0) {
3100 (opP->numSuccesses)++;
3101 fs_stats_GetDiff(elapsedTime, opStartTime, opStopTime);
3102 fs_stats_AddTo((opP->sumTime), elapsedTime);
3103 fs_stats_SquareAddTo((opP->sqrTime), elapsedTime);
3104 if (fs_stats_TimeLessThan(elapsedTime, (opP->minTime))) {
3105 fs_stats_TimeAssign((opP->minTime), elapsedTime);
3107 if (fs_stats_TimeGreaterThan(elapsedTime, (opP->maxTime))) {
3108 fs_stats_TimeAssign((opP->maxTime), elapsedTime);
3112 #endif /* FS_STATS_DETAILED */
3113 osi_auditU(acall, StoreDataEvent, errorCode,
3114 AUD_ID, t_client ? t_client->ViceId : 0,
3115 AUD_FID, Fid, AUD_END);
3117 } /*common_StoreData64 */
3120 SRXAFS_StoreData(struct rx_call * acall, struct AFSFid * Fid,
3121 struct AFSStoreStatus * InStatus, afs_uint32 Pos,
3122 afs_uint32 Length, afs_uint32 FileLength,
3123 struct AFSFetchStatus * OutStatus, struct AFSVolSync * Sync)
3125 return common_StoreData64(acall, Fid, InStatus, Pos, Length, FileLength,
3127 } /*SRXAFS_StoreData */
3130 SRXAFS_StoreData64(struct rx_call * acall, struct AFSFid * Fid,
3131 struct AFSStoreStatus * InStatus, afs_uint64 Pos,
3132 afs_uint64 Length, afs_uint64 FileLength,
3133 struct AFSFetchStatus * OutStatus,
3134 struct AFSVolSync * Sync)
3138 afs_fsize_t tLength;
3139 afs_fsize_t tFileLength;
3141 #ifdef AFS_64BIT_ENV
3142 #ifndef AFS_LARGEFILE_ENV
3143 if (FileLength > 0x7fffffff)
3145 #endif /* !AFS_LARGEFILE_ENV */
3146 tPos = (afs_fsize_t) Pos;
3147 tLength = (afs_fsize_t) Length;
3148 tFileLength = (afs_fsize_t) FileLength;
3149 #else /* AFS_64BIT_ENV */
3150 if (FileLength.high)
3153 tLength = Length.low;
3154 tFileLength = FileLength.low;
3155 #endif /* AFS_64BIT_ENV */
3158 common_StoreData64(acall, Fid, InStatus, tPos, tLength, tFileLength,
3164 SRXAFS_StoreACL(struct rx_call * acall, struct AFSFid * Fid,
3165 struct AFSOpaque * AccessList,
3166 struct AFSFetchStatus * OutStatus, struct AFSVolSync * Sync)
3168 Vnode *targetptr = 0; /* pointer to input fid */
3169 Vnode *parentwhentargetnotdir = 0; /* parent of Fid to get ACL */
3170 int errorCode = 0; /* return code for caller */
3171 struct AFSStoreStatus InStatus; /* Input status for fid */
3172 Volume *volptr = 0; /* pointer to the volume header */
3173 struct client *client; /* pointer to client structure */
3174 afs_int32 rights, anyrights; /* rights for this and any user */
3175 struct rx_connection *tcon;
3176 struct client *t_client = NULL; /* tmp ptr to client data */
3177 struct in_addr logHostAddr; /* host ip holder for inet_ntoa */
3178 #if FS_STATS_DETAILED
3179 struct fs_stats_opTimingData *opP; /* Ptr to this op's timing struct */
3180 struct timeval opStartTime, opStopTime; /* Start/stop times for RPC op */
3181 struct timeval elapsedTime; /* Transfer time */
3184 * Set our stats pointer, remember when the RPC operation started, and
3185 * tally the operation.
3187 opP = &(afs_FullPerfStats.det.rpcOpTimes[FS_STATS_RPCIDX_STOREACL]);
3191 TM_GetTimeOfDay(&opStartTime, 0);
3192 #endif /* FS_STATS_DETAILED */
3193 if ((errorCode = CallPreamble(acall, ACTIVECALL, &tcon)))
3196 /* Get ptr to client data for user Id for logging */
3197 t_client = (struct client *)rx_GetSpecific(tcon, rxcon_client_key);
3198 logHostAddr.s_addr = rxr_HostOf(tcon);
3200 ("SAFS_StoreACL, Fid = %u.%u.%u, ACL=%s, Host %s:%d, Id %d\n",
3201 Fid->Volume, Fid->Vnode, Fid->Unique, AccessList->AFSOpaque_val,
3202 inet_ntoa(logHostAddr), rxr_PortOf(tcon), t_client->ViceId));
3204 AFSCallStats.StoreACL++, AFSCallStats.TotalCalls++;
3206 InStatus.Mask = 0; /* not storing any status */
3209 * Get associated volume/vnode for the target dir; caller's rights
3210 * are also returned.
3213 GetVolumePackage(tcon, Fid, &volptr, &targetptr, MustBeDIR,
3214 &parentwhentargetnotdir, &client, WRITE_LOCK,
3215 &rights, &anyrights))) {
3219 /* set volume synchronization information */
3220 SetVolumeSync(Sync, volptr);
3222 /* Check if we have permission to change the dir's ACL */
3224 Check_PermissionRights(targetptr, client, rights, CHK_STOREACL,
3229 /* Build and store the new Access List for the dir */
3230 if ((errorCode = RXStore_AccessList(targetptr, AccessList))) {
3234 targetptr->changed_newTime = 1; /* status change of directory */
3236 /* convert the write lock to a read lock before breaking callbacks */
3237 VVnodeWriteToRead(&errorCode, targetptr);
3238 assert(!errorCode || errorCode == VSALVAGE);
3240 /* break call backs on the directory */
3241 BreakCallBack(client->host, Fid, 0);
3243 /* Get the updated dir's status back to the caller */
3244 GetStatus(targetptr, OutStatus, rights, anyrights, 0);
3247 /* Update and store volume/vnode and parent vnodes back */
3248 PutVolumePackage(parentwhentargetnotdir, targetptr, (Vnode *) 0, volptr);
3249 ViceLog(2, ("SAFS_StoreACL returns %d\n", errorCode));
3250 errorCode = CallPostamble(tcon, errorCode);
3252 #if FS_STATS_DETAILED
3253 TM_GetTimeOfDay(&opStopTime, 0);
3254 if (errorCode == 0) {
3256 (opP->numSuccesses)++;
3257 fs_stats_GetDiff(elapsedTime, opStartTime, opStopTime);
3258 fs_stats_AddTo((opP->sumTime), elapsedTime);
3259 fs_stats_SquareAddTo((opP->sqrTime), elapsedTime);
3260 if (fs_stats_TimeLessThan(elapsedTime, (opP->minTime))) {
3261 fs_stats_TimeAssign((opP->minTime), elapsedTime);
3263 if (fs_stats_TimeGreaterThan(elapsedTime, (opP->maxTime))) {
3264 fs_stats_TimeAssign((opP->maxTime), elapsedTime);
3268 #endif /* FS_STATS_DETAILED */
3270 osi_auditU(acall, StoreACLEvent, errorCode,
3271 AUD_ID, t_client ? t_client->ViceId : 0,
3272 AUD_FID, Fid, AUD_ACL, AccessList->AFSOpaque_val, AUD_END);
3275 } /*SRXAFS_StoreACL */
3279 * Note: This routine is called exclusively from SRXAFS_StoreStatus(), and
3280 * should be merged when possible.
3283 SAFSS_StoreStatus(struct rx_call *acall, struct AFSFid *Fid,
3284 struct AFSStoreStatus *InStatus,
3285 struct AFSFetchStatus *OutStatus, struct AFSVolSync *Sync)
3287 Vnode *targetptr = 0; /* pointer to input fid */
3288 Vnode *parentwhentargetnotdir = 0; /* parent of Fid to get ACL */
3289 int errorCode = 0; /* return code for caller */
3290 Volume *volptr = 0; /* pointer to the volume header */
3291 struct client *client; /* pointer to client structure */
3292 afs_int32 rights, anyrights; /* rights for this and any user */
3293 struct client *t_client = NULL; /* tmp ptr to client data */
3294 struct in_addr logHostAddr; /* host ip holder for inet_ntoa */
3295 struct rx_connection *tcon = rx_ConnectionOf(acall);
3297 /* Get ptr to client data for user Id for logging */
3298 t_client = (struct client *)rx_GetSpecific(tcon, rxcon_client_key);
3299 logHostAddr.s_addr = rxr_HostOf(tcon);
3301 ("SAFS_StoreStatus, Fid = %u.%u.%u, Host %s:%d, Id %d\n",
3302 Fid->Volume, Fid->Vnode, Fid->Unique, inet_ntoa(logHostAddr),
3303 rxr_PortOf(tcon), t_client->ViceId));
3305 AFSCallStats.StoreStatus++, AFSCallStats.TotalCalls++;
3308 * Get volume/vnode for the target file; caller's rights to it are
3312 GetVolumePackage(tcon, Fid, &volptr, &targetptr, DONTCHECK,
3313 &parentwhentargetnotdir, &client, WRITE_LOCK,
3314 &rights, &anyrights))) {
3315 goto Bad_StoreStatus;
3318 /* set volume synchronization information */
3319 SetVolumeSync(Sync, volptr);
3321 /* Check if the caller has proper permissions to store status to Fid */
3323 Check_PermissionRights(targetptr, client, rights, CHK_STORESTATUS,
3325 goto Bad_StoreStatus;
3328 * Check for a symbolic link; we can't chmod these (otherwise could
3329 * change a symlink to a mt pt or vice versa)
3331 if (targetptr->disk.type == vSymlink && (InStatus->Mask & AFS_SETMODE)) {
3333 goto Bad_StoreStatus;
3336 /* Update the status of the target's vnode */
3337 Update_TargetVnodeStatus(targetptr, TVS_SSTATUS, client, InStatus,
3338 (parentwhentargetnotdir ? parentwhentargetnotdir
3339 : targetptr), volptr, 0);
3341 /* convert the write lock to a read lock before breaking callbacks */
3342 VVnodeWriteToRead(&errorCode, targetptr);
3343 assert(!errorCode || errorCode == VSALVAGE);
3345 /* Break call backs on Fid */
3346 BreakCallBack(client->host, Fid, 0);
3348 /* Return the updated status back to caller */
3349 GetStatus(targetptr, OutStatus, rights, anyrights,
3350 parentwhentargetnotdir);
3353 /* Update and store volume/vnode and parent vnodes back */
3354 PutVolumePackage(parentwhentargetnotdir, targetptr, (Vnode *) 0, volptr);
3355 ViceLog(2, ("SAFS_StoreStatus returns %d\n", errorCode));
3358 } /*SAFSS_StoreStatus */
3362 SRXAFS_StoreStatus(struct rx_call * acall, struct AFSFid * Fid,
3363 struct AFSStoreStatus * InStatus,
3364 struct AFSFetchStatus * OutStatus,
3365 struct AFSVolSync * Sync)
3368 struct rx_connection *tcon;
3369 struct client *t_client = NULL; /* tmp ptr to client data */
3370 #if FS_STATS_DETAILED
3371 struct fs_stats_opTimingData *opP; /* Ptr to this op's timing struct */
3372 struct timeval opStartTime, opStopTime; /* Start/stop times for RPC op */
3373 struct timeval elapsedTime; /* Transfer time */
3376 * Set our stats pointer, remember when the RPC operation started, and
3377 * tally the operation.
3379 opP = &(afs_FullPerfStats.det.rpcOpTimes[FS_STATS_RPCIDX_STORESTATUS]);
3383 TM_GetTimeOfDay(&opStartTime, 0);
3384 #endif /* FS_STATS_DETAILED */
3386 if ((code = CallPreamble(acall, ACTIVECALL, &tcon)))
3387 goto Bad_StoreStatus;
3389 code = SAFSS_StoreStatus(acall, Fid, InStatus, OutStatus, Sync);
3392 code = CallPostamble(tcon, code);
3394 t_client = (struct client *)rx_GetSpecific(tcon, rxcon_client_key);
3396 #if FS_STATS_DETAILED
3397 TM_GetTimeOfDay(&opStopTime, 0);
3400 (opP->numSuccesses)++;
3401 fs_stats_GetDiff(elapsedTime, opStartTime, opStopTime);
3402 fs_stats_AddTo((opP->sumTime), elapsedTime);
3403 fs_stats_SquareAddTo((opP->sqrTime), elapsedTime);
3404 if (fs_stats_TimeLessThan(elapsedTime, (opP->minTime))) {
3405 fs_stats_TimeAssign((opP->minTime), elapsedTime);
3407 if (fs_stats_TimeGreaterThan(elapsedTime, (opP->maxTime))) {
3408 fs_stats_TimeAssign((opP->maxTime), elapsedTime);
3412 #endif /* FS_STATS_DETAILED */
3414 osi_auditU(acall, StoreStatusEvent, code,
3415 AUD_ID, t_client ? t_client->ViceId : 0,
3416 AUD_FID, Fid, AUD_END);
3419 } /*SRXAFS_StoreStatus */
3423 * This routine is called exclusively by SRXAFS_RemoveFile(), and should be
3424 * merged in when possible.
3427 SAFSS_RemoveFile(struct rx_call *acall, struct AFSFid *DirFid, char *Name,
3428 struct AFSFetchStatus *OutDirStatus, struct AFSVolSync *Sync)
3430 Vnode *parentptr = 0; /* vnode of input Directory */
3431 Vnode *parentwhentargetnotdir = 0; /* parent for use in SetAccessList */
3432 Vnode *targetptr = 0; /* file to be deleted */
3433 Volume *volptr = 0; /* pointer to the volume header */
3434 AFSFid fileFid; /* area for Fid from the directory */
3435 int errorCode = 0; /* error code */
3436 DirHandle dir; /* Handle for dir package I/O */
3437 struct client *client; /* pointer to client structure */
3438 afs_int32 rights, anyrights; /* rights for this and any user */
3439 struct client *t_client; /* tmp ptr to client data */
3440 struct in_addr logHostAddr; /* host ip holder for inet_ntoa */
3441 struct rx_connection *tcon = rx_ConnectionOf(acall);
3444 /* Get ptr to client data for user Id for logging */
3445 t_client = (struct client *)rx_GetSpecific(tcon, rxcon_client_key);
3446 logHostAddr.s_addr = rxr_HostOf(tcon);
3448 ("SAFS_RemoveFile %s, Did = %u.%u.%u, Host %s:%d, Id %d\n", Name,
3449 DirFid->Volume, DirFid->Vnode, DirFid->Unique,
3450 inet_ntoa(logHostAddr), rxr_PortOf(tcon), t_client->ViceId));
3452 AFSCallStats.RemoveFile++, AFSCallStats.TotalCalls++;
3455 * Get volume/vnode for the parent dir; caller's access rights are
3459 GetVolumePackage(tcon, DirFid, &volptr, &parentptr, MustBeDIR,
3460 &parentwhentargetnotdir, &client, WRITE_LOCK,
3461 &rights, &anyrights))) {
3462 goto Bad_RemoveFile;
3464 /* set volume synchronization information */
3465 SetVolumeSync(Sync, volptr);
3467 /* Does the caller has delete (& write) access to the parent directory? */
3468 if ((errorCode = CheckWriteMode(parentptr, rights, PRSFS_DELETE))) {
3469 goto Bad_RemoveFile;
3472 /* Actually delete the desired file */
3474 DeleteTarget(parentptr, volptr, &targetptr, &dir, &fileFid, Name,
3476 goto Bad_RemoveFile;
3479 /* Update the vnode status of the parent dir */
3480 #if FS_STATS_DETAILED
3481 Update_ParentVnodeStatus(parentptr, volptr, &dir, client->ViceId,
3482 parentptr->disk.linkCount,
3483 client->InSameNetwork);
3485 Update_ParentVnodeStatus(parentptr, volptr, &dir, client->ViceId,
3486 parentptr->disk.linkCount);
3487 #endif /* FS_STATS_DETAILED */
3489 /* Return the updated parent dir's status back to caller */
3490 GetStatus(parentptr, OutDirStatus, rights, anyrights, 0);
3492 /* Handle internal callback state for the parent and the deleted file */
3493 if (targetptr->disk.linkCount == 0) {
3494 /* no references left, discard entry */
3495 DeleteFileCallBacks(&fileFid);
3496 /* convert the parent lock to a read lock before breaking callbacks */
3497 VVnodeWriteToRead(&errorCode, parentptr);
3498 assert(!errorCode || errorCode == VSALVAGE);
3500 /* convert the parent lock to a read lock before breaking callbacks */
3501 VVnodeWriteToRead(&errorCode, parentptr);
3502 assert(!errorCode || errorCode == VSALVAGE);
3503 /* convert the target lock to a read lock before breaking callbacks */
3504 VVnodeWriteToRead(&errorCode, targetptr);
3505 assert(!errorCode || errorCode == VSALVAGE);
3506 /* tell all the file has changed */
3507 BreakCallBack(client->host, &fileFid, 1);
3510 /* break call back on the directory */
3511 BreakCallBack(client->host, DirFid, 0);
3514 /* Update and store volume/vnode and parent vnodes back */
3515 PutVolumePackage(parentwhentargetnotdir, targetptr, parentptr, volptr);
3517 ViceLog(2, ("SAFS_RemoveFile returns %d\n", errorCode));
3520 } /*SAFSS_RemoveFile */
3524 SRXAFS_RemoveFile(struct rx_call * acall, struct AFSFid * DirFid, char *Name,
3525 struct AFSFetchStatus * OutDirStatus,
3526 struct AFSVolSync * Sync)
3529 struct rx_connection *tcon;
3530 struct client *t_client = NULL; /* tmp ptr to client data */
3531 #if FS_STATS_DETAILED
3532 struct fs_stats_opTimingData *opP; /* Ptr to this op's timing struct */
3533 struct timeval opStartTime, opStopTime; /* Start/stop times for RPC op */
3534 struct timeval elapsedTime; /* Transfer time */
3537 * Set our stats pointer, remember when the RPC operation started, and
3538 * tally the operation.
3540 opP = &(afs_FullPerfStats.det.rpcOpTimes[FS_STATS_RPCIDX_REMOVEFILE]);
3544 TM_GetTimeOfDay(&opStartTime, 0);
3545 #endif /* FS_STATS_DETAILED */
3547 if ((code = CallPreamble(acall, ACTIVECALL, &tcon)))
3548 goto Bad_RemoveFile;
3550 code = SAFSS_RemoveFile(acall, DirFid, Name, OutDirStatus, Sync);
3553 code = CallPostamble(tcon, code);
3555 t_client = (struct client *)rx_GetSpecific(tcon, rxcon_client_key);
3557 #if FS_STATS_DETAILED
3558 TM_GetTimeOfDay(&opStopTime, 0);
3561 (opP->numSuccesses)++;
3562 fs_stats_GetDiff(elapsedTime, opStartTime, opStopTime);
3563 fs_stats_AddTo((opP->sumTime), elapsedTime);
3564 fs_stats_SquareAddTo((opP->sqrTime), elapsedTime);
3565 if (fs_stats_TimeLessThan(elapsedTime, (opP->minTime))) {
3566 fs_stats_TimeAssign((opP->minTime), elapsedTime);
3568 if (fs_stats_TimeGreaterThan(elapsedTime, (opP->maxTime))) {
3569 fs_stats_TimeAssign((opP->maxTime), elapsedTime);
3573 #endif /* FS_STATS_DETAILED */
3575 osi_auditU(acall, RemoveFileEvent, code,
3576 AUD_ID, t_client ? t_client->ViceId : 0,
3577 AUD_FID, DirFid, AUD_STR, Name, AUD_END);
3580 } /*SRXAFS_RemoveFile */
3584 * This routine is called exclusively from SRXAFS_CreateFile(), and should
3585 * be merged in when possible.
3588 SAFSS_CreateFile(struct rx_call *acall, struct AFSFid *DirFid, char *Name,
3589 struct AFSStoreStatus *InStatus, struct AFSFid *OutFid,
3590 struct AFSFetchStatus *OutFidStatus,
3591 struct AFSFetchStatus *OutDirStatus,
3592 struct AFSCallBack *CallBack, struct AFSVolSync *Sync)
3594 Vnode *parentptr = 0; /* vnode of input Directory */
3595 Vnode *targetptr = 0; /* vnode of the new file */
3596 Vnode *parentwhentargetnotdir = 0; /* parent for use in SetAccessList */
3597 Volume *volptr = 0; /* pointer to the volume header */
3598 int errorCode = 0; /* error code */
3599 DirHandle dir; /* Handle for dir package I/O */
3600 struct client *client; /* pointer to client structure */
3601 afs_int32 rights, anyrights; /* rights for this and any user */
3602 struct client *t_client; /* tmp ptr to client data */
3603 struct in_addr logHostAddr; /* host ip holder for inet_ntoa */
3604 struct rx_connection *tcon = rx_ConnectionOf(acall);
3608 /* Get ptr to client data for user Id for logging */
3609 t_client = (struct client *)rx_GetSpecific(tcon, rxcon_client_key);
3610 logHostAddr.s_addr = rxr_HostOf(tcon);
3612 ("SAFS_CreateFile %s, Did = %u.%u.%u, Host %s:%d, Id %d\n", Name,
3613 DirFid->Volume, DirFid->Vnode, DirFid->Unique,
3614 inet_ntoa(logHostAddr), rxr_PortOf(tcon), t_client->ViceId));
3616 AFSCallStats.CreateFile++, AFSCallStats.TotalCalls++;
3618 if (!FileNameOK(Name)) {
3620 goto Bad_CreateFile;
3624 * Get associated volume/vnode for the parent dir; caller long are
3628 GetVolumePackage(tcon, DirFid, &volptr, &parentptr, MustBeDIR,
3629 &parentwhentargetnotdir, &client, WRITE_LOCK,
3630 &rights, &anyrights))) {
3631 goto Bad_CreateFile;
3634 /* set volume synchronization information */
3635 SetVolumeSync(Sync, volptr);
3637 /* Can we write (and insert) onto the parent directory? */
3638 if ((errorCode = CheckWriteMode(parentptr, rights, PRSFS_INSERT))) {
3639 goto Bad_CreateFile;
3641 /* get a new vnode for the file to be created and set it up */
3643 Alloc_NewVnode(parentptr, &dir, volptr, &targetptr, Name, OutFid,
3644 vFile, nBlocks(0)))) {
3645 goto Bad_CreateFile;
3648 /* update the status of the parent vnode */
3649 #if FS_STATS_DETAILED
3650 Update_ParentVnodeStatus(parentptr, volptr, &dir, client->ViceId,
3651 parentptr->disk.linkCount,
3652 client->InSameNetwork);
3654 Update_ParentVnodeStatus(parentptr, volptr, &dir, client->ViceId,
3655 parentptr->disk.linkCount);
3656 #endif /* FS_STATS_DETAILED */
3658 /* update the status of the new file's vnode */
3659 Update_TargetVnodeStatus(targetptr, TVS_CFILE, client, InStatus,
3660 parentptr, volptr, 0);
3662 /* set up the return status for the parent dir and the newly created file, and since the newly created file is owned by the creator, give it PRSFS_ADMINISTER to tell the client its the owner of the file */
3663 GetStatus(targetptr, OutFidStatus, rights | PRSFS_ADMINISTER, anyrights, parentptr);
3664 GetStatus(parentptr, OutDirStatus, rights, anyrights, 0);
3666 /* convert the write lock to a read lock before breaking callbacks */
3667 VVnodeWriteToRead(&errorCode, parentptr);
3668 assert(!errorCode || errorCode == VSALVAGE);
3670 /* break call back on parent dir */
3671 BreakCallBack(client->host, DirFid, 0);
3673 /* Return a callback promise for the newly created file to the caller */
3674 SetCallBackStruct(AddCallBack(client->host, OutFid), CallBack);
3677 /* Update and store volume/vnode and parent vnodes back */
3678 (void)PutVolumePackage(parentwhentargetnotdir, targetptr, parentptr,
3681 ViceLog(2, ("SAFS_CreateFile returns %d\n", errorCode));
3684 } /*SAFSS_CreateFile */
3688 SRXAFS_CreateFile(struct rx_call * acall, struct AFSFid * DirFid, char *Name,
3689 struct AFSStoreStatus * InStatus, struct AFSFid * OutFid,
3690 struct AFSFetchStatus * OutFidStatus,
3691 struct AFSFetchStatus * OutDirStatus,
3692 struct AFSCallBack * CallBack, struct AFSVolSync * Sync)
3695 struct rx_connection *tcon;
3696 struct client *t_client = NULL; /* tmp ptr to client data */
3697 #if FS_STATS_DETAILED
3698 struct fs_stats_opTimingData *opP; /* Ptr to this op's timing struct */
3699 struct timeval opStartTime, opStopTime; /* Start/stop times for RPC op */
3700 struct timeval elapsedTime; /* Transfer time */
3703 * Set our stats pointer, remember when the RPC operation started, and
3704 * tally the operation.
3706 opP = &(afs_FullPerfStats.det.rpcOpTimes[FS_STATS_RPCIDX_CREATEFILE]);
3710 TM_GetTimeOfDay(&opStartTime, 0);
3711 #endif /* FS_STATS_DETAILED */
3713 memset(OutFid, 0, sizeof(struct AFSFid));
3715 if ((code = CallPreamble(acall, ACTIVECALL, &tcon)))
3716 goto Bad_CreateFile;
3719 SAFSS_CreateFile(acall, DirFid, Name, InStatus, OutFid, OutFidStatus,
3720 OutDirStatus, CallBack, Sync);
3723 code = CallPostamble(tcon, code);
3725 t_client = (struct client *)rx_GetSpecific(tcon, rxcon_client_key);
3727 #if FS_STATS_DETAILED
3728 TM_GetTimeOfDay(&opStopTime, 0);
3731 (opP->numSuccesses)++;
3732 fs_stats_GetDiff(elapsedTime, opStartTime, opStopTime);
3733 fs_stats_AddTo((opP->sumTime), elapsedTime);
3734 fs_stats_SquareAddTo((opP->sqrTime), elapsedTime);
3735 if (fs_stats_TimeLessThan(elapsedTime, (opP->minTime))) {
3736 fs_stats_TimeAssign((opP->minTime), elapsedTime);
3738 if (fs_stats_TimeGreaterThan(elapsedTime, (opP->maxTime))) {
3739 fs_stats_TimeAssign((opP->maxTime), elapsedTime);
3743 #endif /* FS_STATS_DETAILED */
3745 osi_auditU(acall, CreateFileEvent, code,
3746 AUD_ID, t_client ? t_client->ViceId : 0,
3747 AUD_FID, DirFid, AUD_STR, Name, AUD_FID, OutFid, AUD_END);
3750 } /*SRXAFS_CreateFile */
3754 * This routine is called exclusively from SRXAFS_Rename(), and should be
3755 * merged in when possible.
3758 SAFSS_Rename(struct rx_call *acall, struct AFSFid *OldDirFid, char *OldName,
3759 struct AFSFid *NewDirFid, char *NewName,
3760 struct AFSFetchStatus *OutOldDirStatus,
3761 struct AFSFetchStatus *OutNewDirStatus, struct AFSVolSync *Sync)
3763 Vnode *oldvptr = 0; /* vnode of the old Directory */
3764 Vnode *newvptr = 0; /* vnode of the new Directory */
3765 Vnode *fileptr = 0; /* vnode of the file to move */
3766 Vnode *newfileptr = 0; /* vnode of the file to delete */
3767 Vnode *testvptr = 0; /* used in directory tree walk */
3768 Vnode *parent = 0; /* parent for use in SetAccessList */
3769 int errorCode = 0; /* error code */
3770 int fileCode = 0; /* used when writing Vnodes */
3771 VnodeId testnode; /* used in directory tree walk */
3772 AFSFid fileFid; /* Fid of file to move */
3773 AFSFid newFileFid; /* Fid of new file */
3774 DirHandle olddir; /* Handle for dir package I/O */
3775 DirHandle newdir; /* Handle for dir package I/O */
3776 DirHandle filedir; /* Handle for dir package I/O */
3777 DirHandle newfiledir; /* Handle for dir package I/O */
3778 Volume *volptr = 0; /* pointer to the volume header */
3779 struct client *client; /* pointer to client structure */
3780 afs_int32 rights, anyrights; /* rights for this and any user */
3781 afs_int32 newrights; /* rights for this user */
3782 afs_int32 newanyrights; /* rights for any user */
3783 int doDelete; /* deleted the rename target (ref count now 0) */
3785 struct client *t_client; /* tmp ptr to client data */
3786 struct in_addr logHostAddr; /* host ip holder for inet_ntoa */
3787 struct rx_connection *tcon = rx_ConnectionOf(acall);
3792 FidZero(&newfiledir);
3794 /* Get ptr to client data for user Id for logging */
3795 t_client = (struct client *)rx_GetSpecific(tcon, rxcon_client_key);
3796 logHostAddr.s_addr = rxr_HostOf(tcon);
3798 ("SAFS_Rename %s to %s, Fid = %u.%u.%u to %u.%u.%u, Host %s:%d, Id %d\n",
3799 OldName, NewName, OldDirFid->Volume, OldDirFid->Vnode,
3800 OldDirFid->Unique, NewDirFid->Volume, NewDirFid->Vnode,
3801 NewDirFid->Unique, inet_ntoa(logHostAddr), rxr_PortOf(tcon), t_client->ViceId));
3803 AFSCallStats.Rename++, AFSCallStats.TotalCalls++;
3805 if (!FileNameOK(NewName)) {
3809 if (OldDirFid->Volume != NewDirFid->Volume) {
3814 if ((strcmp(OldName, ".") == 0) || (strcmp(OldName, "..") == 0)
3815 || (strcmp(NewName, ".") == 0) || (strcmp(NewName, "..") == 0)
3816 || (strlen(NewName) == 0) || (strlen(OldName) == 0)) {
3822 if (OldDirFid->Vnode <= NewDirFid->Vnode) {
3824 GetVolumePackage(tcon, OldDirFid, &volptr, &oldvptr, MustBeDIR,
3825 &parent, &client, WRITE_LOCK, &rights,
3830 if (OldDirFid->Vnode == NewDirFid->Vnode) {
3832 newrights = rights, newanyrights = anyrights;
3835 GetVolumePackage(tcon, NewDirFid, &volptr, &newvptr,
3836 MustBeDIR, &parent, &client, WRITE_LOCK,
3837 &newrights, &newanyrights))) {
3843 GetVolumePackage(tcon, NewDirFid, &volptr, &newvptr, MustBeDIR,
3844 &parent, &client, WRITE_LOCK, &newrights,
3850 GetVolumePackage(tcon, OldDirFid, &volptr, &oldvptr, MustBeDIR,
3851 &parent, &client, WRITE_LOCK, &rights,
3858 /* set volume synchronization information */
3859 SetVolumeSync(Sync, volptr);
3861 if ((errorCode = CheckWriteMode(oldvptr, rights, PRSFS_DELETE))) {
3864 if ((errorCode = CheckWriteMode(newvptr, newrights, PRSFS_INSERT))) {
3868 /* The CopyOnWrite might return ENOSPC ( disk full). Even if the second
3869 * call to CopyOnWrite returns error, it is not necessary to revert back
3870 * the effects of the first call because the contents of the volume is
3871 * not modified, it is only replicated.
3873 if (oldvptr->disk.cloned) {
3874 ViceLog(25, ("Rename : calling CopyOnWrite on old dir\n"));
3875 if ((errorCode = CopyOnWrite(oldvptr, volptr)))
3878 SetDirHandle(&olddir, oldvptr);
3879 if (newvptr->disk.cloned) {
3880 ViceLog(25, ("Rename : calling CopyOnWrite on new dir\n"));
3881 if ((errorCode = CopyOnWrite(newvptr, volptr)))
3885 SetDirHandle(&newdir, newvptr);
3887 /* Lookup the file to delete its vnode */
3888 if (Lookup(&olddir, OldName, &fileFid)) {
3892 if (fileFid.Vnode == oldvptr->vnodeNumber
3893 || fileFid.Vnode == newvptr->vnodeNumber) {
3894 errorCode = FSERR_ELOOP;
3897 fileFid.Volume = V_id(volptr);
3898 fileptr = VGetVnode(&errorCode, volptr, fileFid.Vnode, WRITE_LOCK);
3899 if (errorCode != 0) {
3901 ("SAFSS_Rename(): Error in VGetVnode() for old file %s, code %d\n",
3902 OldName, errorCode));
3903 VTakeOffline(volptr);
3906 if (fileptr->disk.uniquifier != fileFid.Unique) {
3908 ("SAFSS_Rename(): Old file %s uniquifier mismatch\n",
3910 VTakeOffline(volptr);
3915 if (fileptr->disk.type != vDirectory && oldvptr != newvptr
3916 && fileptr->disk.linkCount != 1) {
3918 * Hard links exist to this file - cannot move one of the links to
3919 * a new directory because of AFS restrictions (this is the same
3920 * reason that links cannot be made across directories, i.e.
3927 /* Lookup the new file */
3928 if (!(Lookup(&newdir, NewName, &newFileFid))) {
3929 if (readonlyServer) {
3930 errorCode = VREADONLY;
3933 if (!(newrights & PRSFS_DELETE)) {
3937 if (newFileFid.Vnode == oldvptr->vnodeNumber
3938 || newFileFid.Vnode == newvptr->vnodeNumber
3939 || newFileFid.Vnode == fileFid.Vnode) {
3943 newFileFid.Volume = V_id(volptr);
3945 VGetVnode(&errorCode, volptr, newFileFid.Vnode, WRITE_LOCK);
3946 if (errorCode != 0) {
3948 ("SAFSS_Rename(): Error in VGetVnode() for new file %s, code %d\n",
3949 NewName, errorCode));
3950 VTakeOffline(volptr);
3953 if (fileptr->disk.uniquifier != fileFid.Unique) {
3955 ("SAFSS_Rename(): New file %s uniquifier mismatch\n",
3957 VTakeOffline(volptr);
3961 SetDirHandle(&newfiledir, newfileptr);
3962 /* Now check that we're moving directories over directories properly, etc.
3963 * return proper POSIX error codes:
3964 * if fileptr is a file and new is a dir: EISDIR.
3965 * if fileptr is a dir and new is a file: ENOTDIR.
3966 * Also, dir to be removed must be empty, of course.
3968 if (newfileptr->disk.type == vDirectory) {
3969 if (fileptr->disk.type != vDirectory) {
3973 if ((IsEmpty(&newfiledir))) {
3978 if (fileptr->disk.type == vDirectory) {
3979 errorCode = ENOTDIR;
3986 * ok - now we check that the old name is not above new name in the
3987 * directory structure. This is to prevent removing a subtree alltogether
3989 if ((oldvptr != newvptr) && (fileptr->disk.type == vDirectory)) {
3990 afs_int32 forpass = 0, vnum = 0, top = 0;
3991 for (testnode = newvptr->disk.parent; testnode != 0; forpass++) {
3992 if (testnode > vnum) vnum = testnode;
3993 if (forpass > vnum) {
3994 errorCode = FSERR_ELOOP;
3997 if (testnode == oldvptr->vnodeNumber) {
3998 testnode = oldvptr->disk.parent;
4001 if ((testnode == fileptr->vnodeNumber)
4002 || (testnode == newvptr->vnodeNumber)) {
4003 errorCode = FSERR_ELOOP;
4006 if ((newfileptr) && (testnode == newfileptr->vnodeNumber)) {
4007 errorCode = FSERR_ELOOP;
4010 if (testnode == 1) top = 1;
4011 testvptr = VGetVnode(&errorCode, volptr, testnode, READ_LOCK);
4012 assert(errorCode == 0);
4013 testnode = testvptr->disk.parent;
4014 VPutVnode(&errorCode, testvptr);
4015 if ((top == 1) && (testnode != 0)) {
4016 VTakeOffline(volptr);
4020 assert(errorCode == 0);
4023 /* Do the CopyonWrite first before modifying anything else. Copying is
4024 * required because we may have to change entries for ..
4026 if ((fileptr->disk.type == vDirectory) && (fileptr->disk.cloned)) {
4027 ViceLog(25, ("Rename : calling CopyOnWrite on target dir\n"));
4028 if ((errorCode = CopyOnWrite(fileptr, volptr)))
4032 /* If the new name exists already, delete it and the file it points to */
4035 /* Delete NewName from its directory */
4036 code = Delete(&newdir, NewName);
4039 /* Drop the link count */
4040 newfileptr->disk.linkCount--;
4041 if (newfileptr->disk.linkCount == 0) { /* Link count 0 - delete */
4042 afs_fsize_t newSize;
4043 VN_GET_LEN(newSize, newfileptr);
4044 VAdjustDiskUsage((Error *) & errorCode, volptr,
4045 (afs_sfsize_t) - nBlocks(newSize), 0);
4046 if (VN_GET_INO(newfileptr)) {
4047 IH_REALLYCLOSE(newfileptr->handle);
4049 IH_DEC(V_linkHandle(volptr), VN_GET_INO(newfileptr),
4050 V_parentId(volptr));
4051 IH_RELEASE(newfileptr->handle);
4052 if (errorCode == -1) {
4054 ("Del: inode=%s, name=%s, errno=%d\n",
4055 PrintInode(NULL, VN_GET_INO(newfileptr)),
4057 if ((errno != ENOENT) && (errno != EIO)
4058 && (errno != ENXIO))
4059 ViceLog(0, ("Do we need to fsck?"));
4062 VN_SET_INO(newfileptr, (Inode) 0);
4063 newfileptr->delete = 1; /* Mark NewName vnode to delete */
4066 /* Link count did not drop to zero.
4067 * Mark NewName vnode as changed - updates stime.
4069 newfileptr->changed_newTime = 1;
4074 * If the create below fails, and the delete above worked, we have
4075 * removed the new name and not replaced it. This is not very likely,
4076 * but possible. We could try to put the old file back, but it is
4077 * highly unlikely that it would work since it would involve issuing
4080 if ((errorCode = Create(&newdir, (char *)NewName, &fileFid)))
4083 /* Delete the old name */
4084 assert(Delete(&olddir, (char *)OldName) == 0);
4086 /* if the directory length changes, reflect it in the statistics */
4087 #if FS_STATS_DETAILED
4088 Update_ParentVnodeStatus(oldvptr, volptr, &olddir, client->ViceId,
4089 oldvptr->disk.linkCount, client->InSameNetwork);
4090 Update_ParentVnodeStatus(newvptr, volptr, &newdir, client->ViceId,
4091 newvptr->disk.linkCount, client->InSameNetwork);
4093 Update_ParentVnodeStatus(oldvptr, volptr, &olddir, client->ViceId,
4094 oldvptr->disk.linkCount);
4095 Update_ParentVnodeStatus(newvptr, volptr, &newdir, client->ViceId,
4096 newvptr->disk.linkCount);
4097 #endif /* FS_STATS_DETAILED */
4099 if (oldvptr == newvptr)
4100 oldvptr->disk.dataVersion--; /* Since it was bumped by 2! */
4102 fileptr->disk.parent = newvptr->vnodeNumber;
4103 fileptr->changed_newTime = 1; /* status change of moved file */
4105 /* if we are dealing with a rename of a directory */
4106 if (fileptr->disk.type == vDirectory) {
4107 assert(!fileptr->disk.cloned);
4108 SetDirHandle(&filedir, fileptr);
4109 /* fix .. to point to the correct place */
4110 Delete(&filedir, ".."); /* No assert--some directories may be bad */
4111 assert(Create(&filedir, "..", NewDirFid) == 0);
4112 fileptr->disk.dataVersion++;
4113 /* if the parent directories are different the link counts have to be */
4114 /* changed due to .. in the renamed directory */
4115 if (oldvptr != newvptr) {
4116 oldvptr->disk.linkCount--;
4117 newvptr->disk.linkCount++;
4121 /* set up return status */
4122 GetStatus(oldvptr, OutOldDirStatus, rights, anyrights, 0);
4123 GetStatus(newvptr, OutNewDirStatus, newrights, newanyrights, 0);
4124 if (newfileptr && doDelete) {
4125 DeleteFileCallBacks(&newFileFid); /* no other references */
4130 /* convert the write locks to a read locks before breaking callbacks */
4131 VVnodeWriteToRead(&errorCode, newvptr);
4132 assert(!errorCode || errorCode == VSALVAGE);
4133 if (oldvptr != newvptr) {
4134 VVnodeWriteToRead(&errorCode, oldvptr);
4135 assert(!errorCode || errorCode == VSALVAGE);
4137 if (newfileptr && !doDelete) {
4138 /* convert the write lock to a read lock before breaking callbacks */
4139 VVnodeWriteToRead(&errorCode, newfileptr);
4140 assert(!errorCode || errorCode == VSALVAGE);
4143 /* break call back on NewDirFid, OldDirFid, NewDirFid and newFileFid */
4144 BreakCallBack(client->host, NewDirFid, 0);
4145 if (oldvptr != newvptr) {
4146 BreakCallBack(client->host, OldDirFid, 0);
4147 if (fileptr->disk.type == vDirectory) /* if a dir moved, .. changed */
4148 BreakCallBack(client->host, &fileFid, 0);
4151 /* Note: it is not necessary to break the callback */
4153 DeleteFileCallBacks(&newFileFid); /* no other references */
4155 /* other's still exist (with wrong link count) */
4156 BreakCallBack(client->host, &newFileFid, 1);
4161 VPutVnode(&fileCode, newfileptr);
4162 assert(fileCode == 0);
4164 (void)PutVolumePackage(fileptr,
4166 && newvptr != oldvptr ? newvptr : 0), oldvptr,
4171 FidZap(&newfiledir);
4172 ViceLog(2, ("SAFS_Rename returns %d\n", errorCode));
4179 SRXAFS_Rename(struct rx_call * acall, struct AFSFid * OldDirFid,
4180 char *OldName, struct AFSFid * NewDirFid, char *NewName,
4181 struct AFSFetchStatus * OutOldDirStatus,
4182 struct AFSFetchStatus * OutNewDirStatus,
4183 struct AFSVolSync * Sync)
4186 struct rx_connection *tcon;
4187 struct client *t_client = NULL; /* tmp ptr to client data */
4188 #if FS_STATS_DETAILED
4189 struct fs_stats_opTimingData *opP; /* Ptr to this op's timing struct */
4190 struct timeval opStartTime, opStopTime; /* Start/stop times for RPC op */
4191 struct timeval elapsedTime; /* Transfer time */
4194 * Set our stats pointer, remember when the RPC operation started, and
4195 * tally the operation.
4197 opP = &(afs_FullPerfStats.det.rpcOpTimes[FS_STATS_RPCIDX_RENAME]);
4201 TM_GetTimeOfDay(&opStartTime, 0);
4202 #endif /* FS_STATS_DETAILED */
4204 if ((code = CallPreamble(acall, ACTIVECALL, &tcon)))
4208 SAFSS_Rename(acall, OldDirFid, OldName, NewDirFid, NewName,
4209 OutOldDirStatus, OutNewDirStatus, Sync);
4212 code = CallPostamble(tcon, code);
4214 t_client = (struct client *)rx_GetSpecific(tcon, rxcon_client_key);
4216 #if FS_STATS_DETAILED
4217 TM_GetTimeOfDay(&opStopTime, 0);
4220 (opP->numSuccesses)++;
4221 fs_stats_GetDiff(elapsedTime, opStartTime, opStopTime);
4222 fs_stats_AddTo((opP->sumTime), elapsedTime);
4223 fs_stats_SquareAddTo((opP->sqrTime), elapsedTime);
4224 if (fs_stats_TimeLessThan(elapsedTime, (opP->minTime))) {
4225 fs_stats_TimeAssign((opP->minTime), elapsedTime);
4227 if (fs_stats_TimeGreaterThan(elapsedTime, (opP->maxTime))) {
4228 fs_stats_TimeAssign((opP->maxTime), elapsedTime);
4232 #endif /* FS_STATS_DETAILED */
4234 osi_auditU(acall, RenameFileEvent, code,
4235 AUD_ID, t_client ? t_client->ViceId : 0,
4236 AUD_FID, OldDirFid, AUD_STR, OldName,
4237 AUD_FID, NewDirFid, AUD_STR, NewName, AUD_END);
4240 } /*SRXAFS_Rename */
4244 * This routine is called exclusively by SRXAFS_Symlink(), and should be
4245 * merged into it when possible.
4248 SAFSS_Symlink(struct rx_call *acall, struct AFSFid *DirFid, char *Name,
4249 char *LinkContents, struct AFSStoreStatus *InStatus,
4250 struct AFSFid *OutFid, struct AFSFetchStatus *OutFidStatus,
4251 struct AFSFetchStatus *OutDirStatus, struct AFSVolSync *Sync)
4253 Vnode *parentptr = 0; /* vnode of input Directory */
4254 Vnode *targetptr = 0; /* vnode of the new link */
4255 Vnode *parentwhentargetnotdir = 0; /* parent for use in SetAccessList */
4256 int errorCode = 0; /* error code */
4258 DirHandle dir; /* Handle for dir package I/O */
4259 Volume *volptr = 0; /* pointer to the volume header */
4260 struct client *client; /* pointer to client structure */
4261 afs_int32 rights, anyrights; /* rights for this and any user */
4262 struct client *t_client; /* tmp ptr to client data */
4263 struct in_addr logHostAddr; /* host ip holder for inet_ntoa */
4265 struct rx_connection *tcon = rx_ConnectionOf(acall);
4269 /* Get ptr to client data for user Id for logging */
4270 t_client = (struct client *)rx_GetSpecific(tcon, rxcon_client_key);
4271 logHostAddr.s_addr = rxr_HostOf(tcon);
4273 ("SAFS_Symlink %s to %s, Did = %u.%u.%u, Host %s:%d, Id %d\n", Name,
4274 LinkContents, DirFid->Volume, DirFid->Vnode, DirFid->Unique,
4275 inet_ntoa(logHostAddr), rxr_PortOf(tcon), t_client->ViceId));
4277 AFSCallStats.Symlink++, AFSCallStats.TotalCalls++;
4279 if (!FileNameOK(Name)) {
4285 * Get the vnode and volume for the parent dir along with the caller's
4289 GetVolumePackage(tcon, DirFid, &volptr, &parentptr, MustBeDIR,
4290 &parentwhentargetnotdir, &client, WRITE_LOCK,
4291 &rights, &anyrights))) {
4295 /* set volume synchronization information */
4296 SetVolumeSync(Sync, volptr);
4298 /* Does the caller has insert (and write) access to the parent directory? */
4299 if ((errorCode = CheckWriteMode(parentptr, rights, PRSFS_INSERT))) {
4304 * If we're creating a mount point (any x bits clear), we must have
4305 * administer access to the directory, too. Always allow sysadmins
4308 if ((InStatus->Mask & AFS_SETMODE) && !(InStatus->UnixModeBits & 0111)) {
4309 if (readonlyServer) {
4310 errorCode = VREADONLY;
4314 * We have a mountpoint, 'cause we're trying to set the Unix mode
4315 * bits to something with some x bits missing (default mode bits
4316 * if AFS_SETMODE is false is 0777)
4318 if (VanillaUser(client) && !(rights & PRSFS_ADMINISTER)) {
4324 /* get a new vnode for the symlink and set it up */
4326 Alloc_NewVnode(parentptr, &dir, volptr, &targetptr, Name, OutFid,
4327 vSymlink, nBlocks(strlen((char *)LinkContents))))) {
4331 /* update the status of the parent vnode */
4332 #if FS_STATS_DETAILED
4333 Update_ParentVnodeStatus(parentptr, volptr, &dir, client->ViceId,
4334 parentptr->disk.linkCount,
4335 client->InSameNetwork);
4337 Update_ParentVnodeStatus(parentptr, volptr, &dir, client->ViceId,
4338 parentptr->disk.linkCount);
4339 #endif /* FS_STATS_DETAILED */
4341 /* update the status of the new symbolic link file vnode */
4342 Update_TargetVnodeStatus(targetptr, TVS_SLINK, client, InStatus,
4343 parentptr, volptr, strlen((char *)LinkContents));
4345 /* Write the contents of the symbolic link name into the target inode */
4346 fdP = IH_OPEN(targetptr->handle);
4347 assert(fdP != NULL);
4348 len = strlen((char *) LinkContents);
4349 code = (len == FDH_WRITE(fdP, (char *) LinkContents, len)) ? 0 : VDISKFULL;
4350 if (code) ViceLog(0, ("SAFSS_Symlink FDH_WRITE failed for len=%d, Fid=%u.%d.%d\n", len, OutFid->Volume, OutFid->Vnode, OutFid->Unique));
4353 * Set up and return modified status for the parent dir and new symlink
4356 GetStatus(targetptr, OutFidStatus, rights, anyrights, parentptr);
4357 GetStatus(parentptr, OutDirStatus, rights, anyrights, 0);
4359 /* convert the write lock to a read lock before breaking callbacks */
4360 VVnodeWriteToRead(&errorCode, parentptr);
4361 assert(!errorCode || errorCode == VSALVAGE);
4363 /* break call back on the parent dir */
4364 BreakCallBack(client->host, DirFid, 0);
4367 /* Write the all modified vnodes (parent, new files) and volume back */
4368 (void)PutVolumePackage(parentwhentargetnotdir, targetptr, parentptr,
4371 ViceLog(2, ("SAFS_Symlink returns %d\n", errorCode));
4372 return ( errorCode ? errorCode : code );
4374 } /*SAFSS_Symlink */
4378 SRXAFS_Symlink(acall, DirFid, Name, LinkContents, InStatus, OutFid,
4379 OutFidStatus, OutDirStatus, Sync)
4380 struct AFSVolSync *Sync;
4381 struct rx_call *acall; /* Rx call */
4382 struct AFSFid *DirFid; /* Parent dir's fid */
4383 char *Name; /* File name to create */
4384 char *LinkContents; /* Contents of the new created file */
4385 struct AFSStoreStatus *InStatus; /* Input status for the new symbolic link */
4386 struct AFSFid *OutFid; /* Fid for newly created symbolic link */
4387 struct AFSFetchStatus *OutFidStatus; /* Output status for new symbolic link */
4388 struct AFSFetchStatus *OutDirStatus; /* Output status for parent dir */
4392 struct rx_connection *tcon;
4393 struct client *t_client = NULL; /* tmp ptr to client data */
4394 #if FS_STATS_DETAILED
4395 struct fs_stats_opTimingData *opP; /* Ptr to this op's timing struct */
4396 struct timeval opStartTime, opStopTime; /* Start/stop times for RPC op */
4397 struct timeval elapsedTime; /* Transfer time */
4400 * Set our stats pointer, remember when the RPC operation started, and
4401 * tally the operation.
4403 opP = &(afs_FullPerfStats.det.rpcOpTimes[FS_STATS_RPCIDX_SYMLINK]);
4407 TM_GetTimeOfDay(&opStartTime, 0);
4408 #endif /* FS_STATS_DETAILED */
4410 if ((code = CallPreamble(acall, ACTIVECALL, &tcon)))
4414 SAFSS_Symlink(acall, DirFid, Name, LinkContents, InStatus, OutFid,
4415 OutFidStatus, OutDirStatus, Sync);
4418 code = CallPostamble(tcon, code);
4420 t_client = (struct client *)rx_GetSpecific(tcon, rxcon_client_key);
4422 #if FS_STATS_DETAILED
4423 TM_GetTimeOfDay(&opStopTime, 0);
4426 (opP->numSuccesses)++;
4427 fs_stats_GetDiff(elapsedTime, opStartTime, opStopTime);
4428 fs_stats_AddTo((opP->sumTime), elapsedTime);
4429 fs_stats_SquareAddTo((opP->sqrTime), elapsedTime);
4430 if (fs_stats_TimeLessThan(elapsedTime, (opP->minTime))) {
4431 fs_stats_TimeAssign((opP->minTime), elapsedTime);
4433 if (fs_stats_TimeGreaterThan(elapsedTime, (opP->maxTime))) {
4434 fs_stats_TimeAssign((opP->maxTime), elapsedTime);
4438 #endif /* FS_STATS_DETAILED */
4440 osi_auditU(acall, SymlinkEvent, code,
4441 AUD_ID, t_client ? t_client->ViceId : 0,
4442 AUD_FID, DirFid, AUD_STR, Name,
4443 AUD_FID, OutFid, AUD_STR, LinkContents, AUD_END);
4446 } /*SRXAFS_Symlink */
4450 * This routine is called exclusively by SRXAFS_Link(), and should be
4451 * merged into it when possible.
4454 SAFSS_Link(struct rx_call *acall, struct AFSFid *DirFid, char *Name,
4455 struct AFSFid *ExistingFid, struct AFSFetchStatus *OutFidStatus,
4456 struct AFSFetchStatus *OutDirStatus, struct AFSVolSync *Sync)
4458 Vnode *parentptr = 0; /* vnode of input Directory */
4459 Vnode *targetptr = 0; /* vnode of the new file */
4460 Vnode *parentwhentargetnotdir = 0; /* parent for use in SetAccessList */
4461 Volume *volptr = 0; /* pointer to the volume header */
4462 int errorCode = 0; /* error code */
4463 DirHandle dir; /* Handle for dir package I/O */
4464 struct client *client; /* pointer to client structure */
4465 afs_int32 rights, anyrights; /* rights for this and any user */
4466 struct client *t_client; /* tmp ptr to client data */
4467 struct in_addr logHostAddr; /* host ip holder for inet_ntoa */
4468 struct rx_connection *tcon = rx_ConnectionOf(acall);
4472 /* Get ptr to client data for user Id for logging */
4473 t_client = (struct client *)rx_GetSpecific(tcon, rxcon_client_key);
4474 logHostAddr.s_addr = rxr_HostOf(tcon);
4476 ("SAFS_Link %s, Did = %u.%u.%u, Fid = %u.%u.%u, Host %s:%d, Id %d\n",
4477 Name, DirFid->Volume, DirFid->Vnode, DirFid->Unique,
4478 ExistingFid->Volume, ExistingFid->Vnode, ExistingFid->Unique,
4479 inet_ntoa(logHostAddr), rxr_PortOf(tcon), t_client->ViceId));
4481 AFSCallStats.Link++, AFSCallStats.TotalCalls++;
4483 if (DirFid->Volume != ExistingFid->Volume) {
4487 if (!FileNameOK(Name)) {
4493 * Get the vnode and volume for the parent dir along with the caller's
4497 GetVolumePackage(tcon, DirFid, &volptr, &parentptr, MustBeDIR,
4498 &parentwhentargetnotdir, &client, WRITE_LOCK,
4499 &rights, &anyrights))) {
4503 /* set volume synchronization information */
4504 SetVolumeSync(Sync, volptr);
4506 /* Can the caller insert into the parent directory? */
4507 if ((errorCode = CheckWriteMode(parentptr, rights, PRSFS_INSERT))) {
4511 if (((DirFid->Vnode & 1) && (ExistingFid->Vnode & 1)) || (DirFid->Vnode == ExistingFid->Vnode)) { /* at present, */
4512 /* AFS fileservers always have directory vnodes that are odd. */
4517 /* get the file vnode */
4519 CheckVnode(ExistingFid, &volptr, &targetptr, WRITE_LOCK))) {
4522 if (targetptr->disk.type != vFile) {
4526 if (targetptr->disk.parent != DirFid->Vnode) {
4530 if (parentptr->disk.cloned) {
4531 ViceLog(25, ("Link : calling CopyOnWrite on target dir\n"));
4532 if ((errorCode = CopyOnWrite(parentptr, volptr)))
4533 goto Bad_Link; /* disk full error */
4536 /* add the name to the directory */
4537 SetDirHandle(&dir, parentptr);
4538 if ((errorCode = Create(&dir, (char *)Name, ExistingFid)))
4542 /* update the status in the parent vnode */
4543 /**WARNING** --> disk.author SHOULDN'T be modified???? */
4544 #if FS_STATS_DETAILED
4545 Update_ParentVnodeStatus(parentptr, volptr, &dir, client->ViceId,
4546 parentptr->disk.linkCount,
4547 client->InSameNetwork);
4549 Update_ParentVnodeStatus(parentptr, volptr, &dir, client->ViceId,
4550 parentptr->disk.linkCount);
4551 #endif /* FS_STATS_DETAILED */
4553 targetptr->disk.linkCount++;
4554 targetptr->disk.author = client->ViceId;
4555 targetptr->changed_newTime = 1; /* Status change of linked-to file */
4557 /* set up return status */
4558 GetStatus(targetptr, OutFidStatus, rights, anyrights, parentptr);
4559 GetStatus(parentptr, OutDirStatus, rights, anyrights, 0);
4561 /* convert the write locks to read locks before breaking callbacks */
4562 VVnodeWriteToRead(&errorCode, targetptr);
4563 assert(!errorCode || errorCode == VSALVAGE);
4564 VVnodeWriteToRead(&errorCode, parentptr);
4565 assert(!errorCode || errorCode == VSALVAGE);
4567 /* break call back on DirFid */
4568 BreakCallBack(client->host, DirFid, 0);
4570 * We also need to break the callback for the file that is hard-linked since part
4571 * of its status (like linkcount) is changed
4573 BreakCallBack(client->host, ExistingFid, 0);
4576 /* Write the all modified vnodes (parent, new files) and volume back */
4577 (void)PutVolumePackage(parentwhentargetnotdir, targetptr, parentptr,
4580 ViceLog(2, ("SAFS_Link returns %d\n", errorCode));
4587 SRXAFS_Link(struct rx_call * acall, struct AFSFid * DirFid, char *Name,
4588 struct AFSFid * ExistingFid, struct AFSFetchStatus * OutFidStatus,
4589 struct AFSFetchStatus * OutDirStatus, struct AFSVolSync * Sync)
4592 struct rx_connection *tcon;
4593 struct client *t_client = NULL; /* tmp ptr to client data */
4594 #if FS_STATS_DETAILED
4595 struct fs_stats_opTimingData *opP; /* Ptr to this op's timing struct */
4596 struct timeval opStartTime, opStopTime; /* Start/stop times for RPC op */
4597 struct timeval elapsedTime; /* Transfer time */
4600 * Set our stats pointer, remember when the RPC operation started, and
4601 * tally the operation.
4603 opP = &(afs_FullPerfStats.det.rpcOpTimes[FS_STATS_RPCIDX_LINK]);
4607 TM_GetTimeOfDay(&opStartTime, 0);
4608 #endif /* FS_STATS_DETAILED */
4610 if ((code = CallPreamble(acall, ACTIVECALL, &tcon)))
4614 SAFSS_Link(acall, DirFid, Name, ExistingFid, OutFidStatus,
4615 OutDirStatus, Sync);
4618 code = CallPostamble(tcon, code);
4620 t_client = (struct client *)rx_GetSpecific(tcon, rxcon_client_key);
4622 #if FS_STATS_DETAILED
4623 TM_GetTimeOfDay(&opStopTime, 0);
4626 (opP->numSuccesses)++;
4627 fs_stats_GetDiff(elapsedTime, opStartTime, opStopTime);
4628 fs_stats_AddTo((opP->sumTime), elapsedTime);
4629 fs_stats_SquareAddTo((opP->sqrTime), elapsedTime);
4630 if (fs_stats_TimeLessThan(elapsedTime, (opP->minTime))) {
4631 fs_stats_TimeAssign((opP->minTime), elapsedTime);
4633 if (fs_stats_TimeGreaterThan(elapsedTime, (opP->maxTime))) {
4634 fs_stats_TimeAssign((opP->maxTime), elapsedTime);
4638 #endif /* FS_STATS_DETAILED */
4640 osi_auditU(acall, LinkEvent, code,
4641 AUD_ID, t_client ? t_client->ViceId : 0,
4642 AUD_FID, DirFid, AUD_STR, Name,
4643 AUD_FID, ExistingFid, AUD_END);
4650 * This routine is called exclusively by SRXAFS_MakeDir(), and should be
4651 * merged into it when possible.
4654 SAFSS_MakeDir(struct rx_call *acall, struct AFSFid *DirFid, char *Name,
4655 struct AFSStoreStatus *InStatus, struct AFSFid *OutFid,
4656 struct AFSFetchStatus *OutFidStatus,
4657 struct AFSFetchStatus *OutDirStatus,
4658 struct AFSCallBack *CallBack, struct AFSVolSync *Sync)
4660 Vnode *parentptr = 0; /* vnode of input Directory */
4661 Vnode *targetptr = 0; /* vnode of the new file */
4662 Vnode *parentwhentargetnotdir = 0; /* parent for use in SetAccessList */
4663 Volume *volptr = 0; /* pointer to the volume header */
4664 int errorCode = 0; /* error code */
4665 struct acl_accessList *newACL; /* Access list */
4666 int newACLSize; /* Size of access list */
4667 DirHandle dir; /* Handle for dir package I/O */
4668 DirHandle parentdir; /* Handle for dir package I/O */
4669 struct client *client; /* pointer to client structure */
4670 afs_int32 rights, anyrights; /* rights for this and any user */
4671 struct client *t_client; /* tmp ptr to client data */
4672 struct in_addr logHostAddr; /* host ip holder for inet_ntoa */
4673 struct rx_connection *tcon = rx_ConnectionOf(acall);
4676 FidZero(&parentdir);
4678 /* Get ptr to client data for user Id for logging */
4679 t_client = (struct client *)rx_GetSpecific(tcon, rxcon_client_key);
4680 logHostAddr.s_addr = rxr_HostOf(tcon);
4682 ("SAFS_MakeDir %s, Did = %u.%u.%u, Host %s:%d, Id %d\n", Name,
4683 DirFid->Volume, DirFid->Vnode, DirFid->Unique,
4684 inet_ntoa(logHostAddr), rxr_PortOf(tcon), t_client->ViceId));
4686 AFSCallStats.MakeDir++, AFSCallStats.TotalCalls++;
4688 if (!FileNameOK(Name)) {
4694 * Get the vnode and volume for the parent dir along with the caller's
4698 GetVolumePackage(tcon, DirFid, &volptr, &parentptr, MustBeDIR,
4699 &parentwhentargetnotdir, &client, WRITE_LOCK,
4700 &rights, &anyrights))) {
4704 /* set volume synchronization information */
4705 SetVolumeSync(Sync, volptr);
4707 /* Write access to the parent directory? */
4708 #ifdef DIRCREATE_NEED_WRITE
4710 * requires w access for the user to create a directory. this
4711 * closes a loophole in the current security arrangement, since a
4712 * user with i access only can create a directory and get the
4713 * implcit a access that goes with dir ownership, and proceed to
4714 * subvert quota in the volume.
4716 if ((errorCode = CheckWriteMode(parentptr, rights, PRSFS_INSERT))
4717 || (errorCode = CheckWriteMode(parentptr, rights, PRSFS_WRITE))) {
4719 if ((errorCode = CheckWriteMode(parentptr, rights, PRSFS_INSERT))) {
4720 #endif /* DIRCREATE_NEED_WRITE */
4723 #define EMPTYDIRBLOCKS 2
4724 /* get a new vnode and set it up */
4726 Alloc_NewVnode(parentptr, &parentdir, volptr, &targetptr, Name,
4727 OutFid, vDirectory, EMPTYDIRBLOCKS))) {
4731 /* Update the status for the parent dir */
4732 #if FS_STATS_DETAILED
4733 Update_ParentVnodeStatus(parentptr, volptr, &parentdir, client->ViceId,
4734 parentptr->disk.linkCount + 1,
4735 client->InSameNetwork);
4737 Update_ParentVnodeStatus(parentptr, volptr, &parentdir, client->ViceId,
4738 parentptr->disk.linkCount + 1);
4739 #endif /* FS_STATS_DETAILED */
4741 /* Point to target's ACL buffer and copy the parent's ACL contents to it */
4742 assert((SetAccessList
4743 (&targetptr, &volptr, &newACL, &newACLSize,
4744 &parentwhentargetnotdir, (AFSFid *) 0, 0)) == 0);
4745 assert(parentwhentargetnotdir == 0);
4746 memcpy((char *)newACL, (char *)VVnodeACL(parentptr), VAclSize(parentptr));
4748 /* update the status for the target vnode */
4749 Update_TargetVnodeStatus(targetptr, TVS_MKDIR, client, InStatus,
4750 parentptr, volptr, 0);
4752 /* Actually create the New directory in the directory package */
4753 SetDirHandle(&dir, targetptr);
4754 assert(!(MakeDir(&dir, OutFid, DirFid)));
4756 VN_SET_LEN(targetptr, (afs_fsize_t) Length(&dir));
4758 /* set up return status */
4759 GetStatus(targetptr, OutFidStatus, rights, anyrights, parentptr);
4760 GetStatus(parentptr, OutDirStatus, rights, anyrights, NULL);
4762 /* convert the write lock to a read lock before breaking callbacks */
4763 VVnodeWriteToRead(&errorCode, parentptr);
4764 assert(!errorCode || errorCode == VSALVAGE);
4766 /* break call back on DirFid */
4767 BreakCallBack(client->host, DirFid, 0);
4769 /* Return a callback promise to caller */
4770 SetCallBackStruct(AddCallBack(client->host, OutFid), CallBack);
4773 /* Write the all modified vnodes (parent, new files) and volume back */
4774 (void)PutVolumePackage(parentwhentargetnotdir, targetptr, parentptr,
4778 ViceLog(2, ("SAFS_MakeDir returns %d\n", errorCode));
4781 } /*SAFSS_MakeDir */
4785 SRXAFS_MakeDir(struct rx_call * acall, struct AFSFid * DirFid, char *Name,
4786 struct AFSStoreStatus * InStatus, struct AFSFid * OutFid,
4787 struct AFSFetchStatus * OutFidStatus,
4788 struct AFSFetchStatus * OutDirStatus,
4789 struct AFSCallBack * CallBack, struct AFSVolSync * Sync)
4792 struct rx_connection *tcon;
4793 struct client *t_client = NULL; /* tmp ptr to client data */
4794 #if FS_STATS_DETAILED
4795 struct fs_stats_opTimingData *opP; /* Ptr to this op's timing struct */
4796 struct timeval opStartTime, opStopTime; /* Start/stop times for RPC op */
4797 struct timeval elapsedTime; /* Transfer time */
4800 * Set our stats pointer, remember when the RPC operation started, and
4801 * tally the operation.
4803 opP = &(afs_FullPerfStats.det.rpcOpTimes[FS_STATS_RPCIDX_MAKEDIR]);
4807 TM_GetTimeOfDay(&opStartTime, 0);
4808 #endif /* FS_STATS_DETAILED */
4809 if ((code = CallPreamble(acall, ACTIVECALL, &tcon)))
4813 SAFSS_MakeDir(acall, DirFid, Name, InStatus, OutFid, OutFidStatus,
4814 OutDirStatus, CallBack, Sync);
4817 code = CallPostamble(tcon, code);
4819 t_client = (struct client *)rx_GetSpecific(tcon, rxcon_client_key);
4821 #if FS_STATS_DETAILED
4822 TM_GetTimeOfDay(&opStopTime, 0);
4825 (opP->numSuccesses)++;
4826 fs_stats_GetDiff(elapsedTime, opStartTime, opStopTime);
4827 fs_stats_AddTo((opP->sumTime), elapsedTime);
4828 fs_stats_SquareAddTo((opP->sqrTime), elapsedTime);
4829 if (fs_stats_TimeLessThan(elapsedTime, (opP->minTime))) {
4830 fs_stats_TimeAssign((opP->minTime), elapsedTime);
4832 if (fs_stats_TimeGreaterThan(elapsedTime, (opP->maxTime))) {
4833 fs_stats_TimeAssign((opP->maxTime), elapsedTime);
4837 #endif /* FS_STATS_DETAILED */
4839 osi_auditU(acall, MakeDirEvent, code,
4840 AUD_ID, t_client ? t_client->ViceId : 0,
4841 AUD_FID, DirFid, AUD_STR, Name,
4842 AUD_FID, OutFid, AUD_END);
4845 } /*SRXAFS_MakeDir */
4849 * This routine is called exclusively by SRXAFS_RemoveDir(), and should be
4850 * merged into it when possible.
4853 SAFSS_RemoveDir(struct rx_call *acall, struct AFSFid *DirFid, char *Name,
4854 struct AFSFetchStatus *OutDirStatus, struct AFSVolSync *Sync)
4856 Vnode *parentptr = 0; /* vnode of input Directory */
4857 Vnode *parentwhentargetnotdir = 0; /* parent for use in SetAccessList */
4858 Vnode *targetptr = 0; /* file to be deleted */
4859 AFSFid fileFid; /* area for Fid from the directory */
4860 int errorCode = 0; /* error code */
4861 DirHandle dir; /* Handle for dir package I/O */
4862 Volume *volptr = 0; /* pointer to the volume header */
4863 struct client *client; /* pointer to client structure */
4864 afs_int32 rights, anyrights; /* rights for this and any user */
4865 Vnode debugvnode1, debugvnode2;
4866 struct client *t_client; /* tmp ptr to client data */
4867 struct in_addr logHostAddr; /* host ip holder for inet_ntoa */
4868 struct rx_connection *tcon = rx_ConnectionOf(acall);
4872 /* Get ptr to client data for user Id for logging */
4873 t_client = (struct client *)rx_GetSpecific(tcon, rxcon_client_key);
4874 logHostAddr.s_addr = rxr_HostOf(tcon);
4876 ("SAFS_RemoveDir %s, Did = %u.%u.%u, Host %s:%d, Id %d\n", Name,
4877 DirFid->Volume, DirFid->Vnode, DirFid->Unique,
4878 inet_ntoa(logHostAddr), rxr_PortOf(tcon), t_client->ViceId));
4880 AFSCallStats.RemoveDir++, AFSCallStats.TotalCalls++;
4883 * Get the vnode and volume for the parent dir along with the caller's
4887 GetVolumePackage(tcon, DirFid, &volptr, &parentptr, MustBeDIR,
4888 &parentwhentargetnotdir, &client, WRITE_LOCK,
4889 &rights, &anyrights))) {
4892 debugvnode1 = *parentptr;
4894 /* set volume synchronization information */
4895 SetVolumeSync(Sync, volptr);
4897 /* Does the caller has delete (&write) access to the parent dir? */
4898 if ((errorCode = CheckWriteMode(parentptr, rights, PRSFS_DELETE))) {
4902 debugvnode2 = *parentptr;
4903 /* Do the actual delete of the desired (empty) directory, Name */
4905 DeleteTarget(parentptr, volptr, &targetptr, &dir, &fileFid, Name,
4910 /* Update the status for the parent dir; link count is also adjusted */
4911 #if FS_STATS_DETAILED
4912 Update_ParentVnodeStatus(parentptr, volptr, &dir, client->ViceId,
4913 parentptr->disk.linkCount - 1,
4914 client->InSameNetwork);
4916 Update_ParentVnodeStatus(parentptr, volptr, &dir, client->ViceId,
4917 parentptr->disk.linkCount - 1);
4918 #endif /* FS_STATS_DETAILED */
4920 /* Return to the caller the updated parent dir status */
4921 GetStatus(parentptr, OutDirStatus, rights, anyrights, NULL);
4924 * Note: it is not necessary to break the callback on fileFid, since
4925 * refcount is now 0, so no one should be able to refer to the dir
4928 DeleteFileCallBacks(&fileFid);
4930 /* convert the write lock to a read lock before breaking callbacks */
4931 VVnodeWriteToRead(&errorCode, parentptr);
4932 assert(!errorCode || errorCode == VSALVAGE);
4934 /* break call back on DirFid and fileFid */
4935 BreakCallBack(client->host, DirFid, 0);
4938 /* Write the all modified vnodes (parent, new files) and volume back */
4939 (void)PutVolumePackage(parentwhentargetnotdir, targetptr, parentptr,
4942 ViceLog(2, ("SAFS_RemoveDir returns %d\n", errorCode));
4945 } /*SAFSS_RemoveDir */
4949 SRXAFS_RemoveDir(struct rx_call * acall, struct AFSFid * DirFid, char *Name,
4950 struct AFSFetchStatus * OutDirStatus,
4951 struct AFSVolSync * Sync)
4954 struct rx_connection *tcon;
4955 struct client *t_client = NULL; /* tmp ptr to client data */
4956 #if FS_STATS_DETAILED
4957 struct fs_stats_opTimingData *opP; /* Ptr to this op's timing struct */
4958 struct timeval opStartTime, opStopTime; /* Start/stop times for RPC op */
4959 struct timeval elapsedTime; /* Transfer time */
4962 * Set our stats pointer, remember when the RPC operation started, and
4963 * tally the operation.
4965 opP = &(afs_FullPerfStats.det.rpcOpTimes[FS_STATS_RPCIDX_REMOVEDIR]);
4969 TM_GetTimeOfDay(&opStartTime, 0);
4970 #endif /* FS_STATS_DETAILED */
4972 if ((code = CallPreamble(acall, ACTIVECALL, &tcon)))
4975 code = SAFSS_RemoveDir(acall, DirFid, Name, OutDirStatus, Sync);
4978 code = CallPostamble(tcon, code);
4980 t_client = (struct client *)rx_GetSpecific(tcon, rxcon_client_key);
4982 #if FS_STATS_DETAILED
4983 TM_GetTimeOfDay(&opStopTime, 0);
4986 (opP->numSuccesses)++;
4987 fs_stats_GetDiff(elapsedTime, opStartTime, opStopTime);
4988 fs_stats_AddTo((opP->sumTime), elapsedTime);
4989 fs_stats_SquareAddTo((opP->sqrTime), elapsedTime);
4990 if (fs_stats_TimeLessThan(elapsedTime, (opP->minTime))) {
4991 fs_stats_TimeAssign((opP->minTime), elapsedTime);
4993 if (fs_stats_TimeGreaterThan(elapsedTime, (opP->maxTime))) {
4994 fs_stats_TimeAssign((opP->maxTime), elapsedTime);
4998 #endif /* FS_STATS_DETAILED */
5000 osi_auditU(acall, RemoveDirEvent, code,
5001 AUD_ID, t_client ? t_client->ViceId : 0,
5002 AUD_FID, DirFid, AUD_STR, Name, AUD_END);
5005 } /*SRXAFS_RemoveDir */
5009 * This routine is called exclusively by SRXAFS_SetLock(), and should be
5010 * merged into it when possible.
5013 SAFSS_SetLock(struct rx_call *acall, struct AFSFid *Fid, ViceLockType type,
5014 struct AFSVolSync *Sync)
5016 Vnode *targetptr = 0; /* vnode of input file */
5017 Vnode *parentwhentargetnotdir = 0; /* parent for use in SetAccessList */
5018 int errorCode = 0; /* error code */
5019 Volume *volptr = 0; /* pointer to the volume header */
5020 struct client *client; /* pointer to client structure */
5021 afs_int32 rights, anyrights; /* rights for this and any user */
5022 struct client *t_client; /* tmp ptr to client data */
5023 struct in_addr logHostAddr; /* host ip holder for inet_ntoa */
5024 static char *locktype[2] = { "LockRead", "LockWrite" };
5025 struct rx_connection *tcon = rx_ConnectionOf(acall);
5027 if (type != LockRead && type != LockWrite) {
5031 /* Get ptr to client data for user Id for logging */
5032 t_client = (struct client *)rx_GetSpecific(tcon, rxcon_client_key);
5033 logHostAddr.s_addr = rxr_HostOf(tcon);
5035 ("SAFS_SetLock type = %s Fid = %u.%u.%u, Host %s:%d, Id %d\n",
5036 locktype[(int)type], Fid->Volume, Fid->Vnode, Fid->Unique,
5037 inet_ntoa(logHostAddr), rxr_PortOf(tcon), t_client->ViceId));
5039 AFSCallStats.SetLock++, AFSCallStats.TotalCalls++;
5042 * Get the vnode and volume for the desired file along with the caller's
5046 GetVolumePackage(tcon, Fid, &volptr, &targetptr, DONTCHECK,
5047 &parentwhentargetnotdir, &client, WRITE_LOCK,
5048 &rights, &anyrights))) {
5052 /* set volume synchronization information */
5053 SetVolumeSync(Sync, volptr);
5055 /* Handle the particular type of set locking, type */
5056 errorCode = HandleLocking(targetptr, rights, type);
5059 /* Write the all modified vnodes (parent, new files) and volume back */
5060 (void)PutVolumePackage(parentwhentargetnotdir, targetptr, (Vnode *) 0,
5063 if ((errorCode == VREADONLY) && (type == LockRead))
5064 errorCode = 0; /* allow read locks on RO volumes without saving state */
5066 ViceLog(2, ("SAFS_SetLock returns %d\n", errorCode));
5069 } /*SAFSS_SetLock */
5073 SRXAFS_OldSetLock(struct rx_call * acall, struct AFSFid * Fid,
5074 ViceLockType type, struct AFSVolSync * Sync)
5076 return SRXAFS_SetLock(acall, Fid, type, Sync);
5077 } /*SRXAFS_OldSetLock */
5081 SRXAFS_SetLock(struct rx_call * acall, struct AFSFid * Fid, ViceLockType type,
5082 struct AFSVolSync * Sync)
5085 struct rx_connection *tcon;
5086 struct client *t_client = NULL; /* tmp ptr to client data */
5087 #if FS_STATS_DETAILED
5088 struct fs_stats_opTimingData *opP; /* Ptr to this op's timing struct */
5089 struct timeval opStartTime, opStopTime; /* Start/stop times for RPC op */
5090 struct timeval elapsedTime; /* Transfer time */
5093 * Set our stats pointer, remember when the RPC operation started, and
5094 * tally the operation.
5096 opP = &(afs_FullPerfStats.det.rpcOpTimes[FS_STATS_RPCIDX_SETLOCK]);
5100 TM_GetTimeOfDay(&opStartTime, 0);
5101 #endif /* FS_STATS_DETAILED */
5103 if ((code = CallPreamble(acall, ACTIVECALL, &tcon)))
5106 code = SAFSS_SetLock(acall, Fid, type, Sync);
5109 code = CallPostamble(tcon, code);
5111 t_client = (struct client *)rx_GetSpecific(tcon, rxcon_client_key);
5113 #if FS_STATS_DETAILED
5114 TM_GetTimeOfDay(&opStopTime, 0);
5117 (opP->numSuccesses)++;
5118 fs_stats_GetDiff(elapsedTime, opStartTime, opStopTime);
5119 fs_stats_AddTo((opP->sumTime), elapsedTime);
5120 fs_stats_SquareAddTo((opP->sqrTime), elapsedTime);
5121 if (fs_stats_TimeLessThan(elapsedTime, (opP->minTime))) {
5122 fs_stats_TimeAssign((opP->minTime), elapsedTime);
5124 if (fs_stats_TimeGreaterThan(elapsedTime, (opP->maxTime))) {
5125 fs_stats_TimeAssign((opP->maxTime), elapsedTime);
5129 #endif /* FS_STATS_DETAILED */
5131 osi_auditU(acall, SetLockEvent, code,
5132 AUD_ID, t_client ? t_client->ViceId : 0,
5133 AUD_FID, Fid, AUD_LONG, type, AUD_END);
5135 } /*SRXAFS_SetLock */
5139 * This routine is called exclusively by SRXAFS_ExtendLock(), and should be
5140 * merged into it when possible.
5143 SAFSS_ExtendLock(struct rx_call *acall, struct AFSFid *Fid,
5144 struct AFSVolSync *Sync)
5146 Vnode *targetptr = 0; /* vnode of input file */
5147 Vnode *parentwhentargetnotdir = 0; /* parent for use in SetAccessList */
5148 int errorCode = 0; /* error code */
5149 Volume *volptr = 0; /* pointer to the volume header */
5150 struct client *client; /* pointer to client structure */
5151 afs_int32 rights, anyrights; /* rights for this and any user */
5152 struct client *t_client; /* tmp ptr to client data */
5153 struct in_addr logHostAddr; /* host ip holder for inet_ntoa */
5154 struct rx_connection *tcon = rx_ConnectionOf(acall);
5156 /* Get ptr to client data for user Id for logging */
5157 t_client = (struct client *)rx_GetSpecific(tcon, rxcon_client_key);
5158 logHostAddr.s_addr = rxr_HostOf(tcon);
5160 ("SAFS_ExtendLock Fid = %u.%u.%u, Host %s:%d, Id %d\n", Fid->Volume,
5161 Fid->Vnode, Fid->Unique, inet_ntoa(logHostAddr),
5162 rxr_PortOf(tcon), t_client->ViceId));
5164 AFSCallStats.ExtendLock++, AFSCallStats.TotalCalls++;
5167 * Get the vnode and volume for the desired file along with the caller's
5171 GetVolumePackage(tcon, Fid, &volptr, &targetptr, DONTCHECK,
5172 &parentwhentargetnotdir, &client, WRITE_LOCK,
5173 &rights, &anyrights))) {
5174 goto Bad_ExtendLock;
5177 /* set volume synchronization information */
5178 SetVolumeSync(Sync, volptr);
5180 /* Handle the actual lock extension */
5181 errorCode = HandleLocking(targetptr, rights, LockExtend);
5184 /* Put back file's vnode and volume */
5185 (void)PutVolumePackage(parentwhentargetnotdir, targetptr, (Vnode *) 0,
5188 if ((errorCode == VREADONLY)) /* presumably, we already granted this lock */
5189 errorCode = 0; /* under our generous policy re RO vols */
5191 ViceLog(2, ("SAFS_ExtendLock returns %d\n", errorCode));
5194 } /*SAFSS_ExtendLock */
5198 SRXAFS_OldExtendLock(struct rx_call * acall, struct AFSFid * Fid,
5199 struct AFSVolSync * Sync)
5201 return SRXAFS_ExtendLock(acall, Fid, Sync);
5202 } /*SRXAFS_OldExtendLock */
5206 SRXAFS_ExtendLock(struct rx_call * acall, struct AFSFid * Fid,
5207 struct AFSVolSync * Sync)
5210 struct rx_connection *tcon;
5211 struct client *t_client = NULL; /* tmp ptr to client data */
5212 #if FS_STATS_DETAILED
5213 struct fs_stats_opTimingData *opP; /* Ptr to this op's timing struct */
5214 struct timeval opStartTime, opStopTime; /* Start/stop times for RPC op */
5215 struct timeval elapsedTime; /* Transfer time */
5218 * Set our stats pointer, remember when the RPC operation started, and
5219 * tally the operation.
5221 opP = &(afs_FullPerfStats.det.rpcOpTimes[FS_STATS_RPCIDX_EXTENDLOCK]);
5225 TM_GetTimeOfDay(&opStartTime, 0);
5226 #endif /* FS_STATS_DETAILED */
5228 if ((code = CallPreamble(acall, ACTIVECALL, &tcon)))
5229 goto Bad_ExtendLock;
5231 code = SAFSS_ExtendLock(acall, Fid, Sync);
5234 code = CallPostamble(tcon, code);
5236 t_client = (struct client *)rx_GetSpecific(tcon, rxcon_client_key);
5238 #if FS_STATS_DETAILED
5239 TM_GetTimeOfDay(&opStopTime, 0);
5242 (opP->numSuccesses)++;
5243 fs_stats_GetDiff(elapsedTime, opStartTime, opStopTime);
5244 fs_stats_AddTo((opP->sumTime), elapsedTime);
5245 fs_stats_SquareAddTo((opP->sqrTime), elapsedTime);
5246 if (fs_stats_TimeLessThan(elapsedTime, (opP->minTime))) {
5247 fs_stats_TimeAssign((opP->minTime), elapsedTime);
5249 if (fs_stats_TimeGreaterThan(elapsedTime, (opP->maxTime))) {
5250 fs_stats_TimeAssign((opP->maxTime), elapsedTime);
5254 #endif /* FS_STATS_DETAILED */
5256 osi_auditU(acall, ExtendLockEvent, code,
5257 AUD_ID, t_client ? t_client->ViceId : 0,
5258 AUD_FID, Fid, AUD_END);
5261 } /*SRXAFS_ExtendLock */
5265 * This routine is called exclusively by SRXAFS_ReleaseLock(), and should be
5266 * merged into it when possible.
5269 SAFSS_ReleaseLock(struct rx_call *acall, struct AFSFid *Fid,
5270 struct AFSVolSync *Sync)
5272 Vnode *targetptr = 0; /* vnode of input file */
5273 Vnode *parentwhentargetnotdir = 0; /* parent for use in SetAccessList */
5274 int errorCode = 0; /* error code */
5275 Volume *volptr = 0; /* pointer to the volume header */
5276 struct client *client; /* pointer to client structure */
5277 afs_int32 rights, anyrights; /* rights for this and any user */
5278 struct client *t_client; /* tmp ptr to client data */
5279 struct in_addr logHostAddr; /* host ip holder for inet_ntoa */
5280 struct rx_connection *tcon = rx_ConnectionOf(acall);
5282 /* Get ptr to client data for user Id for logging */
5283 t_client = (struct client *)rx_GetSpecific(tcon, rxcon_client_key);
5284 logHostAddr.s_addr = rxr_HostOf(tcon);
5286 ("SAFS_ReleaseLock Fid = %u.%u.%u, Host %s:%d, Id %d\n", Fid->Volume,
5287 Fid->Vnode, Fid->Unique, inet_ntoa(logHostAddr),
5288 rxr_PortOf(tcon), t_client->ViceId));
5290 AFSCallStats.ReleaseLock++, AFSCallStats.TotalCalls++;
5293 * Get the vnode and volume for the desired file along with the caller's
5297 GetVolumePackage(tcon, Fid, &volptr, &targetptr, DONTCHECK,
5298 &parentwhentargetnotdir, &client, WRITE_LOCK,
5299 &rights, &anyrights))) {
5300 goto Bad_ReleaseLock;
5303 /* set volume synchronization information */
5304 SetVolumeSync(Sync, volptr);
5306 /* Handle the actual lock release */
5307 if ((errorCode = HandleLocking(targetptr, rights, LockRelease)))
5308 goto Bad_ReleaseLock;
5310 /* if no more locks left, a callback would be triggered here */
5311 if (targetptr->disk.lock.lockCount <= 0) {
5312 /* convert the write lock to a read lock before breaking callbacks */
5313 VVnodeWriteToRead(&errorCode, targetptr);
5314 assert(!errorCode || errorCode == VSALVAGE);
5315 BreakCallBack(client->host, Fid, 0);
5319 /* Put back file's vnode and volume */
5320 (void)PutVolumePackage(parentwhentargetnotdir, targetptr, (Vnode *) 0,
5323 if ((errorCode == VREADONLY)) /* presumably, we already granted this lock */
5324 errorCode = 0; /* under our generous policy re RO vols */
5326 ViceLog(2, ("SAFS_ReleaseLock returns %d\n", errorCode));
5329 } /*SAFSS_ReleaseLock */
5333 SRXAFS_OldReleaseLock(struct rx_call * acall, struct AFSFid * Fid,
5334 struct AFSVolSync * Sync)
5336 return SRXAFS_ReleaseLock(acall, Fid, Sync);
5337 } /*SRXAFS_OldReleaseLock */
5341 SRXAFS_ReleaseLock(struct rx_call * acall, struct AFSFid * Fid,
5342 struct AFSVolSync * Sync)
5345 struct rx_connection *tcon;
5346 struct client *t_client = NULL; /* tmp ptr to client data */
5347 #if FS_STATS_DETAILED
5348 struct fs_stats_opTimingData *opP; /* Ptr to this op's timing struct */
5349 struct timeval opStartTime, opStopTime; /* Start/stop times for RPC op */
5350 struct timeval elapsedTime; /* Transfer time */
5353 * Set our stats pointer, remember when the RPC operation started, and
5354 * tally the operation.
5356 opP = &(afs_FullPerfStats.det.rpcOpTimes[FS_STATS_RPCIDX_RELEASELOCK]);
5360 TM_GetTimeOfDay(&opStartTime, 0);
5361 #endif /* FS_STATS_DETAILED */
5363 if ((code = CallPreamble(acall, ACTIVECALL, &tcon)))
5364 goto Bad_ReleaseLock;
5366 code = SAFSS_ReleaseLock(acall, Fid, Sync);
5369 code = CallPostamble(tcon, code);
5371 t_client = (struct client *)rx_GetSpecific(tcon, rxcon_client_key);
5373 #if FS_STATS_DETAILED
5374 TM_GetTimeOfDay(&opStopTime, 0);
5377 (opP->numSuccesses)++;
5378 fs_stats_GetDiff(elapsedTime, opStartTime, opStopTime);
5379 fs_stats_AddTo((opP->sumTime), elapsedTime);
5380 fs_stats_SquareAddTo((opP->sqrTime), elapsedTime);
5381 if (fs_stats_TimeLessThan(elapsedTime, (opP->minTime))) {
5382 fs_stats_TimeAssign((opP->minTime), elapsedTime);
5384 if (fs_stats_TimeGreaterThan(elapsedTime, (opP->maxTime))) {
5385 fs_stats_TimeAssign((opP->maxTime), elapsedTime);
5389 #endif /* FS_STATS_DETAILED */
5391 osi_auditU(acall, ReleaseLockEvent, code,
5392 AUD_ID, t_client ? t_client->ViceId : 0,
5393 AUD_FID, Fid, AUD_END);
5396 } /*SRXAFS_ReleaseLock */
5400 SetSystemStats(struct AFSStatistics *stats)
5402 /* Fix this sometime soon.. */
5403 /* Because hey, it's not like we have a network monitoring protocol... */
5404 struct timeval time;
5406 /* this works on all system types */
5407 TM_GetTimeOfDay(&time, 0);
5408 stats->CurrentTime = time.tv_sec;
5409 } /*SetSystemStats */
5412 SetAFSStats(struct AFSStatistics *stats)
5414 extern afs_int32 StartTime, CurrentConnections;
5418 stats->CurrentMsgNumber = 0;
5419 stats->OldestMsgNumber = 0;
5420 stats->StartTime = StartTime;
5421 stats->CurrentConnections = CurrentConnections;
5422 stats->TotalAFSCalls = AFSCallStats.TotalCalls;
5423 stats->TotalFetchs =
5424 AFSCallStats.FetchData + AFSCallStats.FetchACL +
5425 AFSCallStats.FetchStatus;
5426 stats->FetchDatas = AFSCallStats.FetchData;
5427 stats->FetchedBytes = AFSCallStats.TotalFetchedBytes;
5428 seconds = AFSCallStats.AccumFetchTime / 1000;
5431 stats->FetchDataRate = AFSCallStats.TotalFetchedBytes / seconds;
5432 stats->TotalStores =
5433 AFSCallStats.StoreData + AFSCallStats.StoreACL +
5434 AFSCallStats.StoreStatus;
5435 stats->StoreDatas = AFSCallStats.StoreData;
5436 stats->StoredBytes = AFSCallStats.TotalStoredBytes;
5437 seconds = AFSCallStats.AccumStoreTime / 1000;
5440 stats->StoreDataRate = AFSCallStats.TotalStoredBytes / seconds;
5442 stats->ProcessSize = -1; /* TODO: */
5444 stats->ProcessSize = (afs_int32) ((long)sbrk(0) >> 10);
5447 h_GetWorkStats((int *)&(stats->WorkStations),
5448 (int *)&(stats->ActiveWorkStations), (int *)0,
5449 (afs_int32) (FT_ApproxTime()) - (15 * 60));
5453 /* Get disk related information from all AFS partitions. */
5456 SetVolumeStats(struct AFSStatistics *stats)
5458 struct DiskPartition *part;
5461 for (part = DiskPartitionList; part && i < AFS_MSTATDISKS;
5462 part = part->next) {
5463 stats->Disks[i].TotalBlocks = part->totalUsable;
5464 stats->Disks[i].BlocksAvailable = part->free;
5465 memset(stats->Disks[i].Name, 0, AFS_DISKNAMESIZE);
5466 strncpy(stats->Disks[i].Name, part->name, AFS_DISKNAMESIZE);
5469 while (i < AFS_MSTATDISKS) {
5470 stats->Disks[i].TotalBlocks = -1;
5473 } /*SetVolumeStats */
5476 SRXAFS_GetStatistics(struct rx_call *acall, struct ViceStatistics *Statistics)
5479 struct rx_connection *tcon = rx_ConnectionOf(acall);
5480 struct client *t_client = NULL; /* tmp ptr to client data */
5481 #if FS_STATS_DETAILED
5482 struct fs_stats_opTimingData *opP; /* Ptr to this op's timing struct */
5483 struct timeval opStartTime, opStopTime; /* Start/stop times for RPC op */
5484 struct timeval elapsedTime; /* Transfer time */
5487 * Set our stats pointer, remember when the RPC operation started, and
5488 * tally the operation.
5490 opP = &(afs_FullPerfStats.det.rpcOpTimes[FS_STATS_RPCIDX_GETSTATISTICS]);
5494 TM_GetTimeOfDay(&opStartTime, 0);
5495 #endif /* FS_STATS_DETAILED */
5497 if ((code = CallPreamble(acall, NOTACTIVECALL, &tcon)))
5498 goto Bad_GetStatistics;
5500 ViceLog(1, ("SAFS_GetStatistics Received\n"));
5502 AFSCallStats.GetStatistics++, AFSCallStats.TotalCalls++;
5504 memset(Statistics, 0, sizeof(*Statistics));
5505 SetAFSStats((struct AFSStatistics *)Statistics);
5506 SetVolumeStats((struct AFSStatistics *)Statistics);
5507 SetSystemStats((struct AFSStatistics *)Statistics);
5510 code = CallPostamble(tcon, code);
5512 t_client = (struct client *)rx_GetSpecific(tcon, rxcon_client_key);
5514 #if FS_STATS_DETAILED
5515 TM_GetTimeOfDay(&opStopTime, 0);
5518 (opP->numSuccesses)++;
5519 fs_stats_GetDiff(elapsedTime, opStartTime, opStopTime);
5520 fs_stats_AddTo((opP->sumTime), elapsedTime);
5521 fs_stats_SquareAddTo((opP->sqrTime), elapsedTime);
5522 if (fs_stats_TimeLessThan(elapsedTime, (opP->minTime))) {
5523 fs_stats_TimeAssign((opP->minTime), elapsedTime);
5525 if (fs_stats_TimeGreaterThan(elapsedTime, (opP->maxTime))) {
5526 fs_stats_TimeAssign((opP->maxTime), elapsedTime);
5530 #endif /* FS_STATS_DETAILED */
5532 osi_auditU(acall, GetStatisticsEvent, code,
5533 AUD_ID, t_client ? t_client->ViceId : 0, AUD_END);
5535 } /*SRXAFS_GetStatistics */
5538 /*------------------------------------------------------------------------
5539 * EXPORTED SRXAFS_XStatsVersion
5542 * Routine called by the server-side RPC interface to implement
5543 * pulling out the xstat version number for the File Server.
5546 * a_versionP : Ptr to the version number variable to set.
5552 * Nothing interesting.
5556 *------------------------------------------------------------------------*/
5559 SRXAFS_XStatsVersion(struct rx_call * a_call, afs_int32 * a_versionP)
5560 { /*SRXAFS_XStatsVersion */
5562 struct client *t_client = NULL; /* tmp ptr to client data */
5563 struct rx_connection *tcon;
5564 #if FS_STATS_DETAILED
5565 struct fs_stats_opTimingData *opP; /* Ptr to this op's timing struct */
5566 struct timeval opStartTime, opStopTime; /* Start/stop times for RPC op */
5567 struct timeval elapsedTime; /* Transfer time */
5570 * Set our stats pointer, remember when the RPC operation started, and
5571 * tally the operation.
5573 opP = &(afs_FullPerfStats.det.rpcOpTimes[FS_STATS_RPCIDX_XSTATSVERSION]);
5577 TM_GetTimeOfDay(&opStartTime, 0);
5578 #endif /* FS_STATS_DETAILED */
5580 *a_versionP = AFS_XSTAT_VERSION;
5582 t_client = (struct client *)rx_GetSpecific(tcon, rxcon_client_key);
5584 #if FS_STATS_DETAILED
5585 TM_GetTimeOfDay(&opStopTime, 0);
5586 fs_stats_GetDiff(elapsedTime, opStartTime, opStopTime);
5587 fs_stats_AddTo((opP->sumTime), elapsedTime);
5588 fs_stats_SquareAddTo((opP->sqrTime), elapsedTime);
5589 if (fs_stats_TimeLessThan(elapsedTime, (opP->minTime))) {
5590 fs_stats_TimeAssign((opP->minTime), elapsedTime);
5592 if (fs_stats_TimeGreaterThan(elapsedTime, (opP->maxTime))) {
5593 fs_stats_TimeAssign((opP->maxTime), elapsedTime);
5596 (opP->numSuccesses)++;
5598 #endif /* FS_STATS_DETAILED */
5600 osi_auditU(a_call, XStatsVersionEvent, 0,
5601 AUD_ID, t_client ? t_client->ViceId : 0, AUD_END);
5603 } /*SRXAFS_XStatsVersion */
5606 /*------------------------------------------------------------------------
5607 * PRIVATE FillPerfValues
5610 * Routine called to fill a regular performance data structure.
5613 * a_perfP : Ptr to perf structure to fill
5619 * Various collections need this info, so the guts were put in
5620 * this separate routine.
5624 *------------------------------------------------------------------------*/
5627 FillPerfValues(struct afs_PerfStats *a_perfP)
5628 { /*FillPerfValues */
5630 int dir_Buffers; /*# buffers in use by dir package */
5631 int dir_Calls; /*# read calls in dir package */
5632 int dir_IOs; /*# I/O ops in dir package */
5635 * Vnode cache section.
5637 a_perfP->vcache_L_Entries = VnodeClassInfo[vLarge].cacheSize;
5638 a_perfP->vcache_L_Allocs = VnodeClassInfo[vLarge].allocs;
5639 a_perfP->vcache_L_Gets = VnodeClassInfo[vLarge].gets;
5640 a_perfP->vcache_L_Reads = VnodeClassInfo[vLarge].reads;
5641 a_perfP->vcache_L_Writes = VnodeClassInfo[vLarge].writes;
5642 a_perfP->vcache_S_Entries = VnodeClassInfo[vSmall].cacheSize;
5643 a_perfP->vcache_S_Allocs = VnodeClassInfo[vSmall].allocs;
5644 a_perfP->vcache_S_Gets = VnodeClassInfo[vSmall].gets;
5645 a_perfP->vcache_S_Reads = VnodeClassInfo[vSmall].reads;
5646 a_perfP->vcache_S_Writes = VnodeClassInfo[vSmall].writes;
5647 a_perfP->vcache_H_Entries = VolumeCacheSize;
5648 a_perfP->vcache_H_Gets = VolumeGets;
5649 a_perfP->vcache_H_Replacements = VolumeReplacements;
5652 * Directory section.
5654 DStat(&dir_Buffers, &dir_Calls, &dir_IOs);
5655 a_perfP->dir_Buffers = (afs_int32) dir_Buffers;
5656 a_perfP->dir_Calls = (afs_int32) dir_Calls;
5657 a_perfP->dir_IOs = (afs_int32) dir_IOs;
5662 a_perfP->rx_packetRequests = (afs_int32) rx_stats.packetRequests;
5663 a_perfP->rx_noPackets_RcvClass =
5664 (afs_int32) rx_stats.receivePktAllocFailures;
5665 a_perfP->rx_noPackets_SendClass =
5666 (afs_int32) rx_stats.sendPktAllocFailures;
5667 a_perfP->rx_noPackets_SpecialClass =
5668 (afs_int32) rx_stats.specialPktAllocFailures;
5669 a_perfP->rx_socketGreedy = (afs_int32) rx_stats.socketGreedy;
5670 a_perfP->rx_bogusPacketOnRead = (afs_int32) rx_stats.bogusPacketOnRead;
5671 a_perfP->rx_bogusHost = (afs_int32) rx_stats.bogusHost;
5672 a_perfP->rx_noPacketOnRead = (afs_int32) rx_stats.noPacketOnRead;
5673 a_perfP->rx_noPacketBuffersOnRead =
5674 (afs_int32) rx_stats.noPacketBuffersOnRead;
5675 a_perfP->rx_selects = (afs_int32) rx_stats.selects;
5676 a_perfP->rx_sendSelects = (afs_int32) rx_stats.sendSelects;
5677 a_perfP->rx_packetsRead_RcvClass =
5678 (afs_int32) rx_stats.packetsRead[RX_PACKET_CLASS_RECEIVE];
5679 a_perfP->rx_packetsRead_SendClass =
5680 (afs_int32) rx_stats.packetsRead[RX_PACKET_CLASS_SEND];
5681 a_perfP->rx_packetsRead_SpecialClass =
5682 (afs_int32) rx_stats.packetsRead[RX_PACKET_CLASS_SPECIAL];
5683 a_perfP->rx_dataPacketsRead = (afs_int32) rx_stats.dataPacketsRead;
5684 a_perfP->rx_ackPacketsRead = (afs_int32) rx_stats.ackPacketsRead;
5685 a_perfP->rx_dupPacketsRead = (afs_int32) rx_stats.dupPacketsRead;
5686 a_perfP->rx_spuriousPacketsRead =
5687 (afs_int32) rx_stats.spuriousPacketsRead;
5688 a_perfP->rx_packetsSent_RcvClass =
5689 (afs_int32) rx_stats.packetsSent[RX_PACKET_CLASS_RECEIVE];
5690 a_perfP->rx_packetsSent_SendClass =
5691 (afs_int32) rx_stats.packetsSent[RX_PACKET_CLASS_SEND];
5692 a_perfP->rx_packetsSent_SpecialClass =
5693 (afs_int32) rx_stats.packetsSent[RX_PACKET_CLASS_SPECIAL];
5694 a_perfP->rx_ackPacketsSent = (afs_int32) rx_stats.ackPacketsSent;
5695 a_perfP->rx_pingPacketsSent = (afs_int32) rx_stats.pingPacketsSent;
5696 a_perfP->rx_abortPacketsSent = (afs_int32) rx_stats.abortPacketsSent;
5697 a_perfP->rx_busyPacketsSent = (afs_int32) rx_stats.busyPacketsSent;
5698 a_perfP->rx_dataPacketsSent = (afs_int32) rx_stats.dataPacketsSent;
5699 a_perfP->rx_dataPacketsReSent = (afs_int32) rx_stats.dataPacketsReSent;
5700 a_perfP->rx_dataPacketsPushed = (afs_int32) rx_stats.dataPacketsPushed;
5701 a_perfP->rx_ignoreAckedPacket = (afs_int32) rx_stats.ignoreAckedPacket;
5702 a_perfP->rx_totalRtt_Sec = (afs_int32) rx_stats.totalRtt.sec;
5703 a_perfP->rx_totalRtt_Usec = (afs_int32) rx_stats.totalRtt.usec;
5704 a_perfP->rx_minRtt_Sec = (afs_int32) rx_stats.minRtt.sec;
5705 a_perfP->rx_minRtt_Usec = (afs_int32) rx_stats.minRtt.usec;
5706 a_perfP->rx_maxRtt_Sec = (afs_int32) rx_stats.maxRtt.sec;
5707 a_perfP->rx_maxRtt_Usec = (afs_int32) rx_stats.maxRtt.usec;
5708 a_perfP->rx_nRttSamples = (afs_int32) rx_stats.nRttSamples;
5709 a_perfP->rx_nServerConns = (afs_int32) rx_stats.nServerConns;
5710 a_perfP->rx_nClientConns = (afs_int32) rx_stats.nClientConns;
5711 a_perfP->rx_nPeerStructs = (afs_int32) rx_stats.nPeerStructs;
5712 a_perfP->rx_nCallStructs = (afs_int32) rx_stats.nCallStructs;
5713 a_perfP->rx_nFreeCallStructs = (afs_int32) rx_stats.nFreeCallStructs;
5715 a_perfP->host_NumHostEntries = HTs;
5716 a_perfP->host_HostBlocks = HTBlocks;
5717 h_GetHostNetStats(&(a_perfP->host_NonDeletedHosts),
5718 &(a_perfP->host_HostsInSameNetOrSubnet),
5719 &(a_perfP->host_HostsInDiffSubnet),
5720 &(a_perfP->host_HostsInDiffNetwork));
5721 a_perfP->host_NumClients = CEs;
5722 a_perfP->host_ClientBlocks = CEBlocks;
5724 a_perfP->sysname_ID = afs_perfstats.sysname_ID;
5725 a_perfP->rx_nBusies = (afs_int32) rx_stats.nBusies;
5726 a_perfP->fs_nBusies = afs_perfstats.fs_nBusies;
5727 } /*FillPerfValues */
5730 /*------------------------------------------------------------------------
5731 * EXPORTED SRXAFS_GetXStats
5734 * Routine called by the server-side callback RPC interface to
5735 * implement getting the given data collection from the extended
5736 * File Server statistics.
5739 * a_call : Ptr to Rx call on which this request came in.
5740 * a_clientVersionNum : Client version number.
5741 * a_opCode : Desired operation.
5742 * a_serverVersionNumP : Ptr to version number to set.
5743 * a_timeP : Ptr to time value (seconds) to set.
5744 * a_dataP : Ptr to variable array structure to return
5751 * Nothing interesting.
5755 *------------------------------------------------------------------------*/
5758 SRXAFS_GetXStats(struct rx_call *a_call, afs_int32 a_clientVersionNum,
5759 afs_int32 a_collectionNumber, afs_int32 * a_srvVersionNumP,
5760 afs_int32 * a_timeP, AFS_CollData * a_dataP)
5761 { /*SRXAFS_GetXStats */
5763 register int code; /*Return value */
5764 afs_int32 *dataBuffP; /*Ptr to data to be returned */
5765 afs_int32 dataBytes; /*Bytes in data buffer */
5766 #if FS_STATS_DETAILED
5767 struct fs_stats_opTimingData *opP; /* Ptr to this op's timing struct */
5768 struct timeval opStartTime, opStopTime; /* Start/stop times for RPC op */
5769 struct timeval elapsedTime; /* Transfer time */
5772 * Set our stats pointer, remember when the RPC operation started, and
5773 * tally the operation.
5775 opP = &(afs_FullPerfStats.det.rpcOpTimes[FS_STATS_RPCIDX_GETXSTATS]);
5779 TM_GetTimeOfDay(&opStartTime, 0);
5780 #endif /* FS_STATS_DETAILED */
5783 * Record the time of day and the server version number.
5785 *a_srvVersionNumP = AFS_XSTAT_VERSION;
5786 *a_timeP = FT_ApproxTime();
5789 * Stuff the appropriate data in there (assume victory)
5794 ("Received GetXStats call for collection %d\n",
5795 a_collectionNumber));
5799 * We're not keeping stats, so just return successfully with
5802 a_dataP->AFS_CollData_len = 0;
5803 a_dataP->AFS_CollData_val = NULL;
5806 switch (a_collectionNumber) {
5807 case AFS_XSTATSCOLL_CALL_INFO:
5809 * Pass back all the call-count-related data.
5811 * >>> We are forced to allocate a separate area in which to
5812 * >>> put this stuff in by the RPC stub generator, since it
5813 * >>> will be freed at the tail end of the server stub code.
5817 * I don't think call-level stats are being collected yet
5818 * for the File Server.
5820 dataBytes = sizeof(struct afs_Stats);
5821 dataBuffP = (afs_int32 *) malloc(dataBytes);
5822 memcpy(dataBuffP, &afs_cmstats, dataBytes);
5823 a_dataP->AFS_CollData_len = dataBytes >> 2;
5824 a_dataP->AFS_CollData_val = dataBuffP;
5826 a_dataP->AFS_CollData_len = 0;
5827 a_dataP->AFS_CollData_val = NULL;
5831 case AFS_XSTATSCOLL_PERF_INFO:
5833 * Pass back all the regular performance-related data.
5835 * >>> We are forced to allocate a separate area in which to
5836 * >>> put this stuff in by the RPC stub generator, since it
5837 * >>> will be freed at the tail end of the server stub code.
5840 afs_perfstats.numPerfCalls++;
5841 FillPerfValues(&afs_perfstats);
5844 * Don't overwrite the spares at the end.
5847 dataBytes = sizeof(struct afs_PerfStats);
5848 dataBuffP = (afs_int32 *) malloc(dataBytes);
5849 memcpy(dataBuffP, &afs_perfstats, dataBytes);
5850 a_dataP->AFS_CollData_len = dataBytes >> 2;
5851 a_dataP->AFS_CollData_val = dataBuffP;
5854 case AFS_XSTATSCOLL_FULL_PERF_INFO:
5856 * Pass back the full collection of performance-related data.
5857 * We have to stuff the basic, overall numbers in, but the
5858 * detailed numbers are kept in the structure already.
5860 * >>> We are forced to allocate a separate area in which to
5861 * >>> put this stuff in by the RPC stub generator, since it
5862 * >>> will be freed at the tail end of the server stub code.
5865 afs_perfstats.numPerfCalls++;
5866 #if FS_STATS_DETAILED
5867 afs_FullPerfStats.overall.numPerfCalls = afs_perfstats.numPerfCalls;
5868 FillPerfValues(&afs_FullPerfStats.overall);
5871 * Don't overwrite the spares at the end.
5874 dataBytes = sizeof(struct fs_stats_FullPerfStats);
5875 dataBuffP = (afs_int32 *) malloc(dataBytes);
5876 memcpy(dataBuffP, &afs_FullPerfStats, dataBytes);
5877 a_dataP->AFS_CollData_len = dataBytes >> 2;
5878 a_dataP->AFS_CollData_val = dataBuffP;
5884 * Illegal collection number.
5886 a_dataP->AFS_CollData_len = 0;
5887 a_dataP->AFS_CollData_val = NULL;
5889 } /*Switch on collection number */
5891 #if FS_STATS_DETAILED
5892 TM_GetTimeOfDay(&opStopTime, 0);
5895 (opP->numSuccesses)++;
5896 fs_stats_GetDiff(elapsedTime, opStartTime, opStopTime);
5897 fs_stats_AddTo((opP->sumTime), elapsedTime);
5898 fs_stats_SquareAddTo((opP->sqrTime), elapsedTime);
5899 if (fs_stats_TimeLessThan(elapsedTime, (opP->minTime))) {
5900 fs_stats_TimeAssign((opP->minTime), elapsedTime);
5902 if (fs_stats_TimeGreaterThan(elapsedTime, (opP->maxTime))) {
5903 fs_stats_TimeAssign((opP->maxTime), elapsedTime);
5907 #endif /* FS_STATS_DETAILED */
5911 } /*SRXAFS_GetXStats */
5915 common_GiveUpCallBacks(struct rx_call *acall, struct AFSCBFids *FidArray,
5916 struct AFSCBs *CallBackArray)
5918 afs_int32 errorCode = 0;
5920 struct client *client;
5921 struct rx_connection *tcon;
5922 #if FS_STATS_DETAILED
5923 struct fs_stats_opTimingData *opP; /* Ptr to this op's timing struct */
5924 struct timeval opStartTime, opStopTime; /* Start/stop times for RPC op */
5925 struct timeval elapsedTime; /* Transfer time */
5928 * Set our stats pointer, remember when the RPC operation started, and
5929 * tally the operation.
5932 &(afs_FullPerfStats.det.rpcOpTimes[FS_STATS_RPCIDX_GIVEUPCALLBACKS]);
5936 TM_GetTimeOfDay(&opStartTime, 0);
5937 #endif /* FS_STATS_DETAILED */
5941 ("SAFS_GiveUpCallBacks (Noffids=%d)\n",
5942 FidArray->AFSCBFids_len));
5945 AFSCallStats.GiveUpCallBacks++, AFSCallStats.TotalCalls++;
5947 if ((errorCode = CallPreamble(acall, ACTIVECALL, &tcon)))
5948 goto Bad_GiveUpCallBacks;
5950 if (!FidArray && !CallBackArray) {
5952 ("SAFS_GiveUpAllCallBacks: host=%x\n",
5953 (tcon->peer ? tcon->peer->host : 0)));
5954 errorCode = GetClient(tcon, &client);
5956 DeleteAllCallBacks_r(client->host, 1);
5958 if (FidArray->AFSCBFids_len < CallBackArray->AFSCBs_len) {
5960 ("GiveUpCallBacks: #Fids %d < #CallBacks %d, host=%x\n",
5961 FidArray->AFSCBFids_len, CallBackArray->AFSCBs_len,
5962 (tcon->peer ? tcon->peer->host : 0)));
5964 goto Bad_GiveUpCallBacks;
5967 errorCode = GetClient(tcon, &client);
5969 for (i = 0; i < FidArray->AFSCBFids_len; i++) {
5970 register struct AFSFid *fid = &(FidArray->AFSCBFids_val[i]);
5971 DeleteCallBack(client->host, fid);
5976 Bad_GiveUpCallBacks:
5977 errorCode = CallPostamble(tcon, errorCode);
5979 #if FS_STATS_DETAILED
5980 TM_GetTimeOfDay(&opStopTime, 0);
5981 if (errorCode == 0) {
5983 (opP->numSuccesses)++;
5984 fs_stats_GetDiff(elapsedTime, opStartTime, opStopTime);
5985 fs_stats_AddTo((opP->sumTime), elapsedTime);
5986 fs_stats_SquareAddTo((opP->sqrTime), elapsedTime);
5987 if (fs_stats_TimeLessThan(elapsedTime, (opP->minTime))) {
5988 fs_stats_TimeAssign((opP->minTime), elapsedTime);
5990 if (fs_stats_TimeGreaterThan(elapsedTime, (opP->maxTime))) {
5991 fs_stats_TimeAssign((opP->maxTime), elapsedTime);
5995 #endif /* FS_STATS_DETAILED */
5998 } /*common_GiveUpCallBacks */
6002 SRXAFS_GiveUpCallBacks(struct rx_call * acall, struct AFSCBFids * FidArray,
6003 struct AFSCBs * CallBackArray)
6005 return common_GiveUpCallBacks(acall, FidArray, CallBackArray);
6006 } /*SRXAFS_GiveUpCallBacks */
6009 SRXAFS_GiveUpAllCallBacks(struct rx_call * acall)
6011 return common_GiveUpCallBacks(acall, 0, 0);
6012 } /*SRXAFS_GiveUpAllCallBacks */
6016 SRXAFS_NGetVolumeInfo(struct rx_call * acall, char *avolid,
6017 struct AFSVolumeInfo * avolinfo)
6019 return (VNOVOL); /* XXX Obsolete routine XXX */
6021 } /*SRXAFS_NGetVolumeInfo */
6025 * Dummy routine. Should never be called (the cache manager should only
6026 * invoke this interface when communicating with a AFS/DFS Protocol
6030 SRXAFS_Lookup(struct rx_call * call_p, struct AFSFid * afs_dfid_p,
6031 char *afs_name_p, struct AFSFid * afs_fid_p,
6032 struct AFSFetchStatus * afs_status_p,
6033 struct AFSFetchStatus * afs_dir_status_p,
6034 struct AFSCallBack * afs_callback_p,
6035 struct AFSVolSync * afs_sync_p)
6042 SRXAFS_GetCapabilities(struct rx_call * acall, Capabilities * capabilities)
6045 struct rx_connection *tcon;
6046 afs_int32 *dataBuffP;
6047 afs_int32 dataBytes;
6048 #if FS_STATS_DETAILED
6049 struct fs_stats_opTimingData *opP; /* Ptr to this op's timing struct */
6050 struct timeval opStartTime, opStopTime; /* Start/stop times for RPC op */
6051 struct timeval elapsedTime; /* Transfer time */
6054 * Set our stats pointer, remember when the RPC operation started, and
6055 * tally the operation.
6057 opP = &(afs_FullPerfStats.det.rpcOpTimes[FS_STATS_RPCIDX_GETCAPABILITIES]);
6061 TM_GetTimeOfDay(&opStartTime, 0);
6062 #endif /* FS_STATS_DETAILED */
6064 if ((code = CallPreamble(acall, NOTACTIVECALL, &tcon)))
6068 AFSCallStats.GetCapabilities++, AFSCallStats.TotalCalls++;
6070 dataBytes = 1 * sizeof(afs_int32);
6071 dataBuffP = (afs_int32 *) malloc(dataBytes);
6072 dataBuffP[0] = VICED_CAPABILITY_ERRORTRANS;
6073 #if defined(AFS_64BIT_ENV) && defined(AFS_LARGEFILE_ENV)
6074 dataBuffP[0] |= VICED_CAPABILITY_64BITFILES;
6077 capabilities->Capabilities_len = dataBytes / sizeof(afs_int32);
6078 capabilities->Capabilities_val = dataBuffP;
6080 ViceLog(2, ("SAFS_GetCapabilties\n"));
6083 code = CallPostamble(tcon, code);
6085 #if FS_STATS_DETAILED
6086 TM_GetTimeOfDay(&opStopTime, 0);
6087 fs_stats_GetDiff(elapsedTime, opStartTime, opStopTime);
6090 (opP->numSuccesses)++;
6091 fs_stats_AddTo((opP->sumTime), elapsedTime);
6092 fs_stats_SquareAddTo((opP->sqrTime), elapsedTime);
6093 if (fs_stats_TimeLessThan(elapsedTime, (opP->minTime))) {
6094 fs_stats_TimeAssign((opP->minTime), elapsedTime);
6096 if (fs_stats_TimeGreaterThan(elapsedTime, (opP->maxTime))) {
6097 fs_stats_TimeAssign((opP->maxTime), elapsedTime);
6101 #endif /* FS_STATS_DETAILED */
6106 SRXAFS_FlushCPS(struct rx_call * acall, struct ViceIds * vids,
6107 struct IPAddrs * addrs, afs_int32 spare1, afs_int32 * spare2,
6111 afs_int32 nids, naddrs;
6112 afs_int32 *vd, *addr;
6113 int errorCode = 0; /* return code to caller */
6114 struct client *client;
6115 struct rx_connection *tcon = rx_ConnectionOf(acall);
6117 ViceLog(1, ("SRXAFS_FlushCPS\n"));
6119 AFSCallStats.TotalCalls++;
6121 nids = vids->ViceIds_len; /* # of users in here */
6122 naddrs = addrs->IPAddrs_len; /* # of hosts in here */
6123 if (nids < 0 || naddrs < 0) {
6128 vd = vids->ViceIds_val;
6129 for (i = 0; i < nids; i++, vd++) {
6132 client = h_ID2Client(*vd); /* returns client write locked, or NULL */
6136 client->prfail = 2; /* Means re-eval client's cps */
6139 rx_SetRock(((struct rx_connection *)client->tcon), 0);
6142 if ((client->ViceId != ANONYMOUSID) && client->CPS.prlist_val) {
6143 free(client->CPS.prlist_val);
6144 client->CPS.prlist_val = NULL;
6145 client->CPS.prlist_len = 0;
6147 ReleaseWriteLock(&client->lock);
6150 addr = addrs->IPAddrs_val;
6151 for (i = 0; i < naddrs; i++, addr++) {
6153 h_flushhostcps(*addr, htons(7001));
6157 ViceLog(2, ("SAFS_FlushCPS returns %d\n", errorCode));
6159 } /*SRXAFS_FlushCPS */
6161 /* worthless hack to let CS keep running ancient software */
6163 afs_vtoi(register char *aname)
6165 register afs_int32 temp;
6169 while ((tc = *aname++)) {
6170 if (tc > '9' || tc < '0')
6171 return 0; /* invalid name */
6179 * may get name or #, but must handle all weird cases (recognize readonly
6180 * or backup volumes by name or #
6183 CopyVolumeEntry(char *aname, register struct vldbentry *ave,
6184 register struct VolumeInfo *av)
6186 register int i, j, vol;
6187 afs_int32 mask, whichType;
6188 afs_uint32 *serverHost, *typePtr;
6190 /* figure out what type we want if by name */
6192 if (i >= 8 && strcmp(aname + i - 7, ".backup") == 0)
6193 whichType = BACKVOL;
6194 else if (i >= 10 && strcmp(aname + i - 9, ".readonly") == 0)
6199 vol = afs_vtoi(aname);
6201 vol = ave->volumeId[whichType];
6204 * Now vol has volume # we're interested in. Next, figure out the type
6205 * of the volume by looking finding it in the vldb entry
6207 if ((ave->flags & VLF_RWEXISTS) && vol == ave->volumeId[RWVOL]) {
6210 } else if ((ave->flags & VLF_ROEXISTS) && vol == ave->volumeId[ROVOL]) {
6213 } else if ((ave->flags & VLF_BACKEXISTS) && vol == ave->volumeId[BACKVOL]) {
6214 mask = VLSF_RWVOL; /* backup always is on the same volume as parent */
6215 whichType = BACKVOL;
6217 return EINVAL; /* error: can't find volume in vldb entry */
6219 typePtr = &av->Type0;
6220 serverHost = &av->Server0;
6222 av->Type = whichType;
6223 av->Type0 = av->Type1 = av->Type2 = av->Type3 = av->Type4 = 0;
6224 if (ave->flags & VLF_RWEXISTS)
6225 typePtr[RWVOL] = ave->volumeId[RWVOL];
6226 if (ave->flags & VLF_ROEXISTS)
6227 typePtr[ROVOL] = ave->volumeId[ROVOL];
6228 if (ave->flags & VLF_BACKEXISTS)
6229 typePtr[BACKVOL] = ave->volumeId[BACKVOL];
6231 for (i = 0, j = 0; i < ave->nServers; i++) {
6232 if ((ave->serverFlags[i] & mask) == 0)
6233 continue; /* wrong volume */
6234 serverHost[j] = ave->serverNumber[i];
6237 av->ServerCount = j;
6239 serverHost[j++] = 0; /* bogus 8, but compat only now */
6244 TryLocalVLServer(char *avolid, struct VolumeInfo *avolinfo)
6246 static struct rx_connection *vlConn = 0;
6247 static int down = 0;
6248 static afs_int32 lastDownTime = 0;
6249 struct vldbentry tve;
6250 struct rx_securityClass *vlSec;
6251 register afs_int32 code;
6254 vlSec = rxnull_NewClientSecurityObject();
6256 rx_NewConnection(htonl(0x7f000001), htons(7003), 52, vlSec, 0);
6257 rx_SetConnDeadTime(vlConn, 15); /* don't wait long */
6259 if (down && (FT_ApproxTime() < lastDownTime + 180)) {
6260 return 1; /* failure */
6263 code = VL_GetEntryByNameO(vlConn, avolid, &tve);
6265 down = 0; /* call worked */
6268 lastDownTime = FT_ApproxTime(); /* last time we tried an RPC */
6274 /* otherwise convert to old format vldb entry */
6275 code = CopyVolumeEntry(avolid, &tve, avolinfo);
6285 SRXAFS_GetVolumeInfo(struct rx_call * acall, char *avolid,
6286 struct VolumeInfo * avolinfo)
6289 struct rx_connection *tcon;
6290 #if FS_STATS_DETAILED
6291 struct fs_stats_opTimingData *opP; /* Ptr to this op's timing struct */
6292 struct timeval opStartTime, opStopTime; /* Start/stop times for RPC op */
6293 struct timeval elapsedTime; /* Transfer time */
6296 * Set our stats pointer, remember when the RPC operation started, and
6297 * tally the operation.
6299 opP = &(afs_FullPerfStats.det.rpcOpTimes[FS_STATS_RPCIDX_GETVOLUMEINFO]);
6303 TM_GetTimeOfDay(&opStartTime, 0);
6304 #endif /* FS_STATS_DETAILED */
6305 if ((code = CallPreamble(acall, ACTIVECALL, &tcon)))
6306 goto Bad_GetVolumeInfo;
6309 AFSCallStats.GetVolumeInfo++, AFSCallStats.TotalCalls++;
6311 code = TryLocalVLServer(avolid, avolinfo);
6313 ("SAFS_GetVolumeInfo returns %d, Volume %u, type %x, servers %x %x %x %x...\n",
6314 code, avolinfo->Vid, avolinfo->Type, avolinfo->Server0,
6315 avolinfo->Server1, avolinfo->Server2, avolinfo->Server3));
6316 avolinfo->Type4 = 0xabcd9999; /* tell us to try new vldb */
6319 code = CallPostamble(tcon, code);
6321 #if FS_STATS_DETAILED
6322 TM_GetTimeOfDay(&opStopTime, 0);
6325 (opP->numSuccesses)++;
6326 fs_stats_GetDiff(elapsedTime, opStartTime, opStopTime);
6327 fs_stats_AddTo((opP->sumTime), elapsedTime);
6328 fs_stats_SquareAddTo((opP->sqrTime), elapsedTime);
6329 if (fs_stats_TimeLessThan(elapsedTime, (opP->minTime))) {
6330 fs_stats_TimeAssign((opP->minTime), elapsedTime);
6332 if (fs_stats_TimeGreaterThan(elapsedTime, (opP->maxTime))) {
6333 fs_stats_TimeAssign((opP->maxTime), elapsedTime);
6337 #endif /* FS_STATS_DETAILED */
6341 } /*SRXAFS_GetVolumeInfo */
6345 SRXAFS_GetVolumeStatus(struct rx_call * acall, afs_int32 avolid,
6346 AFSFetchVolumeStatus * FetchVolStatus, char **Name,
6347 char **OfflineMsg, char **Motd)
6349 Vnode *targetptr = 0; /* vnode of the new file */
6350 Vnode *parentwhentargetnotdir = 0; /* vnode of parent */
6351 int errorCode = 0; /* error code */
6352 Volume *volptr = 0; /* pointer to the volume header */
6353 struct client *client; /* pointer to client entry */
6354 afs_int32 rights, anyrights; /* rights for this and any user */
6356 struct rx_connection *tcon;
6357 struct client *t_client = NULL; /* tmp ptr to client data */
6358 #if FS_STATS_DETAILED
6359 struct fs_stats_opTimingData *opP; /* Ptr to this op's timing struct */
6360 struct timeval opStartTime, opStopTime; /* Start/stop times for RPC op */
6361 struct timeval elapsedTime; /* Transfer time */
6364 * Set our stats pointer, remember when the RPC operation started, and
6365 * tally the operation.
6368 &(afs_FullPerfStats.det.rpcOpTimes[FS_STATS_RPCIDX_GETVOLUMESTATUS]);
6372 TM_GetTimeOfDay(&opStartTime, 0);
6373 #endif /* FS_STATS_DETAILED */
6375 ViceLog(1, ("SAFS_GetVolumeStatus for volume %u\n", avolid));
6376 if ((errorCode = CallPreamble(acall, ACTIVECALL, &tcon)))
6377 goto Bad_GetVolumeStatus;
6380 AFSCallStats.GetVolumeStatus++, AFSCallStats.TotalCalls++;
6384 goto Bad_GetVolumeStatus;
6386 dummyFid.Volume = avolid, dummyFid.Vnode =
6387 (afs_int32) ROOTVNODE, dummyFid.Unique = 1;
6390 GetVolumePackage(tcon, &dummyFid, &volptr, &targetptr, MustBeDIR,
6391 &parentwhentargetnotdir, &client, READ_LOCK,
6392 &rights, &anyrights)))
6393 goto Bad_GetVolumeStatus;
6395 if ((VanillaUser(client)) && (!(rights & PRSFS_READ))) {
6397 goto Bad_GetVolumeStatus;
6399 (void)RXGetVolumeStatus(FetchVolStatus, Name, OfflineMsg, Motd, volptr);
6401 Bad_GetVolumeStatus:
6402 (void)PutVolumePackage(parentwhentargetnotdir, targetptr, (Vnode *) 0,
6404 ViceLog(2, ("SAFS_GetVolumeStatus returns %d\n", errorCode));
6405 /* next is to guarantee out strings exist for stub */
6407 *Name = (char *)malloc(1);
6411 *Motd = (char *)malloc(1);
6414 if (*OfflineMsg == 0) {
6415 *OfflineMsg = (char *)malloc(1);
6418 errorCode = CallPostamble(tcon, errorCode);
6420 t_client = (struct client *)rx_GetSpecific(tcon, rxcon_client_key);
6422 #if FS_STATS_DETAILED
6423 TM_GetTimeOfDay(&opStopTime, 0);
6424 if (errorCode == 0) {
6426 (opP->numSuccesses)++;
6427 fs_stats_GetDiff(elapsedTime, opStartTime, opStopTime);
6428 fs_stats_AddTo((opP->sumTime), elapsedTime);
6429 fs_stats_SquareAddTo((opP->sqrTime), elapsedTime);
6430 if (fs_stats_TimeLessThan(elapsedTime, (opP->minTime))) {
6431 fs_stats_TimeAssign((opP->minTime), elapsedTime);
6433 if (fs_stats_TimeGreaterThan(elapsedTime, (opP->maxTime))) {
6434 fs_stats_TimeAssign((opP->maxTime), elapsedTime);
6438 #endif /* FS_STATS_DETAILED */
6440 osi_auditU(acall, GetVolumeStatusEvent, errorCode,
6441 AUD_ID, t_client ? t_client->ViceId : 0,
6442 AUD_LONG, avolid, AUD_STR, *Name, AUD_END);
6445 } /*SRXAFS_GetVolumeStatus */
6449 SRXAFS_SetVolumeStatus(struct rx_call * acall, afs_int32 avolid,
6450 AFSStoreVolumeStatus * StoreVolStatus, char *Name,
6451 char *OfflineMsg, char *Motd)
6453 Vnode *targetptr = 0; /* vnode of the new file */
6454 Vnode *parentwhentargetnotdir = 0; /* vnode of parent */
6455 int errorCode = 0; /* error code */
6456 Volume *volptr = 0; /* pointer to the volume header */
6457 struct client *client; /* pointer to client entry */
6458 afs_int32 rights, anyrights; /* rights for this and any user */
6460 struct rx_connection *tcon = rx_ConnectionOf(acall);
6461 struct client *t_client = NULL; /* tmp ptr to client data */
6462 #if FS_STATS_DETAILED
6463 struct fs_stats_opTimingData *opP; /* Ptr to this op's timing struct */
6464 struct timeval opStartTime, opStopTime; /* Start/stop times for RPC op */
6465 struct timeval elapsedTime; /* Transfer time */
6468 * Set our stats pointer, remember when the RPC operation started, and
6469 * tally the operation.
6472 &(afs_FullPerfStats.det.rpcOpTimes[FS_STATS_RPCIDX_SETVOLUMESTATUS]);
6476 TM_GetTimeOfDay(&opStartTime, 0);
6477 #endif /* FS_STATS_DETAILED */
6479 ViceLog(1, ("SAFS_SetVolumeStatus for volume %u\n", avolid));
6480 if ((errorCode = CallPreamble(acall, ACTIVECALL, &tcon)))
6481 goto Bad_SetVolumeStatus;
6484 AFSCallStats.SetVolumeStatus++, AFSCallStats.TotalCalls++;
6488 goto Bad_SetVolumeStatus;
6490 dummyFid.Volume = avolid, dummyFid.Vnode =
6491 (afs_int32) ROOTVNODE, dummyFid.Unique = 1;
6494 GetVolumePackage(tcon, &dummyFid, &volptr, &targetptr, MustBeDIR,
6495 &parentwhentargetnotdir, &client, READ_LOCK,
6496 &rights, &anyrights)))
6497 goto Bad_SetVolumeStatus;
6499 if (readonlyServer) {
6500 errorCode = VREADONLY;
6501 goto Bad_SetVolumeStatus;
6503 if (VanillaUser(client)) {
6505 goto Bad_SetVolumeStatus;
6509 RXUpdate_VolumeStatus(volptr, StoreVolStatus, Name, OfflineMsg, Motd);
6511 Bad_SetVolumeStatus:
6512 PutVolumePackage(parentwhentargetnotdir, targetptr, (Vnode *) 0, volptr);
6513 ViceLog(2, ("SAFS_SetVolumeStatus returns %d\n", errorCode));
6514 errorCode = CallPostamble(tcon, errorCode);
6516 t_client = (struct client *)rx_GetSpecific(tcon, rxcon_client_key);
6518 #if FS_STATS_DETAILED
6519 TM_GetTimeOfDay(&opStopTime, 0);
6520 if (errorCode == 0) {
6522 (opP->numSuccesses)++;
6523 fs_stats_GetDiff(elapsedTime, opStartTime, opStopTime);
6524 fs_stats_AddTo((opP->sumTime), elapsedTime);
6525 fs_stats_SquareAddTo((opP->sqrTime), elapsedTime);
6526 if (fs_stats_TimeLessThan(elapsedTime, (opP->minTime))) {
6527 fs_stats_TimeAssign((opP->minTime), elapsedTime);
6529 if (fs_stats_TimeGreaterThan(elapsedTime, (opP->maxTime))) {
6530 fs_stats_TimeAssign((opP->maxTime), elapsedTime);
6534 #endif /* FS_STATS_DETAILED */
6536 osi_auditU(acall, SetVolumeStatusEvent, errorCode,
6537 AUD_ID, t_client ? t_client->ViceId : 0,
6538 AUD_LONG, avolid, AUD_STR, Name, AUD_END);
6540 } /*SRXAFS_SetVolumeStatus */
6542 #define DEFAULTVOLUME "root.afs"
6545 SRXAFS_GetRootVolume(struct rx_call * acall, char **VolumeName)
6551 struct rx_connection *tcon;
6554 #if FS_STATS_DETAILED
6555 struct fs_stats_opTimingData *opP; /* Ptr to this op's timing struct */
6556 struct timeval opStartTime; /* Start time for RPC op */
6558 struct timeval opStopTime;
6559 struct timeval elapsedTime; /* Transfer time */
6563 * Set our stats pointer, remember when the RPC operation started, and
6564 * tally the operation.
6566 opP = &(afs_FullPerfStats.det.rpcOpTimes[FS_STATS_RPCIDX_GETROOTVOLUME]);
6570 TM_GetTimeOfDay(&opStartTime, 0);
6571 #endif /* FS_STATS_DETAILED */
6573 return FSERR_EOPNOTSUPP;
6576 if (errorCode = CallPreamble(acall, ACTIVECALL, &tcon))
6577 goto Bad_GetRootVolume;
6579 AFSCallStats.GetRootVolume++, AFSCallStats.TotalCalls++;
6582 fd = afs_open(AFSDIR_SERVER_ROOTVOL_FILEPATH, O_RDONLY, 0666);
6584 strcpy(temp, DEFAULTVOLUME);
6586 #if defined (AFS_AIX_ENV) || defined (AFS_HPUX_ENV)
6587 lockf(fd, F_LOCK, 0);
6591 len = read(fd, temp, 256);
6592 #if defined (AFS_AIX_ENV) || defined (AFS_HPUX_ENV)
6593 lockf(fd, F_ULOCK, 0);
6598 if (temp[len - 1] == '\n')
6602 *VolumeName = temp; /* freed by rx server-side stub */
6605 errorCode = CallPostamble(tcon, errorCode);
6607 #if FS_STATS_DETAILED
6608 TM_GetTimeOfDay(&opStopTime, 0);
6609 if (errorCode == 0) {
6611 (opP->numSuccesses)++;
6612 fs_stats_GetDiff(elapsedTime, opStartTime, opStopTime);
6613 fs_stats_AddTo((opP->sumTime), elapsedTime);
6614 fs_stats_SquareAddTo((opP->sqrTime), elapsedTime);
6615 if (fs_stats_TimeLessThan(elapsedTime, (opP->minTime))) {
6616 fs_stats_TimeAssign((opP->minTime), elapsedTime);
6618 if (fs_stats_TimeGreaterThan(elapsedTime, (opP->maxTime))) {
6619 fs_stats_TimeAssign((opP->maxTime), elapsedTime);
6623 #endif /* FS_STATS_DETAILED */
6628 } /*SRXAFS_GetRootVolume */
6631 /* still works because a struct CBS is the same as a struct AFSOpaque */
6633 SRXAFS_CheckToken(struct rx_call * acall, afs_int32 AfsId,
6634 struct AFSOpaque * Token)
6637 struct rx_connection *tcon;
6638 #if FS_STATS_DETAILED
6639 struct fs_stats_opTimingData *opP; /* Ptr to this op's timing struct */
6640 struct timeval opStartTime, opStopTime; /* Start/stop times for RPC op */
6641 struct timeval elapsedTime; /* Transfer time */
6644 * Set our stats pointer, remember when the RPC operation started, and
6645 * tally the operation.
6647 opP = &(afs_FullPerfStats.det.rpcOpTimes[FS_STATS_RPCIDX_CHECKTOKEN]);
6651 TM_GetTimeOfDay(&opStartTime, 0);
6652 #endif /* FS_STATS_DETAILED */
6654 if ((code = CallPreamble(acall, ACTIVECALL, &tcon)))
6655 goto Bad_CheckToken;
6657 code = FSERR_ECONNREFUSED;
6660 code = CallPostamble(tcon, code);
6662 #if FS_STATS_DETAILED
6663 TM_GetTimeOfDay(&opStopTime, 0);
6666 (opP->numSuccesses)++;
6667 fs_stats_GetDiff(elapsedTime, opStartTime, opStopTime);
6668 fs_stats_AddTo((opP->sumTime), elapsedTime);
6669 fs_stats_SquareAddTo((opP->sqrTime), elapsedTime);
6670 if (fs_stats_TimeLessThan(elapsedTime, (opP->minTime))) {
6671 fs_stats_TimeAssign((opP->minTime), elapsedTime);
6673 if (fs_stats_TimeGreaterThan(elapsedTime, (opP->maxTime))) {
6674 fs_stats_TimeAssign((opP->maxTime), elapsedTime);
6678 #endif /* FS_STATS_DETAILED */
6682 } /*SRXAFS_CheckToken */
6685 SRXAFS_GetTime(struct rx_call * acall, afs_uint32 * Seconds,
6686 afs_uint32 * USeconds)
6689 struct rx_connection *tcon;
6691 #if FS_STATS_DETAILED
6692 struct fs_stats_opTimingData *opP; /* Ptr to this op's timing struct */
6693 struct timeval opStartTime, opStopTime; /* Start/stop times for RPC op */
6694 struct timeval elapsedTime; /* Transfer time */
6697 * Set our stats pointer, remember when the RPC operation started, and
6698 * tally the operation.
6700 opP = &(afs_FullPerfStats.det.rpcOpTimes[FS_STATS_RPCIDX_GETTIME]);
6704 TM_GetTimeOfDay(&opStartTime, 0);
6705 #endif /* FS_STATS_DETAILED */
6707 if ((code = CallPreamble(acall, NOTACTIVECALL, &tcon)))
6711 AFSCallStats.GetTime++, AFSCallStats.TotalCalls++;
6713 TM_GetTimeOfDay(&tpl, 0);
6714 *Seconds = tpl.tv_sec;
6715 *USeconds = tpl.tv_usec;
6717 ViceLog(2, ("SAFS_GetTime returns %u, %u\n", *Seconds, *USeconds));
6720 code = CallPostamble(tcon, code);
6722 #if FS_STATS_DETAILED
6723 TM_GetTimeOfDay(&opStopTime, 0);
6724 fs_stats_GetDiff(elapsedTime, opStartTime, opStopTime);
6727 (opP->numSuccesses)++;
6728 fs_stats_AddTo((opP->sumTime), elapsedTime);
6729 fs_stats_SquareAddTo((opP->sqrTime), elapsedTime);
6730 if (fs_stats_TimeLessThan(elapsedTime, (opP->minTime))) {
6731 fs_stats_TimeAssign((opP->minTime), elapsedTime);
6733 if (fs_stats_TimeGreaterThan(elapsedTime, (opP->maxTime))) {
6734 fs_stats_TimeAssign((opP->maxTime), elapsedTime);
6738 #endif /* FS_STATS_DETAILED */
6742 } /*SRXAFS_GetTime */
6749 * Implement a client's data fetch using Rx.
6752 * volptr : Ptr to the given volume's info.
6753 * targetptr : Pointer to the vnode involved.
6754 * Call : Ptr to the Rx call involved.
6755 * Pos : Offset within the file.
6756 * Len : Length in bytes to read; this value is bogus!
6757 * if FS_STATS_DETAILED
6758 * a_bytesToFetchP : Set to the number of bytes to be fetched from
6760 * a_bytesFetchedP : Set to the actual number of bytes fetched from
6766 FetchData_RXStyle(Volume * volptr, Vnode * targetptr,
6767 register struct rx_call * Call, afs_sfsize_t Pos,
6768 afs_sfsize_t Len, afs_int32 Int64Mode,
6769 #if FS_STATS_DETAILED
6770 afs_sfsize_t * a_bytesToFetchP,
6771 afs_sfsize_t * a_bytesFetchedP
6772 #endif /* FS_STATS_DETAILED */
6775 struct timeval StartTime, StopTime; /* used to calculate file transfer rates */
6776 int errorCode = 0; /* Returned error code to caller */
6780 register char *tbuffer;
6781 #else /* AFS_NT40_ENV */
6782 struct iovec tiov[RX_MAXIOVECS];
6784 #endif /* AFS_NT40_ENV */
6788 #if FS_STATS_DETAILED
6790 * Initialize the byte count arguments.
6792 (*a_bytesToFetchP) = 0;
6793 (*a_bytesFetchedP) = 0;
6794 #endif /* FS_STATS_DETAILED */
6798 ("FetchData_RXStyle: Pos %llu, Len %llu\n", (afs_uintmax_t) Pos,
6799 (afs_uintmax_t) Len));
6801 if (!VN_GET_INO(targetptr)) {
6802 afs_int32 zero = htonl(0);
6804 * This is used for newly created files; we simply send 0 bytes
6805 * back to make the cache manager happy...
6808 rx_Write(Call, (char *)&zero, sizeof(afs_int32)); /* send 0-length */
6809 rx_Write(Call, (char *)&zero, sizeof(afs_int32)); /* send 0-length */
6812 TM_GetTimeOfDay(&StartTime, 0);
6813 ihP = targetptr->handle;
6816 VTakeOffline(volptr);
6819 optSize = sendBufSize;
6820 tlen = FDH_SIZE(fdP);
6822 ("FetchData_RXStyle: file size %llu\n", (afs_uintmax_t) tlen));
6825 VTakeOffline(volptr);
6832 if (Pos + Len > tlen)
6833 Len = tlen - Pos; /* get length we should send */
6834 (void)FDH_SEEK(fdP, Pos, 0);
6836 afs_int32 high, low;
6837 SplitOffsetOrSize(Len, high, low);
6838 assert(Int64Mode || (Len >= 0 && high == 0) || Len < 0);
6841 rx_Write(Call, (char *)&high, sizeof(afs_int32)); /* High order bits */
6844 rx_Write(Call, (char *)&low, sizeof(afs_int32)); /* send length on fetch */
6846 #if FS_STATS_DETAILED
6847 (*a_bytesToFetchP) = Len;
6848 #endif /* FS_STATS_DETAILED */
6850 tbuffer = AllocSendBuffer();
6851 #endif /* AFS_NT40_ENV */
6859 errorCode = FDH_READ(fdP, tbuffer, wlen);
6860 if (errorCode != wlen) {
6862 FreeSendBuffer((struct afs_buffer *)tbuffer);
6863 VTakeOffline(volptr);
6866 errorCode = rx_Write(Call, tbuffer, wlen);
6867 #else /* AFS_NT40_ENV */
6868 errorCode = rx_WritevAlloc(Call, tiov, &tnio, RX_MAXIOVECS, wlen);
6869 if (errorCode <= 0) {
6871 VTakeOffline(volptr);
6875 errorCode = FDH_READV(fdP, tiov, tnio);
6876 if (errorCode != wlen) {
6878 VTakeOffline(volptr);
6881 errorCode = rx_Writev(Call, tiov, tnio, wlen);
6882 #endif /* AFS_NT40_ENV */
6883 #if FS_STATS_DETAILED
6885 * Bump the number of bytes actually sent by the number from this
6888 (*a_bytesFetchedP) += errorCode;
6889 #endif /* FS_STATS_DETAILED */
6890 if (errorCode != wlen) {
6893 FreeSendBuffer((struct afs_buffer *)tbuffer);
6894 #endif /* AFS_NT40_ENV */
6900 FreeSendBuffer((struct afs_buffer *)tbuffer);
6901 #endif /* AFS_NT40_ENV */
6903 TM_GetTimeOfDay(&StopTime, 0);
6905 /* Adjust all Fetch Data related stats */
6907 if (AFSCallStats.TotalFetchedBytes > 2000000000) /* Reset if over 2 billion */
6908 AFSCallStats.TotalFetchedBytes = AFSCallStats.AccumFetchTime = 0;
6909 AFSCallStats.AccumFetchTime +=
6910 ((StopTime.tv_sec - StartTime.tv_sec) * 1000) +
6911 ((StopTime.tv_usec - StartTime.tv_usec) / 1000);
6913 afs_fsize_t targLen;
6914 VN_GET_LEN(targLen, targetptr);
6915 AFSCallStats.TotalFetchedBytes += targLen;
6916 AFSCallStats.FetchSize1++;
6917 if (targLen < SIZE2)
6918 AFSCallStats.FetchSize2++;
6919 else if (targLen < SIZE3)
6920 AFSCallStats.FetchSize3++;
6921 else if (targLen < SIZE4)
6922 AFSCallStats.FetchSize4++;
6924 AFSCallStats.FetchSize5++;
6929 } /*FetchData_RXStyle */
6932 GetLinkCountAndSize(Volume * vp, FdHandle_t * fdP, int *lc,
6933 afs_sfsize_t * size)
6935 #ifdef AFS_NAMEI_ENV
6937 lhp = IH_OPEN(V_linkHandle(vp));
6941 *lc = nt_GetLinkCount(lhp, fdP->fd_ih->ih_ino, 0);
6943 *lc = namei_GetLinkCount(lhp, fdP->fd_ih->ih_ino, 0);
6948 *size = OS_SIZE(fdP->fd_fd);
6949 return (*size == -1) ? -1 : 0;
6951 struct afs_stat status;
6953 if (afs_fstat(fdP->fd_fd, &status) < 0) {
6957 *lc = GetLinkCount(vp, &status);
6958 *size = status.st_size;
6967 * Implement a client's data store using Rx.
6970 * volptr : Ptr to the given volume's info.
6971 * targetptr : Pointer to the vnode involved.
6972 * Call : Ptr to the Rx call involved.
6973 * Pos : Offset within the file.
6974 * Len : Length in bytes to store; this value is bogus!
6975 * if FS_STATS_DETAILED
6976 * a_bytesToStoreP : Set to the number of bytes to be stored to
6978 * a_bytesStoredP : Set to the actual number of bytes stored to
6983 StoreData_RXStyle(Volume * volptr, Vnode * targetptr, struct AFSFid * Fid,
6984 struct client * client, register struct rx_call * Call,
6985 afs_fsize_t Pos, afs_fsize_t Length, afs_fsize_t FileLength,
6987 #if FS_STATS_DETAILED
6988 afs_sfsize_t * a_bytesToStoreP,
6989 afs_sfsize_t * a_bytesStoredP
6990 #endif /* FS_STATS_DETAILED */
6993 afs_sfsize_t bytesTransfered; /* number of bytes actually transfered */
6994 struct timeval StartTime, StopTime; /* Used to measure how long the store takes */
6995 int errorCode = 0; /* Returned error code to caller */
6997 register char *tbuffer; /* data copying buffer */
6998 #else /* AFS_NT40_ENV */
6999 struct iovec tiov[RX_MAXIOVECS]; /* no data copying with iovec */
7000 int tnio; /* temp for iovec size */
7001 #endif /* AFS_NT40_ENV */
7002 afs_sfsize_t tlen; /* temp for xfr length */
7003 Inode tinode; /* inode for I/O */
7004 afs_int32 optSize; /* optimal transfer size */
7005 afs_sfsize_t DataLength; /* size of inode */
7006 afs_sfsize_t TruncatedLength; /* size after ftruncate */
7007 afs_fsize_t NewLength; /* size after this store completes */
7008 afs_sfsize_t adjustSize; /* bytes to call VAdjust... with */
7009 int linkCount; /* link count on inode */
7011 struct in_addr logHostAddr; /* host ip holder for inet_ntoa */
7013 #if FS_STATS_DETAILED
7015 * Initialize the byte count arguments.
7017 (*a_bytesToStoreP) = 0;
7018 (*a_bytesStoredP) = 0;
7019 #endif /* FS_STATS_DETAILED */
7022 * We break the callbacks here so that the following signal will not
7025 BreakCallBack(client->host, Fid, 0);
7027 if (Pos == -1 || VN_GET_INO(targetptr) == 0) {
7028 /* the inode should have been created in Alloc_NewVnode */
7029 logHostAddr.s_addr = rxr_HostOf(rx_ConnectionOf(Call));
7031 ("StoreData_RXStyle : Inode non-existent Fid = %u.%u.%u, inode = %llu, Pos %llu Host %s:%d\n",
7032 Fid->Volume, Fid->Vnode, Fid->Unique,
7033 (afs_uintmax_t) VN_GET_INO(targetptr), (afs_uintmax_t) Pos,
7034 inet_ntoa(logHostAddr), rxr_PortOf(rx_ConnectionOf(Call))));
7035 return ENOENT; /* is this proper error code? */
7038 * See if the file has several links (from other volumes). If it
7039 * does, then we have to make a copy before changing it to avoid
7040 *changing read-only clones of this dude
7043 ("StoreData_RXStyle : Opening inode %s\n",
7044 PrintInode(NULL, VN_GET_INO(targetptr))));
7045 fdP = IH_OPEN(targetptr->handle);
7048 if (GetLinkCountAndSize(volptr, fdP, &linkCount, &DataLength) < 0) {
7050 VTakeOffline(volptr);
7054 if (linkCount != 1) {
7057 ("StoreData_RXStyle : inode %s has more than onelink\n",
7058 PrintInode(NULL, VN_GET_INO(targetptr))));
7059 /* other volumes share this data, better copy it first */
7061 /* Adjust the disk block count by the creation of the new inode.
7062 * We call the special VDiskUsage so we don't adjust the volume's
7063 * quota since we don't want to penalyze the user for afs's internal
7064 * mechanisms (i.e. copy on write overhead.) Also the right size
7065 * of the disk will be recorded...
7068 VN_GET_LEN(size, targetptr);
7069 volptr->partition->flags &= ~PART_DONTUPDATE;
7070 VSetPartitionDiskUsage(volptr->partition);
7071 volptr->partition->flags |= PART_DONTUPDATE;
7072 if ((errorCode = VDiskUsage(volptr, nBlocks(size)))) {
7073 volptr->partition->flags &= ~PART_DONTUPDATE;
7077 ViceLog(25, ("StoreData : calling CopyOnWrite on target dir\n"));
7078 if ((errorCode = CopyOnWrite(targetptr, volptr))) {
7079 ViceLog(25, ("StoreData : CopyOnWrite failed\n"));
7080 volptr->partition->flags &= ~PART_DONTUPDATE;
7083 volptr->partition->flags &= ~PART_DONTUPDATE;
7084 VSetPartitionDiskUsage(volptr->partition);
7085 fdP = IH_OPEN(targetptr->handle);
7088 ("StoreData : Reopen after CopyOnWrite failed\n"));
7092 tinode = VN_GET_INO(targetptr);
7094 assert(VALID_INO(tinode));
7096 /* compute new file length */
7097 NewLength = DataLength;
7098 if (FileLength < NewLength)
7099 /* simulate truncate */
7100 NewLength = FileLength;
7101 TruncatedLength = NewLength; /* remember length after possible ftruncate */
7102 if (Pos + Length > NewLength)
7103 NewLength = Pos + Length; /* and write */
7105 /* adjust the disk block count by the difference in the files */
7107 afs_fsize_t targSize;
7108 VN_GET_LEN(targSize, targetptr);
7109 adjustSize = nBlocks(NewLength) - nBlocks(targSize);
7112 AdjustDiskUsage(volptr, adjustSize,
7113 adjustSize - SpareComp(volptr)))) {
7118 /* can signal cache manager to proceed from close now */
7119 /* this bit means that the locks are set and protections are OK */
7120 rx_SetLocalStatus(Call, 1);
7122 TM_GetTimeOfDay(&StartTime, 0);
7124 optSize = sendBufSize;
7126 ("StoreData_RXStyle: Pos %llu, DataLength %llu, FileLength %llu, Length %llu\n",
7127 (afs_uintmax_t) Pos, (afs_uintmax_t) DataLength,
7128 (afs_uintmax_t) FileLength, (afs_uintmax_t) Length));
7130 /* truncate the file iff it needs it (ftruncate is slow even when its a noop) */
7131 if (FileLength < DataLength)
7132 FDH_TRUNC(fdP, FileLength);
7134 FDH_SEEK(fdP, Pos, 0);
7135 bytesTransfered = 0;
7137 tbuffer = AllocSendBuffer();
7138 #endif /* AFS_NT40_ENV */
7139 /* if length == 0, the loop below isn't going to do anything, including
7140 * extend the length of the inode, which it must do, since the file system
7141 * assumes that the inode length == vnode's file length. So, we extend
7142 * the file length manually if need be. Note that if file is bigger than
7143 * Pos+(Length==0), we dont' have to do anything, and certainly shouldn't
7144 * do what we're going to do below.
7146 if (Length == 0 && Pos > TruncatedLength) {
7147 /* Set the file's length; we've already done an lseek to the right
7150 errorCode = FDH_WRITE(fdP, &tlen, 1);
7153 errorCode = FDH_TRUNC(fdP, Pos);
7155 /* have some data to copy */
7156 #if FS_STATS_DETAILED
7157 (*a_bytesToStoreP) = Length;
7158 #endif /* FS_STATS_DETAILED */
7161 if (bytesTransfered >= Length) {
7165 tlen = Length - bytesTransfered; /* how much more to do */
7167 rlen = optSize; /* bound by buffer size */
7171 errorCode = rx_Read(Call, tbuffer, rlen);
7172 #else /* AFS_NT40_ENV */
7173 errorCode = rx_Readv(Call, tiov, &tnio, RX_MAXIOVECS, rlen);
7174 #endif /* AFS_NT40_ENV */
7175 #if FS_STATS_DETAILED
7176 (*a_bytesStoredP) += errorCode;
7177 #endif /* FS_STATS_DETAILED */
7178 if (errorCode <= 0) {
7184 errorCode = FDH_WRITE(fdP, tbuffer, rlen);
7185 #else /* AFS_NT40_ENV */
7186 errorCode = FDH_WRITEV(fdP, tiov, tnio);
7187 #endif /* AFS_NT40_ENV */
7188 if (errorCode != rlen) {
7189 errorCode = VDISKFULL;
7192 bytesTransfered += rlen;
7197 FreeSendBuffer((struct afs_buffer *)tbuffer);
7198 #endif /* AFS_NT40_ENV */
7203 afs_fsize_t nfSize = (afs_fsize_t) FDH_SIZE(fdP);
7204 /* something went wrong: adjust size and return */
7205 VN_SET_LEN(targetptr, nfSize); /* set new file size. */
7206 /* changed_newTime is tested in StoreData to detemine if we
7207 * need to update the target vnode.
7209 targetptr->changed_newTime = 1;
7211 /* set disk usage to be correct */
7212 VAdjustDiskUsage(&errorCode, volptr,
7213 (afs_sfsize_t) (nBlocks(nfSize) -
7214 nBlocks(NewLength)), 0);
7219 TM_GetTimeOfDay(&StopTime, 0);
7221 VN_SET_LEN(targetptr, NewLength);
7223 /* Update all StoreData related stats */
7225 if (AFSCallStats.TotalStoredBytes > 2000000000) /* reset if over 2 billion */
7226 AFSCallStats.TotalStoredBytes = AFSCallStats.AccumStoreTime = 0;
7227 AFSCallStats.StoreSize1++; /* Piggybacked data */
7229 afs_fsize_t targLen;
7230 VN_GET_LEN(targLen, targetptr);
7231 if (targLen < SIZE2)
7232 AFSCallStats.StoreSize2++;
7233 else if (targLen < SIZE3)
7234 AFSCallStats.StoreSize3++;
7235 else if (targLen < SIZE4)
7236 AFSCallStats.StoreSize4++;
7238 AFSCallStats.StoreSize5++;
7243 } /*StoreData_RXStyle */
7245 static int sys2et[512];
7248 init_sys_error_to_et(void)
7250 memset(&sys2et, 0, sizeof(sys2et));
7251 sys2et[EPERM] = UAEPERM;
7252 sys2et[ENOENT] = UAENOENT;
7253 sys2et[ESRCH] = UAESRCH;
7254 sys2et[EINTR] = UAEINTR;
7255 sys2et[EIO] = UAEIO;
7256 sys2et[ENXIO] = UAENXIO;
7257 sys2et[E2BIG] = UAE2BIG;
7258 sys2et[ENOEXEC] = UAENOEXEC;
7259 sys2et[EBADF] = UAEBADF;
7260 sys2et[ECHILD] = UAECHILD;
7261 sys2et[EAGAIN] = UAEAGAIN;
7262 sys2et[ENOMEM] = UAENOMEM;
7263 sys2et[EACCES] = UAEACCES;
7264 sys2et[EFAULT] = UAEFAULT;
7265 sys2et[ENOTBLK] = UAENOTBLK;
7266 sys2et[EBUSY] = UAEBUSY;
7267 sys2et[EEXIST] = UAEEXIST;
7268 sys2et[EXDEV] = UAEXDEV;
7269 sys2et[ENODEV] = UAENODEV;
7270 sys2et[ENOTDIR] = UAENOTDIR;
7271 sys2et[EISDIR] = UAEISDIR;
7272 sys2et[EINVAL] = UAEINVAL;
7273 sys2et[ENFILE] = UAENFILE;
7274 sys2et[EMFILE] = UAEMFILE;
7275 sys2et[ENOTTY] = UAENOTTY;
7276 sys2et[ETXTBSY] = UAETXTBSY;
7277 sys2et[EFBIG] = UAEFBIG;
7278 sys2et[ENOSPC] = UAENOSPC;
7279 sys2et[ESPIPE] = UAESPIPE;
7280 sys2et[EROFS] = UAEROFS;
7281 sys2et[EMLINK] = UAEMLINK;
7282 sys2et[EPIPE] = UAEPIPE;
7283 sys2et[EDOM] = UAEDOM;
7284 sys2et[ERANGE] = UAERANGE;
7285 sys2et[EDEADLK] = UAEDEADLK;
7286 sys2et[ENAMETOOLONG] = UAENAMETOOLONG;
7287 sys2et[ENOLCK] = UAENOLCK;
7288 sys2et[ENOSYS] = UAENOSYS;
7289 sys2et[ENOTEMPTY] = UAENOTEMPTY;
7290 sys2et[ELOOP] = UAELOOP;
7291 sys2et[EWOULDBLOCK] = UAEWOULDBLOCK;
7292 sys2et[ENOMSG] = UAENOMSG;
7293 sys2et[EIDRM] = UAEIDRM;
7294 sys2et[ECHRNG] = UAECHRNG;
7295 sys2et[EL2NSYNC] = UAEL2NSYNC;
7296 sys2et[EL3HLT] = UAEL3HLT;
7297 sys2et[EL3RST] = UAEL3RST;
7298 sys2et[ELNRNG] = UAELNRNG;
7299 sys2et[EUNATCH] = UAEUNATCH;
7300 sys2et[ENOCSI] = UAENOCSI;
7301 sys2et[EL2HLT] = UAEL2HLT;
7302 sys2et[EBADE] = UAEBADE;
7303 sys2et[EBADR] = UAEBADR;
7304 sys2et[EXFULL] = UAEXFULL;
7305 sys2et[ENOANO] = UAENOANO;
7306 sys2et[EBADRQC] = UAEBADRQC;
7307 sys2et[EBADSLT] = UAEBADSLT;
7308 sys2et[EDEADLK] = UAEDEADLK;
7309 sys2et[EBFONT] = UAEBFONT;
7310 sys2et[ENOSTR] = UAENOSTR;
7311 sys2et[ENODATA] = UAENODATA;
7312 sys2et[ETIME] = UAETIME;
7313 sys2et[ENOSR] = UAENOSR;
7314 sys2et[ENONET] = UAENONET;
7315 sys2et[ENOPKG] = UAENOPKG;
7316 sys2et[EREMOTE] = UAEREMOTE;
7317 sys2et[ENOLINK] = UAENOLINK;
7318 sys2et[EADV] = UAEADV;
7319 sys2et[ESRMNT] = UAESRMNT;
7320 sys2et[ECOMM] = UAECOMM;
7321 sys2et[EPROTO] = UAEPROTO;
7322 sys2et[EMULTIHOP] = UAEMULTIHOP;
7323 sys2et[EDOTDOT] = UAEDOTDOT;
7324 sys2et[EBADMSG] = UAEBADMSG;
7325 sys2et[EOVERFLOW] = UAEOVERFLOW;
7326 sys2et[ENOTUNIQ] = UAENOTUNIQ;
7327 sys2et[EBADFD] = UAEBADFD;
7328 sys2et[EREMCHG] = UAEREMCHG;
7329 sys2et[ELIBACC] = UAELIBACC;
7330 sys2et[ELIBBAD] = UAELIBBAD;
7331 sys2et[ELIBSCN] = UAELIBSCN;
7332 sys2et[ELIBMAX] = UAELIBMAX;
7333 sys2et[ELIBEXEC] = UAELIBEXEC;
7334 sys2et[EILSEQ] = UAEILSEQ;
7335 sys2et[ERESTART] = UAERESTART;
7336 sys2et[ESTRPIPE] = UAESTRPIPE;
7337 sys2et[EUSERS] = UAEUSERS;
7338 sys2et[ENOTSOCK] = UAENOTSOCK;
7339 sys2et[EDESTADDRREQ] = UAEDESTADDRREQ;
7340 sys2et[EMSGSIZE] = UAEMSGSIZE;
7341 sys2et[EPROTOTYPE] = UAEPROTOTYPE;
7342 sys2et[ENOPROTOOPT] = UAENOPROTOOPT;
7343 sys2et[EPROTONOSUPPORT] = UAEPROTONOSUPPORT;
7344 sys2et[ESOCKTNOSUPPORT] = UAESOCKTNOSUPPORT;
7345 sys2et[EOPNOTSUPP] = UAEOPNOTSUPP;
7346 sys2et[EPFNOSUPPORT] = UAEPFNOSUPPORT;
7347 sys2et[EAFNOSUPPORT] = UAEAFNOSUPPORT;
7348 sys2et[EADDRINUSE] = UAEADDRINUSE;
7349 sys2et[EADDRNOTAVAIL] = UAEADDRNOTAVAIL;
7350 sys2et[ENETDOWN] = UAENETDOWN;
7351 sys2et[ENETUNREACH] = UAENETUNREACH;
7352 sys2et[ENETRESET] = UAENETRESET;
7353 sys2et[ECONNABORTED] = UAECONNABORTED;
7354 sys2et[ECONNRESET] = UAECONNRESET;
7355 sys2et[ENOBUFS] = UAENOBUFS;
7356 sys2et[EISCONN] = UAEISCONN;
7357 sys2et[ENOTCONN] = UAENOTCONN;
7358 sys2et[ESHUTDOWN] = UAESHUTDOWN;
7359 sys2et[ETOOMANYREFS] = UAETOOMANYREFS;
7360 sys2et[ETIMEDOUT] = UAETIMEDOUT;
7361 sys2et[ECONNREFUSED] = UAECONNREFUSED;
7362 sys2et[EHOSTDOWN] = UAEHOSTDOWN;
7363 sys2et[EHOSTUNREACH] = UAEHOSTUNREACH;
7364 sys2et[EALREADY] = UAEALREADY;
7365 sys2et[EINPROGRESS] = UAEINPROGRESS;
7366 sys2et[ESTALE] = UAESTALE;
7367 sys2et[EUCLEAN] = UAEUCLEAN;
7368 sys2et[ENOTNAM] = UAENOTNAM;
7369 sys2et[ENAVAIL] = UAENAVAIL;
7370 sys2et[EISNAM] = UAEISNAM;
7371 sys2et[EREMOTEIO] = UAEREMOTEIO;
7372 sys2et[EDQUOT] = UAEDQUOT;
7373 sys2et[ENOMEDIUM] = UAENOMEDIUM;
7374 sys2et[EMEDIUMTYPE] = UAEMEDIUMTYPE;
7378 SRXAFS_CallBackRxConnAddr (struct rx_call * acall, afs_int32 *addr)
7380 Error errorCode = 0;
7382 struct client *tclient;
7383 static struct rx_securityClass *sc = 0;
7385 struct rx_connection *tcon;
7386 struct rx_connection *conn;
7388 if (errorCode = CallPreamble(acall, ACTIVECALL, &tcon))
7389 goto Bad_CallBackRxConnAddr1;
7391 #ifndef __EXPERIMENTAL_CALLBACK_CONN_MOVING
7395 tclient = h_FindClient_r(tcon);
7396 thost = tclient->host;
7398 /* nothing more can be done */
7399 if ( !thost->interface )
7400 goto Bad_CallBackRxConnAddr;
7402 assert(thost->interface->numberOfInterfaces > 0 );
7404 /* the only address is the primary interface */
7405 /* can't change when there's only 1 address, anyway */
7406 if ( thost->interface->numberOfInterfaces == 1 )
7407 goto Bad_CallBackRxConnAddr;
7409 /* initialise a security object only once */
7411 sc = (struct rx_securityClass *) rxnull_NewClientSecurityObject();
7413 for ( i=0; i < thost->interface->numberOfInterfaces; i++)
7415 if ( *addr == thost->interface->addr[i] ) {
7420 if ( *addr != thost->interface->addr[i] )
7421 goto Bad_CallBackRxConnAddr;
7423 conn = rx_NewConnection (thost->interface->addr[i],
7424 thost->port, 1, sc, 0);
7425 rx_SetConnDeadTime(conn, 2);
7426 rx_SetConnHardDeadTime(conn, AFS_HARDDEADTIME);
7428 errorCode = RXAFSCB_Probe(conn);
7431 if ( thost->callback_rxcon )
7432 rx_DestroyConnection(thost->callback_rxcon);
7433 thost->callback_rxcon = conn;
7435 rx_SetConnDeadTime(thost->callback_rxcon, 50);
7436 rx_SetConnHardDeadTime(thost->callback_rxcon, AFS_HARDDEADTIME);
7438 errorCode = CallPostamble(tcon, errorCode);
7441 rx_DestroyConnection(conn);
7443 Bad_CallBackRxConnAddr:
7447 errorCode = CallPostamble(tcon, errorCode);
7448 Bad_CallBackRxConnAddr1:
7449 return errorCode; /* failure */
7453 sys_error_to_et(afs_int32 in)
7457 if (in < 0 || in > 511)
7459 if (sys2et[in] != 0)