make-storedata-use-unsigned-values-so-quota-cant-get-corrupted-20011203
[openafs.git] / src / viced / afsfileprocs.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
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
8  */
9
10 /*  afs_fileprocs.c - Complete File Server request routines              */
11 /*                                                                       */
12 /*  Information Technology Center                                        */
13 /*  Carnegie Mellon University                                           */
14 /*                                                                       */
15 /*  Date: 8/10/88                                                        */
16 /*                                                                       */
17 /*  Function    - A set of routines to handle the various file Server    */
18 /*                  requests; these routines are invoked by rxgen.       */
19 /*                                                                       */
20 /* ********************************************************************** */
21
22 /* 
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 
25  * privilege"? 
26  */
27
28 #include <afsconfig.h>
29 #include <afs/param.h>
30
31 RCSID("$Header$");
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <errno.h>
36 #ifdef  AFS_SGI_ENV
37 #undef SHARED           /* XXX */
38 #endif
39 #ifdef AFS_NT40_ENV
40 #include <fcntl.h>
41 #else
42 #include <sys/param.h>
43 #include <sys/file.h>
44 #include <netinet/in.h>
45 #include <netdb.h>
46 #include <sys/ioctl.h>
47 #include <sys/socket.h>
48 #ifndef AFS_LINUX20_ENV
49 #include <net/if.h>
50 #include <netinet/if_ether.h>
51 #endif
52 #ifdef notdef
53 #include <nlist.h>
54 #endif
55 #endif
56 #ifdef AFS_HPUX_ENV
57 /* included early because of name conflict on IOPEN */
58 #include <sys/inode.h>
59 #ifdef IOPEN
60 #undef IOPEN
61 #endif
62 #endif /* AFS_HPUX_ENV */
63 #include <afs/stds.h>
64 #include <rx/xdr.h>
65 #include <afs/nfs.h>
66 #include <afs/assert.h>
67 #include <lwp.h>
68 #include <lock.h>
69 #include <afs/afsint.h>
70 #include <afs/vldbint.h>
71 #include <afs/errors.h>
72 #include <afs/ihandle.h>
73 #include <afs/vnode.h>
74 #include <afs/volume.h>
75 #include <afs/acl.h>
76 #include <afs/ptclient.h>
77 #include <afs/prs_fs.h>
78 #include <rx/rx.h>
79 #include <rx/rx_globals.h>
80 #include <sys/stat.h>
81 #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)
82 #include <sys/map.h>
83 #endif
84 #if !defined(AFS_NT40_ENV)
85 #include <unistd.h>
86 #endif
87 #if !defined(AFS_SGI_ENV) && !defined(AFS_NT40_ENV)
88 #ifdef  AFS_AIX_ENV
89 #include <sys/statfs.h>
90 #include <sys/lockf.h>
91 #else
92 #if !defined(AFS_SUN5_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_XBSD_ENV)
93 #include <sys/dk.h>
94 #endif
95 #endif
96 #endif
97 #include <afs/cellconfig.h>
98 #include <afs/keys.h>
99
100 #include <afs/auth.h>
101 #include <signal.h>
102 #include <afs/partition.h>
103 #include "viced.h"
104 #include "host.h"
105 #include <afs/audit.h>
106 #include <afs/afsutil.h>
107
108 #ifdef AFS_PTHREAD_ENV
109 pthread_mutex_t fileproc_glock_mutex;
110 #endif /* AFS_PTHREAD_ENV */
111
112
113 /* Useful local defines used by this module */
114
115 #define DONTCHECK       0
116 #define MustNOTBeDIR    1
117 #define MustBeDIR       2
118
119 #define TVS_SDATA       1
120 #define TVS_SSTATUS     2
121 #define TVS_CFILE       4
122 #define TVS_SLINK       8
123 #define TVS_MKDIR       0x10
124
125 #define CHK_FETCH       0x10
126 #define CHK_FETCHDATA   0x10
127 #define CHK_FETCHACL    0x11
128 #define CHK_FETCHSTATUS 0x12
129 #define CHK_STOREDATA   0x00
130 #define CHK_STOREACL    0x01
131 #define CHK_STORESTATUS 0x02
132
133 #define OWNERREAD       0400
134 #define OWNERWRITE      0200
135 #define OWNEREXEC       0100
136 #ifdef USE_GROUP_PERMS
137 #define GROUPREAD       0040
138 #define GROUPWRITE      0020
139 #define GROUPREXEC      0010
140 #endif
141
142 /* The following errors were not defined in NT. They are given unique
143  * names here to avoid any potential collision.
144  */
145 #define FSERR_ELOOP              90
146 #define FSERR_EOPNOTSUPP        122
147 #define FSERR_ECONNREFUSED      130
148
149 #define NOTACTIVECALL   0
150 #define ACTIVECALL      1
151
152 extern struct afsconf_dir *confDir;
153 extern afs_int32 dataVersionHigh;
154
155 extern  int         SystemId;
156 extern  struct AFSCallStatistics AFSCallStats;
157 struct AFSCallStatistics AFSCallStats;
158 #if FS_STATS_DETAILED
159 struct fs_stats_FullPerfStats afs_FullPerfStats;
160 extern int AnonymousID;
161 #endif /* FS_STATS_DETAILED */
162 #if TRANSARC_VOL_STATS
163 static const char nullString[] = "";
164 #endif /* TRANSARC_VOL_STATS */
165
166 struct afs_FSStats {
167     afs_int32 NothingYet;
168 };
169
170 struct afs_FSStats afs_fsstats;
171
172 void    ResetDebug(), SetDebug(), GetStatus(), Terminate();
173 int     CopyOnWrite();          /* returns 0 on success */
174
175
176 void SetSystemStats(), SetAFSStats(), SetVolumeStats();
177 int     LogLevel = 0;
178 int     supported = 1;
179 int     Console = 0;
180 afs_int32 BlocksSpare = 1024;   /* allow 1 MB overruns */
181 afs_int32 PctSpare;
182 extern afs_int32 implicitAdminRights;
183
184 static TryLocalVLServer();
185
186 /*
187  * Externals used by the xstat code.
188  */
189 extern int VolumeCacheSize, VolumeGets, VolumeReplacements;
190 extern int CEs, CEBlocks;
191
192 extern int HTs, HTBlocks;
193
194 #ifdef AFS_SGI_XFS_IOPS_ENV
195 #include <afs/xfsattrs.h>
196 static int GetLinkCount(avp, astat)
197      Volume *avp;
198      struct stat *astat;
199 {
200     if (!strcmp("xfs", astat->st_fstype)) {
201         return (astat->st_mode & AFS_XFS_MODE_LINK_MASK);
202     }
203     else
204         return astat->st_nlink;
205 }
206 #else
207 #define GetLinkCount(V, S) (S)->st_nlink
208 #endif
209
210 afs_int32 SpareComp(avolp)
211     Volume *avolp;
212
213 {
214     register afs_int32 temp;
215
216     FS_LOCK
217     if (PctSpare) {
218         temp = V_maxquota(avolp);
219         if (temp == 0) {
220             /* no matter; doesn't check in this case */
221             FS_UNLOCK
222             return 0;
223         }
224         temp = (temp * PctSpare) / 100;
225         FS_UNLOCK
226         return temp;
227     }
228     else {
229         FS_UNLOCK
230         return BlocksSpare;
231     }
232
233 } /*SpareComp*/
234
235
236 /*
237  * Set the volume synchronization parameter for this volume.  If it changes,
238  * the Cache Manager knows that the volume must be purged from the stat cache.
239  */
240 static SetVolumeSync(async, avol)
241     register struct AFSVolSync *async;
242     register Volume *avol;
243
244 {
245     FS_LOCK
246     /* date volume instance was created */
247     if (async) {
248         if (avol)
249             async->spare1 = avol->header->diskstuff.creationDate;
250         else
251             async->spare1 = 0;
252         async->spare2 = 0;
253         async->spare3 = 0;
254         async->spare4 = 0;
255         async->spare5 = 0;
256         async->spare6 = 0;
257     }
258     FS_UNLOCK
259 } /*SetVolumeSync*/
260
261 /*
262  * This call overwrites the pointed-to rx_call with an rx_connection.  This
263  * is really bogus.  Note that this function always returns a held host, so
264  * that CallPostamble can block without the host's disappearing.
265  */
266 static CallPreamble(acall, activecall)
267     register struct rx_call **acall;
268     int activecall;
269
270 {
271     struct host *thost;
272     struct rx_connection *tconn;
273     struct client *tclient;
274     int retry_flag=1;
275     int code = 0;
276     char hoststr[16];
277     tconn = rx_ConnectionOf(*acall);
278     *acall = (struct rx_call *)tconn;       /* change it! */
279
280     H_LOCK
281 retry:
282     tclient = h_FindClient_r(tconn);
283     if (tclient->prfail == 1) { /* couldn't get the CPS */
284        if (!retry_flag) {
285           h_ReleaseClient_r(tclient);
286           ViceLog(0, ("CallPreamble: Couldn't get CPS. Fail\n"));
287           H_UNLOCK
288           return -1001;
289        }
290        retry_flag=0;    /* Retry once */
291
292        /* Take down the old connection and re-read the key file */
293        ViceLog(0, ("CallPreamble: Couldn't get CPS. Reconnect to ptserver\n"));
294        H_UNLOCK
295        code = pr_Initialize(2, AFSDIR_SERVER_ETC_DIRPATH, 0);
296        H_LOCK
297        if (code) {
298           h_ReleaseClient_r(tclient);
299           H_UNLOCK
300           ViceLog(0,("CallPreamble: couldn't reconnect to ptserver\n"));
301           return -1001;
302        }
303
304        tclient->prfail = 2;      /* Means re-eval client's cps */
305        h_ReleaseClient_r(tclient);
306        goto retry;
307     }
308
309     thost = tclient->host;
310     tclient->LastCall = thost->LastCall = FT_ApproxTime();
311     if (activecall) /* For all but "GetTime" calls */
312         thost->ActiveCall = thost->LastCall;
313
314     h_Lock_r(thost);
315     if (thost->hostFlags & HOSTDELETED) {
316       ViceLog(3,("Discarded a packet for deleted host %s\n",afs_inet_ntoa_r(thost->host,hoststr)));
317       code = VBUSY; /* raced, so retry */
318     }
319     else if (thost->hostFlags & VENUSDOWN) {
320       if (BreakDelayedCallBacks_r(thost)) {
321         ViceLog(0,("BreakDelayedCallbacks FAILED for host %s which IS UP.  Possible network or routing failure.\n",
322                 afs_inet_ntoa_r(thost->host, hoststr)));
323         if ( MultiProbeAlternateAddress_r (thost) ) {
324             ViceLog(0, ("MultiProbe failed to find new address for host %s:%d\n",
325                         afs_inet_ntoa_r(thost->host, hoststr), thost->port));
326             code = -1;
327         } else {
328             ViceLog(0, ("MultiProbe found new address for host %s:%d\n",
329                         afs_inet_ntoa_r(thost->host, hoststr), thost->port));
330             if (BreakDelayedCallBacks_r(thost)) {
331                 ViceLog(0,("BreakDelayedCallbacks FAILED AGAIN for host %s which IS UP.  Possible network or routing failure.\n",
332                         afs_inet_ntoa_r(thost->host, hoststr)));
333                 code = -1;
334             }
335         }
336       }
337     } else {
338        code =  0;
339     }
340
341     h_ReleaseClient_r(tclient);
342     h_Unlock_r(thost);
343     H_UNLOCK
344     return code;      
345
346 } /*CallPreamble*/
347
348
349 static CallPostamble(aconn)
350     register struct rx_connection *aconn;
351
352 {
353     struct host *thost;
354     struct client *tclient;
355
356     H_LOCK
357     tclient = h_FindClient_r(aconn);
358     thost = tclient->host;
359     h_ReleaseClient_r(tclient);
360     h_Release_r(thost);
361     H_UNLOCK
362
363 } /*CallPostamble*/
364
365
366 #define AFSV_BUFFERSIZE 16384 
367
368 static struct afs_buffer {
369     struct afs_buffer *next;
370 } *freeBufferList = 0;
371 static int afs_buffersAlloced = 0;
372
373
374 static FreeSendBuffer(adata)
375     register struct afs_buffer *adata;
376
377 {
378     FS_LOCK
379     afs_buffersAlloced--;
380     adata->next = freeBufferList;
381     freeBufferList = adata;
382     FS_UNLOCK
383     return 0;
384
385 } /*FreeSendBuffer*/
386
387
388 /* allocate space for sender */
389 static char *AllocSendBuffer()
390
391 {
392     register struct afs_buffer *tp;
393
394     FS_LOCK
395     afs_buffersAlloced++;
396     if (!freeBufferList) {
397         FS_UNLOCK
398         return malloc(AFSV_BUFFERSIZE);
399     }
400     tp = freeBufferList;
401     freeBufferList = tp->next;
402     FS_UNLOCK
403     return (char *) tp;
404
405 } /*AllocSendBuffer*/
406
407
408 static int VolumeOwner (client, targetptr)
409     register struct client *client;
410     register Vnode *targetptr;
411
412 {
413     afs_int32 owner = V_owner(targetptr->volumePtr);    /* get volume owner */
414
415     if (owner >= 0)
416         return (client->ViceId == owner);
417     else {
418         /* 
419          * We don't have to check for host's cps since only regular
420          * viceid are volume owners.
421          */
422         return (acl_IsAMember(owner, &client->CPS));
423     }
424
425 } /*VolumeOwner*/
426
427
428 static int VolumeRootVnode (targetptr)
429     Vnode *targetptr;
430
431 {
432     return ((targetptr->vnodeNumber == ROOTVNODE) &&
433             (targetptr->disk.uniquifier == 1));
434
435 } /*VolumeRootVnode*/
436
437
438 SRXAFS_FetchData (tcon, Fid, Pos, Len, OutStatus, CallBack, Sync)
439     struct rx_connection *tcon;         /* Rx connection handle */
440     struct AFSFid *Fid;                 /* Fid of file to fetch */
441     afs_int32 Pos, Len;                 /* Not implemented yet */
442     struct AFSFetchStatus *OutStatus;   /* Returned status for Fid */
443     struct AFSCallBack *CallBack;       /* If r/w return CB for Fid */
444     struct AFSVolSync *Sync;            /* synchronization info */
445
446 {
447     int code;
448
449     code = common_FetchData (tcon, Fid, Pos, Len, OutStatus,
450                                                  CallBack, Sync, 0);
451     return code;
452 }
453
454 SRXAFS_FetchData64 (tcon, Fid, Pos, Len, OutStatus, CallBack, Sync)
455     struct rx_connection *tcon;         /* Rx connection handle */
456     struct AFSFid *Fid;                 /* Fid of file to fetch */
457     afs_int64 Pos, Len;                 /* Not implemented yet */
458     struct AFSFetchStatus *OutStatus;   /* Returned status for Fid */
459     struct AFSCallBack *CallBack;       /* If r/w return CB for Fid */
460     struct AFSVolSync *Sync;            /* synchronization info */
461 {
462     int code;
463     afs_int32 tPos, tLen;
464
465 #ifdef AFS_64BIT_ENV
466     if (Pos + Len > 0x7fffffff)
467         return E2BIG;
468     tPos = Pos;
469     tLen = Len;
470 #else /* AFS_64BIT_ENV */
471     if (Pos.high || Len.high)
472         return E2BIG;
473     tPos = Pos.low;
474     tLen = Len.low;
475 #endif /* AFS_64BIT_ENV */
476
477     code = common_FetchData (tcon, Fid, tPos, tLen, OutStatus,
478                                                  CallBack, Sync, 1);
479     return code;
480 }
481
482 common_FetchData (tcon, Fid, Pos, Len, OutStatus, CallBack, Sync, type)
483     struct rx_connection *tcon;         /* Rx connection handle */
484     struct AFSFid *Fid;                 /* Fid of file to fetch */
485     afs_int32 Pos, Len;                 /* Not implemented yet */
486     struct AFSFetchStatus *OutStatus;   /* Returned status for Fid */
487     struct AFSCallBack *CallBack;       /* If r/w return CB for Fid */
488     struct AFSVolSync *Sync;            /* synchronization info */
489     int type;                           /* 32 bit or 64 bit call */
490
491
492     Vnode * targetptr = 0;                  /* pointer to vnode to fetch */
493     Vnode * parentwhentargetnotdir = 0;     /* parent vnode if vptr is a file */
494     Vnode   tparentwhentargetnotdir;        /* parent vnode for GetStatus */
495     int     errorCode = 0;                  /* return code to caller */
496     int     fileCode =  0;                  /* return code from vol package */
497     Volume * volptr = 0;                    /* pointer to the volume */
498     struct client *client;                  /* pointer to the client data */
499     struct rx_call *tcall;                  /* the call we're a part of */
500     afs_int32 rights, anyrights;                    /* rights for this and any user */
501     struct client *t_client;                /* tmp ptr to client data */
502     struct in_addr logHostAddr;             /* host ip holder for inet_ntoa */
503 #if FS_STATS_DETAILED
504     struct fs_stats_opTimingData *opP;      /* Ptr to this op's timing struct */
505     struct fs_stats_xferData *xferP;        /* Ptr to this op's byte size struct */
506     struct timeval opStartTime,
507                    opStopTime;              /* Start/stop times for RPC op*/
508     struct timeval xferStartTime,
509                    xferStopTime;            /* Start/stop times for xfer portion*/
510     struct timeval elapsedTime;             /* Transfer time */
511     afs_int32 bytesToXfer;                          /* # bytes to xfer*/
512     afs_int32 bytesXferred;                         /* # bytes actually xferred*/
513     int readIdx;                            /* Index of read stats array to bump*/
514     static afs_int32 tot_bytesXferred; /* shared access protected by FS_LOCK */
515
516     /*
517      * Set our stats pointers, remember when the RPC operation started, and
518      * tally the operation.
519      */
520     opP   = &(afs_FullPerfStats.det.rpcOpTimes[FS_STATS_RPCIDX_FETCHDATA]);
521     xferP = &(afs_FullPerfStats.det.xferOpTimes[FS_STATS_XFERIDX_FETCHDATA]);
522     FS_LOCK
523     (opP->numOps)++;
524     FS_UNLOCK
525     TM_GetTimeOfDay(&opStartTime, 0);
526 #endif /* FS_STATS_DETAILED */
527
528     ViceLog(1,("SRXAFS_FetchData, Fid = %u.%d.%d\n",
529             Fid->Volume, Fid->Vnode, Fid->Unique));     
530     FS_LOCK
531     AFSCallStats.FetchData++, AFSCallStats.TotalCalls++;
532     FS_UNLOCK
533
534     /* CallPreamble changes tcon from a call to a conn */
535     tcall = (struct rx_call *) tcon;
536     if (errorCode = CallPreamble((struct rx_call **) &tcon, ACTIVECALL))
537         goto Bad_FetchData;
538
539     /* Get ptr to client data for user Id for logging */
540     t_client = (struct client *)  rx_GetSpecific(tcon, rxcon_client_key);
541     logHostAddr.s_addr =  rx_HostOf(rx_PeerOf(tcon));
542     ViceLog(5,("SRXAFS_FetchData, Fid = %u.%d.%d, Host %s, Id %d\n",
543             Fid->Volume, Fid->Vnode, Fid->Unique,
544             inet_ntoa(logHostAddr), t_client->ViceId)); 
545     /*
546      * Get volume/vnode for the fetched file; caller's access rights to
547      * it are also returned
548      */
549     if (errorCode = GetVolumePackage(tcon, Fid, &volptr, &targetptr,
550                                      DONTCHECK, &parentwhentargetnotdir,
551                                      &client, READ_LOCK, &rights, &anyrights))
552         goto Bad_FetchData;
553
554     SetVolumeSync(Sync, volptr);
555
556 #if FS_STATS_DETAILED
557     /*
558      * Remember that another read operation was performed.
559      */
560     FS_LOCK
561     if (client->InSameNetwork)
562         readIdx = VOL_STATS_SAME_NET;
563     else
564         readIdx = VOL_STATS_DIFF_NET;
565     V_stat_reads(volptr, readIdx)++;
566     if (client->ViceId != AnonymousID) {
567         V_stat_reads(volptr, readIdx+1)++;
568     }
569     FS_UNLOCK
570 #endif /* FS_STATS_DETAILED */
571
572     /* Check whether the caller has permission access to fetch the data */
573     if (errorCode = Check_PermissionRights(targetptr, client, rights,
574                                            CHK_FETCHDATA, 0)) 
575         goto Bad_FetchData;
576
577     /*
578      * Drop the read lock on the parent directory after saving the parent
579      * vnode information we need to pass to GetStatus
580      */
581     if (parentwhentargetnotdir != NULL) {
582         tparentwhentargetnotdir = *parentwhentargetnotdir;
583         VPutVnode(&fileCode, parentwhentargetnotdir);
584         assert(!fileCode || (fileCode == VSALVAGE));
585         parentwhentargetnotdir = NULL;
586     }
587
588 #if FS_STATS_DETAILED
589     /*
590      * Remember when the data transfer started.
591      */
592     TM_GetTimeOfDay(&xferStartTime, 0);
593 #endif /* FS_STATS_DETAILED */
594
595     /* actually do the data transfer */
596 #if FS_STATS_DETAILED
597     errorCode = FetchData_RXStyle(volptr, targetptr, tcall, Pos, Len, type,
598                                   &bytesToXfer, &bytesXferred);
599 #else
600     if (errorCode = FetchData_RXStyle(volptr, targetptr, tcall, Pos, Len, type))
601         goto Bad_FetchData;
602 #endif /* FS_STATS_DETAILED */
603
604 #if FS_STATS_DETAILED
605     /*
606      * At this point, the data transfer is done, for good or ill.  Remember
607      * when the transfer ended, bump the number of successes/failures, and
608      * integrate the transfer size and elapsed time into the stats.  If the
609      * operation failed, we jump to the appropriate point.
610      */
611     TM_GetTimeOfDay(&xferStopTime, 0);
612     FS_LOCK
613     (xferP->numXfers)++;
614     if (!errorCode) {
615         (xferP->numSuccesses)++;
616
617         /*
618          * Bump the xfer sum by the number of bytes actually sent, NOT the
619          * target number.
620          */
621         tot_bytesXferred += bytesXferred;
622         (xferP->sumBytes) += (tot_bytesXferred >> 10);
623         tot_bytesXferred &= 0x3FF;
624         if (bytesXferred < xferP->minBytes)
625             xferP->minBytes = bytesXferred;
626         if (bytesXferred > xferP->maxBytes)
627             xferP->maxBytes = bytesXferred;
628
629         /*
630          * Tally the size of the object.  Note: we tally the actual size,
631          * NOT the number of bytes that made it out over the wire.
632          */
633         if (bytesToXfer <= FS_STATS_MAXBYTES_BUCKET0)
634             (xferP->count[0])++;
635         else
636             if (bytesToXfer <= FS_STATS_MAXBYTES_BUCKET1)
637                 (xferP->count[1])++;
638         else
639             if (bytesToXfer <= FS_STATS_MAXBYTES_BUCKET2)
640                 (xferP->count[2])++;
641         else
642             if (bytesToXfer <= FS_STATS_MAXBYTES_BUCKET3)
643                 (xferP->count[3])++;
644         else
645             if (bytesToXfer <= FS_STATS_MAXBYTES_BUCKET4)
646                 (xferP->count[4])++;
647         else
648             if (bytesToXfer <= FS_STATS_MAXBYTES_BUCKET5)
649                 (xferP->count[5])++;
650         else
651             if (bytesToXfer <= FS_STATS_MAXBYTES_BUCKET6)
652                 (xferP->count[6])++;
653         else
654             if (bytesToXfer <= FS_STATS_MAXBYTES_BUCKET7)
655                 (xferP->count[7])++;
656         else
657             (xferP->count[8])++;
658
659         fs_stats_GetDiff(elapsedTime, xferStartTime, xferStopTime);
660         fs_stats_AddTo((xferP->sumTime), elapsedTime);
661         fs_stats_SquareAddTo((xferP->sqrTime), elapsedTime);
662         if (fs_stats_TimeLessThan(elapsedTime, (xferP->minTime))) {
663             fs_stats_TimeAssign((xferP->minTime), elapsedTime);
664         }
665         if (fs_stats_TimeGreaterThan(elapsedTime, (xferP->maxTime))) {
666             fs_stats_TimeAssign((xferP->maxTime), elapsedTime);
667         }
668       }
669     FS_UNLOCK
670     /*
671      * Finally, go off to tell our caller the bad news in case the
672      * fetch failed.
673      */
674     if (errorCode)
675         goto Bad_FetchData;
676 #endif /* FS_STATS_DETAILED */
677
678     /* write back  the OutStatus from the target vnode  */
679     GetStatus(targetptr, OutStatus, rights, anyrights, &tparentwhentargetnotdir);
680
681     /* if a r/w volume, promise a callback to the caller */
682     if (VolumeWriteable(volptr))
683         SetCallBackStruct(AddCallBack(client->host, Fid), CallBack);
684     else {
685       struct AFSFid myFid;              
686       memset(&myFid, 0, sizeof(struct AFSFid));
687       myFid.Volume = Fid->Volume;
688       SetCallBackStruct(AddVolCallBack(client->host, &myFid), CallBack);
689       }
690
691 Bad_FetchData: 
692     /* Update and store volume/vnode and parent vnodes back */
693     PutVolumePackage(parentwhentargetnotdir, targetptr, (Vnode *)0, volptr);
694     ViceLog(2, ("SRXAFS_FetchData returns %d\n", errorCode)); 
695     CallPostamble(tcon);
696
697 #if FS_STATS_DETAILED
698     TM_GetTimeOfDay(&opStopTime, 0);
699     if (errorCode == 0) {
700         FS_LOCK
701         (opP->numSuccesses)++;
702         fs_stats_GetDiff(elapsedTime, opStartTime, opStopTime);
703         fs_stats_AddTo((opP->sumTime), elapsedTime);
704         fs_stats_SquareAddTo((opP->sqrTime), elapsedTime);
705         if (fs_stats_TimeLessThan(elapsedTime, (opP->minTime))) {
706             fs_stats_TimeAssign((opP->minTime), elapsedTime);
707         }
708         if (fs_stats_TimeGreaterThan(elapsedTime, (opP->maxTime))) {
709             fs_stats_TimeAssign((opP->maxTime), elapsedTime);
710         }
711         FS_UNLOCK
712       }
713
714 #endif /* FS_STATS_DETAILED */
715
716     osi_auditU (tcall, FetchDataEvent, errorCode, AUD_FID, Fid, AUD_END);
717     return(errorCode);
718
719 } /*SRXAFS_FetchData*/
720
721
722 SRXAFS_FetchACL (tcon, Fid, AccessList, OutStatus, Sync)
723     struct AFSVolSync *Sync;
724     struct rx_connection *tcon;         /* Rx connection handle */
725     struct AFSFid *Fid;                 /* Fid of target dir */
726     struct AFSOpaque *AccessList;       /* Returned contents of dir's ACL */
727     struct AFSFetchStatus *OutStatus;   /* Returned status for the dir */
728
729 {
730     Vnode * targetptr = 0;              /* pointer to vnode to fetch */
731     Vnode * parentwhentargetnotdir = 0; /* parent vnode if targetptr is a file */
732     int     errorCode = 0;              /* return error code to caller */
733     Volume * volptr = 0;                /* pointer to the volume */
734     struct client *client;              /* pointer to the client data */
735     afs_int32 rights, anyrights;                /* rights for this and any user */
736     struct rx_call *tcall = (struct rx_call *) tcon; 
737     struct client *t_client;                /* tmp ptr to client data */
738     struct in_addr logHostAddr;             /* host ip holder for inet_ntoa */
739 #if FS_STATS_DETAILED
740     struct fs_stats_opTimingData *opP;      /* Ptr to this op's timing struct */
741     struct timeval opStartTime,
742                    opStopTime;              /* Start/stop times for RPC op*/
743     struct timeval elapsedTime;             /* Transfer time */
744
745     /*
746      * Set our stats pointer, remember when the RPC operation started, and
747      * tally the operation.
748      */
749     opP = &(afs_FullPerfStats.det.rpcOpTimes[FS_STATS_RPCIDX_FETCHACL]);
750     FS_LOCK
751     (opP->numOps)++;
752     FS_UNLOCK
753     TM_GetTimeOfDay(&opStartTime, 0);
754 #endif /* FS_STATS_DETAILED */
755
756     ViceLog(1, ("SAFS_FetchACL, Fid = %u.%d.%d\n",
757             Fid->Volume, Fid->Vnode, Fid->Unique));
758     FS_LOCK
759     AFSCallStats.FetchACL++, AFSCallStats.TotalCalls++;
760     FS_UNLOCK
761     if (errorCode = CallPreamble((struct rx_call **) &tcon, ACTIVECALL))
762         goto Bad_FetchACL;
763
764     /* Get ptr to client data for user Id for logging */
765     t_client = (struct client *)  rx_GetSpecific(tcon, rxcon_client_key);
766     logHostAddr.s_addr =  rx_HostOf(rx_PeerOf(tcon));
767     ViceLog(5, ("SAFS_FetchACL, Fid = %u.%d.%d, Host %s, Id %d\n",
768             Fid->Volume, Fid->Vnode, Fid->Unique,
769             inet_ntoa(logHostAddr), t_client->ViceId));
770
771     AccessList->AFSOpaque_len = 0;
772     AccessList->AFSOpaque_val = malloc(AFSOPAQUEMAX);
773
774     /*
775      * Get volume/vnode for the fetched file; caller's access rights to it
776      * are also returned
777      */
778     if (errorCode = GetVolumePackage(tcon, Fid, &volptr, &targetptr,
779                                      DONTCHECK, &parentwhentargetnotdir,
780                                      &client, READ_LOCK, &rights, &anyrights))
781         goto Bad_FetchACL;
782
783     SetVolumeSync(Sync, volptr);
784
785     /* Check whether we have permission to fetch the ACL */
786     if (errorCode = Check_PermissionRights(targetptr, client, rights,
787                                            CHK_FETCHACL, 0))
788         goto Bad_FetchACL;
789
790     /* Get the Access List from the dir's vnode */
791     if (errorCode = RXFetch_AccessList(targetptr, parentwhentargetnotdir,
792                                        AccessList))
793         goto Bad_FetchACL;
794
795     /* Get OutStatus back From the target Vnode  */
796     GetStatus(targetptr, OutStatus, rights, anyrights, parentwhentargetnotdir);
797
798 Bad_FetchACL: 
799     /* Update and store volume/vnode and parent vnodes back */
800     PutVolumePackage(parentwhentargetnotdir, targetptr, (Vnode *)0, volptr);
801     ViceLog(2, ("SAFS_FetchACL returns %d (ACL=%s)\n",
802             errorCode, AccessList->AFSOpaque_val));
803     CallPostamble(tcon);
804
805 #if FS_STATS_DETAILED
806     TM_GetTimeOfDay(&opStopTime, 0);
807     if (errorCode == 0) {
808         FS_LOCK
809         (opP->numSuccesses)++;
810         fs_stats_GetDiff(elapsedTime, opStartTime, opStopTime);
811         fs_stats_AddTo((opP->sumTime), elapsedTime);
812         fs_stats_SquareAddTo((opP->sqrTime), elapsedTime);
813         if (fs_stats_TimeLessThan(elapsedTime, (opP->minTime))) {
814             fs_stats_TimeAssign((opP->minTime), elapsedTime);
815         }
816         if (fs_stats_TimeGreaterThan(elapsedTime, (opP->maxTime))) {
817             fs_stats_TimeAssign((opP->maxTime), elapsedTime);
818         }
819         FS_UNLOCK
820       }
821
822 #endif /* FS_STATS_DETAILED */
823
824     osi_auditU (tcall, FetchACLEvent, errorCode, AUD_FID, Fid, AUD_END);
825     return errorCode;
826
827 } /*SRXAFS_FetchACL*/
828
829
830 /*
831  * This routine is called exclusively by SRXAFS_FetchStatus(), and should be
832  * merged into it when possible.
833  */
834 SAFSS_FetchStatus (tcall, Fid, OutStatus, CallBack, Sync)
835     struct rx_call *tcall;
836     struct AFSFid *Fid;                 /* Fid of target file */
837     struct AFSFetchStatus *OutStatus;   /* Returned status for the fid */
838     struct AFSCallBack *CallBack;       /* if r/w, callback promise for Fid */
839     struct AFSVolSync *Sync;            /* volume synchronization parm */
840
841 {
842     Vnode * targetptr = 0;              /* pointer to vnode to fetch */
843     Vnode * parentwhentargetnotdir = 0; /* parent vnode if targetptr is a file */
844     int     errorCode = 0;              /* return code to caller */
845     Volume * volptr = 0;                /* pointer to the volume */
846     struct client *client;              /* pointer to the client data */
847     afs_int32 rights, anyrights;                /* rights for this and any user */
848     struct client *t_client;            /* tmp ptr to client data */
849     struct in_addr logHostAddr;         /* host ip holder for inet_ntoa */
850     struct rx_connection *tcon = rx_ConnectionOf(tcall);
851
852     /* Get ptr to client data for user Id for logging */
853     t_client = (struct client *)  rx_GetSpecific(tcon, rxcon_client_key);
854     logHostAddr.s_addr =  rx_HostOf(rx_PeerOf(tcon));
855     ViceLog(1, ("SAFS_FetchStatus,  Fid = %u.%d.%d, Host %s, Id %d\n",
856             Fid->Volume, Fid->Vnode, Fid->Unique,
857             inet_ntoa(logHostAddr), t_client->ViceId));
858     FS_LOCK
859     AFSCallStats.FetchStatus++, AFSCallStats.TotalCalls++;
860     FS_UNLOCK
861     /*
862      * Get volume/vnode for the fetched file; caller's rights to it are
863      * also returned
864      */
865     if (errorCode = GetVolumePackage(tcon, Fid, &volptr, &targetptr,
866                                      DONTCHECK, &parentwhentargetnotdir,
867                                      &client, READ_LOCK, &rights, &anyrights))
868         goto Bad_FetchStatus;
869
870     /* set volume synchronization information */
871     SetVolumeSync(Sync, volptr);
872
873     /* Are we allowed to fetch Fid's status? */
874     if (targetptr->disk.type != vDirectory) {
875       if (errorCode = Check_PermissionRights(targetptr, client, rights,
876                                              CHK_FETCHSTATUS, 0)) {
877           if (rx_GetCallAbortCode(tcall) == errorCode) 
878               rx_SetCallAbortCode(tcall, 0);
879           goto Bad_FetchStatus;
880       }
881     }
882
883     /* set OutStatus From the Fid  */
884     GetStatus(targetptr, OutStatus, rights, anyrights, parentwhentargetnotdir);
885
886     /* If a r/w volume, also set the CallBack state */
887     if (VolumeWriteable(volptr))
888         SetCallBackStruct(AddCallBack(client->host, Fid), CallBack);
889     else {
890       struct AFSFid myFid;              
891       memset(&myFid, 0, sizeof(struct AFSFid));
892       myFid.Volume = Fid->Volume;
893       SetCallBackStruct(AddVolCallBack(client->host, &myFid), CallBack);
894       }
895
896 Bad_FetchStatus: 
897     /* Update and store volume/vnode and parent vnodes back */
898     PutVolumePackage(parentwhentargetnotdir, targetptr, (Vnode *)0, volptr);
899     ViceLog(2, ("SAFS_FetchStatus returns %d\n", errorCode)); 
900     return errorCode;
901
902 } /*SAFSS_FetchStatus*/
903
904
905 SRXAFS_BulkStatus(tcon, Fids, OutStats, CallBacks, Sync)
906     struct rx_connection *tcon;
907     struct AFSCBFids *Fids;
908     struct AFSBulkStats *OutStats;
909     struct AFSCBs *CallBacks;
910     struct AFSVolSync *Sync;
911
912 {
913     register int i;
914     afs_int32 nfiles;
915     Vnode * targetptr = 0;              /* pointer to vnode to fetch */
916     Vnode * parentwhentargetnotdir = 0; /* parent vnode if targetptr is a file */
917     int     errorCode = 0;              /* return code to caller */
918     Volume * volptr = 0;                /* pointer to the volume */
919     struct client *client;              /* pointer to the client data */
920     afs_int32 rights, anyrights;                /* rights for this and any user */
921     register struct AFSFid *tfid;       /* file id we're dealing with now */
922     struct rx_call *tcall = (struct rx_call *) tcon; 
923 #if FS_STATS_DETAILED
924     struct fs_stats_opTimingData *opP;      /* Ptr to this op's timing struct */
925     struct timeval opStartTime,
926                    opStopTime;              /* Start/stop times for RPC op*/
927     struct timeval elapsedTime;             /* Transfer time */
928
929     /*
930      * Set our stats pointer, remember when the RPC operation started, and
931      * tally the operation.
932      */
933     opP = &(afs_FullPerfStats.det.rpcOpTimes[FS_STATS_RPCIDX_BULKSTATUS]);
934     FS_LOCK
935     (opP->numOps)++;
936     FS_UNLOCK
937     TM_GetTimeOfDay(&opStartTime, 0);
938 #endif /* FS_STATS_DETAILED */
939
940     ViceLog(1, ("SAFS_BulkStatus\n"));
941     FS_LOCK
942     AFSCallStats.TotalCalls++;
943     FS_UNLOCK
944
945     nfiles = Fids->AFSCBFids_len;       /* # of files in here */
946     if (nfiles <= 0) {                  /* Sanity check */
947         errorCode = EINVAL;
948         goto Audit_and_Return;
949     }
950
951     /* allocate space for return output parameters */
952     OutStats->AFSBulkStats_val = (struct AFSFetchStatus *)
953         malloc(nfiles * sizeof(struct AFSFetchStatus));
954     OutStats->AFSBulkStats_len = nfiles;
955     CallBacks->AFSCBs_val = (struct AFSCallBack *)
956         malloc(nfiles * sizeof(struct AFSCallBack));
957     CallBacks->AFSCBs_len = nfiles;
958
959     if (errorCode = CallPreamble((struct rx_call **) &tcon, ACTIVECALL))
960         goto Bad_BulkStatus;
961
962     tfid = Fids->AFSCBFids_val;
963     for (i=0; i<nfiles; i++, tfid++) {
964         /*
965          * Get volume/vnode for the fetched file; caller's rights to it
966          * are also returned
967          */
968         if (errorCode =
969             GetVolumePackage(tcon, tfid, &volptr, &targetptr,
970                              DONTCHECK, &parentwhentargetnotdir, &client,
971                              READ_LOCK, &rights, &anyrights))
972                 goto Bad_BulkStatus;
973         /* set volume synchronization information, but only once per call */
974         if (i == nfiles)
975             SetVolumeSync(Sync, volptr);
976
977         /* Are we allowed to fetch Fid's status? */
978         if (targetptr->disk.type != vDirectory) {
979             if (errorCode = Check_PermissionRights(targetptr, client, rights,
980                                                    CHK_FETCHSTATUS, 0)) {
981                 if (rx_GetCallAbortCode(tcall) == errorCode) 
982                     rx_SetCallAbortCode(tcall, 0);
983                 goto Bad_BulkStatus;
984             }
985         }
986
987         /* set OutStatus From the Fid  */
988         GetStatus(targetptr, &OutStats->AFSBulkStats_val[i],
989                   rights, anyrights, parentwhentargetnotdir);
990
991         /* If a r/w volume, also set the CallBack state */
992         if (VolumeWriteable(volptr))
993             SetCallBackStruct(AddBulkCallBack(client->host, tfid),
994                               &CallBacks->AFSCBs_val[i]);
995         else {
996           struct AFSFid myFid;          
997           memset(&myFid, 0, sizeof(struct AFSFid));
998           myFid.Volume = tfid->Volume;
999           SetCallBackStruct(AddVolCallBack(client->host, &myFid),
1000                               &CallBacks->AFSCBs_val[i]);
1001         }
1002
1003         /* put back the file ID and volume */
1004         PutVolumePackage(parentwhentargetnotdir, targetptr, (Vnode *) 0, volptr);
1005         parentwhentargetnotdir = (Vnode *) 0;
1006         targetptr = (Vnode *) 0;
1007         volptr = (Volume *) 0;
1008     }
1009
1010 Bad_BulkStatus: 
1011     /* Update and store volume/vnode and parent vnodes back */
1012     PutVolumePackage(parentwhentargetnotdir, targetptr, (Vnode *)0, volptr);
1013     CallPostamble(tcon);
1014
1015 #if FS_STATS_DETAILED
1016     TM_GetTimeOfDay(&opStopTime, 0);
1017     if (errorCode == 0) {
1018         FS_LOCK
1019         (opP->numSuccesses)++;
1020         fs_stats_GetDiff(elapsedTime, opStartTime, opStopTime);
1021         fs_stats_AddTo((opP->sumTime), elapsedTime);
1022         fs_stats_SquareAddTo((opP->sqrTime), elapsedTime);
1023         if (fs_stats_TimeLessThan(elapsedTime, (opP->minTime))) {
1024             fs_stats_TimeAssign((opP->minTime), elapsedTime);
1025         }
1026         if (fs_stats_TimeGreaterThan(elapsedTime, (opP->maxTime))) {
1027             fs_stats_TimeAssign((opP->maxTime), elapsedTime);
1028         }
1029         FS_UNLOCK
1030     }   
1031
1032 #endif /* FS_STATS_DETAILED */
1033
1034 Audit_and_Return:
1035     ViceLog(2, ("SAFS_BulkStatus        returns %d\n", errorCode)); 
1036     osi_auditU (tcall, BulkFetchStatusEvent, errorCode, AUD_FIDS, Fids, AUD_END);
1037     return errorCode;
1038
1039 } /*SRXAFS_BulkStatus*/
1040
1041
1042 SRXAFS_InlineBulkStatus(tcon, Fids, OutStats, CallBacks, Sync)
1043     struct rx_connection *tcon;
1044     struct AFSCBFids *Fids;
1045     struct AFSBulkStats *OutStats;
1046     struct AFSCBs *CallBacks;
1047     struct AFSVolSync *Sync;
1048 {
1049     register int i;
1050     afs_int32 nfiles;
1051     Vnode * targetptr = 0;              /* pointer to vnode to fetch */
1052     Vnode * parentwhentargetnotdir = 0; /* parent vnode if targetptr is a file */
1053     int     errorCode = 0;              /* return code to caller */
1054     Volume * volptr = 0;                /* pointer to the volume */
1055     struct client *client;              /* pointer to the client data */
1056     afs_int32 rights, anyrights;                /* rights for this and any user */
1057     register struct AFSFid *tfid;       /* file id we're dealing with now */
1058     struct rx_call *tcall = (struct rx_call *) tcon; 
1059     AFSFetchStatus *tstatus;
1060 #if FS_STATS_DETAILED
1061     struct fs_stats_opTimingData *opP;      /* Ptr to this op's timing struct */
1062     struct timeval opStartTime,
1063                    opStopTime;              /* Start/stop times for RPC op*/
1064     struct timeval elapsedTime;             /* Transfer time */
1065
1066     /*
1067      * Set our stats pointer, remember when the RPC operation started, and
1068      * tally the operation.
1069      */
1070     opP = &(afs_FullPerfStats.det.rpcOpTimes[FS_STATS_RPCIDX_BULKSTATUS]);
1071     FS_LOCK
1072     (opP->numOps)++;
1073     FS_UNLOCK
1074     TM_GetTimeOfDay(&opStartTime, 0);
1075 #endif /* FS_STATS_DETAILED */
1076
1077     ViceLog(1, ("SAFS_InlineBulkStatus\n"));
1078     FS_LOCK
1079     AFSCallStats.TotalCalls++;
1080     FS_UNLOCK
1081
1082     nfiles = Fids->AFSCBFids_len;       /* # of files in here */
1083     if (nfiles <= 0) {                  /* Sanity check */
1084         errorCode = EINVAL;
1085         goto Audit_and_Return;
1086     }
1087
1088     /* allocate space for return output parameters */
1089     OutStats->AFSBulkStats_val = (struct AFSFetchStatus *)
1090         malloc(nfiles * sizeof(struct AFSFetchStatus));
1091     OutStats->AFSBulkStats_len = nfiles;
1092     CallBacks->AFSCBs_val = (struct AFSCallBack *)
1093         malloc(nfiles * sizeof(struct AFSCallBack));
1094     CallBacks->AFSCBs_len = nfiles;
1095
1096     if (errorCode = CallPreamble((struct rx_call **) &tcon, ACTIVECALL)) {
1097         goto Bad_InlineBulkStatus;
1098     }
1099
1100     tfid = Fids->AFSCBFids_val;
1101     for (i=0; i<nfiles; i++, tfid++) {
1102         /*
1103          * Get volume/vnode for the fetched file; caller's rights to it
1104          * are also returned
1105          */
1106         if (errorCode =
1107             GetVolumePackage(tcon, tfid, &volptr, &targetptr,
1108                              DONTCHECK, &parentwhentargetnotdir, &client,
1109                              READ_LOCK, &rights, &anyrights)) {
1110             tstatus = &OutStats->AFSBulkStats_val[i];
1111             tstatus->errorCode = errorCode;
1112             parentwhentargetnotdir = (Vnode *) 0;
1113             targetptr = (Vnode *) 0;
1114             volptr = (Volume *) 0;
1115             continue;
1116         }
1117
1118         /* set volume synchronization information, but only once per call */
1119         if (i == nfiles)
1120             SetVolumeSync(Sync, volptr);
1121
1122         /* Are we allowed to fetch Fid's status? */
1123         if (targetptr->disk.type != vDirectory) {
1124             if (errorCode = Check_PermissionRights(targetptr, client, rights,
1125                                                    CHK_FETCHSTATUS, 0)) {
1126                 tstatus = &OutStats->AFSBulkStats_val[i];
1127                 tstatus->errorCode = errorCode;
1128                 PutVolumePackage(parentwhentargetnotdir, targetptr, (Vnode *) 0, volptr);
1129                 parentwhentargetnotdir = (Vnode *) 0;
1130                 targetptr = (Vnode *) 0;
1131                 volptr = (Volume *) 0;
1132                 continue;
1133             }
1134         }
1135
1136         /* set OutStatus From the Fid  */
1137         GetStatus(targetptr, &OutStats->AFSBulkStats_val[i],
1138                   rights, anyrights, parentwhentargetnotdir);
1139
1140         /* If a r/w volume, also set the CallBack state */
1141         if (VolumeWriteable(volptr))
1142             SetCallBackStruct(AddBulkCallBack(client->host, tfid),
1143                               &CallBacks->AFSCBs_val[i]);
1144         else {
1145           struct AFSFid myFid;          
1146           memset(&myFid, 0, sizeof(struct AFSFid));
1147           myFid.Volume = tfid->Volume;
1148           SetCallBackStruct(AddVolCallBack(client->host, &myFid),
1149                               &CallBacks->AFSCBs_val[i]);
1150         }
1151
1152         /* put back the file ID and volume */
1153         PutVolumePackage(parentwhentargetnotdir, targetptr, (Vnode *) 0, volptr);
1154         parentwhentargetnotdir = (Vnode *) 0;
1155         targetptr = (Vnode *) 0;
1156         volptr = (Volume *) 0;
1157     }
1158
1159 Bad_InlineBulkStatus: 
1160     /* Update and store volume/vnode and parent vnodes back */
1161     PutVolumePackage(parentwhentargetnotdir, targetptr, (Vnode *)0, volptr);
1162     CallPostamble(tcon);
1163
1164 #if FS_STATS_DETAILED
1165     TM_GetTimeOfDay(&opStopTime, 0);
1166     if (errorCode == 0) {
1167         FS_LOCK
1168         (opP->numSuccesses)++;
1169         fs_stats_GetDiff(elapsedTime, opStartTime, opStopTime);
1170         fs_stats_AddTo((opP->sumTime), elapsedTime);
1171         fs_stats_SquareAddTo((opP->sqrTime), elapsedTime);
1172         if (fs_stats_TimeLessThan(elapsedTime, (opP->minTime))) {
1173             fs_stats_TimeAssign((opP->minTime), elapsedTime);
1174         }
1175         if (fs_stats_TimeGreaterThan(elapsedTime, (opP->maxTime))) {
1176             fs_stats_TimeAssign((opP->maxTime), elapsedTime);
1177         }
1178         FS_UNLOCK
1179     }   
1180
1181 #endif /* FS_STATS_DETAILED */
1182
1183 Audit_and_Return:
1184     ViceLog(2, ("SAFS_InlineBulkStatus  returns %d\n", errorCode)); 
1185     osi_auditU (tcall, InlineBulkFetchStatusEvent, errorCode, AUD_FIDS, Fids, AUD_END);
1186     return 0;
1187
1188 } /*SRXAFS_InlineBulkStatus*/
1189
1190
1191 SRXAFS_FetchStatus (tcon, Fid, OutStatus, CallBack, Sync)
1192     struct AFSVolSync *Sync;
1193     struct rx_connection *tcon;         /* Rx connection handle */
1194     struct AFSFid *Fid;                 /* Fid of target file */
1195     struct AFSFetchStatus *OutStatus;   /* Returned status for the fid */
1196     struct AFSCallBack *CallBack;       /* if r/w, callback promise for Fid */
1197
1198 {
1199     afs_int32 code;
1200     struct rx_call *tcall = (struct rx_call *) tcon; 
1201 #if FS_STATS_DETAILED
1202     struct fs_stats_opTimingData *opP;      /* Ptr to this op's timing struct */
1203     struct timeval opStartTime,
1204                    opStopTime;              /* Start/stop times for RPC op*/
1205     struct timeval elapsedTime;             /* Transfer time */
1206
1207     /*
1208      * Set our stats pointer, remember when the RPC operation started, and
1209      * tally the operation.
1210      */
1211     opP = &(afs_FullPerfStats.det.rpcOpTimes[FS_STATS_RPCIDX_FETCHSTATUS]);
1212     FS_LOCK
1213     (opP->numOps)++;
1214     FS_UNLOCK
1215     TM_GetTimeOfDay(&opStartTime, 0);
1216 #endif /* FS_STATS_DETAILED */
1217
1218     if (code = CallPreamble((struct rx_call **) &tcon, ACTIVECALL))
1219         goto Bad_FetchStatus;
1220
1221     code = SAFSS_FetchStatus (tcall, Fid, OutStatus, CallBack, Sync);
1222
1223 Bad_FetchStatus:    
1224     CallPostamble(tcon);
1225
1226 #if FS_STATS_DETAILED
1227     TM_GetTimeOfDay(&opStopTime, 0);
1228     if (code == 0) {
1229         FS_LOCK
1230         (opP->numSuccesses)++;
1231         fs_stats_GetDiff(elapsedTime, opStartTime, opStopTime);
1232         fs_stats_AddTo((opP->sumTime), elapsedTime);
1233         fs_stats_SquareAddTo((opP->sqrTime), elapsedTime);
1234         if (fs_stats_TimeLessThan(elapsedTime, (opP->minTime))) {
1235             fs_stats_TimeAssign((opP->minTime), elapsedTime);
1236         }
1237         if (fs_stats_TimeGreaterThan(elapsedTime, (opP->maxTime))) {
1238             fs_stats_TimeAssign((opP->maxTime), elapsedTime);
1239         }
1240         FS_UNLOCK
1241       }
1242
1243 #endif /* FS_STATS_DETAILED */
1244
1245     osi_auditU (tcall, FetchStatusEvent, code, AUD_FID, Fid, AUD_END);
1246     return code;
1247
1248 } /*SRXAFS_FetchStatus*/
1249
1250
1251 SRXAFS_StoreData (tcon, Fid, InStatus, Pos, Length, FileLength, OutStatus, Sync)
1252     struct AFSVolSync *Sync;
1253     struct rx_connection *tcon;         /* Rx connection Handle */
1254     struct AFSFid *Fid;                 /* Fid of taret file */
1255     struct AFSStoreStatus *InStatus;    /* Input Status for Fid */
1256     afs_uint32 Pos;                    /* Not implemented yet */
1257     afs_uint32 Length;                 /* Length of data to store */
1258     afs_uint32 FileLength;             /* Length of file after store */
1259     struct AFSFetchStatus *OutStatus;   /* Returned status for target fid */
1260
1261 {
1262     Vnode * targetptr = 0;              /* pointer to input fid */
1263     Vnode * parentwhentargetnotdir = 0; /* parent of Fid to get ACL */
1264     Vnode   tparentwhentargetnotdir;    /* parent vnode for GetStatus */
1265     int     errorCode = 0;              /* return code for caller */
1266     int     fileCode =  0;              /* return code from vol package */
1267     Volume * volptr = 0;                /* pointer to the volume header */
1268     struct client * client;             /* pointer to client structure */
1269     struct rx_call *tcall;              /* remember the call structure for ftp */
1270     afs_int32 rights, anyrights;                /* rights for this and any user */
1271     struct client *t_client;            /* tmp ptr to client data */
1272     struct in_addr logHostAddr;             /* host ip holder for inet_ntoa */
1273 #if FS_STATS_DETAILED
1274     struct fs_stats_opTimingData *opP;      /* Ptr to this op's timing struct */
1275     struct fs_stats_xferData *xferP;        /* Ptr to this op's byte size struct */
1276     struct timeval opStartTime,
1277                    opStopTime;              /* Start/stop times for RPC op*/
1278     struct timeval xferStartTime,
1279                    xferStopTime;            /* Start/stop times for xfer portion*/
1280     struct timeval elapsedTime;             /* Transfer time */
1281     afs_int32 bytesToXfer;                          /* # bytes to xfer */
1282     afs_int32 bytesXferred;                         /* # bytes actually xfer */
1283     static afs_int32 tot_bytesXferred; /* shared access protected by FS_LOCK */
1284
1285     /*
1286      * Set our stats pointers, remember when the RPC operation started, and
1287      * tally the operation.
1288      */
1289     opP   = &(afs_FullPerfStats.det.rpcOpTimes[FS_STATS_RPCIDX_STOREDATA]);
1290     xferP = &(afs_FullPerfStats.det.xferOpTimes[FS_STATS_XFERIDX_STOREDATA]);
1291     FS_LOCK
1292     (opP->numOps)++;
1293     FS_UNLOCK
1294
1295     ViceLog(1, ("StoreData: Fid = %u.%d.%d\n",
1296             Fid->Volume, Fid->Vnode, Fid->Unique));
1297     TM_GetTimeOfDay(&opStartTime, 0);
1298 #endif /* FS_STATS_DETAILED */
1299
1300     FS_LOCK
1301     AFSCallStats.StoreData++, AFSCallStats.TotalCalls++;
1302     FS_UNLOCK
1303     /* CallPreamble changes tcon from a call to a conn */
1304     tcall = (struct rx_call *) tcon;
1305     if (errorCode = CallPreamble((struct rx_call **) &tcon, ACTIVECALL))
1306         goto Bad_StoreData;
1307
1308     /* Get ptr to client data for user Id for logging */
1309     t_client = (struct client *) rx_GetSpecific(tcon, rxcon_client_key); 
1310     logHostAddr.s_addr =  rx_HostOf(rx_PeerOf(tcon));
1311     ViceLog(5, ("StoreData: Fid = %u.%d.%d, Host %s, Id %d\n",
1312             Fid->Volume, Fid->Vnode, Fid->Unique,
1313             inet_ntoa(logHostAddr), t_client->ViceId));
1314
1315     /*
1316      * Get associated volume/vnode for the stored file; caller's rights
1317      * are also returned
1318      */
1319     if (errorCode = GetVolumePackage(tcon, Fid, &volptr, &targetptr,
1320                                      MustNOTBeDIR, &parentwhentargetnotdir,
1321                                      &client, WRITE_LOCK, &rights, &anyrights)) {
1322         goto Bad_StoreData;
1323     }
1324
1325     /* set volume synchronization information */
1326     SetVolumeSync(Sync, volptr);
1327
1328     if ((targetptr->disk.type == vSymlink)) {
1329         /* Should we return a better error code here??? */
1330         errorCode = EISDIR;
1331         goto Bad_StoreData;
1332     }
1333
1334     /* Check if we're allowed to store the data */
1335     if (errorCode = Check_PermissionRights(targetptr, client, rights,
1336                                            CHK_STOREDATA, InStatus)) {
1337         goto Bad_StoreData;
1338     }
1339
1340     /*
1341      * Drop the read lock on the parent directory after saving the parent
1342      * vnode information we need to pass to GetStatus
1343      */
1344     if (parentwhentargetnotdir != NULL) {
1345         tparentwhentargetnotdir = *parentwhentargetnotdir;
1346         VPutVnode(&fileCode, parentwhentargetnotdir);
1347         assert(!fileCode || (fileCode == VSALVAGE));
1348         parentwhentargetnotdir = NULL;
1349     }
1350
1351
1352
1353 #if FS_STATS_DETAILED
1354     /*
1355      * Remember when the data transfer started.
1356      */
1357     TM_GetTimeOfDay(&xferStartTime, 0);
1358 #endif /* FS_STATS_DETAILED */
1359
1360     /* Do the actual storing of the data */
1361 #if FS_STATS_DETAILED
1362     errorCode = StoreData_RXStyle(volptr, targetptr, Fid, client, tcall,
1363                                   Pos, Length, FileLength,
1364                                   (InStatus->Mask & AFS_FSYNC),
1365                                   &bytesToXfer, &bytesXferred);
1366 #else
1367     errorCode = StoreData_RXStyle(volptr, targetptr, Fid, client,
1368                                       tcall, Pos, Length, FileLength,
1369                                       (InStatus->Mask & AFS_FSYNC));
1370     if (errorCode && (!targetptr->changed_newTime))
1371             goto Bad_StoreData;
1372 #endif /* FS_STATS_DETAILED */
1373 #if FS_STATS_DETAILED
1374     /*
1375      * At this point, the data transfer is done, for good or ill.  Remember
1376      * when the transfer ended, bump the number of successes/failures, and
1377      * integrate the transfer size and elapsed time into the stats.  If the
1378      * operation failed, we jump to the appropriate point.
1379      */
1380     TM_GetTimeOfDay(&xferStopTime, 0);
1381     FS_LOCK
1382     (xferP->numXfers)++;
1383     if (!errorCode) {
1384         (xferP->numSuccesses)++;
1385
1386         /*
1387          * Bump the xfer sum by the number of bytes actually sent, NOT the
1388          * target number.
1389          */
1390         tot_bytesXferred += bytesXferred;
1391         (xferP->sumBytes) += (tot_bytesXferred >> 10);
1392         tot_bytesXferred &= 0x3FF;
1393         if (bytesXferred < xferP->minBytes)
1394             xferP->minBytes = bytesXferred;
1395         if (bytesXferred > xferP->maxBytes)
1396             xferP->maxBytes = bytesXferred;
1397       
1398         /*
1399          * Tally the size of the object.  Note: we tally the actual size,
1400          * NOT the number of bytes that made it out over the wire.
1401          */
1402         if (bytesToXfer <= FS_STATS_MAXBYTES_BUCKET0)
1403             (xferP->count[0])++;
1404         else
1405             if (bytesToXfer <= FS_STATS_MAXBYTES_BUCKET1)
1406                 (xferP->count[1])++;
1407         else
1408             if (bytesToXfer <= FS_STATS_MAXBYTES_BUCKET2)
1409                 (xferP->count[2])++;
1410         else
1411             if (bytesToXfer <= FS_STATS_MAXBYTES_BUCKET3)
1412                 (xferP->count[3])++;
1413         else
1414             if (bytesToXfer <= FS_STATS_MAXBYTES_BUCKET4)
1415                 (xferP->count[4])++;
1416         else
1417             if (bytesToXfer <= FS_STATS_MAXBYTES_BUCKET5)
1418                 (xferP->count[5])++;
1419         else
1420             if (bytesToXfer <= FS_STATS_MAXBYTES_BUCKET6)
1421                 (xferP->count[6])++;
1422         else
1423             if (bytesToXfer <= FS_STATS_MAXBYTES_BUCKET7)
1424                 (xferP->count[7])++;
1425         else
1426             (xferP->count[8])++;
1427       
1428         fs_stats_GetDiff(elapsedTime, xferStartTime, xferStopTime);
1429         fs_stats_AddTo((xferP->sumTime), elapsedTime);
1430         fs_stats_SquareAddTo((xferP->sqrTime), elapsedTime);
1431         if (fs_stats_TimeLessThan(elapsedTime, (xferP->minTime))) {
1432             fs_stats_TimeAssign((xferP->minTime), elapsedTime);
1433         }
1434         if (fs_stats_TimeGreaterThan(elapsedTime, (xferP->maxTime))) {
1435             fs_stats_TimeAssign((xferP->maxTime), elapsedTime);
1436         }
1437     }
1438     FS_UNLOCK
1439
1440     /*
1441      * Finally, go off to tell our caller the bad news in case the
1442      * store failed.
1443      */
1444     if (errorCode && (!targetptr->changed_newTime))
1445             goto Bad_StoreData;
1446 #endif /* FS_STATS_DETAILED */
1447
1448     /* Update the status of the target's vnode */
1449     Update_TargetVnodeStatus(targetptr, TVS_SDATA, client, InStatus, targetptr,
1450                              volptr, 0);
1451
1452     /* Get the updated File's status back to the caller */
1453     GetStatus(targetptr, OutStatus, rights, anyrights, &tparentwhentargetnotdir);
1454
1455 Bad_StoreData: 
1456     /* Update and store volume/vnode and parent vnodes back */
1457     PutVolumePackage(parentwhentargetnotdir, targetptr, (Vnode *)0, volptr);
1458     ViceLog(2, ("SAFS_StoreData returns %d\n", errorCode));
1459
1460     CallPostamble(tcon);
1461
1462 #if FS_STATS_DETAILED
1463     TM_GetTimeOfDay(&opStopTime, 0);
1464     if (errorCode == 0) {
1465         FS_LOCK
1466         (opP->numSuccesses)++;
1467         fs_stats_GetDiff(elapsedTime, opStartTime, opStopTime);
1468         fs_stats_AddTo((opP->sumTime), elapsedTime);
1469         fs_stats_SquareAddTo((opP->sqrTime), elapsedTime);
1470         if (fs_stats_TimeLessThan(elapsedTime, (opP->minTime))) {
1471             fs_stats_TimeAssign((opP->minTime), elapsedTime);
1472         }
1473         if (fs_stats_TimeGreaterThan(elapsedTime, (opP->maxTime))) {
1474             fs_stats_TimeAssign((opP->maxTime), elapsedTime);
1475         }
1476         FS_UNLOCK
1477       }
1478 #endif /* FS_STATS_DETAILED */
1479
1480     osi_auditU (tcall, StoreDataEvent, errorCode, AUD_FID, Fid, AUD_END);
1481     return(errorCode);
1482
1483 } /*SRXAFS_StoreData*/
1484
1485 SRXAFS_StoreData64 (tcon, Fid, InStatus, Pos, Length, FileLength, OutStatus, Sync)
1486     struct AFSVolSync *Sync;
1487     struct rx_connection *tcon;         /* Rx connection Handle */
1488     struct AFSFid *Fid;                 /* Fid of taret file */
1489     struct AFSStoreStatus *InStatus;    /* Input Status for Fid */
1490     afs_uint64 Pos;                     /* Not implemented yet */
1491     afs_uint64 Length;                  /* Length of data to store */
1492     afs_uint64 FileLength;              /* Length of file after store */
1493     struct AFSFetchStatus *OutStatus;   /* Returned status for target fid */
1494 {
1495     int code;
1496     afs_int32 tPos;
1497     afs_int32 tLength;
1498     afs_int32 tFileLength;
1499
1500 #ifdef AFS_64BIT_ENV
1501     if (FileLength > 0x7fffffff)
1502         return E2BIG;
1503     tPos = Pos;
1504     tLength = Length;
1505     tFileLength = FileLength;
1506 #else /* AFS_64BIT_ENV */
1507     if (FileLength.high)
1508         return E2BIG;
1509     tPos = Pos.low;
1510     tLength = Length.low;
1511     tFileLength = FileLength.low;
1512 #endif /* AFS_64BIT_ENV */
1513
1514     code = SRXAFS_StoreData (tcon, Fid, InStatus, tPos, tLength, tFileLength,
1515                                 OutStatus, Sync);
1516     return code;
1517 }
1518
1519 SRXAFS_StoreACL (tcon, Fid, AccessList, OutStatus, Sync)
1520     struct AFSVolSync *Sync;
1521     struct rx_connection *tcon;         /* Rx connection handle */
1522     struct AFSFid *Fid;                 /* Target dir's fid */
1523     struct AFSOpaque *AccessList;       /* Access List's contents */
1524     struct AFSFetchStatus *OutStatus;   /* Returned status of fid */
1525
1526 {
1527     Vnode * targetptr = 0;              /* pointer to input fid */
1528     Vnode * parentwhentargetnotdir = 0; /* parent of Fid to get ACL */
1529     int     errorCode = 0;              /* return code for caller */
1530     struct AFSStoreStatus InStatus;     /* Input status for fid */
1531     Volume * volptr = 0;                /* pointer to the volume header */
1532     struct client * client;             /* pointer to client structure */
1533     afs_int32 rights, anyrights;                /* rights for this and any user */
1534     struct rx_call *tcall = (struct rx_call *) tcon; 
1535     struct client *t_client;            /* tmp ptr to client data */
1536     struct in_addr logHostAddr;             /* host ip holder for inet_ntoa */
1537 #if FS_STATS_DETAILED
1538     struct fs_stats_opTimingData *opP;      /* Ptr to this op's timing struct */
1539     struct timeval opStartTime,
1540                    opStopTime;              /* Start/stop times for RPC op*/
1541     struct timeval elapsedTime;             /* Transfer time */
1542
1543     /*
1544      * Set our stats pointer, remember when the RPC operation started, and
1545      * tally the operation.
1546      */
1547     opP = &(afs_FullPerfStats.det.rpcOpTimes[FS_STATS_RPCIDX_STOREACL]);
1548     FS_LOCK
1549     (opP->numOps)++;
1550     FS_UNLOCK
1551     TM_GetTimeOfDay(&opStartTime, 0);
1552 #endif /* FS_STATS_DETAILED */
1553     if (errorCode = CallPreamble((struct rx_call **) &tcon, ACTIVECALL))
1554         goto Bad_StoreACL;
1555
1556     /* Get ptr to client data for user Id for logging */
1557     t_client = (struct client *) rx_GetSpecific(tcon, rxcon_client_key); 
1558     logHostAddr.s_addr =  rx_HostOf(rx_PeerOf(tcon));
1559     ViceLog(1, ("SAFS_StoreACL, Fid = %u.%d.%d, ACL=%s, Host %s, Id %d\n",
1560             Fid->Volume, Fid->Vnode, Fid->Unique, AccessList->AFSOpaque_val,
1561             inet_ntoa(logHostAddr), t_client->ViceId));
1562     FS_LOCK
1563     AFSCallStats.StoreACL++, AFSCallStats.TotalCalls++;
1564     FS_UNLOCK
1565
1566     InStatus.Mask = 0;      /* not storing any status */
1567
1568     /*
1569      * Get associated volume/vnode for the target dir; caller's rights
1570      * are also returned.
1571      */
1572     if (errorCode = GetVolumePackage(tcon, Fid, &volptr, &targetptr,
1573                                      MustBeDIR, &parentwhentargetnotdir,
1574                                      &client, WRITE_LOCK, &rights, &anyrights)) {
1575         goto Bad_StoreACL;
1576     }
1577
1578     /* set volume synchronization information */
1579     SetVolumeSync(Sync, volptr);
1580
1581     /* Check if we have permission to change the dir's ACL */
1582     if (errorCode = Check_PermissionRights(targetptr, client, rights,
1583                                            CHK_STOREACL, &InStatus)) {
1584         goto Bad_StoreACL;
1585     }
1586
1587     /* Build and store the new Access List for the dir */
1588     if (errorCode = RXStore_AccessList(targetptr, AccessList)) {
1589         goto Bad_StoreACL;
1590     }
1591     
1592     targetptr->changed_newTime = 1; /* status change of directory */
1593
1594     /* convert the write lock to a read lock before breaking callbacks */
1595     VVnodeWriteToRead(&errorCode, targetptr);
1596     assert(!errorCode || errorCode == VSALVAGE);
1597
1598     /* break call backs on the directory  */
1599     BreakCallBack(client->host, Fid, 0);
1600
1601     /* Get the updated dir's status back to the caller */
1602     GetStatus(targetptr, OutStatus, rights, anyrights, (struct vnode *)0);
1603
1604 Bad_StoreACL: 
1605     /* Update and store volume/vnode and parent vnodes back */
1606     PutVolumePackage(parentwhentargetnotdir, targetptr, (Vnode *)0, volptr);
1607     ViceLog(2, ("SAFS_StoreACL returns %d\n", errorCode)); 
1608     CallPostamble(tcon);
1609
1610 #if FS_STATS_DETAILED
1611     TM_GetTimeOfDay(&opStopTime, 0);
1612     if (errorCode == 0) {
1613       FS_LOCK
1614       (opP->numSuccesses)++;
1615       fs_stats_GetDiff(elapsedTime, opStartTime, opStopTime);
1616       fs_stats_AddTo((opP->sumTime), elapsedTime);
1617       fs_stats_SquareAddTo((opP->sqrTime), elapsedTime);
1618       if (fs_stats_TimeLessThan(elapsedTime, (opP->minTime))) {
1619         fs_stats_TimeAssign((opP->minTime), elapsedTime);
1620       }
1621       if (fs_stats_TimeGreaterThan(elapsedTime, (opP->maxTime))) {
1622         fs_stats_TimeAssign((opP->maxTime), elapsedTime);
1623       }
1624       FS_UNLOCK
1625     }
1626 #endif /* FS_STATS_DETAILED */
1627
1628     osi_auditU (tcall, StoreACLEvent, errorCode, AUD_FID, Fid, AUD_END);
1629     return errorCode;
1630
1631 } /*SRXAFS_StoreACL*/
1632
1633
1634 /*
1635  * Note: This routine is called exclusively from SRXAFS_StoreStatus(), and
1636  * should be merged when possible.
1637  */
1638 SAFSS_StoreStatus (tcon, Fid, InStatus, OutStatus, Sync)
1639     struct rx_connection *tcon;         /* Rx connection Handle */
1640     struct AFSFid *Fid;                 /* Target file's fid */
1641     struct AFSStoreStatus *InStatus;    /* Input status for Fid */
1642     struct AFSFetchStatus *OutStatus;   /* Output status for fid */
1643     struct AFSVolSync *Sync;
1644
1645 {
1646     Vnode * targetptr = 0;              /* pointer to input fid */
1647     Vnode * parentwhentargetnotdir = 0; /* parent of Fid to get ACL */
1648     int     errorCode = 0;              /* return code for caller */
1649     Volume * volptr = 0;                /* pointer to the volume header */
1650     struct client * client;             /* pointer to client structure */
1651     afs_int32 rights, anyrights;                /* rights for this and any user */
1652     struct client *t_client;            /* tmp ptr to client data */
1653     struct in_addr logHostAddr;         /* host ip holder for inet_ntoa */
1654
1655     /* Get ptr to client data for user Id for logging */
1656     t_client = (struct client *) rx_GetSpecific(tcon, rxcon_client_key); 
1657     logHostAddr.s_addr =  rx_HostOf(rx_PeerOf(tcon));
1658     ViceLog(1, ("SAFS_StoreStatus,  Fid = %u.%d.%d, Host %s, Id %d\n",
1659             Fid->Volume, Fid->Vnode,    Fid->Unique,
1660             inet_ntoa(logHostAddr), t_client->ViceId));
1661     FS_LOCK
1662     AFSCallStats.StoreStatus++, AFSCallStats.TotalCalls++;
1663     FS_UNLOCK
1664     /*
1665      * Get volume/vnode for the target file; caller's rights to it are
1666      * also returned
1667      */
1668     if (errorCode = GetVolumePackage(tcon, Fid, &volptr, &targetptr,
1669                                      DONTCHECK, &parentwhentargetnotdir,
1670                                      &client, WRITE_LOCK, &rights, &anyrights)) {
1671         goto Bad_StoreStatus;
1672     }
1673
1674     /* set volume synchronization information */
1675     SetVolumeSync(Sync, volptr);
1676
1677     /* Check if the caller has proper permissions to store status to Fid */
1678     if (errorCode = Check_PermissionRights(targetptr, client, rights,
1679                                            CHK_STORESTATUS, InStatus)) {
1680         goto Bad_StoreStatus;
1681     }
1682     /*
1683      * Check for a symbolic link; we can't chmod these (otherwise could
1684      * change a symlink to a mt pt or vice versa)
1685      */
1686     if (targetptr->disk.type == vSymlink && (InStatus->Mask & AFS_SETMODE)) {
1687         errorCode = EINVAL;
1688         goto Bad_StoreStatus;
1689     }
1690
1691     /* Update the status of the target's vnode */
1692     Update_TargetVnodeStatus(targetptr, TVS_SSTATUS, client, InStatus,
1693                              (parentwhentargetnotdir ?
1694                               parentwhentargetnotdir : targetptr), volptr, 0);
1695
1696     /* convert the write lock to a read lock before breaking callbacks */
1697     VVnodeWriteToRead(&errorCode, targetptr);
1698     assert(!errorCode || errorCode == VSALVAGE);
1699
1700     /* Break call backs on Fid */
1701     BreakCallBack(client->host, Fid, 0);
1702
1703     /* Return the updated status back to caller */
1704     GetStatus(targetptr, OutStatus, rights, anyrights, parentwhentargetnotdir);
1705
1706 Bad_StoreStatus: 
1707     /* Update and store volume/vnode and parent vnodes back */
1708     PutVolumePackage(parentwhentargetnotdir, targetptr, (Vnode *)0, volptr);
1709     ViceLog(2, ("SAFS_StoreStatus returns %d\n", errorCode));
1710     return errorCode;
1711
1712 } /*SAFSS_StoreStatus*/
1713
1714
1715 SRXAFS_StoreStatus (tcon, Fid, InStatus, OutStatus, Sync)
1716     struct AFSVolSync *Sync;
1717     struct rx_connection *tcon;         /* Rx connection Handle */
1718     struct AFSFid *Fid;                 /* Target file's fid */
1719     struct AFSStoreStatus *InStatus;    /* Input status for Fid */
1720     struct AFSFetchStatus *OutStatus;   /* Output status for fid */
1721
1722 {
1723     afs_int32 code;
1724     struct rx_call *tcall = (struct rx_call *) tcon; 
1725 #if FS_STATS_DETAILED
1726     struct fs_stats_opTimingData *opP;      /* Ptr to this op's timing struct */
1727     struct timeval opStartTime,
1728                    opStopTime;              /* Start/stop times for RPC op*/
1729     struct timeval elapsedTime;             /* Transfer time */
1730
1731     /*
1732      * Set our stats pointer, remember when the RPC operation started, and
1733      * tally the operation.
1734      */
1735     opP = &(afs_FullPerfStats.det.rpcOpTimes[FS_STATS_RPCIDX_STORESTATUS]);
1736     FS_LOCK
1737     (opP->numOps)++;
1738     FS_UNLOCK
1739     TM_GetTimeOfDay(&opStartTime, 0);
1740 #endif /* FS_STATS_DETAILED */
1741
1742     if (code = CallPreamble((struct rx_call **) &tcon, ACTIVECALL))
1743         goto Bad_StoreStatus;
1744
1745     code = SAFSS_StoreStatus (tcon, Fid, InStatus, OutStatus, Sync);
1746
1747 Bad_StoreStatus:
1748     CallPostamble(tcon);
1749
1750 #if FS_STATS_DETAILED
1751     TM_GetTimeOfDay(&opStopTime, 0);
1752     if (code == 0) {
1753       FS_LOCK
1754       (opP->numSuccesses)++;
1755       fs_stats_GetDiff(elapsedTime, opStartTime, opStopTime);
1756       fs_stats_AddTo((opP->sumTime), elapsedTime);
1757       fs_stats_SquareAddTo((opP->sqrTime), elapsedTime);
1758       if (fs_stats_TimeLessThan(elapsedTime, (opP->minTime))) {
1759         fs_stats_TimeAssign((opP->minTime), elapsedTime);
1760       }
1761       if (fs_stats_TimeGreaterThan(elapsedTime, (opP->maxTime))) {
1762         fs_stats_TimeAssign((opP->maxTime), elapsedTime);
1763       }
1764       FS_UNLOCK
1765     }
1766
1767 #endif /* FS_STATS_DETAILED */
1768
1769     osi_auditU (tcall, StoreStatusEvent, code, AUD_FID, Fid, AUD_END);
1770     return code;
1771
1772 } /*SRXAFS_StoreStatus*/
1773
1774
1775 /*
1776  * This routine is called exclusively by SRXAFS_RemoveFile(), and should be
1777  * merged in when possible.
1778  */
1779 SAFSS_RemoveFile (tcon, DirFid, Name, OutDirStatus, Sync)
1780     struct rx_connection *tcon;          /* Rx connection handle */
1781     struct AFSFid *DirFid;               /* Dir fid for file to remove */
1782     char *Name;                          /* File name to remove */
1783     struct AFSFetchStatus *OutDirStatus; /* Output status for dir fid's */
1784     struct AFSVolSync *Sync;
1785
1786 {
1787     Vnode * parentptr = 0;              /* vnode of input Directory */
1788     Vnode * parentwhentargetnotdir = 0; /* parent for use in SetAccessList */
1789     Vnode * targetptr = 0;              /* file to be deleted */
1790     Volume * volptr = 0;                /* pointer to the volume header */
1791     AFSFid fileFid;                     /* area for Fid from the directory */
1792     int     errorCode = 0;              /* error code */
1793     DirHandle dir;                      /* Handle for dir package I/O */
1794     struct client * client;             /* pointer to client structure */
1795     afs_int32 rights, anyrights;                /* rights for this and any user */
1796     struct client *t_client;            /* tmp ptr to client data */
1797     struct in_addr logHostAddr;         /* host ip holder for inet_ntoa */
1798
1799     /* Get ptr to client data for user Id for logging */
1800     t_client = (struct client *) rx_GetSpecific(tcon, rxcon_client_key); 
1801     logHostAddr.s_addr =  rx_HostOf(rx_PeerOf(tcon));
1802     ViceLog(1, ("SAFS_RemoveFile %s,  Did = %u.%d.%d, Host %s, Id %d\n",
1803             Name, DirFid->Volume, DirFid->Vnode, DirFid->Unique,
1804             inet_ntoa(logHostAddr), t_client->ViceId));
1805     FS_LOCK
1806     AFSCallStats.RemoveFile++, AFSCallStats.TotalCalls++;
1807     FS_UNLOCK
1808     /*
1809      * Get volume/vnode for the parent dir; caller's access rights are
1810      * also returned
1811      */
1812     if (errorCode = GetVolumePackage(tcon, DirFid, &volptr, &parentptr,
1813                                      MustBeDIR, &parentwhentargetnotdir,
1814                                      &client, WRITE_LOCK, &rights, &anyrights)) {
1815         goto Bad_RemoveFile;
1816     }
1817     /* set volume synchronization information */
1818     SetVolumeSync(Sync, volptr);
1819
1820     /* Does the caller has delete (& write) access to the parent directory? */
1821     if (errorCode = CheckWriteMode(parentptr, rights, PRSFS_DELETE)) {
1822         goto Bad_RemoveFile;
1823     }
1824
1825     /* Actually delete the desired file */
1826     if (errorCode = DeleteTarget(parentptr, volptr, &targetptr, &dir,
1827                                  &fileFid, Name, MustNOTBeDIR)) {
1828         goto Bad_RemoveFile;
1829     }
1830
1831     /* Update the vnode status of the parent dir */
1832 #if FS_STATS_DETAILED
1833     Update_ParentVnodeStatus(parentptr, volptr, &dir, client->ViceId,
1834                              parentptr->disk.linkCount, client->InSameNetwork);
1835 #else
1836     Update_ParentVnodeStatus(parentptr, volptr, &dir, client->ViceId,
1837                              parentptr->disk.linkCount);
1838 #endif /* FS_STATS_DETAILED */
1839
1840     /* Return the updated parent dir's status back to caller */
1841     GetStatus(parentptr, OutDirStatus, rights, anyrights, (struct vnode *)0);
1842
1843     /* Handle internal callback state for the parent and the deleted file */
1844     if (targetptr->disk.linkCount == 0) {
1845         /* no references left, discard entry */
1846         DeleteFileCallBacks(&fileFid);
1847         /* convert the parent lock to a read lock before breaking callbacks */
1848         VVnodeWriteToRead(&errorCode, parentptr);
1849         assert(!errorCode || errorCode == VSALVAGE);
1850     } else {
1851         /* convert the parent lock to a read lock before breaking callbacks */
1852         VVnodeWriteToRead(&errorCode, parentptr);
1853         assert(!errorCode || errorCode == VSALVAGE);
1854         /* convert the target lock to a read lock before breaking callbacks */
1855         VVnodeWriteToRead(&errorCode, targetptr);
1856         assert(!errorCode || errorCode == VSALVAGE);
1857         /* tell all the file has changed */
1858         BreakCallBack(client->host, &fileFid, 1);
1859     }
1860
1861     /* break call back on the directory */
1862     BreakCallBack(client->host, DirFid, 0);
1863
1864 Bad_RemoveFile: 
1865     /* Update and store volume/vnode and parent vnodes back */
1866     PutVolumePackage(parentwhentargetnotdir, targetptr, parentptr, volptr);
1867     ViceLog(2, ("SAFS_RemoveFile returns %d\n", errorCode)); 
1868     return errorCode;
1869
1870 } /*SAFSS_RemoveFile*/
1871
1872
1873 SRXAFS_RemoveFile (tcon, DirFid, Name, OutDirStatus, Sync)
1874     struct AFSVolSync *Sync;
1875     struct rx_connection *tcon;          /* Rx connection handle */
1876     struct AFSFid *DirFid;               /* Dir fid for file to remove */
1877     char *Name;                          /* File name to remove */
1878     struct AFSFetchStatus *OutDirStatus; /* Output status for dir fid's */
1879
1880 {
1881     afs_int32 code;
1882     struct rx_call *tcall = (struct rx_call *) tcon; 
1883 #if FS_STATS_DETAILED
1884     struct fs_stats_opTimingData *opP;      /* Ptr to this op's timing struct */
1885     struct timeval opStartTime,
1886                    opStopTime;              /* Start/stop times for RPC op*/
1887     struct timeval elapsedTime;             /* Transfer time */
1888
1889     /*
1890      * Set our stats pointer, remember when the RPC operation started, and
1891      * tally the operation.
1892      */
1893     opP = &(afs_FullPerfStats.det.rpcOpTimes[FS_STATS_RPCIDX_REMOVEFILE]);
1894     FS_LOCK
1895     (opP->numOps)++;
1896     FS_UNLOCK
1897     TM_GetTimeOfDay(&opStartTime, 0);
1898 #endif /* FS_STATS_DETAILED */
1899
1900     if (code = CallPreamble((struct rx_call **) &tcon, ACTIVECALL))
1901         goto Bad_RemoveFile;
1902
1903     code = SAFSS_RemoveFile (tcon, DirFid, Name, OutDirStatus, Sync);
1904
1905 Bad_RemoveFile:    
1906     CallPostamble(tcon);
1907
1908 #if FS_STATS_DETAILED
1909     TM_GetTimeOfDay(&opStopTime, 0);
1910     if (code == 0) {
1911       FS_LOCK
1912       (opP->numSuccesses)++;
1913       fs_stats_GetDiff(elapsedTime, opStartTime, opStopTime);
1914       fs_stats_AddTo((opP->sumTime), elapsedTime);
1915       fs_stats_SquareAddTo((opP->sqrTime), elapsedTime);
1916       if (fs_stats_TimeLessThan(elapsedTime, (opP->minTime))) {
1917         fs_stats_TimeAssign((opP->minTime), elapsedTime);
1918       }
1919       if (fs_stats_TimeGreaterThan(elapsedTime, (opP->maxTime))) {
1920         fs_stats_TimeAssign((opP->maxTime), elapsedTime);
1921       }
1922       FS_UNLOCK
1923     }
1924
1925 #endif /* FS_STATS_DETAILED */
1926
1927     osi_auditU (tcall, RemoveFileEvent, code, AUD_FID, DirFid, AUD_STR, Name, AUD_END);
1928     return code;
1929
1930 } /*SRXAFS_RemoveFile*/
1931
1932
1933 /*
1934  * This routine is called exclusively from SRXAFS_CreateFile(), and should
1935  * be merged in when possible.
1936  */
1937 SAFSS_CreateFile (tcon, DirFid, Name, InStatus, OutFid, OutFidStatus,
1938                  OutDirStatus, CallBack, Sync)
1939     struct rx_connection *tcon;          /* Rx connection handle */
1940     struct AFSFid *DirFid;               /* Parent Dir fid */
1941     char *Name;                          /* File name to be created */
1942     struct AFSStoreStatus *InStatus;     /* Input status for newly created file */
1943     struct AFSFid *OutFid;               /* Fid for newly created file */
1944     struct AFSFetchStatus *OutFidStatus; /* Output status for new file */
1945     struct AFSFetchStatus *OutDirStatus; /* Ouput status for the parent dir */
1946     struct AFSCallBack *CallBack;        /* Return callback promise for new file */
1947     struct AFSVolSync *Sync;
1948
1949 {
1950     Vnode * parentptr = 0;              /* vnode of input Directory */
1951     Vnode * targetptr = 0;              /* vnode of the new file */
1952     Vnode * parentwhentargetnotdir = 0; /* parent for use in SetAccessList */
1953     Volume * volptr = 0;                /* pointer to the volume header */
1954     int     errorCode = 0;              /* error code */
1955     DirHandle dir;                      /* Handle for dir package I/O */
1956     struct client * client;             /* pointer to client structure */
1957     afs_int32 rights, anyrights;                /* rights for this and any user */
1958     struct client *t_client;            /* tmp ptr to client data */
1959     struct in_addr logHostAddr;         /* host ip holder for inet_ntoa */
1960
1961     /* Get ptr to client data for user Id for logging */
1962     t_client = (struct client *) rx_GetSpecific(tcon, rxcon_client_key); 
1963     logHostAddr.s_addr =  rx_HostOf(rx_PeerOf(tcon));
1964     ViceLog(1, ("SAFS_CreateFile %s,  Did = %u.%d.%d, Host %s, Id %d\n",
1965             Name, DirFid->Volume, DirFid->Vnode, DirFid->Unique,
1966             inet_ntoa(logHostAddr), t_client->ViceId));
1967     FS_LOCK
1968     AFSCallStats.CreateFile++, AFSCallStats.TotalCalls++;
1969     FS_UNLOCK
1970     if (!FileNameOK(Name)) {
1971       errorCode = EINVAL;
1972       goto Bad_CreateFile;
1973     }
1974
1975     /*
1976      * Get associated volume/vnode for the parent dir; caller long are
1977      * also returned
1978      */
1979     if (errorCode = GetVolumePackage(tcon, DirFid, &volptr, &parentptr,
1980                                      MustBeDIR, &parentwhentargetnotdir,
1981                                      &client, WRITE_LOCK, &rights, &anyrights)) {
1982         goto Bad_CreateFile;
1983     }
1984
1985     /* set volume synchronization information */
1986     SetVolumeSync(Sync, volptr);
1987
1988     /* Can we write (and insert) onto the parent directory? */
1989     if (errorCode = CheckWriteMode(parentptr, rights, PRSFS_INSERT)) {
1990         goto Bad_CreateFile;
1991     }
1992     /* get a new vnode for the file to be created and set it up */
1993     if (errorCode = Alloc_NewVnode(parentptr, &dir, volptr, &targetptr,
1994                                    Name, OutFid, vFile, nBlocks(0))) {
1995         goto Bad_CreateFile;
1996     }
1997
1998     /* update the status of the parent vnode */
1999 #if FS_STATS_DETAILED
2000     Update_ParentVnodeStatus(parentptr, volptr, &dir, client->ViceId,
2001                              parentptr->disk.linkCount, client->InSameNetwork);
2002 #else
2003     Update_ParentVnodeStatus(parentptr, volptr, &dir, client->ViceId,
2004                              parentptr->disk.linkCount);
2005 #endif /* FS_STATS_DETAILED */
2006
2007     /* update the status of the new file's vnode */
2008     Update_TargetVnodeStatus(targetptr, TVS_CFILE, client, InStatus,
2009                              parentptr, volptr, 0);
2010
2011     /* set up the return status for the parent dir and the newly created file */
2012     GetStatus(targetptr, OutFidStatus, rights, anyrights, parentptr);
2013     GetStatus(parentptr, OutDirStatus, rights, anyrights, (struct vnode *)0);
2014
2015     /* convert the write lock to a read lock before breaking callbacks */
2016     VVnodeWriteToRead(&errorCode, parentptr);
2017     assert(!errorCode || errorCode == VSALVAGE);
2018     
2019     /* break call back on parent dir */
2020     BreakCallBack(client->host, DirFid, 0);
2021
2022     /* Return a callback promise for the newly created file to the caller */
2023     SetCallBackStruct(AddCallBack(client->host, OutFid), CallBack);
2024
2025 Bad_CreateFile:
2026     /* Update and store volume/vnode and parent vnodes back */
2027     PutVolumePackage(parentwhentargetnotdir, targetptr, parentptr, volptr);
2028     ViceLog(2, ("SAFS_CreateFile returns %d\n", errorCode)); 
2029     return errorCode;
2030
2031 } /*SAFSS_CreateFile*/
2032
2033
2034 SRXAFS_CreateFile (tcon, DirFid, Name, InStatus, OutFid, OutFidStatus, OutDirStatus, CallBack, Sync)
2035     struct AFSVolSync *Sync;
2036     struct rx_connection *tcon;          /* Rx connection handle */
2037     struct AFSFid *DirFid;               /* Parent Dir fid */
2038     char *Name;                          /* File name to be created */
2039     struct AFSStoreStatus *InStatus;     /* Input status for newly created file */
2040     struct AFSFid *OutFid;               /* Fid for newly created file */
2041     struct AFSFetchStatus *OutFidStatus; /* Output status for new file */
2042     struct AFSFetchStatus *OutDirStatus; /* Ouput status for the parent dir */
2043     struct AFSCallBack *CallBack;        /* Return callback promise for new file */
2044
2045 {
2046     afs_int32 code;
2047     struct rx_call *tcall = (struct rx_call *) tcon; 
2048 #if FS_STATS_DETAILED
2049     struct fs_stats_opTimingData *opP;      /* Ptr to this op's timing struct */
2050     struct timeval opStartTime,
2051                    opStopTime;              /* Start/stop times for RPC op*/
2052     struct timeval elapsedTime;             /* Transfer time */
2053
2054     /*
2055      * Set our stats pointer, remember when the RPC operation started, and
2056      * tally the operation.
2057      */
2058     opP = &(afs_FullPerfStats.det.rpcOpTimes[FS_STATS_RPCIDX_CREATEFILE]);
2059     FS_LOCK
2060     (opP->numOps)++;
2061     FS_UNLOCK
2062     TM_GetTimeOfDay(&opStartTime, 0);
2063 #endif /* FS_STATS_DETAILED */
2064
2065     if (code = CallPreamble((struct rx_call **) &tcon, ACTIVECALL))
2066         goto Bad_CreateFile;
2067
2068     code = SAFSS_CreateFile (tcon, DirFid, Name, InStatus, OutFid,
2069                             OutFidStatus, OutDirStatus, CallBack, Sync);
2070
2071 Bad_CreateFile:    
2072     CallPostamble(tcon);
2073
2074 #if FS_STATS_DETAILED
2075     TM_GetTimeOfDay(&opStopTime, 0);
2076     if (code == 0) {
2077       FS_LOCK
2078       (opP->numSuccesses)++;
2079       fs_stats_GetDiff(elapsedTime, opStartTime, opStopTime);
2080       fs_stats_AddTo((opP->sumTime), elapsedTime);
2081       fs_stats_SquareAddTo((opP->sqrTime), elapsedTime);
2082       if (fs_stats_TimeLessThan(elapsedTime, (opP->minTime))) {
2083         fs_stats_TimeAssign((opP->minTime), elapsedTime);
2084       }
2085       if (fs_stats_TimeGreaterThan(elapsedTime, (opP->maxTime))) {
2086         fs_stats_TimeAssign((opP->maxTime), elapsedTime);
2087       }
2088       FS_UNLOCK
2089     }
2090 #endif /* FS_STATS_DETAILED */
2091
2092     osi_auditU (tcall, CreateFileEvent, code, AUD_FID, DirFid, AUD_STR, Name, AUD_END);
2093     return code;
2094
2095 } /*SRXAFS_CreateFile*/
2096
2097
2098 /*
2099  * This routine is called exclusively from SRXAFS_Rename(), and should be
2100  * merged in when possible.
2101  */
2102 SAFSS_Rename (tcon, OldDirFid, OldName, NewDirFid, NewName, OutOldDirStatus,
2103              OutNewDirStatus, Sync)
2104     struct rx_connection *tcon;             /* Rx connection handle */
2105     struct AFSFid *OldDirFid;               /* From parent dir's fid */
2106     char *OldName;                          /* From file name */
2107     struct AFSFid *NewDirFid;               /* To parent dir's fid */
2108     char *NewName;                          /* To new file name */
2109     struct AFSFetchStatus *OutOldDirStatus; /* Output status for From parent dir */
2110     struct AFSFetchStatus *OutNewDirStatus; /* Output status for To parent dir */
2111     struct AFSVolSync *Sync;
2112
2113 {
2114     Vnode * oldvptr = 0;        /* vnode of the old Directory */
2115     Vnode * newvptr = 0;        /* vnode of the new Directory */
2116     Vnode * fileptr = 0;        /* vnode of the file to move */
2117     Vnode * newfileptr = 0;     /* vnode of the file to delete */
2118     Vnode * testvptr = 0;       /* used in directory tree walk */
2119     Vnode * parent = 0;         /* parent for use in SetAccessList */
2120     int     errorCode = 0;      /* error code */
2121     int     fileCode = 0;       /* used when writing Vnodes */
2122     VnodeId testnode;           /* used in directory tree walk */
2123     AFSFid fileFid;             /* Fid of file to move */
2124     AFSFid newFileFid;          /* Fid of new file */
2125     DirHandle olddir;           /* Handle for dir package I/O */
2126     DirHandle newdir;           /* Handle for dir package I/O */
2127     DirHandle filedir;          /* Handle for dir package I/O */
2128     DirHandle newfiledir;       /* Handle for dir package I/O */
2129     Volume * volptr = 0;        /* pointer to the volume header */
2130     struct client * client;     /* pointer to client structure */
2131     afs_int32 rights, anyrights;        /* rights for this and any user */
2132     afs_int32 newrights;                /* rights for this user */
2133     afs_int32 newanyrights;             /* rights for any user */
2134     int doDelete;               /* deleted the rename target (ref count now 0) */
2135     int code;
2136     struct client *t_client;            /* tmp ptr to client data */
2137     struct in_addr logHostAddr;         /* host ip holder for inet_ntoa */
2138
2139     /* Get ptr to client data for user Id for logging */
2140     t_client = (struct client *) rx_GetSpecific(tcon, rxcon_client_key); 
2141     logHostAddr.s_addr =  rx_HostOf(rx_PeerOf(tcon));
2142     ViceLog(1, ("SAFS_Rename %s to %s,  Fid = %u.%d.%d to %u.%d.%d, Host %s, Id %d\n",
2143             OldName, NewName, OldDirFid->Volume, OldDirFid->Vnode,
2144             OldDirFid->Unique, NewDirFid->Volume, NewDirFid->Vnode,
2145             NewDirFid->Unique,
2146             inet_ntoa(logHostAddr), t_client->ViceId));
2147     FS_LOCK
2148     AFSCallStats.Rename++, AFSCallStats.TotalCalls++;
2149     FS_UNLOCK
2150     if (!FileNameOK(NewName)) {
2151         errorCode = EINVAL;
2152         goto Bad_Rename;
2153     }
2154     if (OldDirFid->Volume != NewDirFid->Volume) {
2155         DFlush();
2156         errorCode = EXDEV;
2157         goto Bad_Rename;
2158     }
2159     if ( (strcmp(OldName, ".") == 0) || (strcmp(OldName, "..") == 0) ||
2160          (strcmp(NewName, ".") == 0) || (strcmp(NewName, "..") == 0) || 
2161          (strlen(NewName) == 0) || (strlen(OldName) == 0)  ) {
2162         DFlush();
2163         errorCode = EINVAL;
2164         goto Bad_Rename;
2165     }
2166
2167     if (OldDirFid->Vnode <= NewDirFid->Vnode) {
2168         if  (errorCode = GetVolumePackage(tcon, OldDirFid, &volptr,
2169                                           &oldvptr, MustBeDIR, &parent,
2170                                           &client, WRITE_LOCK, &rights,
2171                                           &anyrights)) {
2172             DFlush();
2173             goto Bad_Rename;
2174         }
2175         if (OldDirFid->Vnode == NewDirFid->Vnode) {
2176             newvptr = oldvptr;
2177             newrights = rights, newanyrights = anyrights;
2178         }
2179         else
2180             if (errorCode = GetVolumePackage(tcon, NewDirFid, &volptr,
2181                                              &newvptr, MustBeDIR, &parent,
2182                                              &client, WRITE_LOCK, &newrights,
2183                                              &newanyrights)) {
2184                 DFlush();
2185                 goto Bad_Rename;
2186             }
2187     }
2188     else {
2189         if (errorCode = GetVolumePackage(tcon, NewDirFid, &volptr,
2190                                          &newvptr, MustBeDIR, &parent,
2191                                          &client, WRITE_LOCK, &newrights,
2192                                          &newanyrights)) {
2193             DFlush();
2194             goto Bad_Rename;
2195         }
2196         if (errorCode = GetVolumePackage(tcon, OldDirFid, &volptr, &oldvptr,
2197                                          MustBeDIR, &parent, &client, WRITE_LOCK,
2198                                          &rights, &anyrights)) {
2199             DFlush();
2200             goto Bad_Rename;
2201         }
2202     }
2203
2204     /* set volume synchronization information */
2205     SetVolumeSync(Sync, volptr);
2206
2207     if (errorCode = CheckWriteMode(oldvptr, rights, PRSFS_DELETE)) {
2208         goto Bad_Rename;
2209     }
2210     if (errorCode = CheckWriteMode(newvptr, newrights, PRSFS_INSERT)) {
2211         goto Bad_Rename;
2212     }
2213
2214     /* The CopyOnWrite might return ENOSPC ( disk full). Even if the second
2215     *  call to CopyOnWrite returns error, it is not necessary to revert back
2216     *  the effects of the first call because the contents of the volume is 
2217     *  not modified, it is only replicated.
2218     */
2219     if (oldvptr->disk.cloned)
2220     {
2221         ViceLog(25, ("Rename : calling CopyOnWrite on  old dir\n"));
2222          if ( errorCode = CopyOnWrite(oldvptr, volptr) )
2223                 goto Bad_Rename;
2224     }
2225     SetDirHandle(&olddir, oldvptr);
2226     if (newvptr->disk.cloned)
2227     {
2228         ViceLog(25, ("Rename : calling CopyOnWrite on  new dir\n"));
2229         if ( errorCode = CopyOnWrite(newvptr, volptr) )
2230                 goto Bad_Rename;        
2231     }
2232
2233     SetDirHandle(&newdir, newvptr);
2234
2235     /* Lookup the file to delete its vnode */
2236     if (Lookup(&olddir, OldName, &fileFid)) {
2237         errorCode = ENOENT;
2238         goto Bad_Rename;
2239     }
2240     if (fileFid.Vnode == oldvptr->vnodeNumber ||
2241         fileFid.Vnode == newvptr->vnodeNumber) {
2242         errorCode = FSERR_ELOOP;
2243         goto Bad_Rename;
2244     }
2245     fileFid.Volume = V_id(volptr);
2246     fileptr = VGetVnode(&errorCode, volptr, fileFid.Vnode, WRITE_LOCK);
2247     if (errorCode != 0) {
2248         ViceLog (0, ("SAFSS_Rename(): Error in VGetVnode() for old file %s, code %d\n", OldName, errorCode));
2249         VTakeOffline (volptr);
2250         goto Bad_Rename;
2251     }
2252     if (fileptr->disk.uniquifier != fileFid.Unique) {
2253         ViceLog (0, ("SAFSS_Rename(): Old file %s uniquifier mismatch\n", OldName));
2254         VTakeOffline (volptr);
2255         errorCode = EIO;
2256         goto Bad_Rename;
2257     }
2258
2259     if (fileptr->disk.type != vDirectory &&
2260         oldvptr != newvptr &&
2261         fileptr->disk.linkCount != 1) {
2262         /*
2263          * Hard links exist to this file - cannot move one of the links to
2264          * a new directory because of AFS restrictions (this is the same
2265          * reason that links cannot be made across directories, i.e.
2266          * access lists)
2267          */
2268         errorCode = EXDEV;
2269         goto Bad_Rename;
2270     }
2271
2272     /* Lookup the new file  */
2273     if (!(Lookup(&newdir, NewName, &newFileFid))) {
2274         if (!(newrights & PRSFS_DELETE)) {
2275             errorCode = EACCES;
2276             goto Bad_Rename;
2277         }
2278         if (newFileFid.Vnode == oldvptr->vnodeNumber ||
2279                 newFileFid.Vnode == newvptr->vnodeNumber ||
2280                 newFileFid.Vnode == fileFid.Vnode) {
2281             errorCode = EINVAL;
2282             goto Bad_Rename;
2283         }
2284         newFileFid.Volume = V_id(volptr);
2285         newfileptr = VGetVnode(&errorCode, volptr, newFileFid.Vnode, WRITE_LOCK);
2286         if (errorCode != 0) {
2287             ViceLog (0, ("SAFSS_Rename(): Error in VGetVnode() for new file %s, code %d\n", NewName, errorCode));
2288             VTakeOffline (volptr);
2289             goto Bad_Rename;
2290         }
2291         if (fileptr->disk.uniquifier != fileFid.Unique) {
2292             ViceLog (0, ("SAFSS_Rename(): New file %s uniquifier mismatch\n", NewName));
2293             VTakeOffline (volptr);
2294             errorCode = EIO;
2295             goto Bad_Rename;
2296         }
2297         SetDirHandle(&newfiledir, newfileptr);
2298         /* Now check that we're moving directories over directories properly, etc.
2299          * return proper POSIX error codes:
2300          * if fileptr is a file and new is a dir: EISDIR.
2301          * if fileptr is a dir and new is a file: ENOTDIR.
2302          * Also, dir to be removed must be empty, of course.
2303          */
2304         if (newfileptr->disk.type == vDirectory) {
2305             if (fileptr->disk.type != vDirectory) {
2306                 errorCode = EISDIR;
2307                 goto Bad_Rename;
2308             }
2309             if ((IsEmpty(&newfiledir))) {
2310                 errorCode = EEXIST;
2311                 goto Bad_Rename;
2312             }
2313         }
2314         else {
2315             if (fileptr->disk.type == vDirectory) {
2316                 errorCode = ENOTDIR;
2317                 goto Bad_Rename;
2318             }
2319         }
2320     }
2321
2322     /*
2323      * ok - now we check that the old name is not above new name in the
2324      * directory structure.  This is to prevent removing a subtree alltogether
2325      */
2326     if ((oldvptr != newvptr) && (fileptr->disk.type == vDirectory)) {
2327         for (testnode = newvptr->disk.parent; testnode != 0;) {
2328             if (testnode == oldvptr->vnodeNumber) {
2329                 testnode = oldvptr->disk.parent;
2330                 continue;
2331             }
2332             if ((testnode == fileptr->vnodeNumber) ||
2333                 (testnode == newvptr->vnodeNumber)) {
2334                 errorCode = FSERR_ELOOP;
2335                 goto Bad_Rename;
2336             }
2337             if ((newfileptr) && (testnode == newfileptr->vnodeNumber)) {
2338                 errorCode = FSERR_ELOOP;
2339                 goto Bad_Rename;
2340             }
2341             testvptr = VGetVnode(&errorCode, volptr, testnode, READ_LOCK);
2342             assert(errorCode == 0);
2343             testnode = testvptr->disk.parent;
2344             VPutVnode(&errorCode, testvptr);
2345             assert(errorCode == 0);
2346         }
2347     }
2348     /* Do the CopyonWrite first before modifying anything else. Copying is
2349      *  required because we may have to change entries for .. 
2350      */
2351     if ((fileptr->disk.type == vDirectory ) && (fileptr->disk.cloned) )
2352     {
2353         ViceLog(25, ("Rename : calling CopyOnWrite on  target dir\n"));
2354         if ( errorCode = CopyOnWrite(fileptr, volptr) )
2355                 goto Bad_Rename;
2356     }
2357
2358     /* If the new name exists already, delete it and the file it points to */
2359     doDelete = 0;
2360     if (newfileptr) {
2361         /* Delete NewName from its directory */
2362         code = Delete(&newdir, NewName);
2363         assert(code == 0);
2364
2365         /* Drop the link count */
2366         newfileptr->disk.linkCount--;
2367         if (newfileptr->disk.linkCount == 0) {      /* Link count 0 - delete */
2368             VAdjustDiskUsage(&errorCode, volptr,
2369                              -(int)nBlocks(newfileptr->disk.length), 0);
2370             if (VN_GET_INO(newfileptr)) {
2371                 IH_REALLYCLOSE(newfileptr->handle);
2372                 errorCode = IH_DEC(V_linkHandle(volptr),
2373                                  VN_GET_INO(newfileptr),
2374                                  V_parentId(volptr));
2375                 IH_RELEASE(newfileptr->handle);
2376                 if (errorCode == -1) {
2377                     ViceLog(0, ("Del: inode=%d, name=%s, errno=%d\n",
2378                                 PrintInode(NULL, VN_GET_INO(newfileptr)),
2379                                 NewName, errno));
2380                     if ((errno != ENOENT) && (errno != EIO) && (errno != ENXIO))
2381                         ViceLog(0, ("Do we need to fsck?"));
2382                 } 
2383             }
2384             VN_SET_INO(newfileptr, (Inode)0);
2385             newfileptr->delete = 1;         /* Mark NewName vnode to delete */
2386             doDelete = 1;
2387         } else {
2388             /* Link count did not drop to zero.
2389              * Mark NewName vnode as changed - updates stime.
2390              */
2391             newfileptr->changed_newTime = 1;
2392         }
2393     }
2394     
2395     /*
2396      * If the create below fails, and the delete above worked, we have
2397      * removed the new name and not replaced it.  This is not very likely,
2398      * but possible.  We could try to put the old file back, but it is
2399      * highly unlikely that it would work since it would involve issuing
2400      * another create.
2401      */
2402     if (errorCode = Create(&newdir,(char *) NewName, &fileFid))
2403         goto Bad_Rename;
2404
2405     /* Delete the old name */
2406     assert(Delete(&olddir,(char *) OldName) == 0);
2407
2408     /* if the directory length changes, reflect it in the statistics */
2409 #if FS_STATS_DETAILED
2410     Update_ParentVnodeStatus(oldvptr, volptr, &olddir, client->ViceId,
2411                              oldvptr->disk.linkCount, client->InSameNetwork);
2412     Update_ParentVnodeStatus(newvptr, volptr, &newdir, client->ViceId,
2413                              newvptr->disk.linkCount, client->InSameNetwork);
2414 #else
2415     Update_ParentVnodeStatus(oldvptr, volptr, &olddir, client->ViceId,
2416                              oldvptr->disk.linkCount);
2417     Update_ParentVnodeStatus(newvptr, volptr, &newdir, client->ViceId,
2418                              newvptr->disk.linkCount);
2419 #endif /* FS_STATS_DETAILED */
2420
2421     if (oldvptr == newvptr)
2422         oldvptr->disk.dataVersion--;    /* Since it was bumped by 2! */
2423
2424     fileptr->disk.parent = newvptr->vnodeNumber;
2425     fileptr->changed_newTime = 1;       /* status change of moved file */
2426
2427     /* if we are dealing with a rename of a directory */
2428     if (fileptr->disk.type == vDirectory) {
2429         assert(!fileptr->disk.cloned);          
2430         SetDirHandle(&filedir, fileptr);
2431         /* fix .. to point to the correct place */
2432         Delete(&filedir, ".."); /* No assert--some directories may be bad */
2433         assert(Create(&filedir, "..", NewDirFid) == 0);
2434         fileptr->disk.dataVersion++;
2435         /* if the parent directories are different the link counts have to be   */
2436         /* changed due to .. in the renamed directory */
2437         if (oldvptr != newvptr) {
2438             oldvptr->disk.linkCount--;
2439             newvptr->disk.linkCount++;
2440         }
2441     }
2442
2443     /* set up return status */
2444     GetStatus(oldvptr, OutOldDirStatus, rights, anyrights, (struct vnode *)0);
2445     GetStatus(newvptr, OutNewDirStatus, newrights, newanyrights, (struct vnode *)0);
2446     if (newfileptr && doDelete) {
2447         DeleteFileCallBacks(&newFileFid);       /* no other references */
2448     }
2449
2450     DFlush();
2451
2452     /* convert the write locks to a read locks before breaking callbacks */
2453     VVnodeWriteToRead(&errorCode, newvptr);
2454     assert(!errorCode || errorCode == VSALVAGE);
2455     if (oldvptr != newvptr) {
2456         VVnodeWriteToRead(&errorCode, oldvptr);
2457         assert(!errorCode || errorCode == VSALVAGE);
2458     }
2459     if (newfileptr && !doDelete) {
2460         /* convert the write lock to a read lock before breaking callbacks */
2461         VVnodeWriteToRead(&errorCode, newfileptr);
2462         assert(!errorCode || errorCode == VSALVAGE);
2463     }
2464
2465     /* break call back on NewDirFid, OldDirFid, NewDirFid and newFileFid  */
2466     BreakCallBack(client->host, NewDirFid, 0);
2467     if (oldvptr != newvptr) {
2468         BreakCallBack(client->host, OldDirFid, 0);
2469         if (fileptr->disk.type == vDirectory) /* if a dir moved, .. changed */
2470             BreakCallBack(client->host, &fileFid, 0);
2471     }
2472     if (newfileptr) {
2473         /* Note:  it is not necessary to break the callback */
2474         if (doDelete)
2475             DeleteFileCallBacks(&newFileFid);   /* no other references */
2476         else
2477             /* other's still exist (with wrong link count) */
2478             BreakCallBack(client->host, &newFileFid, 1);
2479     }
2480
2481 Bad_Rename: 
2482     if (newfileptr) {
2483         VPutVnode(&fileCode, newfileptr);
2484         assert(fileCode == 0);
2485     }
2486     PutVolumePackage(fileptr, (newvptr && newvptr != oldvptr? newvptr : 0),
2487                      oldvptr, volptr);
2488     ViceLog(2, ("SAFS_Rename returns %d\n", errorCode));
2489     return errorCode;
2490
2491 } /*SAFSS_Rename*/
2492
2493
2494 SRXAFS_Rename (tcon, OldDirFid, OldName, NewDirFid, NewName, OutOldDirStatus, OutNewDirStatus, Sync)
2495     struct AFSVolSync *Sync;
2496     struct rx_connection *tcon;              /* Rx connection handle */
2497     struct AFSFid *OldDirFid;                /* From parent dir's fid */
2498     char *OldName;                           /* From file name */
2499     struct AFSFid *NewDirFid;                /* To parent dir's fid */
2500     char *NewName;                           /* To new file name */
2501     struct AFSFetchStatus *OutOldDirStatus;  /* Output status for From parent dir */
2502     struct AFSFetchStatus *OutNewDirStatus;  /* Output status for To parent dir */
2503
2504 {
2505     afs_int32 code;
2506     struct rx_call *tcall = (struct rx_call *) tcon; 
2507 #if FS_STATS_DETAILED
2508     struct fs_stats_opTimingData *opP;      /* Ptr to this op's timing struct */
2509     struct timeval opStartTime,
2510                    opStopTime;              /* Start/stop times for RPC op*/
2511     struct timeval elapsedTime;             /* Transfer time */
2512
2513     /*
2514      * Set our stats pointer, remember when the RPC operation started, and
2515      * tally the operation.
2516      */
2517     opP = &(afs_FullPerfStats.det.rpcOpTimes[FS_STATS_RPCIDX_RENAME]);
2518     FS_LOCK
2519     (opP->numOps)++;
2520     FS_UNLOCK
2521     TM_GetTimeOfDay(&opStartTime, 0);
2522 #endif /* FS_STATS_DETAILED */
2523
2524     if (code = CallPreamble((struct rx_call **) &tcon, ACTIVECALL))
2525         goto Bad_Rename;
2526
2527     code = SAFSS_Rename (tcon, OldDirFid, OldName, NewDirFid, NewName,
2528                          OutOldDirStatus, OutNewDirStatus, Sync);
2529
2530 Bad_Rename:    
2531     CallPostamble(tcon);
2532
2533 #if FS_STATS_DETAILED
2534     TM_GetTimeOfDay(&opStopTime, 0);
2535     if (code == 0) {
2536       FS_LOCK
2537       (opP->numSuccesses)++;
2538       fs_stats_GetDiff(elapsedTime, opStartTime, opStopTime);
2539       fs_stats_AddTo((opP->sumTime), elapsedTime);
2540       fs_stats_SquareAddTo((opP->sqrTime), elapsedTime);
2541       if (fs_stats_TimeLessThan(elapsedTime, (opP->minTime))) {
2542         fs_stats_TimeAssign((opP->minTime), elapsedTime);
2543       }
2544       if (fs_stats_TimeGreaterThan(elapsedTime, (opP->maxTime))) {
2545         fs_stats_TimeAssign((opP->maxTime), elapsedTime);
2546       }
2547       FS_UNLOCK
2548     }
2549
2550 #endif /* FS_STATS_DETAILED */
2551
2552     osi_auditU (tcall, RenameFileEvent, code, AUD_FID, OldDirFid, AUD_STR, OldName, AUD_FID, NewDirFid, AUD_STR, NewName, AUD_END);
2553     return code;
2554
2555 } /*SRXAFS_Rename*/
2556
2557
2558 /*
2559  * This routine is called exclusively by SRXAFS_Symlink(), and should be
2560  * merged into it when possible.
2561  */
2562 SAFSS_Symlink (tcon, DirFid, Name, LinkContents, InStatus, OutFid, OutFidStatus, OutDirStatus, Sync)
2563     struct rx_connection *tcon;          /* Rx connection handle */
2564     struct AFSFid *DirFid;               /* Parent dir's fid */
2565     char *Name;                          /* File name to create */
2566     char *LinkContents;                  /* Contents of the new created file */
2567     struct AFSStoreStatus *InStatus;     /* Input status for the new symbolic link */
2568     struct AFSFid *OutFid;               /* Fid for newly created symbolic link */
2569     struct AFSFetchStatus *OutFidStatus; /* Output status for new symbolic link */
2570     struct AFSFetchStatus *OutDirStatus; /* Output status for parent dir */
2571     struct AFSVolSync *Sync;             /* volume synchronization information */
2572
2573 {
2574     Vnode * parentptr = 0;              /* vnode of input Directory */
2575     Vnode * targetptr = 0;              /* vnode of the new link */
2576     Vnode * parentwhentargetnotdir = 0; /* parent for use in SetAccessList */
2577     int     errorCode = 0;              /* error code */
2578     int code = 0;
2579     DirHandle dir;                      /* Handle for dir package I/O */
2580     Volume * volptr = 0;                /* pointer to the volume header */
2581     struct client * client;             /* pointer to client structure */
2582     afs_int32 rights, anyrights, fd;    /* rights for this and any user */
2583     struct client *t_client;            /* tmp ptr to client data */
2584     struct in_addr logHostAddr;         /* host ip holder for inet_ntoa */
2585     FdHandle_t *fdP;
2586
2587     /* Get ptr to client data for user Id for logging */
2588     t_client = (struct client *) rx_GetSpecific(tcon, rxcon_client_key); 
2589     logHostAddr.s_addr =  rx_HostOf(rx_PeerOf(tcon));
2590     ViceLog(1, ("SAFS_Symlink %s to %s,  Did = %u.%d.%d, Host %s, Id %d\n", Name,
2591             LinkContents, DirFid->Volume, DirFid->Vnode, DirFid->Unique,
2592             inet_ntoa(logHostAddr), t_client->ViceId));
2593     FS_LOCK
2594     AFSCallStats.Symlink++, AFSCallStats.TotalCalls++;
2595     FS_UNLOCK
2596     if (!FileNameOK(Name)) {
2597         errorCode = EINVAL;
2598         goto Bad_SymLink;
2599     }
2600
2601     /*
2602      * Get the vnode and volume for the parent dir along with the caller's
2603      * rights to it
2604      */
2605     if (errorCode = GetVolumePackage(tcon, DirFid, &volptr, &parentptr,
2606                                      MustBeDIR, &parentwhentargetnotdir,
2607                                      &client, WRITE_LOCK, &rights, &anyrights)) {
2608         goto Bad_SymLink;
2609     }
2610
2611     /* set volume synchronization information */
2612     SetVolumeSync(Sync, volptr);
2613
2614     /* Does the caller has insert (and write) access to the parent directory? */
2615     if (errorCode = CheckWriteMode(parentptr, rights, PRSFS_INSERT)) {
2616         goto Bad_SymLink;
2617     }
2618
2619     /*
2620      * If we're creating a mount point (any x bits clear), we must have
2621      * administer access to the directory, too.  Always allow sysadmins
2622      * to do this.
2623      */
2624     if ((InStatus->Mask & AFS_SETMODE) && !(InStatus->UnixModeBits & 0111)) {
2625         /*
2626          * We have a mountpoint, 'cause we're trying to set the Unix mode
2627          * bits to something with some x bits missing (default mode bits
2628          * if AFS_SETMODE is false is 0777)
2629          */
2630         if (VanillaUser(client) && !(rights & PRSFS_ADMINISTER)) {
2631             errorCode = EACCES;
2632             goto Bad_SymLink;
2633         }
2634     }
2635  
2636     /* get a new vnode for the symlink and set it up */
2637     if (errorCode = Alloc_NewVnode(parentptr, &dir, volptr, &targetptr,
2638                                    Name, OutFid, vSymlink,
2639                                    nBlocks(strlen((char *) LinkContents)))) {
2640         goto Bad_SymLink;
2641     }
2642
2643     /* update the status of the parent vnode */
2644 #if FS_STATS_DETAILED
2645     Update_ParentVnodeStatus(parentptr, volptr, &dir, client->ViceId,
2646                              parentptr->disk.linkCount, client->InSameNetwork);
2647 #else
2648     Update_ParentVnodeStatus(parentptr, volptr, &dir, client->ViceId,
2649                              parentptr->disk.linkCount);
2650 #endif /* FS_STATS_DETAILED */
2651
2652     /* update the status of the new symbolic link file vnode */
2653     Update_TargetVnodeStatus(targetptr, TVS_SLINK, client, InStatus, parentptr,
2654                              volptr, strlen((char *)LinkContents));
2655
2656     /* Write the contents of the symbolic link name into the target inode */
2657     fdP = IH_OPEN(targetptr->handle);
2658     assert(fdP != NULL);
2659     assert(FDH_WRITE(fdP, (char *) LinkContents, strlen((char *) LinkContents)) == strlen((char *) LinkContents));
2660     FDH_CLOSE(fdP);
2661     /*
2662      * Set up and return modified status for the parent dir and new symlink
2663      * to caller.
2664      */
2665     GetStatus(targetptr, OutFidStatus, rights, anyrights, parentptr);
2666     GetStatus(parentptr, OutDirStatus, rights, anyrights, (struct vnode *)0);
2667
2668     /* convert the write lock to a read lock before breaking callbacks */
2669     VVnodeWriteToRead(&errorCode, parentptr);
2670     assert(!errorCode || errorCode == VSALVAGE);
2671
2672     /* break call back on the parent dir */
2673     BreakCallBack(client->host, DirFid, 0);
2674
2675 Bad_SymLink: 
2676     /* Write the all modified vnodes (parent, new files) and volume back */
2677     PutVolumePackage(parentwhentargetnotdir, targetptr, parentptr, volptr);
2678     ViceLog(2, ("SAFS_Symlink returns %d\n", errorCode));
2679     return errorCode;
2680
2681 } /*SAFSS_Symlink*/
2682
2683
2684 SRXAFS_Symlink (tcon, DirFid, Name, LinkContents, InStatus, OutFid, OutFidStatus, OutDirStatus, Sync)
2685     struct AFSVolSync *Sync;
2686     struct rx_connection *tcon;          /* Rx connection handle */
2687     struct AFSFid *DirFid;               /* Parent dir's fid */
2688     char *Name;                          /* File name to create */
2689     char *LinkContents;                  /* Contents of the new created file */
2690     struct AFSStoreStatus *InStatus;     /* Input status for the new symbolic link */
2691     struct AFSFid *OutFid;               /* Fid for newly created symbolic link */
2692     struct AFSFetchStatus *OutFidStatus; /* Output status for new symbolic link */
2693     struct AFSFetchStatus *OutDirStatus; /* Output status for parent dir */
2694
2695 {
2696     afs_int32 code;
2697     struct rx_call *tcall = (struct rx_call *) tcon; 
2698 #if FS_STATS_DETAILED
2699     struct fs_stats_opTimingData *opP;      /* Ptr to this op's timing struct */
2700     struct timeval opStartTime,
2701                    opStopTime;              /* Start/stop times for RPC op*/
2702     struct timeval elapsedTime;             /* Transfer time */
2703
2704     /*
2705      * Set our stats pointer, remember when the RPC operation started, and
2706      * tally the operation.
2707      */
2708     opP = &(afs_FullPerfStats.det.rpcOpTimes[FS_STATS_RPCIDX_SYMLINK]);
2709     FS_LOCK
2710     (opP->numOps)++;
2711     FS_UNLOCK
2712     TM_GetTimeOfDay(&opStartTime, 0);
2713 #endif /* FS_STATS_DETAILED */
2714
2715     if (code = CallPreamble((struct rx_call **) &tcon, ACTIVECALL))
2716         goto Bad_Symlink;
2717
2718     code = SAFSS_Symlink (tcon, DirFid, Name, LinkContents, InStatus, OutFid,
2719                          OutFidStatus, OutDirStatus, Sync);
2720
2721 Bad_Symlink:    
2722     CallPostamble(tcon);
2723
2724 #if FS_STATS_DETAILED
2725     TM_GetTimeOfDay(&opStopTime, 0);
2726     if (code == 0) {
2727       FS_LOCK
2728       (opP->numSuccesses)++;
2729       fs_stats_GetDiff(elapsedTime, opStartTime, opStopTime);
2730       fs_stats_AddTo((opP->sumTime), elapsedTime);
2731       fs_stats_SquareAddTo((opP->sqrTime), elapsedTime);
2732       if (fs_stats_TimeLessThan(elapsedTime, (opP->minTime))) {
2733         fs_stats_TimeAssign((opP->minTime), elapsedTime);
2734       }
2735       if (fs_stats_TimeGreaterThan(elapsedTime, (opP->maxTime))) {
2736         fs_stats_TimeAssign((opP->maxTime), elapsedTime);
2737       }
2738       FS_UNLOCK
2739     }
2740
2741 #endif /* FS_STATS_DETAILED */
2742
2743     osi_auditU (tcall, SymlinkEvent, code, AUD_FID, DirFid, AUD_STR, Name, AUD_END);
2744     return code;
2745
2746 } /*SRXAFS_Symlink*/
2747
2748
2749 /*
2750  * This routine is called exclusively by SRXAFS_Link(), and should be
2751  * merged into it when possible.
2752  */
2753 SAFSS_Link (tcon, DirFid, Name, ExistingFid, OutFidStatus, OutDirStatus, Sync)
2754     struct rx_connection *tcon;          /* Rx connection handle */
2755     struct AFSFid *DirFid;               /* Parent dir's fid */
2756     char *Name;                          /* File name to create */
2757     struct AFSFid *ExistingFid;          /* Fid of existing fid we'll make link to */
2758     struct AFSFetchStatus *OutFidStatus; /* Output status for newly created file */
2759     struct AFSFetchStatus *OutDirStatus; /* Outpout status for parent dir */
2760     struct AFSVolSync *Sync;
2761
2762 {
2763     Vnode * parentptr = 0;              /* vnode of input Directory */
2764     Vnode * targetptr = 0;              /* vnode of the new file */
2765     Vnode * parentwhentargetnotdir = 0; /* parent for use in SetAccessList */
2766     Volume * volptr = 0;                /* pointer to the volume header */
2767     int     errorCode = 0;              /* error code */
2768     DirHandle dir;                      /* Handle for dir package I/O */
2769     struct client * client;             /* pointer to client structure */
2770     afs_int32 rights, anyrights;                /* rights for this and any user */
2771     struct client *t_client;            /* tmp ptr to client data */
2772     struct in_addr logHostAddr;         /* host ip holder for inet_ntoa */
2773
2774     /* Get ptr to client data for user Id for logging */
2775     t_client = (struct client *) rx_GetSpecific(tcon, rxcon_client_key); 
2776     logHostAddr.s_addr =  rx_HostOf(rx_PeerOf(tcon));
2777     ViceLog(1, ("SAFS_Link %s,  Did = %u.%d.%d, Fid = %u.%d.%d, Host %s, Id %d\n",
2778             Name, DirFid->Volume, DirFid->Vnode, DirFid->Unique,
2779             ExistingFid->Volume, ExistingFid->Vnode, ExistingFid->Unique,
2780             inet_ntoa(logHostAddr), t_client->ViceId));
2781     FS_LOCK
2782     AFSCallStats.Link++, AFSCallStats.TotalCalls++;
2783     FS_UNLOCK
2784     if (DirFid->Volume != ExistingFid->Volume) {
2785         errorCode = EXDEV;
2786         goto Bad_Link;
2787     }
2788     if (!FileNameOK(Name)) {
2789         errorCode = EINVAL;
2790         goto Bad_Link;
2791     }
2792
2793     /*
2794      * Get the vnode and volume for the parent dir along with the caller's
2795      * rights to it
2796      */
2797     if (errorCode = GetVolumePackage(tcon, DirFid, &volptr, &parentptr,
2798                                      MustBeDIR, &parentwhentargetnotdir,
2799                                      &client, WRITE_LOCK, &rights, &anyrights)) {
2800         goto Bad_Link;
2801     }
2802
2803     /* set volume synchronization information */
2804     SetVolumeSync(Sync, volptr);
2805
2806     /* Can the caller insert into the parent directory? */
2807     if (errorCode = CheckWriteMode(parentptr, rights, PRSFS_INSERT)) {
2808         goto Bad_Link;
2809     }
2810
2811     if (((DirFid->Vnode & 1) && (ExistingFid->Vnode & 1)) ||
2812         (DirFid->Vnode == ExistingFid->Vnode)) {  /* at present, */
2813       /* AFS fileservers always have directory vnodes that are odd.   */
2814       errorCode = EISDIR;
2815       goto Bad_Link;
2816     }
2817
2818     /* get the file vnode  */
2819     if (errorCode = CheckVnode(ExistingFid, &volptr, &targetptr, WRITE_LOCK)) {
2820         goto Bad_Link;
2821     }
2822     if (targetptr->disk.type != vFile) {
2823         errorCode = EISDIR;
2824         goto Bad_Link;
2825     }
2826     if (targetptr->disk.parent != DirFid->Vnode) {
2827         errorCode = EXDEV;
2828         goto Bad_Link;
2829     }
2830     if (parentptr->disk.cloned) 
2831     {
2832         ViceLog(25, ("Link : calling CopyOnWrite on  target dir\n"));
2833         if ( errorCode = CopyOnWrite(parentptr, volptr))
2834                 goto Bad_Link;          /* disk full error */
2835     }
2836
2837     /* add the name to the directory */
2838     SetDirHandle(&dir, parentptr);
2839     if (errorCode = Create(&dir, (char *)Name, ExistingFid))
2840         goto Bad_Link;
2841     DFlush();
2842
2843     /* update the status in the parent vnode */
2844     /**WARNING** --> disk.author SHOULDN'T be modified???? */
2845 #if FS_STATS_DETAILED
2846     Update_ParentVnodeStatus(parentptr, volptr, &dir, client->ViceId,
2847                              parentptr->disk.linkCount, client->InSameNetwork);
2848 #else
2849     Update_ParentVnodeStatus(parentptr, volptr, &dir, client->ViceId,
2850                              parentptr->disk.linkCount);
2851 #endif /* FS_STATS_DETAILED */
2852
2853     targetptr->disk.linkCount++;
2854     targetptr->disk.author = client->ViceId;
2855     targetptr->changed_newTime = 1; /* Status change of linked-to file */
2856
2857     /* set up return status */
2858     GetStatus(targetptr, OutFidStatus, rights, anyrights, parentptr);
2859     GetStatus(parentptr, OutDirStatus, rights, anyrights, (struct vnode *)0);
2860
2861     /* convert the write locks to read locks before breaking callbacks */
2862     VVnodeWriteToRead(&errorCode, targetptr);
2863     assert(!errorCode || errorCode == VSALVAGE);
2864     VVnodeWriteToRead(&errorCode, parentptr);
2865     assert(!errorCode || errorCode == VSALVAGE);
2866     
2867     /* break call back on DirFid */
2868     BreakCallBack(client->host, DirFid, 0);
2869     /*
2870      * We also need to break the callback for the file that is hard-linked since part 
2871      * of its status (like linkcount) is changed
2872      */
2873     BreakCallBack(client->host, ExistingFid, 0);
2874
2875 Bad_Link:
2876     /* Write the all modified vnodes (parent, new files) and volume back */
2877     PutVolumePackage(parentwhentargetnotdir, targetptr, parentptr, volptr);
2878     ViceLog(2, ("SAFS_Link returns %d\n", errorCode));
2879     return errorCode;
2880
2881 } /*SAFSS_Link*/
2882
2883
2884 SRXAFS_Link (tcon, DirFid, Name, ExistingFid, OutFidStatus, OutDirStatus, Sync)
2885     struct AFSVolSync *Sync;
2886     struct rx_connection *tcon;          /* Rx connection handle */
2887     struct AFSFid *DirFid;               /* Parent dir's fid */
2888     char *Name;                          /* File name to create */
2889     struct AFSFid *ExistingFid;          /* Fid of existing fid we'll make link to */
2890     struct AFSFetchStatus *OutFidStatus; /* Output status for newly created file */
2891     struct AFSFetchStatus *OutDirStatus; /* Outpout status for parent dir */
2892
2893 {
2894     afs_int32 code;
2895     struct rx_call *tcall = (struct rx_call *) tcon; 
2896 #if FS_STATS_DETAILED
2897     struct fs_stats_opTimingData *opP;      /* Ptr to this op's timing struct */
2898     struct timeval opStartTime,
2899                    opStopTime;              /* Start/stop times for RPC op*/
2900     struct timeval elapsedTime;             /* Transfer time */
2901
2902     /*
2903      * Set our stats pointer, remember when the RPC operation started, and
2904      * tally the operation.
2905      */
2906     opP = &(afs_FullPerfStats.det.rpcOpTimes[FS_STATS_RPCIDX_LINK]);
2907     FS_LOCK
2908     (opP->numOps)++;
2909     FS_UNLOCK
2910     TM_GetTimeOfDay(&opStartTime, 0);
2911 #endif /* FS_STATS_DETAILED */
2912
2913     if (code = CallPreamble((struct rx_call **) &tcon, ACTIVECALL))
2914         goto Bad_Link;
2915
2916     code = SAFSS_Link (tcon, DirFid, Name, ExistingFid, OutFidStatus,
2917                       OutDirStatus, Sync);
2918     
2919 Bad_Link:
2920     CallPostamble(tcon);
2921
2922 #if FS_STATS_DETAILED
2923     TM_GetTimeOfDay(&opStopTime, 0);
2924     if (code == 0) {
2925       FS_LOCK
2926       (opP->numSuccesses)++;
2927       fs_stats_GetDiff(elapsedTime, opStartTime, opStopTime);
2928       fs_stats_AddTo((opP->sumTime), elapsedTime);
2929       fs_stats_SquareAddTo((opP->sqrTime), elapsedTime);
2930       if (fs_stats_TimeLessThan(elapsedTime, (opP->minTime))) {
2931         fs_stats_TimeAssign((opP->minTime), elapsedTime);
2932       }
2933       if (fs_stats_TimeGreaterThan(elapsedTime, (opP->maxTime))) {
2934         fs_stats_TimeAssign((opP->maxTime), elapsedTime);
2935       }
2936       FS_UNLOCK
2937     }
2938
2939 #endif /* FS_STATS_DETAILED */
2940
2941     osi_auditU (tcall, LinkEvent, code, AUD_FID, DirFid, AUD_STR, Name, AUD_FID, ExistingFid, AUD_END);
2942     return code;
2943
2944 } /*SRXAFS_Link*/
2945
2946
2947 /*
2948  * This routine is called exclusively by SRXAFS_MakeDir(), and should be
2949  * merged into it when possible.
2950  */
2951 SAFSS_MakeDir (tcon, DirFid, Name, InStatus, OutFid, OutFidStatus,
2952               OutDirStatus, CallBack, Sync)
2953     struct rx_connection *tcon;          /* Rx connection handle */
2954     struct AFSFid *DirFid;               /* Parent dir's fid */
2955     char *Name;                          /* Name of dir to be created */
2956     struct AFSStoreStatus *InStatus;     /* Input status for new dir */
2957     struct AFSFid *OutFid;               /* Fid of new dir */
2958     struct AFSFetchStatus *OutFidStatus; /* Output status for new directory */
2959     struct AFSFetchStatus *OutDirStatus; /* Output status for parent dir */
2960     struct AFSCallBack *CallBack;        /* Returned callback promise for new dir */
2961     struct AFSVolSync *Sync;
2962
2963 {
2964     Vnode * parentptr = 0;              /* vnode of input Directory */
2965     Vnode * targetptr = 0;              /* vnode of the new file */
2966     Vnode * parentwhentargetnotdir = 0; /* parent for use in SetAccessList */
2967     Volume * volptr = 0;                /* pointer to the volume header */
2968     int     errorCode = 0;              /* error code */
2969     struct acl_accessList * newACL;     /* Access list */
2970     int     newACLSize;                 /* Size of access list */
2971     DirHandle dir;                      /* Handle for dir package I/O */
2972     DirHandle parentdir;                /* Handle for dir package I/O */
2973     struct client * client;             /* pointer to client structure */
2974     afs_int32 rights, anyrights;                /* rights for this and any user */
2975     struct client *t_client;            /* tmp ptr to client data */
2976     struct in_addr logHostAddr;         /* host ip holder for inet_ntoa */
2977
2978     /* Get ptr to client data for user Id for logging */
2979     t_client = (struct client *) rx_GetSpecific(tcon, rxcon_client_key); 
2980     logHostAddr.s_addr =  rx_HostOf(rx_PeerOf(tcon));
2981     ViceLog(1, ("SAFS_MakeDir %s,  Did = %u.%d.%d, Host %s, Id %d\n",
2982             Name, DirFid->Volume, DirFid->Vnode, DirFid->Unique,
2983             inet_ntoa(logHostAddr), t_client->ViceId));
2984     FS_LOCK
2985     AFSCallStats.MakeDir++, AFSCallStats.TotalCalls++;    
2986     FS_UNLOCK
2987     if (!FileNameOK(Name)) {
2988         errorCode = EINVAL;
2989         goto Bad_MakeDir;
2990     }
2991
2992     /*
2993      * Get the vnode and volume for the parent dir along with the caller's
2994      * rights to it.
2995      */
2996     if (errorCode = GetVolumePackage(tcon, DirFid, &volptr, &parentptr,
2997                                      MustBeDIR, &parentwhentargetnotdir,
2998                                      &client, WRITE_LOCK, &rights, &anyrights)) {
2999         goto Bad_MakeDir;
3000     }
3001  
3002     /* set volume synchronization information */
3003     SetVolumeSync(Sync, volptr);
3004
3005     /* Write access to the parent directory? */
3006 #ifdef DIRCREATE_NEED_WRITE
3007     /*
3008      * requires w access for the user to create a directory. this
3009      * closes a loophole in the current security arrangement, since a
3010      * user with i access only can create a directory and get the
3011      * implcit a access that goes with dir ownership, and proceed to 
3012      * subvert quota in the volume.
3013      */
3014     if ((errorCode = CheckWriteMode(parentptr, rights, PRSFS_INSERT)) ||
3015         (errorCode = CheckWriteMode(parentptr, rights, PRSFS_WRITE))) {
3016 #else 
3017     if (errorCode = CheckWriteMode(parentptr, rights, PRSFS_INSERT)) {
3018 #endif /* DIRCREATE_NEED_WRITE */ 
3019         goto Bad_MakeDir;
3020     }
3021
3022 #define EMPTYDIRBLOCKS 2
3023     /* get a new vnode and set it up */
3024     if (errorCode = Alloc_NewVnode(parentptr, &parentdir, volptr, &targetptr,
3025                                    Name, OutFid, vDirectory, EMPTYDIRBLOCKS)) {
3026         goto Bad_MakeDir;
3027     }
3028
3029     /* Update the status for the parent dir */
3030 #if FS_STATS_DETAILED
3031     Update_ParentVnodeStatus(parentptr, volptr, &parentdir, client->ViceId,
3032                              parentptr->disk.linkCount+1, client->InSameNetwork);
3033 #else
3034     Update_ParentVnodeStatus(parentptr, volptr, &parentdir, client->ViceId,
3035                              parentptr->disk.linkCount+1);
3036 #endif /* FS_STATS_DETAILED */
3037
3038     /* Point to target's ACL buffer and copy the parent's ACL contents to it */
3039     assert((SetAccessList(&targetptr, &volptr, &newACL, &newACLSize,
3040                           &parentwhentargetnotdir, (AFSFid *)0, 0)) == 0);
3041     assert(parentwhentargetnotdir == 0);
3042     memcpy((char *)newACL, (char *)VVnodeACL(parentptr), VAclSize(parentptr));
3043
3044     /* update the status for the target vnode */
3045     Update_TargetVnodeStatus(targetptr, TVS_MKDIR, client, InStatus,
3046                              parentptr, volptr, 0);
3047
3048     /* Actually create the New directory in the directory package */
3049     SetDirHandle(&dir, targetptr);
3050     assert(!(MakeDir(&dir, OutFid, DirFid)));
3051     DFlush();
3052     targetptr->disk.length = Length(&dir);
3053
3054     /* set up return status */
3055     GetStatus(targetptr, OutFidStatus, rights, anyrights, parentptr);
3056     GetStatus(parentptr, OutDirStatus, rights, anyrights, (struct Vnode *)0);
3057
3058     /* convert the write lock to a read lock before breaking callbacks */
3059     VVnodeWriteToRead(&errorCode, parentptr);
3060     assert(!errorCode || errorCode == VSALVAGE);
3061
3062     /* break call back on DirFid */
3063     BreakCallBack(client->host, DirFid, 0);
3064
3065     /* Return a callback promise to caller */
3066     SetCallBackStruct(AddCallBack(client->host, OutFid), CallBack);
3067
3068 Bad_MakeDir: 
3069     /* Write the all modified vnodes (parent, new files) and volume back */
3070     PutVolumePackage(parentwhentargetnotdir, targetptr, parentptr, volptr);
3071     ViceLog(2, ("SAFS_MakeDir returns %d\n", errorCode)); 
3072     return errorCode;
3073
3074 } /*SAFSS_MakeDir*/
3075
3076
3077 SRXAFS_MakeDir (tcon, DirFid, Name, InStatus, OutFid, OutFidStatus, OutDirStatus, CallBack, Sync)
3078     struct AFSVolSync *Sync;
3079     struct rx_connection *tcon;          /* Rx connection handle */
3080     struct AFSFid *DirFid;               /* Parent dir's fid */
3081     char *Name;                          /* Name of dir to be created */
3082     struct AFSStoreStatus *InStatus;     /* Input status for new dir */
3083     struct AFSFid *OutFid;               /* Fid of new dir */
3084     struct AFSFetchStatus *OutFidStatus; /* Output status for new directory */
3085     struct AFSFetchStatus *OutDirStatus; /* Output status for parent dir */
3086     struct AFSCallBack *CallBack;        /* Returned callback promise for new dir */
3087
3088 {
3089     afs_int32 code;
3090     struct rx_call *tcall = (struct rx_call *) tcon; 
3091 #if FS_STATS_DETAILED
3092     struct fs_stats_opTimingData *opP;      /* Ptr to this op's timing struct */
3093     struct timeval opStartTime,
3094                    opStopTime;              /* Start/stop times for RPC op*/
3095     struct timeval elapsedTime;             /* Transfer time */
3096
3097     /*
3098      * Set our stats pointer, remember when the RPC operation started, and
3099      * tally the operation.
3100      */
3101     opP = &(afs_FullPerfStats.det.rpcOpTimes[FS_STATS_RPCIDX_MAKEDIR]);
3102     FS_LOCK
3103     (opP->numOps)++;
3104     FS_UNLOCK
3105     TM_GetTimeOfDay(&opStartTime, 0);
3106 #endif /* FS_STATS_DETAILED */
3107     if (code = CallPreamble((struct rx_call **) &tcon, ACTIVECALL))
3108         goto Bad_MakeDir;
3109
3110     code = SAFSS_MakeDir (tcon, DirFid, Name, InStatus, OutFid,
3111                          OutFidStatus, OutDirStatus, CallBack, Sync);
3112     
3113 Bad_MakeDir:
3114     CallPostamble(tcon);
3115
3116 #if FS_STATS_DETAILED
3117     TM_GetTimeOfDay(&opStopTime, 0);
3118     if (code == 0) {
3119       FS_LOCK
3120       (opP->numSuccesses)++;
3121       fs_stats_GetDiff(elapsedTime, opStartTime, opStopTime);
3122       fs_stats_AddTo((opP->sumTime), elapsedTime);
3123       fs_stats_SquareAddTo((opP->sqrTime), elapsedTime);
3124       if (fs_stats_TimeLessThan(elapsedTime, (opP->minTime))) {
3125         fs_stats_TimeAssign((opP->minTime), elapsedTime);
3126       }
3127       if (fs_stats_TimeGreaterThan(elapsedTime, (opP->maxTime))) {
3128         fs_stats_TimeAssign((opP->maxTime), elapsedTime);
3129       }
3130       FS_UNLOCK
3131     }
3132
3133 #endif /* FS_STATS_DETAILED */
3134
3135     osi_auditU (tcall, MakeDirEvent, code, AUD_FID, DirFid, AUD_STR, Name, AUD_END);
3136     return code;
3137
3138 } /*SRXAFS_MakeDir*/
3139
3140
3141 /*
3142  * This routine is called exclusively by SRXAFS_RemoveDir(), and should be
3143  * merged into it when possible.
3144  */
3145 SAFSS_RemoveDir (tcon, DirFid, Name, OutDirStatus, Sync)
3146     struct rx_connection *tcon;          /* Rx connection handle */
3147     struct AFSFid *DirFid;               /* Parent dir's fid */
3148     char *Name;                          /* (Empty) dir's name to be removed */
3149     struct AFSFetchStatus *OutDirStatus; /* Output status for the parent dir */
3150     struct AFSVolSync *Sync;
3151
3152 {
3153     Vnode * parentptr = 0;              /* vnode of input Directory */
3154     Vnode * parentwhentargetnotdir = 0; /* parent for use in SetAccessList */
3155     Vnode * targetptr = 0;              /* file to be deleted */
3156     AFSFid fileFid;                     /* area for Fid from the directory */
3157     int     errorCode = 0;              /* error code */
3158     DirHandle dir;                      /* Handle for dir package I/O */
3159     Volume * volptr = 0;                /* pointer to the volume header */
3160     struct client * client;             /* pointer to client structure */
3161     afs_int32 rights, anyrights;                /* rights for this and any user */
3162     Vnode debugvnode1, debugvnode2;
3163     struct client *t_client;            /* tmp ptr to client data */
3164     struct in_addr logHostAddr;         /* host ip holder for inet_ntoa */
3165
3166     /* Get ptr to client data for user Id for logging */
3167     t_client = (struct client *) rx_GetSpecific(tcon, rxcon_client_key); 
3168     logHostAddr.s_addr =  rx_HostOf(rx_PeerOf(tcon));
3169     ViceLog(1, ("SAFS_RemoveDir %s,  Did = %u.%d.%d, Host %s, Id %d\n",
3170             Name, DirFid->Volume, DirFid->Vnode, DirFid->Unique,
3171             inet_ntoa(logHostAddr), t_client->ViceId));
3172     FS_LOCK
3173     AFSCallStats.RemoveDir++, AFSCallStats.TotalCalls++;
3174     FS_UNLOCK
3175     /*
3176      * Get the vnode and volume for the parent dir along with the caller's
3177      * rights to it
3178      */
3179     if (errorCode = GetVolumePackage(tcon, DirFid, &volptr, &parentptr,
3180                                      MustBeDIR, &parentwhentargetnotdir,
3181                                      &client, WRITE_LOCK, &rights, &anyrights)) {
3182         goto Bad_RemoveDir;
3183     }
3184     debugvnode1 = *parentptr;
3185
3186     /* set volume synchronization information */
3187     SetVolumeSync(Sync, volptr);
3188
3189     /* Does the caller has delete (&write) access to the parent dir? */
3190     if (errorCode = CheckWriteMode(parentptr, rights, PRSFS_DELETE)) {
3191         goto Bad_RemoveDir;
3192     }
3193
3194     debugvnode2 = *parentptr;
3195     /* Do the actual delete of the desired (empty) directory, Name */
3196     if (errorCode = DeleteTarget(parentptr, volptr, &targetptr, &dir, &fileFid,
3197                                  Name, MustBeDIR)) {
3198         goto Bad_RemoveDir;
3199     }
3200
3201     /* Update the status for the parent dir; link count is also adjusted */
3202 #if FS_STATS_DETAILED
3203     Update_ParentVnodeStatus(parentptr, volptr, &dir, client->ViceId,
3204                              parentptr->disk.linkCount-1, client->InSameNetwork);
3205 #else
3206     Update_ParentVnodeStatus(parentptr, volptr, &dir, client->ViceId,
3207                              parentptr->disk.linkCount-1);
3208 #endif /* FS_STATS_DETAILED */
3209
3210     /* Return to the caller the updated parent dir status */
3211     GetStatus(parentptr, OutDirStatus, rights, anyrights, (struct Vnode *)0);
3212
3213     /*
3214      * Note: it is not necessary to break the callback on fileFid, since
3215      * refcount is now 0, so no one should be able to refer to the dir
3216      * any longer
3217      */
3218     DeleteFileCallBacks(&fileFid);
3219
3220     /* convert the write lock to a read lock before breaking callbacks */
3221     VVnodeWriteToRead(&errorCode, parentptr);
3222     assert(!errorCode || errorCode == VSALVAGE);
3223
3224     /* break call back on DirFid and fileFid */
3225     BreakCallBack(client->host, DirFid, 0);
3226
3227 Bad_RemoveDir: 
3228     /* Write the all modified vnodes (parent, new files) and volume back */
3229     PutVolumePackage(parentwhentargetnotdir, targetptr, parentptr, volptr);
3230     ViceLog(2, ("SAFS_RemoveDir returns %d\n", errorCode));
3231     return errorCode;
3232
3233 } /*SAFSS_RemoveDir*/
3234
3235
3236 SRXAFS_RemoveDir (tcon, DirFid, Name, OutDirStatus, Sync)
3237     struct AFSVolSync *Sync;
3238     struct rx_connection *tcon;          /* Rx connection handle */
3239     struct AFSFid *DirFid;               /* Parent dir's fid */
3240     char *Name;                          /* (Empty) dir's name to be removed */
3241     struct AFSFetchStatus *OutDirStatus; /* Output status for the parent dir */
3242
3243 {
3244     afs_int32 code;
3245     struct rx_call *tcall = (struct rx_call *) tcon; 
3246 #if FS_STATS_DETAILED
3247     struct fs_stats_opTimingData *opP;      /* Ptr to this op's timing struct */
3248     struct timeval opStartTime,
3249                    opStopTime;              /* Start/stop times for RPC op*/
3250     struct timeval elapsedTime;             /* Transfer time */
3251
3252     /*
3253      * Set our stats pointer, remember when the RPC operation started, and
3254      * tally the operation.
3255      */
3256     opP = &(afs_FullPerfStats.det.rpcOpTimes[FS_STATS_RPCIDX_REMOVEDIR]);
3257     FS_LOCK
3258     (opP->numOps)++;
3259     FS_UNLOCK
3260     TM_GetTimeOfDay(&opStartTime, 0);
3261 #endif /* FS_STATS_DETAILED */
3262
3263     if (code = CallPreamble((struct rx_call **) &tcon, ACTIVECALL))
3264         goto Bad_RemoveDir;
3265
3266     code = SAFSS_RemoveDir (tcon, DirFid, Name, OutDirStatus, Sync);
3267     
3268 Bad_RemoveDir:
3269     CallPostamble(tcon);
3270
3271 #if FS_STATS_DETAILED
3272     TM_GetTimeOfDay(&opStopTime, 0);
3273     if (code == 0) {
3274       FS_LOCK
3275       (opP->numSuccesses)++;
3276       fs_stats_GetDiff(elapsedTime, opStartTime, opStopTime);
3277       fs_stats_AddTo((opP->sumTime), elapsedTime);
3278       fs_stats_SquareAddTo((opP->sqrTime), elapsedTime);
3279       if (fs_stats_TimeLessThan(elapsedTime, (opP->minTime))) {
3280         fs_stats_TimeAssign((opP->minTime), elapsedTime);
3281       }
3282       if (fs_stats_TimeGreaterThan(elapsedTime, (opP->maxTime))) {
3283         fs_stats_TimeAssign((opP->maxTime), elapsedTime);
3284       }
3285       FS_UNLOCK
3286     }
3287
3288 #endif /* FS_STATS_DETAILED */
3289
3290     osi_auditU (tcall, RemoveDirEvent, code, AUD_FID, DirFid, AUD_STR, Name, AUD_END);
3291     return code;
3292
3293 } /*SRXAFS_RemoveDir*/
3294
3295
3296 /*
3297  * This routine is called exclusively by SRXAFS_SetLock(), and should be
3298  * merged into it when possible.
3299  */
3300 SAFSS_SetLock (tcon, Fid, type, Sync)
3301     struct rx_connection *tcon; /* Rx connection handle */
3302     struct AFSFid *Fid;         /* Fid of file to lock */
3303     ViceLockType type;          /* Type of lock (Read or write) */
3304     struct AFSVolSync *Sync;
3305
3306 {
3307     Vnode * targetptr = 0;              /* vnode of input file */
3308     Vnode * parentwhentargetnotdir = 0; /* parent for use in SetAccessList */
3309     int     errorCode = 0;              /* error code */
3310     Volume * volptr = 0;                /* pointer to the volume header */
3311     struct client * client;             /* pointer to client structure */
3312     afs_int32 rights, anyrights;                /* rights for this and any user */
3313     struct client *t_client;            /* tmp ptr to client data */
3314     struct in_addr logHostAddr;         /* host ip holder for inet_ntoa */
3315     static char * locktype[2] = {"LockRead","LockWrite"};
3316
3317     if (type != LockRead && type != LockWrite) {
3318         errorCode = EINVAL;
3319         goto Bad_SetLock;
3320     }
3321     /* Get ptr to client data for user Id for logging */
3322     t_client = (struct client *) rx_GetSpecific(tcon, rxcon_client_key); 
3323     logHostAddr.s_addr =  rx_HostOf(rx_PeerOf(tcon));
3324     ViceLog(1,("SAFS_SetLock type = %s Fid = %u.%d.%d, Host %s, Id %d\n",
3325             locktype[(int)type], Fid->Volume, Fid->Vnode, Fid->Unique,
3326             inet_ntoa(logHostAddr), t_client->ViceId));
3327     FS_LOCK
3328     AFSCallStats.SetLock++, AFSCallStats.TotalCalls++;
3329     FS_UNLOCK
3330
3331     /*
3332      * Get the vnode and volume for the desired file along with the caller's
3333      * rights to it
3334      */
3335     if (errorCode = GetVolumePackage(tcon, Fid, &volptr, &targetptr,
3336                                      DONTCHECK, &parentwhentargetnotdir,
3337                                      &client, WRITE_LOCK, &rights, &anyrights)) {
3338         goto Bad_SetLock;
3339     }
3340
3341     /* set volume synchronization information */
3342     SetVolumeSync(Sync, volptr);
3343
3344     /* Handle the particular type of set locking, type */
3345     errorCode = HandleLocking(targetptr, rights, type);
3346
3347 Bad_SetLock: 
3348     /* Write the all modified vnodes (parent, new files) and volume back */
3349     PutVolumePackage(parentwhentargetnotdir, targetptr, (Vnode *)0, volptr);
3350
3351     if ((errorCode == VREADONLY) && (type == LockRead))
3352        errorCode = 0;  /* allow read locks on RO volumes without saving state */
3353
3354     ViceLog(2,("SAFS_SetLock returns %d\n", errorCode));
3355     return(errorCode);
3356
3357 }  /*SAFSS_SetLock*/
3358
3359
3360 SRXAFS_OldSetLock(tcon, Fid, type, Sync)
3361     struct AFSVolSync *Sync;
3362     struct rx_connection *tcon; /* Rx connection handle */
3363     struct AFSFid *Fid;         /* Fid of file to lock */
3364     ViceLockType type;          /* Type of lock (Read or write) */
3365
3366 {
3367     return SRXAFS_SetLock(tcon, Fid, type, Sync);
3368
3369 } /*SRXAFS_OldSetLock*/
3370
3371
3372 SRXAFS_SetLock (tcon, Fid, type, Sync)
3373     struct AFSVolSync *Sync;
3374     struct rx_connection *tcon; /* Rx connection handle */
3375     struct AFSFid *Fid;         /* Fid of file to lock */
3376     ViceLockType type;          /* Type of lock (Read or write) */
3377
3378 {
3379     afs_int32 code;
3380     struct rx_call *tcall = (struct rx_call *) tcon; 
3381 #if FS_STATS_DETAILED
3382     struct fs_stats_opTimingData *opP;      /* Ptr to this op's timing struct */
3383     struct timeval opStartTime,
3384                    opStopTime;              /* Start/stop times for RPC op*/
3385     struct timeval elapsedTime;             /* Transfer time */
3386
3387     /*
3388      * Set our stats pointer, remember when the RPC operation started, and
3389      * tally the operation.
3390      */
3391     opP = &(afs_FullPerfStats.det.rpcOpTimes[FS_STATS_RPCIDX_SETLOCK]);
3392     FS_LOCK
3393     (opP->numOps)++;
3394     FS_UNLOCK
3395     TM_GetTimeOfDay(&opStartTime, 0);
3396 #endif /* FS_STATS_DETAILED */
3397
3398     if (code = CallPreamble((struct rx_call **) &tcon, ACTIVECALL))
3399         goto Bad_SetLock;
3400
3401     code = SAFSS_SetLock (tcon, Fid, type, Sync);
3402     
3403 Bad_SetLock:
3404     CallPostamble(tcon);
3405
3406 #if FS_STATS_DETAILED
3407     TM_GetTimeOfDay(&opStopTime, 0); 
3408     if (code == 0) {
3409       FS_LOCK
3410       (opP->numSuccesses)++;
3411       fs_stats_GetDiff(elapsedTime, opStartTime, opStopTime);
3412       fs_stats_AddTo((opP->sumTime), elapsedTime);
3413       fs_stats_SquareAddTo((opP->sqrTime), elapsedTime);
3414       if (fs_stats_TimeLessThan(elapsedTime, (opP->minTime))) {
3415         fs_stats_TimeAssign((opP->minTime), elapsedTime);
3416       }
3417       if (fs_stats_TimeGreaterThan(elapsedTime, (opP->maxTime))) {
3418         fs_stats_TimeAssign((opP->maxTime), elapsedTime);
3419       }
3420       FS_UNLOCK
3421     }
3422 #endif /* FS_STATS_DETAILED */
3423
3424     osi_auditU (tcall, SetLockEvent, code, AUD_FID, Fid, AUD_LONG, type, AUD_END);
3425     return code;
3426
3427 } /*SRXAFS_SetLock*/
3428
3429
3430 /*
3431  * This routine is called exclusively by SRXAFS_ExtendLock(), and should be
3432  * merged into it when possible.
3433  */
3434 SAFSS_ExtendLock (tcon, Fid, Sync)
3435     struct rx_connection *tcon; /* Rx connection handle */
3436     struct AFSFid *Fid;         /* Fid of file whose lock we extend */
3437     struct AFSVolSync *Sync;
3438
3439 {
3440     Vnode * targetptr = 0;              /* vnode of input file */
3441     Vnode * parentwhentargetnotdir = 0; /* parent for use in SetAccessList */
3442     int     errorCode = 0;              /* error code */
3443     Volume * volptr = 0;                /* pointer to the volume header */
3444     struct client * client;             /* pointer to client structure */
3445     afs_int32 rights, anyrights;                /* rights for this and any user */
3446     struct client *t_client;            /* tmp ptr to client data */
3447     struct in_addr logHostAddr;         /* host ip holder for inet_ntoa */
3448
3449     /* Get ptr to client data for user Id for logging */
3450     t_client = (struct client *) rx_GetSpecific(tcon, rxcon_client_key); 
3451     logHostAddr.s_addr =  rx_HostOf(rx_PeerOf(tcon));
3452     ViceLog(1,("SAFS_ExtendLock Fid = %u.%d.%d, Host %s, Id %d\n", 
3453                Fid->Volume, Fid->Vnode, Fid->Unique, 
3454                inet_ntoa(logHostAddr), t_client->ViceId));
3455     FS_LOCK
3456     AFSCallStats.ExtendLock++, AFSCallStats.TotalCalls++;    
3457     FS_UNLOCK
3458     /*
3459      * Get the vnode and volume for the desired file along with the caller's
3460      * rights to it
3461      */
3462     if (errorCode = GetVolumePackage(tcon, Fid, &volptr, &targetptr,
3463                                      DONTCHECK, &parentwhentargetnotdir,
3464                                      &client, WRITE_LOCK, &rights, &anyrights)) {
3465         goto Bad_ExtendLock;
3466     }
3467
3468     /* set volume synchronization information */
3469     SetVolumeSync(Sync, volptr);
3470
3471     /* Handle the actual lock extension */
3472     errorCode = HandleLocking(targetptr, rights, LockExtend);
3473
3474 Bad_ExtendLock: 
3475     /* Put back file's vnode and volume */
3476     PutVolumePackage(parentwhentargetnotdir, targetptr, (Vnode *)0, volptr);
3477
3478     if ((errorCode == VREADONLY))  /* presumably, we already granted this lock */
3479        errorCode = 0;              /* under our generous policy re RO vols */
3480
3481     ViceLog(2,("SAFS_ExtendLock returns %d\n", errorCode));
3482     return(errorCode);
3483
3484 } /*SAFSS_ExtendLock*/
3485
3486
3487 SRXAFS_OldExtendLock (tcon, Fid, Sync)
3488     struct AFSVolSync *Sync;
3489     struct rx_connection *tcon; /* Rx connection handle */
3490     struct AFSFid *Fid;         /* Fid of file whose lock we extend */
3491
3492 {
3493     return SRXAFS_ExtendLock(tcon, Fid, Sync);
3494
3495 } /*SRXAFS_OldExtendLock*/
3496
3497
3498 SRXAFS_ExtendLock (tcon, Fid, Sync)
3499     struct AFSVolSync *Sync;
3500     struct rx_connection *tcon; /* Rx connection handle */
3501     struct AFSFid *Fid;         /* Fid of file whose lock we extend */
3502
3503 {
3504     afs_int32 code;